mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-05 22:00:10 -05:00
Merge branch 'upstream-curl' into update-curl
* upstream-curl: curl 2021-05-26 (6b951a69)
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -214,24 +214,6 @@ if (sizeof (bool *) )
|
||||
#include <float.h>
|
||||
int main() { return 0; }
|
||||
#endif
|
||||
#ifdef RETSIGTYPE_TEST
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#ifdef signal
|
||||
# undef signal
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" void (*signal (int, void (*)(int)))(int);
|
||||
#else
|
||||
void (*signal ()) ();
|
||||
#endif
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_INET_NTOA_R_DECL
|
||||
#include <arpa/inet.h>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
# Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
@@ -86,8 +86,6 @@ if(NOT UNIX)
|
||||
set(HAVE_INET_ADDR 1)
|
||||
set(HAVE_INET_NTOA 1)
|
||||
set(HAVE_INET_NTOA_R 0)
|
||||
set(HAVE_TCGETATTR 0)
|
||||
set(HAVE_TCSETATTR 0)
|
||||
set(HAVE_PERROR 1)
|
||||
set(HAVE_CLOSESOCKET 1)
|
||||
set(HAVE_SETVBUF 0)
|
||||
@@ -131,7 +129,6 @@ if(NOT UNIX)
|
||||
set(HAVE_GETADDRINFO 0)
|
||||
endif()
|
||||
set(STDC_HEADERS 1)
|
||||
set(RETSIGTYPE_TEST 1)
|
||||
|
||||
set(HAVE_SIGACTION 0)
|
||||
set(HAVE_MACRO_SIGSETJMP 0)
|
||||
|
||||
@@ -15,6 +15,7 @@ set(CURL_DISABLE_DICT ON CACHE INTERNAL "Disable curl dict protocol?")
|
||||
set(CURL_DISABLE_FILE OFF CACHE INTERNAL "Disable curl file protocol?")
|
||||
set(CURL_DISABLE_FTP OFF CACHE INTERNAL "Disable curl ftp protocol?")
|
||||
set(CURL_DISABLE_GOPHER ON CACHE INTERNAL "Disable curl gopher protocol?")
|
||||
set(CURL_DISABLE_HSTS ON)
|
||||
set(CURL_DISABLE_HTTP OFF CACHE INTERNAL "Disable curl http protocol?")
|
||||
set(CURL_DISABLE_IMAP ON CACHE INTERNAL "Disable curl imap protocol?")
|
||||
set(CURL_DISABLE_LDAP ON CACHE INTERNAL "Disable curl ldap protocol?")
|
||||
@@ -28,6 +29,7 @@ set(CURL_DISABLE_SMTP ON CACHE INTERNAL "Disable curl smtp protocol?")
|
||||
set(CURL_DISABLE_TELNET ON CACHE INTERNAL "Disable curl telnet protocol?")
|
||||
set(CURL_DISABLE_TFTP ON CACHE INTERNAL "Disable curl tftp protocol?")
|
||||
set(CURL_DISABLE_VERBOSE_STRINGS OFF CACHE INTERNAL "Do not disable curl verbosity")
|
||||
set(CURL_ENABLE_EXPORT_TARGET OFF)
|
||||
set(CURL_HIDDEN_SYMBOLS OFF CACHE INTERNAL "No curl hidden symbols")
|
||||
set(CURL_LTO OFF CACHE INTERNAL "Turn on compiler Link Time Optimizations")
|
||||
set(CURL_STATIC_CRT OFF CACHE INTERNAL "Set to ON to build libcurl with static CRT on Windows (/MT).")
|
||||
@@ -50,6 +52,7 @@ set(USE_LIBIDN2 ON)
|
||||
set(USE_NGHTTP2 ON)
|
||||
set(USE_NGTCP2 OFF)
|
||||
set(USE_QUICHE OFF)
|
||||
set(USE_WIN32_IDN OFF)
|
||||
set(USE_WIN32_LDAP OFF CACHE INTERNAL "No curl Windows LDAP")
|
||||
if(CMAKE_USE_OPENSSL)
|
||||
elseif(WIN32)
|
||||
@@ -304,6 +307,9 @@ mark_as_advanced(CURL_DISABLE_GOPHER)
|
||||
option(CURL_DISABLE_MQTT "to disable MQTT" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_MQTT)
|
||||
|
||||
option(CURL_ENABLE_EXPORT_TARGET "to enable cmake export target" ON)
|
||||
mark_as_advanced(CURL_ENABLE_EXPORT_TARGET)
|
||||
|
||||
if(HTTP_ONLY)
|
||||
set(CURL_DISABLE_DICT ON)
|
||||
set(CURL_DISABLE_FILE ON)
|
||||
@@ -323,6 +329,8 @@ endif()
|
||||
|
||||
option(CURL_DISABLE_ALTSVC "to disable alt-svc support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_ALTSVC)
|
||||
option(CURL_DISABLE_HSTS "to disable HSTS support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_HSTS)
|
||||
option(CURL_DISABLE_COOKIES "to disable cookies support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_COOKIES)
|
||||
option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF)
|
||||
@@ -433,7 +441,6 @@ check_function_exists(gethostname HAVE_GETHOSTNAME)
|
||||
if(WIN32)
|
||||
check_library_exists_concat("ws2_32" getch HAVE_LIBWS2_32)
|
||||
check_library_exists_concat("winmm" getch HAVE_LIBWINMM)
|
||||
list(APPEND CURL_LIBS "advapi32")
|
||||
endif()
|
||||
|
||||
# check SSL libraries
|
||||
@@ -478,7 +485,6 @@ if(CMAKE_USE_SCHANNEL)
|
||||
set(SSL_ENABLED ON)
|
||||
set(USE_SCHANNEL ON) # Windows native SSL/TLS support
|
||||
set(USE_WINDOWS_SSPI ON) # CMAKE_USE_SCHANNEL implies CURL_WINDOWS_SSPI
|
||||
list(APPEND CURL_LIBS "crypt32")
|
||||
endif()
|
||||
if(CURL_WINDOWS_SSPI)
|
||||
set(USE_WINDOWS_SSPI ON)
|
||||
@@ -505,6 +511,14 @@ if(CMAKE_USE_SECTRANSP)
|
||||
list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}")
|
||||
endif()
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
find_library(SYSTEMCONFIGURATION_FRAMEWORK "SystemConfiguration")
|
||||
if(NOT SYSTEMCONFIGURATION_FRAMEWORK)
|
||||
message(FATAL_ERROR "SystemConfiguration framework not found")
|
||||
endif()
|
||||
list(APPEND CURL_LIBS "${SYSTEMCONFIGURATION_FRAMEWORK}")
|
||||
endif()
|
||||
|
||||
if(CMAKE_USE_OPENSSL)
|
||||
find_package(OpenSSL)
|
||||
if(NOT OpenSSL_FOUND)
|
||||
@@ -633,10 +647,6 @@ if(USE_QUICHE)
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(USE_WIN32_CRYPTO ON)
|
||||
endif()
|
||||
|
||||
if(NOT CURL_DISABLE_LDAP)
|
||||
if(WIN32)
|
||||
option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON)
|
||||
@@ -753,6 +763,14 @@ if(USE_LIBIDN2)
|
||||
check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
option(USE_WIN32_IDN "Use WinIDN for IDN support" OFF)
|
||||
if(USE_WIN32_IDN)
|
||||
list(APPEND CURL_LIBS "Normaliz")
|
||||
set(WANT_IDN_PROTOTYPES ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check for symbol dlopen (same as HAVE_LIBDL)
|
||||
check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)
|
||||
|
||||
@@ -988,7 +1006,8 @@ elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT)
|
||||
foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS})
|
||||
if(EXISTS "${SEARCH_CA_BUNDLE_PATH}")
|
||||
message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}")
|
||||
set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}")
|
||||
set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}" CACHE STRING
|
||||
"Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
|
||||
set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
|
||||
break()
|
||||
endif()
|
||||
@@ -997,7 +1016,8 @@ elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT)
|
||||
|
||||
if(CURL_CA_PATH_AUTODETECT AND (NOT CURL_CA_PATH_SET))
|
||||
if(EXISTS "/etc/ssl/certs")
|
||||
set(CURL_CA_PATH "/etc/ssl/certs")
|
||||
set(CURL_CA_PATH "/etc/ssl/certs" CACHE STRING
|
||||
"Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
|
||||
set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
|
||||
endif()
|
||||
endif()
|
||||
@@ -1016,9 +1036,7 @@ if(NOT UNIX)
|
||||
check_include_file_concat("winsock.h" HAVE_WINSOCK_H)
|
||||
check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H)
|
||||
check_include_file_concat("winsock2.h" HAVE_WINSOCK2_H)
|
||||
if(NOT CURL_WINDOWS_SSPI AND USE_OPENSSL)
|
||||
set(CURL_LIBS ${CURL_LIBS} "crypt32")
|
||||
endif()
|
||||
check_include_file_concat("wincrypt.h" HAVE_WINCRYPT_H)
|
||||
else()
|
||||
set(HAVE_WINDOWS_H 0)
|
||||
set(HAVE_WINSOCK_H 0)
|
||||
@@ -1128,20 +1146,18 @@ check_symbol_exists(alarm "${CURL_INCLUDES}" HAVE_ALARM)
|
||||
if(NOT HAVE_STRNCMPI)
|
||||
set(HAVE_STRCMPI)
|
||||
endif()
|
||||
check_symbol_exists(getppid "${CURL_INCLUDES}" HAVE_GETPPID)
|
||||
check_symbol_exists(utimes "${CURL_INCLUDES}" HAVE_UTIMES)
|
||||
|
||||
check_symbol_exists(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR)
|
||||
check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R)
|
||||
check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
|
||||
check_symbol_exists(inet_addr "${CURL_INCLUDES}" HAVE_INET_ADDR)
|
||||
check_symbol_exists(inet_ntoa "${CURL_INCLUDES}" HAVE_INET_NTOA)
|
||||
check_symbol_exists(inet_ntoa_r "${CURL_INCLUDES}" HAVE_INET_NTOA_R)
|
||||
check_symbol_exists(tcsetattr "${CURL_INCLUDES}" HAVE_TCSETATTR)
|
||||
check_symbol_exists(tcgetattr "${CURL_INCLUDES}" HAVE_TCGETATTR)
|
||||
check_symbol_exists(perror "${CURL_INCLUDES}" HAVE_PERROR)
|
||||
check_symbol_exists(closesocket "${CURL_INCLUDES}" HAVE_CLOSESOCKET)
|
||||
check_symbol_exists(setvbuf "${CURL_INCLUDES}" HAVE_SETVBUF)
|
||||
check_symbol_exists(sigsetjmp "${CURL_INCLUDES}" HAVE_SIGSETJMP)
|
||||
check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R)
|
||||
check_symbol_exists(strlcat "${CURL_INCLUDES}" HAVE_STRLCAT)
|
||||
check_symbol_exists(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID)
|
||||
check_symbol_exists(getpwuid_r "${CURL_INCLUDES}" HAVE_GETPWUID_R)
|
||||
check_symbol_exists(geteuid "${CURL_INCLUDES}" HAVE_GETEUID)
|
||||
@@ -1191,6 +1207,16 @@ if(HAVE_FSETXATTR)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
|
||||
check_type_size("sa_family_t" SIZEOF_SA_FAMILY_T)
|
||||
set(HAVE_SA_FAMILY_T ${HAVE_SIZEOF_SA_FAMILY_T})
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "")
|
||||
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "ws2def.h")
|
||||
check_type_size("ADDRESS_FAMILY" SIZEOF_ADDRESS_FAMILY)
|
||||
set(HAVE_ADDRESS_FAMILY ${HAVE_SIZEOF_ADDRESS_FAMILY})
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "")
|
||||
|
||||
# sigaction and sigsetjmp are special. Use special mechanism for
|
||||
# detecting those, but only if previous attempt failed.
|
||||
if(HAVE_SIGNAL_H)
|
||||
@@ -1239,7 +1265,6 @@ foreach(CURL_TEST
|
||||
HAVE_IN_ADDR_T
|
||||
HAVE_BOOL_T
|
||||
STDC_HEADERS
|
||||
RETSIGTYPE_TEST
|
||||
HAVE_INET_NTOA_R_DECL
|
||||
HAVE_INET_NTOA_R_DECL_REENTRANT
|
||||
HAVE_GETADDRINFO
|
||||
@@ -1340,12 +1365,6 @@ if(HAVE_FIONBIO OR
|
||||
set(HAVE_DISABLED_NONBLOCKING)
|
||||
endif()
|
||||
|
||||
if(RETSIGTYPE_TEST)
|
||||
set(RETSIGTYPE void)
|
||||
else()
|
||||
set(RETSIGTYPE int)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
|
||||
include(CheckCCompilerFlag)
|
||||
check_c_compiler_flag(-Wno-long-double HAVE_C_FLAG_Wno_long_double)
|
||||
@@ -1383,6 +1402,19 @@ if(WIN32)
|
||||
|
||||
# Use the manifest embedded in the Windows Resource
|
||||
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DCURL_EMBED_MANIFEST")
|
||||
|
||||
# Check if crypto functions in wincrypt.h are actually available
|
||||
if(HAVE_WINCRYPT_H)
|
||||
check_symbol_exists(CryptAcquireContext "${CURL_INCLUDES}" USE_WINCRYPT)
|
||||
endif()
|
||||
if(USE_WINCRYPT)
|
||||
set(USE_WIN32_CRYPTO ON)
|
||||
endif()
|
||||
|
||||
# Link required libraries for USE_WIN32_CRYPTO or USE_SCHANNEL
|
||||
if(USE_WIN32_CRYPTO OR USE_SCHANNEL)
|
||||
list(APPEND CURL_LIBS "advapi32" "crypt32")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
@@ -1395,6 +1427,11 @@ if(MSVC)
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
|
||||
endif()
|
||||
|
||||
# Use multithreaded compilation on VS 2008+
|
||||
if(MSVC_VERSION GREATER_EQUAL 1500)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CURL_WERROR)
|
||||
@@ -1479,14 +1516,6 @@ if(BUILD_TESTING)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
# NTLM support requires crypto function adaptions from various SSL libs
|
||||
# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
|
||||
if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_DARWINSSL OR USE_MBEDTLS OR USE_WIN32_CRYPTO))
|
||||
set(use_ntlm ON)
|
||||
else()
|
||||
set(use_ntlm OFF)
|
||||
endif()
|
||||
|
||||
# Helper to populate a list (_items) with a label when conditions (the remaining
|
||||
# args) are satisfied
|
||||
macro(_add_if label)
|
||||
@@ -1496,6 +1525,13 @@ macro(_add_if label)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# NTLM support requires crypto function adaptions from various SSL libs
|
||||
# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
|
||||
if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_MBEDTLS OR
|
||||
USE_DARWINSSL OR USE_WIN32_CRYPTO))
|
||||
set(use_curl_ntlm_core ON)
|
||||
endif()
|
||||
|
||||
# Clear list and try to detect available features
|
||||
set(_items)
|
||||
_add_if("SSL" SSL_ENABLED)
|
||||
@@ -1505,13 +1541,14 @@ _add_if("libz" HAVE_LIBZ)
|
||||
_add_if("brotli" HAVE_BROTLI)
|
||||
_add_if("zstd" HAVE_ZSTD)
|
||||
_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
|
||||
_add_if("IDN" HAVE_LIBIDN2)
|
||||
_add_if("Largefile" (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND
|
||||
_add_if("IDN" HAVE_LIBIDN2 OR USE_WIN32_IDN)
|
||||
_add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND
|
||||
((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES))
|
||||
# TODO SSP1 (Schannel) check is missing
|
||||
_add_if("SSPI" USE_WINDOWS_SSPI)
|
||||
_add_if("GSS-API" HAVE_GSSAPI)
|
||||
_add_if("alt-svc" NOT CURL_DISABLE_ALTSVC)
|
||||
_add_if("HSTS" NOT CURL_DISABLE_HSTS)
|
||||
# TODO SSP1 missing for SPNEGO
|
||||
_add_if("SPNEGO" NOT CURL_DISABLE_CRYPTO_AUTH AND
|
||||
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
|
||||
@@ -1519,9 +1556,12 @@ _add_if("Kerberos" NOT CURL_DISABLE_CRYPTO_AUTH AND
|
||||
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
|
||||
# NTLM support requires crypto function adaptions from various SSL libs
|
||||
# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
|
||||
_add_if("NTLM" use_ntlm OR USE_WINDOWS_SSPI)
|
||||
_add_if("NTLM" NOT CURL_DISABLE_CRYPTO_AUTH AND
|
||||
(use_curl_ntlm_core OR USE_WINDOWS_SSPI))
|
||||
# TODO missing option (autoconf: --enable-ntlm-wb)
|
||||
_add_if("NTLM_WB" use_ntlm AND NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
|
||||
_add_if("NTLM_WB" NOT CURL_DISABLE_CRYPTO_AUTH AND
|
||||
(use_curl_ntlm_core OR USE_WINDOWS_SSPI) AND
|
||||
NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
|
||||
# TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP
|
||||
_add_if("TLS-SRP" USE_TLS_SRP)
|
||||
# TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header
|
||||
@@ -1555,8 +1595,10 @@ _add_if("POP3" NOT CURL_DISABLE_POP3)
|
||||
_add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
|
||||
_add_if("IMAP" NOT CURL_DISABLE_IMAP)
|
||||
_add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED)
|
||||
_add_if("SMB" NOT CURL_DISABLE_SMB AND use_ntlm)
|
||||
_add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND use_ntlm)
|
||||
_add_if("SMB" NOT CURL_DISABLE_SMB AND
|
||||
use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
|
||||
_add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND
|
||||
use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
|
||||
_add_if("SMTP" NOT CURL_DISABLE_SMTP)
|
||||
_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
|
||||
_add_if("SCP" USE_LIBSSH2 OR USE_LIBSSH)
|
||||
@@ -1572,7 +1614,7 @@ message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
|
||||
|
||||
# Clear list and collect SSL backends
|
||||
set(_items)
|
||||
_add_if("Schannel" SSL_ENABLED AND USE_WINDOWS_SSPI)
|
||||
_add_if("Schannel" SSL_ENABLED AND USE_SCHANNEL)
|
||||
_add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL)
|
||||
_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
|
||||
_add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS)
|
||||
@@ -1677,11 +1719,13 @@ configure_package_config_file(CMake/curl-config.cmake.in
|
||||
INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR}
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
NAMESPACE "${PROJECT_NAME}::"
|
||||
DESTINATION ${CURL_INSTALL_CMAKE_DIR}
|
||||
)
|
||||
if(CURL_ENABLE_EXPORT_TARGET)
|
||||
install(
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
NAMESPACE "${PROJECT_NAME}::"
|
||||
DESTINATION ${CURL_INSTALL_CMAKE_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
install(
|
||||
FILES ${version_config} ${project_config}
|
||||
|
||||
@@ -155,7 +155,8 @@ typedef enum {
|
||||
CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */
|
||||
CURLSSLBACKEND_MBEDTLS = 11,
|
||||
CURLSSLBACKEND_MESALINK = 12,
|
||||
CURLSSLBACKEND_BEARSSL = 13
|
||||
CURLSSLBACKEND_BEARSSL = 13,
|
||||
CURLSSLBACKEND_RUSTLS = 14
|
||||
} curl_sslbackend;
|
||||
|
||||
/* aliases for library clones and renames */
|
||||
@@ -611,6 +612,7 @@ typedef enum {
|
||||
CURLE_HTTP3, /* 95 - An HTTP/3 layer problem */
|
||||
CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */
|
||||
CURLE_PROXY, /* 97 - proxy handshake error */
|
||||
CURLE_SSL_CLIENTCERT, /* 98 - client-side certificate required */
|
||||
CURL_LAST /* never use! */
|
||||
} CURLcode;
|
||||
|
||||
@@ -887,6 +889,10 @@ typedef enum {
|
||||
operating system. Currently implemented under MS-Windows. */
|
||||
#define CURLSSLOPT_NATIVE_CA (1<<4)
|
||||
|
||||
/* - CURLSSLOPT_AUTO_CLIENT_CERT tells libcurl to automatically locate and use
|
||||
a client certificate for authentication. (Schannel) */
|
||||
#define CURLSSLOPT_AUTO_CLIENT_CERT (1<<5)
|
||||
|
||||
/* The default connection attempt delay in milliseconds for happy eyeballs.
|
||||
CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
|
||||
this value, keep them in sync. */
|
||||
@@ -1460,8 +1466,8 @@ typedef enum {
|
||||
#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
|
||||
|
||||
/* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
|
||||
tell libcurl to resolve names to those IP versions only. This only has
|
||||
affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
|
||||
tell libcurl to use those IP versions only. This only has effect on
|
||||
systems with support for more than one, i.e IPv4 _and_ IPv6. */
|
||||
CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_VALUES, 113),
|
||||
|
||||
/* Set this option to limit the size of a file that will be downloaded from
|
||||
@@ -2078,6 +2084,23 @@ typedef enum {
|
||||
/* Parameters for V4 signature */
|
||||
CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305),
|
||||
|
||||
/* Same as CURLOPT_SSL_VERIFYPEER but for DOH (DNS-over-HTTPS) servers. */
|
||||
CURLOPT(CURLOPT_DOH_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 306),
|
||||
|
||||
/* Same as CURLOPT_SSL_VERIFYHOST but for DOH (DNS-over-HTTPS) servers. */
|
||||
CURLOPT(CURLOPT_DOH_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 307),
|
||||
|
||||
/* Same as CURLOPT_SSL_VERIFYSTATUS but for DOH (DNS-over-HTTPS) servers. */
|
||||
CURLOPT(CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 308),
|
||||
|
||||
/* The CA certificates as "blob" used to validate the peer certificate
|
||||
this option is used only if SSL_VERIFYPEER is true */
|
||||
CURLOPT(CURLOPT_CAINFO_BLOB, CURLOPTTYPE_BLOB, 309),
|
||||
|
||||
/* The CA certificates as "blob" used to validate the proxy certificate
|
||||
this option is used only if PROXY_SSL_VERIFYPEER is true */
|
||||
CURLOPT(CURLOPT_PROXY_CAINFO_BLOB, CURLOPTTYPE_BLOB, 310),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
@@ -2112,10 +2135,10 @@ typedef enum {
|
||||
/* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host
|
||||
name resolves addresses using more than one IP protocol version, this
|
||||
option might be handy to force libcurl to use a specific IP version. */
|
||||
#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP
|
||||
#define CURL_IPRESOLVE_WHATEVER 0 /* default, uses addresses to all IP
|
||||
versions that your system allows */
|
||||
#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */
|
||||
#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */
|
||||
#define CURL_IPRESOLVE_V4 1 /* uses only IPv4 addresses/connections */
|
||||
#define CURL_IPRESOLVE_V6 2 /* uses only IPv6 addresses/connections */
|
||||
|
||||
/* three convenient "aliases" that follow the name scheme better */
|
||||
#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
|
||||
@@ -2751,8 +2774,9 @@ typedef enum {
|
||||
CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57,
|
||||
CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58,
|
||||
CURLINFO_PROXY_ERROR = CURLINFO_LONG + 59,
|
||||
CURLINFO_REFERER = CURLINFO_STRING + 60,
|
||||
|
||||
CURLINFO_LASTONE = 59
|
||||
CURLINFO_LASTONE = 60
|
||||
} CURLINFO;
|
||||
|
||||
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
|
||||
@@ -2855,6 +2879,7 @@ typedef enum {
|
||||
CURLVERSION_SEVENTH,
|
||||
CURLVERSION_EIGHTH,
|
||||
CURLVERSION_NINTH,
|
||||
CURLVERSION_TENTH,
|
||||
CURLVERSION_LAST /* never actually use this */
|
||||
} CURLversion;
|
||||
|
||||
@@ -2863,7 +2888,7 @@ typedef enum {
|
||||
meant to be a built-in version number for what kind of struct the caller
|
||||
expects. If the struct ever changes, we redefine the NOW to another enum
|
||||
from above. */
|
||||
#define CURLVERSION_NOW CURLVERSION_NINTH
|
||||
#define CURLVERSION_NOW CURLVERSION_TENTH
|
||||
|
||||
struct curl_version_info_data {
|
||||
CURLversion age; /* age of the returned struct */
|
||||
@@ -2916,6 +2941,9 @@ struct curl_version_info_data {
|
||||
|
||||
/* These fields were added in CURLVERSION_NINTH */
|
||||
const char *hyper_version; /* human readable string. */
|
||||
|
||||
/* These fields were added in CURLVERSION_TENTH */
|
||||
const char *gsasl_version; /* human readable string. */
|
||||
};
|
||||
typedef struct curl_version_info_data curl_version_info_data;
|
||||
|
||||
@@ -2953,6 +2981,7 @@ typedef struct curl_version_info_data curl_version_info_data;
|
||||
#define CURL_VERSION_ZSTD (1<<26) /* zstd features are present */
|
||||
#define CURL_VERSION_UNICODE (1<<27) /* Unicode support on Windows */
|
||||
#define CURL_VERSION_HSTS (1<<28) /* HSTS is supported */
|
||||
#define CURL_VERSION_GSASL (1<<29) /* libgsasl is supported */
|
||||
|
||||
/*
|
||||
* NAME curl_version_info()
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -26,16 +26,16 @@
|
||||
a script at release-time. This was made its own header file in 7.11.2 */
|
||||
|
||||
/* This is the global package copyright */
|
||||
#define LIBCURL_COPYRIGHT "1996 - 2020 Daniel Stenberg, <daniel@haxx.se>."
|
||||
#define LIBCURL_COPYRIGHT "1996 - 2021 Daniel Stenberg, <daniel@haxx.se>."
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.75.0"
|
||||
#define LIBCURL_VERSION "7.77.0"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 75
|
||||
#define LIBCURL_VERSION_MINOR 77
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
@@ -57,7 +57,7 @@
|
||||
CURL_VERSION_BITS() macro since curl's own configure script greps for it
|
||||
and needs it to contain the full number.
|
||||
*/
|
||||
#define LIBCURL_VERSION_NUM 0x074b00
|
||||
#define LIBCURL_VERSION_NUM 0x074d00
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -667,11 +667,11 @@ typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
|
||||
/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
|
||||
* this will of course break if we're included before OpenSSL headers...
|
||||
*/
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
|
||||
const void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX *, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX *, const void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX *, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX *,
|
||||
const void *);
|
||||
#else
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
# Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
@@ -20,6 +20,7 @@
|
||||
#
|
||||
###########################################################################
|
||||
set(LIB_NAME cmcurl)
|
||||
set(LIBCURL_OUTPUT_NAME cmcurl)
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(CURL_STATICLIB NO)
|
||||
@@ -125,7 +126,10 @@ if(WIN32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_target_properties(${LIB_NAME} PROPERTIES COMPILE_DEFINITIONS BUILDING_LIBCURL)
|
||||
set_target_properties(${LIB_NAME} PROPERTIES
|
||||
COMPILE_DEFINITIONS BUILDING_LIBCURL
|
||||
OUTPUT_NAME ${LIBCURL_OUTPUT_NAME}
|
||||
)
|
||||
|
||||
if(0) # This code not needed for building within CMake.
|
||||
if(HIDES_CURL_PRIVATE_SYMBOLS)
|
||||
@@ -145,13 +149,16 @@ endif()
|
||||
|
||||
if(WIN32)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
# Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib"
|
||||
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib")
|
||||
if(MSVC)
|
||||
# Add "_imp" as a suffix before the extension to avoid conflicting with
|
||||
# the statically linked "libcurl.lib"
|
||||
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_include_directories(${LIB_NAME} INTERFACE
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
|
||||
|
||||
install(TARGETS ${LIB_NAME}
|
||||
|
||||
@@ -25,6 +25,7 @@ LIB_VAUTH_CFILES = \
|
||||
vauth/cram.c \
|
||||
vauth/digest.c \
|
||||
vauth/digest_sspi.c \
|
||||
vauth/gsasl.c \
|
||||
vauth/krb5_gssapi.c \
|
||||
vauth/krb5_sspi.c \
|
||||
vauth/ntlm.c \
|
||||
@@ -49,6 +50,7 @@ LIB_VTLS_CFILES = \
|
||||
vtls/mesalink.c \
|
||||
vtls/nss.c \
|
||||
vtls/openssl.c \
|
||||
vtls/rustls.c \
|
||||
vtls/schannel.c \
|
||||
vtls/schannel_verify.c \
|
||||
vtls/sectransp.c \
|
||||
@@ -65,6 +67,7 @@ LIB_VTLS_HFILES = \
|
||||
vtls/mesalink.h \
|
||||
vtls/nssg.h \
|
||||
vtls/openssl.h \
|
||||
vtls/rustls.h \
|
||||
vtls/schannel.h \
|
||||
vtls/sectransp.h \
|
||||
vtls/vtls.h \
|
||||
@@ -94,6 +97,7 @@ LIB_CFILES = \
|
||||
asyn-ares.c \
|
||||
asyn-thread.c \
|
||||
base64.c \
|
||||
bufref.c \
|
||||
c-hyper.c \
|
||||
conncache.c \
|
||||
connect.c \
|
||||
@@ -214,6 +218,7 @@ LIB_HFILES = \
|
||||
amigaos.h \
|
||||
arpa_telnet.h \
|
||||
asyn.h \
|
||||
bufref.h \
|
||||
c-hyper.h \
|
||||
conncache.h \
|
||||
connect.h \
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -90,6 +90,33 @@ void Curl_amiga_X509_free(X509 *a)
|
||||
{
|
||||
X509_free(a);
|
||||
}
|
||||
|
||||
/* AmiSSL replaces many functions with macros. Curl requires pointer
|
||||
* to some of these functions. Thus, we have to encapsulate these macros.
|
||||
*/
|
||||
|
||||
#include "warnless.h"
|
||||
|
||||
int (SHA256_Init)(SHA256_CTX *c)
|
||||
{
|
||||
return SHA256_Init(c);
|
||||
};
|
||||
|
||||
int (SHA256_Update)(SHA256_CTX *c, const void *data, size_t len)
|
||||
{
|
||||
return SHA256_Update(c, data, curlx_uztoui(len));
|
||||
};
|
||||
|
||||
int (SHA256_Final)(unsigned char *md, SHA256_CTX *c)
|
||||
{
|
||||
return SHA256_Final(md, c);
|
||||
};
|
||||
|
||||
void (X509_INFO_free)(X509_INFO *a)
|
||||
{
|
||||
X509_INFO_free(a);
|
||||
};
|
||||
|
||||
#endif /* USE_AMISSL */
|
||||
#endif /* __AMIGA__ */
|
||||
|
||||
|
||||
@@ -309,7 +309,7 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
|
||||
pfd[i].fd = socks[i];
|
||||
pfd[i].events |= POLLWRNORM|POLLOUT;
|
||||
}
|
||||
if(pfd[i].events != 0)
|
||||
if(pfd[i].events)
|
||||
num++;
|
||||
else
|
||||
break;
|
||||
@@ -384,13 +384,8 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
|
||||
them */
|
||||
res->temp_ai = NULL;
|
||||
|
||||
if(!data->state.async.dns) {
|
||||
failf(data, "Could not resolve: %s (%s)",
|
||||
data->state.async.hostname,
|
||||
ares_strerror(data->state.async.status));
|
||||
result = data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
|
||||
CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
if(!data->state.async.dns)
|
||||
result = Curl_resolver_error(data);
|
||||
else
|
||||
*dns = data->state.async.dns;
|
||||
|
||||
@@ -625,28 +620,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
|
||||
int *waitp)
|
||||
{
|
||||
char *bufp;
|
||||
int family = PF_INET;
|
||||
|
||||
*waitp = 0; /* default to synchronous response */
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
switch(data->set.ipver) {
|
||||
default:
|
||||
#if ARES_VERSION >= 0x010601
|
||||
family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older
|
||||
c-ares versions this just falls through and defaults
|
||||
to PF_INET */
|
||||
break;
|
||||
#endif
|
||||
case CURL_IPRESOLVE_V4:
|
||||
family = PF_INET;
|
||||
break;
|
||||
case CURL_IPRESOLVE_V6:
|
||||
family = PF_INET6;
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLE_IPV6 */
|
||||
|
||||
bufp = strdup(hostname);
|
||||
if(bufp) {
|
||||
struct thread_data *res = NULL;
|
||||
@@ -666,33 +642,27 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
|
||||
|
||||
/* initial status - failed */
|
||||
res->last_status = ARES_ENOTFOUND;
|
||||
#ifdef ENABLE_IPV6
|
||||
if(family == PF_UNSPEC) {
|
||||
if(Curl_ipv6works(data)) {
|
||||
res->num_pending = 2;
|
||||
|
||||
/* areschannel is already setup in the Curl_open() function */
|
||||
ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
|
||||
PF_INET, query_completed_cb, data);
|
||||
ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
|
||||
PF_INET6, query_completed_cb, data);
|
||||
}
|
||||
else {
|
||||
res->num_pending = 1;
|
||||
#if ARES_VERSION >= 0x010601
|
||||
/* IPv6 supported by c-ares since 1.6.1 */
|
||||
if(Curl_ipv6works(data)) {
|
||||
/* The stack seems to be IPv6-enabled */
|
||||
res->num_pending = 2;
|
||||
|
||||
/* areschannel is already setup in the Curl_open() function */
|
||||
ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
|
||||
PF_INET, query_completed_cb, data);
|
||||
}
|
||||
/* areschannel is already setup in the Curl_open() function */
|
||||
ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
|
||||
PF_INET, query_completed_cb, data);
|
||||
ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
|
||||
PF_INET6, query_completed_cb, data);
|
||||
}
|
||||
else
|
||||
#endif /* ENABLE_IPV6 */
|
||||
#endif /* ARES_VERSION >= 0x010601 */
|
||||
{
|
||||
res->num_pending = 1;
|
||||
|
||||
/* areschannel is already setup in the Curl_open() function */
|
||||
ares_gethostbyname((ares_channel)data->state.async.resolver,
|
||||
hostname, family,
|
||||
hostname, PF_INET,
|
||||
query_completed_cb, data);
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ struct thread_sync_data {
|
||||
int port;
|
||||
char *hostname; /* hostname to resolve, Curl_async.hostname
|
||||
duplicate */
|
||||
#ifdef USE_SOCKETPAIR
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
struct Curl_easy *data;
|
||||
curl_socket_t sock_pair[2]; /* socket pair */
|
||||
#endif
|
||||
@@ -201,7 +201,7 @@ void destroy_thread_sync_data(struct thread_sync_data *tsd)
|
||||
if(tsd->res)
|
||||
Curl_freeaddrinfo(tsd->res);
|
||||
|
||||
#ifdef USE_SOCKETPAIR
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
/*
|
||||
* close one end of the socket pair (may be done in resolver thread);
|
||||
* the other end (for reading) is always closed in the parent thread.
|
||||
@@ -238,12 +238,12 @@ int init_thread_sync_data(struct thread_data *td,
|
||||
#endif
|
||||
|
||||
tsd->mtx = malloc(sizeof(curl_mutex_t));
|
||||
if(tsd->mtx == NULL)
|
||||
if(!tsd->mtx)
|
||||
goto err_exit;
|
||||
|
||||
Curl_mutex_init(tsd->mtx);
|
||||
|
||||
#ifdef USE_SOCKETPAIR
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
/* create socket pair, avoid AF_LOCAL since it doesn't build on Solaris */
|
||||
if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) {
|
||||
tsd->sock_pair[0] = CURL_SOCKET_BAD;
|
||||
@@ -297,7 +297,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
|
||||
struct thread_data *td = tsd->td;
|
||||
char service[12];
|
||||
int rc;
|
||||
#ifdef USE_SOCKETPAIR
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
char buf[1];
|
||||
#endif
|
||||
|
||||
@@ -305,7 +305,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
|
||||
|
||||
rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
|
||||
|
||||
if(rc != 0) {
|
||||
if(rc) {
|
||||
tsd->sock_error = SOCKERRNO?SOCKERRNO:rc;
|
||||
if(tsd->sock_error == 0)
|
||||
tsd->sock_error = RESOLVER_ENOMEM;
|
||||
@@ -322,7 +322,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
|
||||
free(td);
|
||||
}
|
||||
else {
|
||||
#ifdef USE_SOCKETPAIR
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
|
||||
/* DNS has been resolved, signal client task */
|
||||
buf[0] = 1;
|
||||
@@ -382,7 +382,7 @@ static void destroy_async_data(struct Curl_async *async)
|
||||
if(async->tdata) {
|
||||
struct thread_data *td = async->tdata;
|
||||
int done;
|
||||
#ifdef USE_SOCKETPAIR
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
curl_socket_t sock_rd = td->tsd.sock_pair[0];
|
||||
struct Curl_easy *data = td->tsd.data;
|
||||
#endif
|
||||
@@ -407,7 +407,7 @@ static void destroy_async_data(struct Curl_async *async)
|
||||
|
||||
free(async->tdata);
|
||||
}
|
||||
#ifdef USE_SOCKETPAIR
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
/*
|
||||
* ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
|
||||
* before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
|
||||
@@ -483,35 +483,6 @@ static bool init_resolve_thread(struct Curl_easy *data,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* resolver_error() calls failf() with the appropriate message after a resolve
|
||||
* error
|
||||
*/
|
||||
|
||||
static CURLcode resolver_error(struct Curl_easy *data)
|
||||
{
|
||||
const char *host_or_proxy;
|
||||
CURLcode result;
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
struct connectdata *conn = data->conn;
|
||||
if(conn->bits.httpproxy) {
|
||||
host_or_proxy = "proxy";
|
||||
result = CURLE_COULDNT_RESOLVE_PROXY;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
host_or_proxy = "host";
|
||||
result = CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
|
||||
failf(data, "Could not resolve %s: %s", host_or_proxy,
|
||||
data->state.async.hostname);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* 'entry' may be NULL and then no data is returned
|
||||
*/
|
||||
@@ -542,7 +513,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data,
|
||||
|
||||
if(!data->state.async.dns && report)
|
||||
/* a name was not resolved, report error */
|
||||
result = resolver_error(data);
|
||||
result = Curl_resolver_error(data);
|
||||
|
||||
destroy_async_data(&data->state.async);
|
||||
|
||||
@@ -616,7 +587,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
|
||||
getaddrinfo_complete(data);
|
||||
|
||||
if(!data->state.async.dns) {
|
||||
CURLcode result = resolver_error(data);
|
||||
CURLcode result = Curl_resolver_error(data);
|
||||
destroy_async_data(&data->state.async);
|
||||
return result;
|
||||
}
|
||||
@@ -654,13 +625,13 @@ 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;
|
||||
#ifdef USE_SOCKETPAIR
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
struct thread_data *td = data->state.async.tdata;
|
||||
#else
|
||||
(void)socks;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SOCKETPAIR
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
if(td) {
|
||||
/* return read fd to client for polling the DNS resolution status */
|
||||
socks[0] = td->tsd.sock_pair[0];
|
||||
@@ -679,7 +650,7 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
|
||||
else
|
||||
milli = 200;
|
||||
Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
|
||||
#ifdef USE_SOCKETPAIR
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -730,24 +701,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
|
||||
*waitp = 0; /* default to synchronous response */
|
||||
|
||||
#ifdef CURLRES_IPV6
|
||||
/*
|
||||
* Check if a limited name resolve has been requested.
|
||||
*/
|
||||
switch(data->set.ipver) {
|
||||
case CURL_IPRESOLVE_V4:
|
||||
pf = PF_INET;
|
||||
break;
|
||||
case CURL_IPRESOLVE_V6:
|
||||
pf = PF_INET6;
|
||||
break;
|
||||
default:
|
||||
if(Curl_ipv6works(data))
|
||||
/* The stack seems to be IPv6-enabled */
|
||||
pf = PF_UNSPEC;
|
||||
break;
|
||||
}
|
||||
|
||||
if((pf != PF_INET) && !Curl_ipv6works(data))
|
||||
/* The stack seems to be a non-IPv6 one */
|
||||
pf = PF_INET;
|
||||
#endif /* CURLRES_IPV6 */
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
#include "urldata.h"
|
||||
#include "bufref.h"
|
||||
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
#define SIGNATURE 0x5c48e9b2 /* Random pattern. */
|
||||
|
||||
/*
|
||||
* Init a bufref struct.
|
||||
*/
|
||||
void Curl_bufref_init(struct bufref *br)
|
||||
{
|
||||
DEBUGASSERT(br);
|
||||
br->dtor = NULL;
|
||||
br->ptr = NULL;
|
||||
br->len = 0;
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
br->signature = SIGNATURE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the buffer and re-init the necessary fields. It doesn't touch the
|
||||
* 'signature' field and thus this buffer reference can be reused.
|
||||
*/
|
||||
|
||||
void Curl_bufref_free(struct bufref *br)
|
||||
{
|
||||
DEBUGASSERT(br);
|
||||
DEBUGASSERT(br->signature == SIGNATURE);
|
||||
DEBUGASSERT(br->ptr || !br->len);
|
||||
|
||||
if(br->ptr && br->dtor)
|
||||
br->dtor((void *) br->ptr);
|
||||
|
||||
br->dtor = NULL;
|
||||
br->ptr = NULL;
|
||||
br->len = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the buffer reference to new values. The previously referenced buffer
|
||||
* is released before assignment.
|
||||
*/
|
||||
void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len,
|
||||
void (*dtor)(void *))
|
||||
{
|
||||
DEBUGASSERT(ptr || !len);
|
||||
DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH);
|
||||
|
||||
Curl_bufref_free(br);
|
||||
br->ptr = (const unsigned char *) ptr;
|
||||
br->len = len;
|
||||
br->dtor = dtor;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a pointer to the referenced buffer.
|
||||
*/
|
||||
const unsigned char *Curl_bufref_ptr(const struct bufref *br)
|
||||
{
|
||||
DEBUGASSERT(br);
|
||||
DEBUGASSERT(br->signature == SIGNATURE);
|
||||
DEBUGASSERT(br->ptr || !br->len);
|
||||
|
||||
return br->ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the length of the referenced buffer data.
|
||||
*/
|
||||
size_t Curl_bufref_len(const struct bufref *br)
|
||||
{
|
||||
DEBUGASSERT(br);
|
||||
DEBUGASSERT(br->signature == SIGNATURE);
|
||||
DEBUGASSERT(br->ptr || !br->len);
|
||||
|
||||
return br->len;
|
||||
}
|
||||
|
||||
CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len)
|
||||
{
|
||||
unsigned char *cpy = NULL;
|
||||
|
||||
DEBUGASSERT(br);
|
||||
DEBUGASSERT(br->signature == SIGNATURE);
|
||||
DEBUGASSERT(br->ptr || !br->len);
|
||||
DEBUGASSERT(ptr || !len);
|
||||
DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH);
|
||||
|
||||
if(ptr) {
|
||||
cpy = malloc(len + 1);
|
||||
if(!cpy)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(len)
|
||||
memcpy(cpy, ptr, len);
|
||||
cpy[len] = '\0';
|
||||
}
|
||||
|
||||
Curl_bufref_set(br, cpy, len, curl_free);
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef HEADER_CURL_BUFREF_H
|
||||
#define HEADER_CURL_BUFREF_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Generic buffer reference.
|
||||
*/
|
||||
struct bufref {
|
||||
void (*dtor)(void *); /* Associated destructor. */
|
||||
const unsigned char *ptr; /* Referenced data buffer. */
|
||||
size_t len; /* The data size in bytes. */
|
||||
#ifdef DEBUGBUILD
|
||||
int signature; /* Detect API use mistakes. */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
void Curl_bufref_init(struct bufref *br);
|
||||
void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len,
|
||||
void (*dtor)(void *));
|
||||
const unsigned char *Curl_bufref_ptr(const struct bufref *br);
|
||||
size_t Curl_bufref_len(const struct bufref *br);
|
||||
CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len);
|
||||
void Curl_bufref_free(struct bufref *br);
|
||||
|
||||
#endif
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "transfer.h"
|
||||
#include "multiif.h"
|
||||
#include "progress.h"
|
||||
#include "content_encoding.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
@@ -174,8 +175,14 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
|
||||
}
|
||||
if(k->ignorebody)
|
||||
return HYPER_ITER_CONTINUE;
|
||||
if(0 == len)
|
||||
return HYPER_ITER_CONTINUE;
|
||||
Curl_debug(data, CURLINFO_DATA_IN, buf, len);
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
|
||||
if(!data->set.http_ce_skip && k->writer_stack)
|
||||
/* content-encoded data */
|
||||
result = Curl_unencode_write(data, k->writer_stack, buf, len);
|
||||
else
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
|
||||
|
||||
if(result) {
|
||||
data->state.hresult = result;
|
||||
@@ -198,11 +205,8 @@ static CURLcode status_line(struct Curl_easy *data,
|
||||
const uint8_t *reason, size_t rlen)
|
||||
{
|
||||
CURLcode result;
|
||||
size_t wrote;
|
||||
size_t len;
|
||||
const char *vstr;
|
||||
curl_write_callback writeheader =
|
||||
data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func;
|
||||
vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" :
|
||||
(http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0");
|
||||
conn->httpversion =
|
||||
@@ -225,12 +229,12 @@ static CURLcode status_line(struct Curl_easy *data,
|
||||
len = Curl_dyn_len(&data->state.headerb);
|
||||
Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb),
|
||||
len);
|
||||
Curl_set_in_callback(data, true);
|
||||
wrote = writeheader(Curl_dyn_ptr(&data->state.headerb), 1, len,
|
||||
data->set.writeheader);
|
||||
Curl_set_in_callback(data, false);
|
||||
if(wrote != len)
|
||||
return CURLE_WRITE_ERROR;
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER,
|
||||
Curl_dyn_ptr(&data->state.headerb), len);
|
||||
if(result) {
|
||||
data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
|
||||
return HYPER_ITER_BREAK;
|
||||
}
|
||||
|
||||
data->info.header_size += (long)len;
|
||||
data->req.headerbytecount += (long)len;
|
||||
@@ -327,7 +331,7 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
|
||||
infof(data, "hyperstream is done!\n");
|
||||
break;
|
||||
}
|
||||
else if(t != HYPER_TASK_RESPONSE) {
|
||||
else if(t != HYPER_TASK_RESPONSE && t != HYPER_TASK_EMPTY) {
|
||||
*didwhat = KEEP_RECV;
|
||||
break;
|
||||
}
|
||||
@@ -464,8 +468,6 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
|
||||
else
|
||||
linelen = 2; /* CRLF ending */
|
||||
linelen += (p - n);
|
||||
if(!n)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
vlen = p - v;
|
||||
|
||||
if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen,
|
||||
@@ -741,7 +743,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(data->set.httpversion == CURL_HTTP_VERSION_1_0) {
|
||||
if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
|
||||
if(HYPERE_OK != hyper_request_set_version(req,
|
||||
HYPER_HTTP_VERSION_1_0)) {
|
||||
failf(data, "error setting HTTP version");
|
||||
@@ -807,14 +809,27 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
#endif
|
||||
|
||||
Curl_safefree(data->state.aptr.ref);
|
||||
if(data->change.referer && !Curl_checkheaders(data, "Referer")) {
|
||||
data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
|
||||
if(data->state.referer && !Curl_checkheaders(data, "Referer")) {
|
||||
data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
|
||||
if(!data->state.aptr.ref)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(Curl_hyper_header(data, headers, data->state.aptr.ref))
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(!Curl_checkheaders(data, "Accept-Encoding") &&
|
||||
data->set.str[STRING_ENCODING]) {
|
||||
Curl_safefree(data->state.aptr.accept_encoding);
|
||||
data->state.aptr.accept_encoding =
|
||||
aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
|
||||
if(!data->state.aptr.accept_encoding)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(Curl_hyper_header(data, headers, data->state.aptr.accept_encoding))
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
Curl_safefree(data->state.aptr.accept_encoding);
|
||||
|
||||
result = cookies(data, conn, headers);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
@@ -466,7 +466,6 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
|
||||
data->state.conn_cache->num_conn--;
|
||||
DEBUGF(infof(data, "The cache now contains %zu members\n",
|
||||
data->state.conn_cache->num_conn));
|
||||
conn_candidate->data = data; /* associate! */
|
||||
}
|
||||
|
||||
return conn_candidate;
|
||||
@@ -529,7 +528,6 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
|
||||
connc->num_conn--;
|
||||
DEBUGF(infof(data, "The cache now contains %zu members\n",
|
||||
connc->num_conn));
|
||||
conn_candidate->data = data; /* associate! */
|
||||
}
|
||||
CONNCACHE_UNLOCK(data);
|
||||
|
||||
|
||||
@@ -171,65 +171,63 @@ singleipconnect(struct Curl_easy *data,
|
||||
* infinite time left). If the value is negative, the timeout time has already
|
||||
* elapsed.
|
||||
*
|
||||
* The start time is stored in progress.t_startsingle - as set with
|
||||
* Curl_pgrsTime(..., TIMER_STARTSINGLE);
|
||||
*
|
||||
* If 'nowp' is non-NULL, it points to the current time.
|
||||
* 'duringconnect' is FALSE if not during a connect, as then of course the
|
||||
* connect timeout is not taken into account!
|
||||
*
|
||||
* @unittest: 1303
|
||||
*/
|
||||
|
||||
#define TIMEOUT_CONNECT 1
|
||||
#define TIMEOUT_MAXTIME 2
|
||||
|
||||
timediff_t Curl_timeleft(struct Curl_easy *data,
|
||||
struct curltime *nowp,
|
||||
bool duringconnect)
|
||||
{
|
||||
int timeout_set = 0;
|
||||
timediff_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
|
||||
unsigned int timeout_set = 0;
|
||||
timediff_t connect_timeout_ms = 0;
|
||||
timediff_t maxtime_timeout_ms = 0;
|
||||
timediff_t timeout_ms = 0;
|
||||
struct curltime now;
|
||||
|
||||
/* if a timeout is set, use the most restrictive one */
|
||||
/* The duration of a connect and the total transfer are calculated from two
|
||||
different time-stamps. It can end up with the total timeout being reached
|
||||
before the connect timeout expires and we must acknowledge whichever
|
||||
timeout that is reached first. The total timeout is set per entire
|
||||
operation, while the connect timeout is set per connect. */
|
||||
|
||||
if(data->set.timeout > 0)
|
||||
timeout_set |= 1;
|
||||
if(duringconnect && (data->set.connecttimeout > 0))
|
||||
timeout_set |= 2;
|
||||
|
||||
switch(timeout_set) {
|
||||
case 1:
|
||||
timeout_ms = data->set.timeout;
|
||||
break;
|
||||
case 2:
|
||||
timeout_ms = data->set.connecttimeout;
|
||||
break;
|
||||
case 3:
|
||||
if(data->set.timeout < data->set.connecttimeout)
|
||||
timeout_ms = data->set.timeout;
|
||||
else
|
||||
timeout_ms = data->set.connecttimeout;
|
||||
break;
|
||||
default:
|
||||
/* use the default */
|
||||
if(!duringconnect)
|
||||
/* if we're not during connect, there's no default timeout so if we're
|
||||
at zero we better just return zero and not make it a negative number
|
||||
by the math below */
|
||||
return 0;
|
||||
break;
|
||||
if(data->set.timeout > 0) {
|
||||
timeout_set = TIMEOUT_MAXTIME;
|
||||
maxtime_timeout_ms = data->set.timeout;
|
||||
}
|
||||
if(duringconnect) {
|
||||
timeout_set |= TIMEOUT_CONNECT;
|
||||
connect_timeout_ms = (data->set.connecttimeout > 0) ?
|
||||
data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT;
|
||||
}
|
||||
if(!timeout_set)
|
||||
/* no timeout */
|
||||
return 0;
|
||||
|
||||
if(!nowp) {
|
||||
now = Curl_now();
|
||||
nowp = &now;
|
||||
}
|
||||
|
||||
/* subtract elapsed time */
|
||||
if(duringconnect)
|
||||
/* since this most recent connect started */
|
||||
timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle);
|
||||
else
|
||||
/* since the entire operation started */
|
||||
timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop);
|
||||
if(timeout_set & TIMEOUT_MAXTIME) {
|
||||
maxtime_timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop);
|
||||
timeout_ms = maxtime_timeout_ms;
|
||||
}
|
||||
|
||||
if(timeout_set & TIMEOUT_CONNECT) {
|
||||
connect_timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle);
|
||||
|
||||
if(!(timeout_set & TIMEOUT_MAXTIME) ||
|
||||
(connect_timeout_ms < maxtime_timeout_ms))
|
||||
timeout_ms = connect_timeout_ms;
|
||||
}
|
||||
|
||||
if(!timeout_ms)
|
||||
/* avoid returning 0 as that means no timeout! */
|
||||
return -1;
|
||||
@@ -611,7 +609,7 @@ static CURLcode trynextip(struct Curl_easy *data,
|
||||
/* Copies connection info into the transfer handle to make it available when
|
||||
the transfer handle is no longer associated with the connection. */
|
||||
void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
|
||||
char *local_ip, long local_port)
|
||||
char *local_ip, int local_port)
|
||||
{
|
||||
memcpy(data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
|
||||
if(local_ip && local_ip[0])
|
||||
@@ -627,7 +625,7 @@ void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
|
||||
/* retrieves ip address and port from a sockaddr structure.
|
||||
note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
|
||||
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
|
||||
char *addr, long *port)
|
||||
char *addr, int *port)
|
||||
{
|
||||
struct sockaddr_in *si = NULL;
|
||||
#ifdef ENABLE_IPV6
|
||||
@@ -662,7 +660,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
|
||||
#endif
|
||||
#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
|
||||
case AF_UNIX:
|
||||
if(salen > (curl_socklen_t)sizeof(sa_family_t)) {
|
||||
if(salen > (curl_socklen_t)sizeof(CURL_SA_FAMILY_T)) {
|
||||
su = (struct sockaddr_un*)sa;
|
||||
msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
|
||||
}
|
||||
@@ -690,7 +688,7 @@ void Curl_conninfo_remote(struct Curl_easy *data,
|
||||
char buffer[STRERROR_LEN];
|
||||
struct Curl_sockaddr_storage ssrem;
|
||||
curl_socklen_t plen;
|
||||
long port;
|
||||
int port;
|
||||
plen = sizeof(struct Curl_sockaddr_storage);
|
||||
memset(&ssrem, 0, sizeof(ssrem));
|
||||
if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) {
|
||||
@@ -715,7 +713,7 @@ void Curl_conninfo_remote(struct Curl_easy *data,
|
||||
/* retrieves the start/end point information of a socket of an established
|
||||
connection */
|
||||
void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd,
|
||||
char *local_ip, long *local_port)
|
||||
char *local_ip, int *local_port)
|
||||
{
|
||||
#ifdef HAVE_GETSOCKNAME
|
||||
char buffer[STRERROR_LEN];
|
||||
@@ -752,7 +750,7 @@ void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
|
||||
ip address and port number whenever an outgoing connection is
|
||||
**established** from the primary socket to a remote address. */
|
||||
char local_ip[MAX_IPADR_LEN] = "";
|
||||
long local_port = -1;
|
||||
int local_port = -1;
|
||||
|
||||
if(conn->transport == TRNSPRT_TCP) {
|
||||
if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
|
||||
@@ -908,8 +906,10 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
|
||||
connkeep(conn, "HTTP/3 default");
|
||||
return CURLE_OK;
|
||||
}
|
||||
if(result)
|
||||
if(result) {
|
||||
conn->tempsock[i] = CURL_SOCKET_BAD;
|
||||
error = SOCKERRNO;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -1158,7 +1158,7 @@ static CURLcode singleipconnect(struct Curl_easy *data,
|
||||
curl_socket_t sockfd;
|
||||
CURLcode result;
|
||||
char ipaddress[MAX_IPADR_LEN];
|
||||
long port;
|
||||
int port;
|
||||
bool is_tcp;
|
||||
#ifdef TCP_FASTOPEN_CONNECT
|
||||
int optval = 1;
|
||||
@@ -1180,7 +1180,7 @@ static CURLcode singleipconnect(struct Curl_easy *data,
|
||||
Curl_closesocket(data, conn, sockfd);
|
||||
return CURLE_OK;
|
||||
}
|
||||
infof(data, " Trying %s:%ld...\n", ipaddress, port);
|
||||
infof(data, " Trying %s:%d...\n", ipaddress, port);
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
|
||||
@@ -1367,14 +1367,31 @@ CURLcode Curl_connecthost(struct Curl_easy *data,
|
||||
conn->timeoutms_per_addr[1] =
|
||||
conn->tempaddr[1]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
|
||||
|
||||
conn->tempfamily[0] = conn->tempaddr[0]?
|
||||
conn->tempaddr[0]->ai_family:0;
|
||||
if(conn->ip_version == CURL_IPRESOLVE_WHATEVER) {
|
||||
/* any IP version is allowed */
|
||||
conn->tempfamily[0] = conn->tempaddr[0]?
|
||||
conn->tempaddr[0]->ai_family:0;
|
||||
#ifdef ENABLE_IPV6
|
||||
conn->tempfamily[1] = conn->tempfamily[0] == AF_INET6 ?
|
||||
AF_INET : AF_INET6;
|
||||
conn->tempfamily[1] = conn->tempfamily[0] == AF_INET6 ?
|
||||
AF_INET : AF_INET6;
|
||||
#else
|
||||
conn->tempfamily[1] = AF_UNSPEC;
|
||||
conn->tempfamily[1] = AF_UNSPEC;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
/* only one IP version is allowed */
|
||||
conn->tempfamily[0] = (conn->ip_version == CURL_IPRESOLVE_V4) ?
|
||||
AF_INET :
|
||||
#ifdef ENABLE_IPV6
|
||||
AF_INET6;
|
||||
#else
|
||||
AF_UNSPEC;
|
||||
#endif
|
||||
conn->tempfamily[1] = AF_UNSPEC;
|
||||
|
||||
ainext(conn, 0, FALSE); /* find first address of the right type */
|
||||
}
|
||||
|
||||
ainext(conn, 1, FALSE); /* assigns conn->tempaddr[1] accordingly */
|
||||
|
||||
DEBUGF(infof(data, "family0 == %s, family1 == %s\n",
|
||||
@@ -1448,11 +1465,9 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
c = find.found;
|
||||
if(connp) {
|
||||
if(connp)
|
||||
/* only store this if the caller cares for it */
|
||||
*connp = c;
|
||||
c->data = data;
|
||||
}
|
||||
return c->sock[FIRSTSOCKET];
|
||||
}
|
||||
return CURL_SOCKET_BAD;
|
||||
|
||||
@@ -54,7 +54,7 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
|
||||
struct connectdata **connp);
|
||||
|
||||
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
|
||||
char *addr, long *port);
|
||||
char *addr, int *port);
|
||||
|
||||
/*
|
||||
* Check if a connection seems to be alive.
|
||||
@@ -81,9 +81,9 @@ void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
|
||||
void Curl_conninfo_remote(struct Curl_easy *data, struct connectdata *conn,
|
||||
curl_socket_t sockfd);
|
||||
void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd,
|
||||
char *local_ip, long *local_port);
|
||||
char *local_ip, int *local_port);
|
||||
void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
|
||||
char *local_ip, long local_port);
|
||||
char *local_ip, int local_port);
|
||||
int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn,
|
||||
curl_socket_t sock);
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
|
||||
/* Dynamically allocate a buffer for decompression because it's uncommonly
|
||||
large to hold on the stack */
|
||||
decomp = malloc(DSIZ);
|
||||
if(decomp == NULL)
|
||||
if(!decomp)
|
||||
return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
|
||||
|
||||
/* because the buffer size is fixed, iteratively decompress and transfer to
|
||||
@@ -487,7 +487,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data,
|
||||
*/
|
||||
z->avail_in = (uInt) nbytes;
|
||||
z->next_in = malloc(z->avail_in);
|
||||
if(z->next_in == NULL) {
|
||||
if(!z->next_in) {
|
||||
return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
|
||||
}
|
||||
memcpy(z->next_in, buf, z->avail_in);
|
||||
@@ -509,7 +509,7 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data,
|
||||
ssize_t hlen;
|
||||
z->avail_in += (uInt) nbytes;
|
||||
z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
|
||||
if(z->next_in == NULL) {
|
||||
if(!z->next_in) {
|
||||
return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
|
||||
}
|
||||
/* Append the new block of data to the previous one */
|
||||
@@ -985,7 +985,8 @@ new_unencoding_writer(struct Curl_easy *data,
|
||||
return writer;
|
||||
}
|
||||
|
||||
/* Write data using an unencoding writer stack. */
|
||||
/* Write data using an unencoding writer stack. "nbytes" is not
|
||||
allowed to be 0. */
|
||||
CURLcode Curl_unencode_write(struct Curl_easy *data,
|
||||
struct contenc_writer *writer,
|
||||
const char *buf, size_t nbytes)
|
||||
|
||||
+253
-182
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -105,6 +105,8 @@ Example set of cookies:
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
static void strstore(char **str, const char *newstr);
|
||||
|
||||
static void freecookie(struct Cookie *co)
|
||||
{
|
||||
free(co->expirestr);
|
||||
@@ -129,12 +131,13 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
|
||||
if(!strcasecompare(cooke_domain, hostname + hostname_len-cookie_domain_len))
|
||||
return FALSE;
|
||||
|
||||
/* A lead char of cookie_domain is not '.'.
|
||||
RFC6265 4.1.2.3. The Domain Attribute says:
|
||||
For example, if the value of the Domain attribute is
|
||||
"example.com", the user agent will include the cookie in the Cookie
|
||||
header when making HTTP requests to example.com, www.example.com, and
|
||||
www.corp.example.com.
|
||||
/*
|
||||
* A lead char of cookie_domain is not '.'.
|
||||
* RFC6265 4.1.2.3. The Domain Attribute says:
|
||||
* For example, if the value of the Domain attribute is
|
||||
* "example.com", the user agent will include the cookie in the Cookie
|
||||
* header when making HTTP requests to example.com, www.example.com, and
|
||||
* www.corp.example.com.
|
||||
*/
|
||||
if(hostname_len == cookie_domain_len)
|
||||
return TRUE;
|
||||
@@ -144,7 +147,10 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the given string is an IP(v4|v6) address.
|
||||
* isip
|
||||
*
|
||||
* Returns true if the given string is an IPv4 or IPv6 address (if IPv6 has
|
||||
* been enabled while building libcurl, and false otherwise.
|
||||
*/
|
||||
static bool isip(const char *domain)
|
||||
{
|
||||
@@ -193,19 +199,19 @@ static bool pathmatch(const char *cookie_path, const char *request_uri)
|
||||
|
||||
/* #-fragments are already cut off! */
|
||||
if(0 == strlen(uri_path) || uri_path[0] != '/') {
|
||||
free(uri_path);
|
||||
uri_path = strdup("/");
|
||||
strstore(&uri_path, "/");
|
||||
if(!uri_path)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* here, RFC6265 5.1.4 says
|
||||
4. Output the characters of the uri-path from the first character up
|
||||
to, but not including, the right-most %x2F ("/").
|
||||
but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site
|
||||
without redirect.
|
||||
Ignore this algorithm because /hoge is uri path for this case
|
||||
(uri path is not /).
|
||||
/*
|
||||
* here, RFC6265 5.1.4 says
|
||||
* 4. Output the characters of the uri-path from the first character up
|
||||
* to, but not including, the right-most %x2F ("/").
|
||||
* but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site
|
||||
* without redirect.
|
||||
* Ignore this algorithm because /hoge is uri path for this case
|
||||
* (uri path is not /).
|
||||
*/
|
||||
|
||||
uri_path_len = strlen(uri_path);
|
||||
@@ -328,8 +334,7 @@ static char *sanitize_cookie_path(const char *cookie_path)
|
||||
/* RFC6265 5.2.4 The Path Attribute */
|
||||
if(new_path[0] != '/') {
|
||||
/* Let cookie-path be the default-path. */
|
||||
free(new_path);
|
||||
new_path = strdup("/");
|
||||
strstore(&new_path, "/");
|
||||
return new_path;
|
||||
}
|
||||
|
||||
@@ -348,7 +353,7 @@ static char *sanitize_cookie_path(const char *cookie_path)
|
||||
*/
|
||||
void Curl_cookie_loadfiles(struct Curl_easy *data)
|
||||
{
|
||||
struct curl_slist *list = data->change.cookielist;
|
||||
struct curl_slist *list = data->state.cookielist;
|
||||
if(list) {
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
|
||||
while(list) {
|
||||
@@ -357,7 +362,8 @@ void Curl_cookie_loadfiles(struct Curl_easy *data)
|
||||
data->cookies,
|
||||
data->set.cookiesession);
|
||||
if(!newcookies)
|
||||
/* Failure may be due to OOM or a bad cookie; both are ignored
|
||||
/*
|
||||
* Failure may be due to OOM or a bad cookie; both are ignored
|
||||
* but only the first should be
|
||||
*/
|
||||
infof(data, "ignoring failed cookie_init for %s\n", list->data);
|
||||
@@ -365,17 +371,20 @@ void Curl_cookie_loadfiles(struct Curl_easy *data)
|
||||
data->cookies = newcookies;
|
||||
list = list->next;
|
||||
}
|
||||
curl_slist_free_all(data->change.cookielist); /* clean up list */
|
||||
data->change.cookielist = NULL; /* don't do this again! */
|
||||
curl_slist_free_all(data->state.cookielist); /* clean up list */
|
||||
data->state.cookielist = NULL; /* don't do this again! */
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* strstore() makes a strdup() on the 'newstr' and if '*str' is non-NULL
|
||||
* that will be freed before the allocated string is stored there.
|
||||
* strstore
|
||||
*
|
||||
* It is meant to easily replace strdup()
|
||||
* A thin wrapper around strdup which ensures that any memory allocated at
|
||||
* *str will be freed before the string allocated by strdup is stored there.
|
||||
* The intended usecase is repeated assignments to the same variable during
|
||||
* parsing in a last-wins scenario. The caller is responsible for checking
|
||||
* for OOM errors.
|
||||
*/
|
||||
static void strstore(char **str, const char *newstr)
|
||||
{
|
||||
@@ -384,7 +393,11 @@ static void strstore(char **str, const char *newstr)
|
||||
}
|
||||
|
||||
/*
|
||||
* remove_expired() removes expired cookies.
|
||||
* remove_expired
|
||||
*
|
||||
* Remove expired cookies from the hash by inspecting the expires timestamp on
|
||||
* each cookie in the hash, freeing and deleting any where the timestamp is in
|
||||
* the past.
|
||||
*/
|
||||
static void remove_expired(struct CookieInfo *cookies)
|
||||
{
|
||||
@@ -421,25 +434,23 @@ static bool bad_domain(const char *domain)
|
||||
return !strchr(domain, '.') && !strcasecompare(domain, "localhost");
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
/*
|
||||
* Curl_cookie_add
|
||||
*
|
||||
* Curl_cookie_add()
|
||||
*
|
||||
* Add a single cookie line to the cookie keeping object.
|
||||
*
|
||||
* Be aware that sometimes we get an IP-only host name, and that might also be
|
||||
* a numerical IPv6 address.
|
||||
* Add a single cookie line to the cookie keeping object. Be aware that
|
||||
* sometimes we get an IP-only host name, and that might also be a numerical
|
||||
* IPv6 address.
|
||||
*
|
||||
* Returns NULL on out of memory or invalid cookie. This is suboptimal,
|
||||
* as they should be treated separately.
|
||||
***************************************************************************/
|
||||
|
||||
*/
|
||||
struct Cookie *
|
||||
Curl_cookie_add(struct Curl_easy *data,
|
||||
/* The 'data' pointer here may be NULL at times, and thus
|
||||
must only be used very carefully for things that can deal
|
||||
with data being NULL. Such as infof() and similar */
|
||||
|
||||
/*
|
||||
* The 'data' pointer here may be NULL at times, and thus
|
||||
* must only be used very carefully for things that can deal
|
||||
* with data being NULL. Such as infof() and similar
|
||||
*/
|
||||
struct CookieInfo *c,
|
||||
bool httpheader, /* TRUE if HTTP header-style line */
|
||||
bool noexpire, /* if TRUE, skip remove_expired() */
|
||||
@@ -493,9 +504,11 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%"
|
||||
MAX_NAME_TXT "[^;\r\n]",
|
||||
name, what)) {
|
||||
/* Use strstore() below to properly deal with received cookie
|
||||
headers that have the same string property set more than once,
|
||||
and then we use the last one. */
|
||||
/*
|
||||
* Use strstore() below to properly deal with received cookie
|
||||
* headers that have the same string property set more than once,
|
||||
* and then we use the last one.
|
||||
*/
|
||||
const char *whatptr;
|
||||
bool done = FALSE;
|
||||
bool sep;
|
||||
@@ -503,11 +516,13 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
size_t nlen = strlen(name);
|
||||
const char *endofn = &ptr[ nlen ];
|
||||
|
||||
/*
|
||||
* Check for too long individual name or contents, or too long
|
||||
* combination of name + contents. Chrome and Firefox support 4095 or
|
||||
* 4096 bytes combo
|
||||
*/
|
||||
if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) ||
|
||||
((nlen + len) > MAX_NAME)) {
|
||||
/* too long individual name or contents, or too long combination of
|
||||
name + contents. Chrome and Firefox support 4095 or 4096 bytes
|
||||
combo. */
|
||||
freecookie(co);
|
||||
infof(data, "oversized cookie dropped, name/val %zu + %zu bytes\n",
|
||||
nlen, len);
|
||||
@@ -569,8 +584,10 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
else if(!len) {
|
||||
/* this was a "<name>=" with no content, and we must allow
|
||||
'secure' and 'httponly' specified this weirdly */
|
||||
/*
|
||||
* this was a "<name>=" with no content, and we must allow
|
||||
* 'secure' and 'httponly' specified this weirdly
|
||||
*/
|
||||
done = TRUE;
|
||||
/*
|
||||
* secure cookies are only allowed to be set when the connection is
|
||||
@@ -610,8 +627,10 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
else if(strcasecompare("domain", name)) {
|
||||
bool is_ip;
|
||||
|
||||
/* Now, we make sure that our host is within the given domain,
|
||||
or the given domain is not valid and thus cannot be set. */
|
||||
/*
|
||||
* Now, we make sure that our host is within the given domain, or
|
||||
* the given domain is not valid and thus cannot be set.
|
||||
*/
|
||||
|
||||
if('.' == whatptr[0])
|
||||
whatptr++; /* ignore preceding dot */
|
||||
@@ -641,9 +660,10 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
given */
|
||||
}
|
||||
else {
|
||||
/* we did not get a tailmatch and then the attempted set domain
|
||||
is not a domain to which the current host belongs. Mark as
|
||||
bad. */
|
||||
/*
|
||||
* We did not get a tailmatch and then the attempted set domain is
|
||||
* not a domain to which the current host belongs. Mark as bad.
|
||||
*/
|
||||
badcookie = TRUE;
|
||||
infof(data, "skipped cookie with bad tailmatch domain: %s\n",
|
||||
whatptr);
|
||||
@@ -657,15 +677,15 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
else if(strcasecompare("max-age", name)) {
|
||||
/* Defined in RFC2109:
|
||||
|
||||
Optional. The Max-Age attribute defines the lifetime of the
|
||||
cookie, in seconds. The delta-seconds value is a decimal non-
|
||||
negative integer. After delta-seconds seconds elapse, the
|
||||
client should discard the cookie. A value of zero means the
|
||||
cookie should be discarded immediately.
|
||||
|
||||
*/
|
||||
/*
|
||||
* Defined in RFC2109:
|
||||
*
|
||||
* Optional. The Max-Age attribute defines the lifetime of the
|
||||
* cookie, in seconds. The delta-seconds value is a decimal non-
|
||||
* negative integer. After delta-seconds seconds elapse, the
|
||||
* client should discard the cookie. A value of zero means the
|
||||
* cookie should be discarded immediately.
|
||||
*/
|
||||
strstore(&co->maxage, whatptr);
|
||||
if(!co->maxage) {
|
||||
badcookie = TRUE;
|
||||
@@ -679,9 +699,10 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
else this is the second (or more) name we don't know
|
||||
about! */
|
||||
* Else, this is the second (or more) name we don't know about!
|
||||
*/
|
||||
}
|
||||
else {
|
||||
/* this is an "illegal" <what>=<this> pair */
|
||||
@@ -699,8 +720,10 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
semiptr = strchr(ptr, ';'); /* now, find the next semicolon */
|
||||
|
||||
if(!semiptr && *ptr)
|
||||
/* There are no more semicolons, but there's a final name=value pair
|
||||
coming up */
|
||||
/*
|
||||
* There are no more semicolons, but there's a final name=value pair
|
||||
* coming up
|
||||
*/
|
||||
semiptr = strchr(ptr, '\0');
|
||||
} while(semiptr);
|
||||
|
||||
@@ -724,13 +747,16 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
else if(co->expirestr) {
|
||||
/* Note that if the date couldn't get parsed for whatever reason,
|
||||
the cookie will be treated as a session cookie */
|
||||
/*
|
||||
* Note that if the date couldn't get parsed for whatever reason, the
|
||||
* cookie will be treated as a session cookie
|
||||
*/
|
||||
co->expires = Curl_getdate_capped(co->expirestr);
|
||||
|
||||
/* Session cookies have expires set to 0 so if we get that back
|
||||
from the date parser let's add a second to make it a
|
||||
non-session cookie */
|
||||
/*
|
||||
* Session cookies have expires set to 0 so if we get that back from the
|
||||
* date parser let's add a second to make it a non-session cookie
|
||||
*/
|
||||
if(co->expires == 0)
|
||||
co->expires = 1;
|
||||
else if(co->expires < 0)
|
||||
@@ -747,13 +773,17 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
if(!badcookie && !co->path && path) {
|
||||
/* No path was given in the header line, set the default.
|
||||
Note that the passed-in path to this function MAY have a '?' and
|
||||
following part that MUST not be stored as part of the path. */
|
||||
/*
|
||||
* No path was given in the header line, set the default. Note that the
|
||||
* passed-in path to this function MAY have a '?' and following part that
|
||||
* MUST NOT be stored as part of the path.
|
||||
*/
|
||||
char *queryp = strchr(path, '?');
|
||||
|
||||
/* queryp is where the interesting part of the path ends, so now we
|
||||
want to the find the last */
|
||||
/*
|
||||
* queryp is where the interesting part of the path ends, so now we
|
||||
* want to the find the last
|
||||
*/
|
||||
char *endslash;
|
||||
if(!queryp)
|
||||
endslash = strrchr(path, '/');
|
||||
@@ -774,29 +804,34 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we didn't get a cookie name, or a bad one, the this is an illegal
|
||||
* line so bail out.
|
||||
*/
|
||||
if(badcookie || !co->name) {
|
||||
/* we didn't get a cookie name or a bad one,
|
||||
this is an illegal line, bail out */
|
||||
freecookie(co);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
/* This line is NOT a HTTP header style line, we do offer support for
|
||||
reading the odd netscape cookies-file format here */
|
||||
/*
|
||||
* This line is NOT a HTTP header style line, we do offer support for
|
||||
* reading the odd netscape cookies-file format here
|
||||
*/
|
||||
char *ptr;
|
||||
char *firstptr;
|
||||
char *tok_buf = NULL;
|
||||
int fields;
|
||||
|
||||
/* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies
|
||||
marked with httpOnly after the domain name are not accessible
|
||||
from javascripts, but since curl does not operate at javascript
|
||||
level, we include them anyway. In Firefox's cookie files, these
|
||||
lines are preceded with #HttpOnly_ and then everything is
|
||||
as usual, so we skip 10 characters of the line..
|
||||
*/
|
||||
/*
|
||||
* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies marked
|
||||
* with httpOnly after the domain name are not accessible from javascripts,
|
||||
* but since curl does not operate at javascript level, we include them
|
||||
* anyway. In Firefox's cookie files, these lines are preceded with
|
||||
* #HttpOnly_ and then everything is as usual, so we skip 10 characters of
|
||||
* the line..
|
||||
*/
|
||||
if(strncmp(lineptr, "#HttpOnly_", 10) == 0) {
|
||||
lineptr += 10;
|
||||
co->httponly = TRUE;
|
||||
@@ -817,8 +852,10 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
|
||||
firstptr = strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
|
||||
|
||||
/* Now loop through the fields and init the struct we already have
|
||||
allocated */
|
||||
/*
|
||||
* Now loop through the fields and init the struct we already have
|
||||
* allocated
|
||||
*/
|
||||
for(ptr = firstptr, fields = 0; ptr && !badcookie;
|
||||
ptr = strtok_r(NULL, "\t", &tok_buf), fields++) {
|
||||
switch(fields) {
|
||||
@@ -830,10 +867,11 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
badcookie = TRUE;
|
||||
break;
|
||||
case 1:
|
||||
/* 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
|
||||
*/
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
co->tailmatch = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
|
||||
break;
|
||||
case 2:
|
||||
@@ -942,17 +980,23 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
co->livecookie = c->running;
|
||||
co->creationtime = ++c->lastct;
|
||||
|
||||
/* now, we have parsed the incoming line, we must now check if this
|
||||
supersedes an already existing cookie, which it may if the previous have
|
||||
the same domain and path as this */
|
||||
/*
|
||||
* Now we have parsed the incoming line, we must now check if this supersedes
|
||||
* an already existing cookie, which it may if the previous have the same
|
||||
* domain and path as this.
|
||||
*/
|
||||
|
||||
/* at first, remove expired cookies */
|
||||
if(!noexpire)
|
||||
remove_expired(c);
|
||||
|
||||
#ifdef USE_LIBPSL
|
||||
/* Check if the domain is a Public Suffix and if yes, ignore the cookie. */
|
||||
if(domain && co->domain && !isip(co->domain)) {
|
||||
/*
|
||||
* Check if the domain is a Public Suffix and if yes, ignore the cookie. We
|
||||
* must also check that the data handle isn't NULL since the psl code will
|
||||
* dereference it.
|
||||
*/
|
||||
if(data && (domain && co->domain && !isip(co->domain))) {
|
||||
const psl_ctx_t *psl = Curl_psl_use(data);
|
||||
int acceptable;
|
||||
|
||||
@@ -1028,12 +1072,12 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
if(replace_old && !co->livecookie && clist->livecookie) {
|
||||
/* Both cookies matched fine, except that the already present
|
||||
cookie is "live", which means it was set from a header, while
|
||||
the new one isn't "live" and thus only read from a file. We let
|
||||
live cookies stay alive */
|
||||
|
||||
/* Free the newcomer and get out of here! */
|
||||
/*
|
||||
* Both cookies matched fine, except that the already present cookie is
|
||||
* "live", which means it was set from a header, while the new one was
|
||||
* read from a file and thus isn't "live". "live" cookies are preferred
|
||||
* so the new cookie is freed.
|
||||
*/
|
||||
freecookie(co);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1059,8 +1103,10 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
free(co); /* free the newly allocated memory */
|
||||
co = clist; /* point to the previous struct instead */
|
||||
|
||||
/* We have replaced a cookie, now skip the rest of the list but
|
||||
make sure the 'lastc' pointer is properly set */
|
||||
/*
|
||||
* We have replaced a cookie, now skip the rest of the list but make
|
||||
* sure the 'lastc' pointer is properly set
|
||||
*/
|
||||
do {
|
||||
lastc = clist;
|
||||
clist = clist->next;
|
||||
@@ -1092,19 +1138,19 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
/*
|
||||
* Curl_cookie_init()
|
||||
*
|
||||
* Inits a cookie struct to read data from a local file. This is always
|
||||
* called before any cookies are set. File may be NULL.
|
||||
* called before any cookies are set. File may be NULL in which case only the
|
||||
* struct is initialized. Is file is "-" then STDIN is read.
|
||||
*
|
||||
* If 'newsession' is TRUE, discard all "session cookies" on read from file.
|
||||
*
|
||||
* Note that 'data' might be called as NULL pointer.
|
||||
*
|
||||
* Returns NULL on out of memory. Invalid cookies are ignored.
|
||||
****************************************************************************/
|
||||
*/
|
||||
struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
const char *file,
|
||||
struct CookieInfo *inc,
|
||||
@@ -1166,7 +1212,12 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE);
|
||||
}
|
||||
free(line); /* free the line buffer */
|
||||
remove_expired(c); /* run this once, not on every cookie */
|
||||
|
||||
/*
|
||||
* Remove expired cookies from the hash. We must make sure to run this
|
||||
* after reading the file, and not not on every cookie.
|
||||
*/
|
||||
remove_expired(c);
|
||||
|
||||
if(fromfile)
|
||||
fclose(fp);
|
||||
@@ -1180,16 +1231,24 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
|
||||
fail:
|
||||
free(line);
|
||||
/*
|
||||
* Only clean up if we allocated it here, as the original could still be in
|
||||
* use by a share handle.
|
||||
*/
|
||||
if(!inc)
|
||||
/* Only clean up if we allocated it here, as the original could still be in
|
||||
* use by a share handle */
|
||||
Curl_cookie_cleanup(c);
|
||||
if(fromfile && fp)
|
||||
fclose(fp);
|
||||
return NULL; /* out of memory */
|
||||
}
|
||||
|
||||
/* sort this so that the longest path gets before the shorter path */
|
||||
/*
|
||||
* cookie_sort
|
||||
*
|
||||
* Helper function to sort cookies such that the longest path gets before the
|
||||
* shorter path. Path, domain and name lengths are considered in that order,
|
||||
* with tge creationtime as the tiebreaker.
|
||||
*/
|
||||
static int cookie_sort(const void *p1, const void *p2)
|
||||
{
|
||||
struct Cookie *c1 = *(struct Cookie **)p1;
|
||||
@@ -1221,7 +1280,11 @@ static int cookie_sort(const void *p1, const void *p2)
|
||||
return (c2->creationtime > c1->creationtime) ? 1 : -1;
|
||||
}
|
||||
|
||||
/* sort cookies only according to creation time */
|
||||
/*
|
||||
* cookie_sort_ct
|
||||
*
|
||||
* Helper function to sort cookies according to creation time.
|
||||
*/
|
||||
static int cookie_sort_ct(const void *p1, const void *p2)
|
||||
{
|
||||
struct Cookie *c1 = *(struct Cookie **)p1;
|
||||
@@ -1265,18 +1328,15 @@ static struct Cookie *dup_cookie(struct Cookie *src)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
/*
|
||||
* Curl_cookie_getlist
|
||||
*
|
||||
* Curl_cookie_getlist()
|
||||
*
|
||||
* For a given host and path, return a linked list of cookies that the
|
||||
* client should send to the server if used now. The secure boolean informs
|
||||
* the cookie if a secure connection is achieved or not.
|
||||
* For a given host and path, return a linked list of cookies that the client
|
||||
* should send to the server if used now. The secure boolean informs the cookie
|
||||
* if a secure connection is achieved or not.
|
||||
*
|
||||
* It shall only return cookies that haven't expired.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
*/
|
||||
struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
||||
const char *host, const char *path,
|
||||
bool secure)
|
||||
@@ -1307,15 +1367,21 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
||||
if(!co->domain ||
|
||||
(co->tailmatch && !is_ip && tailmatch(co->domain, host)) ||
|
||||
((!co->tailmatch || is_ip) && strcasecompare(host, co->domain)) ) {
|
||||
/* the right part of the host matches the domain stuff in the
|
||||
cookie data */
|
||||
/*
|
||||
* the right part of the host matches the domain stuff in the
|
||||
* cookie data
|
||||
*/
|
||||
|
||||
/* now check the left part of the path with the cookies path
|
||||
requirement */
|
||||
/*
|
||||
* now check the left part of the path with the cookies path
|
||||
* requirement
|
||||
*/
|
||||
if(!co->spath || pathmatch(co->spath, path) ) {
|
||||
|
||||
/* and now, we know this is a match and we should create an
|
||||
entry for the return-linked-list */
|
||||
/*
|
||||
* and now, we know this is a match and we should create an
|
||||
* entry for the return-linked-list
|
||||
*/
|
||||
|
||||
newco = dup_cookie(co);
|
||||
if(newco) {
|
||||
@@ -1336,9 +1402,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
||||
}
|
||||
|
||||
if(matches) {
|
||||
/* Now we need to make sure that if there is a name appearing more than
|
||||
once, the longest specified path version comes first. To make this
|
||||
the swiftest way, we just sort them all based on path length. */
|
||||
/*
|
||||
* Now we need to make sure that if there is a name appearing more than
|
||||
* once, the longest specified path version comes first. To make this
|
||||
* the swiftest way, we just sort them all based on path length.
|
||||
*/
|
||||
struct Cookie **array;
|
||||
size_t i;
|
||||
|
||||
@@ -1373,13 +1441,11 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Curl_cookie_clearall()
|
||||
/*
|
||||
* Curl_cookie_clearall
|
||||
*
|
||||
* Clear all existing cookies and reset the counter.
|
||||
*
|
||||
****************************************************************************/
|
||||
*/
|
||||
void Curl_cookie_clearall(struct CookieInfo *cookies)
|
||||
{
|
||||
if(cookies) {
|
||||
@@ -1392,14 +1458,11 @@ void Curl_cookie_clearall(struct CookieInfo *cookies)
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Curl_cookie_freelist()
|
||||
/*
|
||||
* Curl_cookie_freelist
|
||||
*
|
||||
* Free a list of cookies previously returned by Curl_cookie_getlist();
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
*/
|
||||
void Curl_cookie_freelist(struct Cookie *co)
|
||||
{
|
||||
struct Cookie *next;
|
||||
@@ -1410,14 +1473,11 @@ void Curl_cookie_freelist(struct Cookie *co)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Curl_cookie_clearsess()
|
||||
/*
|
||||
* Curl_cookie_clearsess
|
||||
*
|
||||
* Free all session cookies in the cookies list.
|
||||
*
|
||||
****************************************************************************/
|
||||
*/
|
||||
void Curl_cookie_clearsess(struct CookieInfo *cookies)
|
||||
{
|
||||
struct Cookie *first, *curr, *next, *prev = NULL;
|
||||
@@ -1454,14 +1514,11 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
/*
|
||||
* Curl_cookie_cleanup()
|
||||
*
|
||||
* Free a "cookie object" previous created with Curl_cookie_init().
|
||||
*
|
||||
****************************************************************************/
|
||||
*/
|
||||
void Curl_cookie_cleanup(struct CookieInfo *c)
|
||||
{
|
||||
if(c) {
|
||||
@@ -1473,12 +1530,13 @@ void Curl_cookie_cleanup(struct CookieInfo *c)
|
||||
}
|
||||
}
|
||||
|
||||
/* get_netscape_format()
|
||||
/*
|
||||
* get_netscape_format()
|
||||
*
|
||||
* Formats a string for Netscape output file, w/o a newline at the end.
|
||||
*
|
||||
* Function returns a char * to a formatted line. Has to be free()d
|
||||
*/
|
||||
* Function returns a char * to a formatted line. The caller is responsible
|
||||
* for freeing the returned pointer.
|
||||
*/
|
||||
static char *get_netscape_format(const struct Cookie *co)
|
||||
{
|
||||
return aprintf(
|
||||
@@ -1491,8 +1549,10 @@ static char *get_netscape_format(const struct Cookie *co)
|
||||
"%s\t" /* name */
|
||||
"%s", /* value */
|
||||
co->httponly?"#HttpOnly_":"",
|
||||
/* Make sure all domains are prefixed with a dot if they allow
|
||||
tailmatching. This is Mozilla-style. */
|
||||
/*
|
||||
* Make sure all domains are prefixed with a dot if they allow
|
||||
* tailmatching. This is Mozilla-style.
|
||||
*/
|
||||
(co->tailmatch && co->domain && co->domain[0] != '.')? ".":"",
|
||||
co->domain?co->domain:"unknown",
|
||||
co->tailmatch?"TRUE":"FALSE",
|
||||
@@ -1511,18 +1571,18 @@ static char *get_netscape_format(const struct Cookie *co)
|
||||
*
|
||||
* The function returns non-zero on write failure.
|
||||
*/
|
||||
static int cookie_output(struct Curl_easy *data,
|
||||
struct CookieInfo *c, const char *filename)
|
||||
static CURLcode cookie_output(struct Curl_easy *data,
|
||||
struct CookieInfo *c, const char *filename)
|
||||
{
|
||||
struct Cookie *co;
|
||||
FILE *out = NULL;
|
||||
bool use_stdout = FALSE;
|
||||
char *tempstore = NULL;
|
||||
bool error = false;
|
||||
CURLcode error = CURLE_OK;
|
||||
|
||||
if(!c)
|
||||
/* no cookie engine alive */
|
||||
return 0;
|
||||
return CURLE_OK;
|
||||
|
||||
/* at first, remove expired cookies */
|
||||
remove_expired(c);
|
||||
@@ -1540,11 +1600,13 @@ static int cookie_output(struct Curl_easy *data,
|
||||
|
||||
tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
|
||||
if(!tempstore)
|
||||
return 1;
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
out = fopen(tempstore, FOPEN_WRITETEXT);
|
||||
if(!out)
|
||||
if(!out) {
|
||||
error = CURLE_WRITE_ERROR;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
fputs("# Netscape HTTP Cookie File\n"
|
||||
@@ -1559,6 +1621,7 @@ static int cookie_output(struct Curl_easy *data,
|
||||
|
||||
array = calloc(1, sizeof(struct Cookie *) * c->numcookies);
|
||||
if(!array) {
|
||||
error = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1575,9 +1638,9 @@ static int cookie_output(struct Curl_easy *data,
|
||||
|
||||
for(i = 0; i < nvalid; i++) {
|
||||
char *format_ptr = get_netscape_format(array[i]);
|
||||
if(format_ptr == NULL) {
|
||||
fprintf(out, "#\n# Fatal libcurl error\n");
|
||||
if(!format_ptr) {
|
||||
free(array);
|
||||
error = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
fprintf(out, "%s\n", format_ptr);
|
||||
@@ -1592,18 +1655,24 @@ static int cookie_output(struct Curl_easy *data,
|
||||
out = NULL;
|
||||
if(Curl_rename(tempstore, filename)) {
|
||||
unlink(tempstore);
|
||||
error = CURLE_WRITE_ERROR;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
goto cleanup;
|
||||
/*
|
||||
* If we reach here we have successfully written a cookie file so theree is
|
||||
* no need to inspect the error, any error case should have jumped into the
|
||||
* error block below.
|
||||
*/
|
||||
free(tempstore);
|
||||
return CURLE_OK;
|
||||
|
||||
error:
|
||||
error = true;
|
||||
cleanup:
|
||||
if(out && !use_stdout)
|
||||
fclose(out);
|
||||
free(tempstore);
|
||||
return error ? 1 : 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
static struct curl_slist *cookie_list(struct Curl_easy *data)
|
||||
@@ -1614,8 +1683,7 @@ static struct curl_slist *cookie_list(struct Curl_easy *data)
|
||||
char *line;
|
||||
unsigned int i;
|
||||
|
||||
if((data->cookies == NULL) ||
|
||||
(data->cookies->numcookies == 0))
|
||||
if(!data->cookies || (data->cookies->numcookies == 0))
|
||||
return NULL;
|
||||
|
||||
for(i = 0; i < COOKIE_HASH_SIZE; i++) {
|
||||
@@ -1651,8 +1719,10 @@ struct curl_slist *Curl_cookie_list(struct Curl_easy *data)
|
||||
|
||||
void Curl_flush_cookies(struct Curl_easy *data, bool cleanup)
|
||||
{
|
||||
CURLcode res;
|
||||
|
||||
if(data->set.str[STRING_COOKIEJAR]) {
|
||||
if(data->change.cookielist) {
|
||||
if(data->state.cookielist) {
|
||||
/* If there is a list of cookie files to read, do it first so that
|
||||
we have all the told files read before we write the new jar.
|
||||
Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */
|
||||
@@ -1662,16 +1732,17 @@ void Curl_flush_cookies(struct Curl_easy *data, bool cleanup)
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
|
||||
|
||||
/* if we have a destination file for all the cookies to get dumped to */
|
||||
if(cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR]))
|
||||
infof(data, "WARNING: failed to save cookies in %s\n",
|
||||
data->set.str[STRING_COOKIEJAR]);
|
||||
res = cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR]);
|
||||
if(res)
|
||||
infof(data, "WARNING: failed to save cookies in %s: %s\n",
|
||||
data->set.str[STRING_COOKIEJAR], curl_easy_strerror(res));
|
||||
}
|
||||
else {
|
||||
if(cleanup && data->change.cookielist) {
|
||||
if(cleanup && data->state.cookielist) {
|
||||
/* since nothing is written, we can just free the list of cookie file
|
||||
names */
|
||||
curl_slist_free_all(data->change.cookielist); /* clean up list */
|
||||
data->change.cookielist = NULL;
|
||||
curl_slist_free_all(data->state.cookielist); /* clean up list */
|
||||
data->state.cookielist = NULL;
|
||||
}
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
|
||||
}
|
||||
|
||||
@@ -91,13 +91,13 @@ struct Curl_easy;
|
||||
*/
|
||||
|
||||
struct Cookie *Curl_cookie_add(struct Curl_easy *data,
|
||||
struct CookieInfo *, bool header, bool noexpiry,
|
||||
char *lineptr,
|
||||
struct CookieInfo *c, bool header,
|
||||
bool noexpiry, char *lineptr,
|
||||
const char *domain, const char *path,
|
||||
bool secure);
|
||||
|
||||
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
|
||||
const char *, bool);
|
||||
struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, const char *host,
|
||||
const char *path, bool secure);
|
||||
void Curl_cookie_freelist(struct Cookie *cookies);
|
||||
void Curl_cookie_clearall(struct CookieInfo *cookies);
|
||||
void Curl_cookie_clearsess(struct CookieInfo *cookies);
|
||||
@@ -110,9 +110,10 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies);
|
||||
#define Curl_flush_cookies(x,y) Curl_nop_stmt
|
||||
#else
|
||||
void Curl_flush_cookies(struct Curl_easy *data, bool cleanup);
|
||||
void Curl_cookie_cleanup(struct CookieInfo *);
|
||||
void Curl_cookie_cleanup(struct CookieInfo *c);
|
||||
struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
const char *, struct CookieInfo *, bool);
|
||||
const char *file, struct CookieInfo *inc,
|
||||
bool newsession);
|
||||
struct curl_slist *Curl_cookie_list(struct Curl_easy *data);
|
||||
void Curl_cookie_loadfiles(struct Curl_easy *data);
|
||||
#endif
|
||||
|
||||
@@ -50,6 +50,12 @@
|
||||
# define in_addr_t unsigned long
|
||||
#endif
|
||||
|
||||
#if defined(USE_UNIX_SOCKETS) && defined(WINAPI_FAMILY) && \
|
||||
(WINAPI_FAMILY == WINAPI_FAMILY_APP)
|
||||
/* Required for sockaddr_un type */
|
||||
# include <afunix.h>
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "curl_addrinfo.h"
|
||||
@@ -141,7 +147,7 @@ Curl_getaddrinfo_ex(const char *nodename,
|
||||
continue;
|
||||
|
||||
/* ignore elements without required address info */
|
||||
if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0))
|
||||
if(!ai->ai_addr || !(ai->ai_addrlen > 0))
|
||||
continue;
|
||||
|
||||
/* ignore elements with bogus address size */
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
#endif
|
||||
|
||||
/* Allow SMB to work on Windows */
|
||||
#cmakedefine USE_WIN32_CRYPTO
|
||||
#cmakedefine USE_WIN32_CRYPTO 1
|
||||
|
||||
/* Use Windows LDAP implementation */
|
||||
#cmakedefine USE_WIN32_LDAP 1
|
||||
@@ -105,21 +105,6 @@
|
||||
/* Define if you want to enable IPv6 support */
|
||||
#cmakedefine ENABLE_IPV6 1
|
||||
|
||||
/* Define to the type qualifier of arg 1 for getnameinfo. */
|
||||
#cmakedefine GETNAMEINFO_QUAL_ARG1 ${GETNAMEINFO_QUAL_ARG1}
|
||||
|
||||
/* Define to the type of arg 1 for getnameinfo. */
|
||||
#cmakedefine GETNAMEINFO_TYPE_ARG1 ${GETNAMEINFO_TYPE_ARG1}
|
||||
|
||||
/* Define to the type of arg 2 for getnameinfo. */
|
||||
#cmakedefine GETNAMEINFO_TYPE_ARG2 ${GETNAMEINFO_TYPE_ARG2}
|
||||
|
||||
/* Define to the type of args 4 and 6 for getnameinfo. */
|
||||
#cmakedefine GETNAMEINFO_TYPE_ARG46 ${GETNAMEINFO_TYPE_ARG46}
|
||||
|
||||
/* Define to the type of arg 7 for getnameinfo. */
|
||||
#cmakedefine GETNAMEINFO_TYPE_ARG7 ${GETNAMEINFO_TYPE_ARG7}
|
||||
|
||||
/* Specifies the number of arguments to getservbyport_r */
|
||||
#cmakedefine GETSERVBYPORT_R_ARGS ${GETSERVBYPORT_R_ARGS}
|
||||
|
||||
@@ -201,6 +186,9 @@
|
||||
/* Define to 1 if you have the `geteuid' function. */
|
||||
#cmakedefine HAVE_GETEUID 1
|
||||
|
||||
/* Define to 1 if you have the `getppid' function. */
|
||||
#cmakedefine HAVE_GETPPID 1
|
||||
|
||||
/* Define to 1 if you have the gethostbyaddr function. */
|
||||
#cmakedefine HAVE_GETHOSTBYADDR 1
|
||||
|
||||
@@ -237,9 +225,6 @@
|
||||
/* Define to 1 if you have a working getifaddrs function. */
|
||||
#cmakedefine HAVE_GETIFADDRS 1
|
||||
|
||||
/* Define to 1 if you have the getnameinfo function. */
|
||||
#cmakedefine HAVE_GETNAMEINFO 1
|
||||
|
||||
/* Define to 1 if you have the `getpass_r' function. */
|
||||
#cmakedefine HAVE_GETPASS_R 1
|
||||
|
||||
@@ -315,21 +300,18 @@
|
||||
/* Define to 1 if you have the `inet_addr' function. */
|
||||
#cmakedefine HAVE_INET_ADDR 1
|
||||
|
||||
/* Define to 1 if you have the inet_ntoa_r function. */
|
||||
#cmakedefine HAVE_INET_NTOA_R 1
|
||||
|
||||
/* inet_ntoa_r() takes 2 args */
|
||||
#cmakedefine HAVE_INET_NTOA_R_2 1
|
||||
|
||||
/* inet_ntoa_r() takes 3 args */
|
||||
#cmakedefine HAVE_INET_NTOA_R_3 1
|
||||
|
||||
/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
|
||||
#cmakedefine HAVE_INET_NTOP 1
|
||||
|
||||
/* Define to 1 if you have a IPv6 capable working inet_pton function. */
|
||||
#cmakedefine HAVE_INET_PTON 1
|
||||
|
||||
/* Define to 1 if symbol `sa_family_t' exists */
|
||||
#cmakedefine HAVE_SA_FAMILY_T 1
|
||||
|
||||
/* Define to 1 if symbol `ADDRESS_FAMILY' exists */
|
||||
#cmakedefine HAVE_ADDRESS_FAMILY 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#cmakedefine HAVE_INTTYPES_H 1
|
||||
|
||||
@@ -501,9 +483,6 @@
|
||||
/* Define to 1 if you have the <pem.h> header file. */
|
||||
#cmakedefine HAVE_PEM_H 1
|
||||
|
||||
/* Define to 1 if you have the `perror' function. */
|
||||
#cmakedefine HAVE_PERROR 1
|
||||
|
||||
/* Define to 1 if you have the `pipe' function. */
|
||||
#cmakedefine HAVE_PIPE 1
|
||||
|
||||
@@ -645,15 +624,6 @@
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#cmakedefine HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the strlcat function. */
|
||||
#cmakedefine HAVE_STRLCAT 1
|
||||
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
#cmakedefine HAVE_STRLCPY 1
|
||||
|
||||
/* Define to 1 if you have the strncasecmp function. */
|
||||
#cmakedefine HAVE_STRNCASECMP 1
|
||||
|
||||
/* Define to 1 if you have the strncmpi function. */
|
||||
#cmakedefine HAVE_STRNCMPI 1
|
||||
|
||||
@@ -744,6 +714,9 @@
|
||||
/* Define to 1 if you have the `utime' function. */
|
||||
#cmakedefine HAVE_UTIME 1
|
||||
|
||||
/* Define to 1 if you have the `utimes' function. */
|
||||
#cmakedefine HAVE_UTIMES 1
|
||||
|
||||
/* Define to 1 if you have the <utime.h> header file. */
|
||||
#cmakedefine HAVE_UTIME_H 1
|
||||
|
||||
@@ -871,9 +844,6 @@
|
||||
/* Define to the function return type for recv. */
|
||||
#cmakedefine RECV_TYPE_RETV ${RECV_TYPE_RETV}
|
||||
|
||||
/* Define as the return type of signal handlers (`int' or `void'). */
|
||||
#cmakedefine RETSIGTYPE ${RETSIGTYPE}
|
||||
|
||||
/* Define to the type qualifier of arg 5 for select. */
|
||||
#cmakedefine SELECT_QUAL_ARG5 ${SELECT_QUAL_ARG5}
|
||||
|
||||
@@ -966,9 +936,6 @@ ${SIZEOF_TIME_T_CODE}
|
||||
/* Define if you want to enable WIN32 threaded DNS lookup */
|
||||
#cmakedefine USE_THREADS_WIN32 1
|
||||
|
||||
/* Define to disable non-blocking sockets. */
|
||||
#cmakedefine USE_BLOCKING_SOCKETS 1
|
||||
|
||||
/* if GnuTLS is enabled */
|
||||
#cmakedefine USE_GNUTLS 1
|
||||
|
||||
@@ -1089,3 +1056,9 @@ ${SIZEOF_TIME_T_CODE}
|
||||
|
||||
/* Define to 1 if you have the mach_absolute_time function. */
|
||||
#cmakedefine HAVE_MACH_ABSOLUTE_TIME 1
|
||||
|
||||
/* to enable Windows IDN */
|
||||
#cmakedefine USE_WIN32_IDN 1
|
||||
|
||||
/* to make the compiler know the prototypes of Windows IDN APIs */
|
||||
#cmakedefine WANT_IDN_PROTOTYPES 1
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -81,7 +81,7 @@ unsigned short Curl_read16_be(const unsigned char *buf)
|
||||
((unsigned short)buf[1]));
|
||||
}
|
||||
|
||||
#if (CURL_SIZEOF_CURL_OFF_T > 4)
|
||||
#if (SIZEOF_CURL_OFF_T > 4)
|
||||
/*
|
||||
* write32_le()
|
||||
*
|
||||
@@ -121,4 +121,4 @@ void Curl_write64_le(const __int64 value, unsigned char *buffer)
|
||||
write32_le((int)value, buffer);
|
||||
write32_le((int)(value >> 32), buffer + 4);
|
||||
}
|
||||
#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */
|
||||
#endif /* SIZEOF_CURL_OFF_T > 4 */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -31,7 +31,7 @@ unsigned int Curl_read32_le(const unsigned char *buf);
|
||||
/* Converts a 16-bit integer from big endian */
|
||||
unsigned short Curl_read16_be(const unsigned char *buf);
|
||||
|
||||
#if (CURL_SIZEOF_CURL_OFF_T > 4)
|
||||
#if (SIZEOF_CURL_OFF_T > 4)
|
||||
/* Converts a 64-bit integer to little endian */
|
||||
#if defined(HAVE_LONGLONG)
|
||||
void Curl_write64_le(const long long value, unsigned char *buffer);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
|
||||
defined(USE_HSTS)
|
||||
!defined(CURL_DISABLE_HSTS)
|
||||
|
||||
#include "curl_get_line.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
@@ -102,7 +102,7 @@ static size_t display_gss_error(OM_uint32 status, int type,
|
||||
(char *)status_string.value);
|
||||
}
|
||||
gss_release_buffer(&min_stat, &status_string);
|
||||
} while(!GSS_ERROR(maj_stat) && msg_ctx != 0);
|
||||
} while(!GSS_ERROR(maj_stat) && msg_ctx);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ struct Curl_sec_client_mech {
|
||||
int (*auth)(void *, struct Curl_easy *data, struct connectdata *);
|
||||
void (*end)(void *);
|
||||
int (*check_prot)(void *, int);
|
||||
int (*overhead)(void *, int, int);
|
||||
int (*encode)(void *, const void *, int, int, void **);
|
||||
int (*decode)(void *, void *, int, int, struct connectdata *);
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -21,7 +21,11 @@
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* This file is 'mem-include-scan' clean. See test 1132.
|
||||
* This file is 'mem-include-scan' clean, which means memdebug.h and
|
||||
* curl_memory.h are purposely not included in this file. See test 1132.
|
||||
*
|
||||
* The functions in this file are curlx functions which are not tracked by the
|
||||
* curl memory tracker memdebug.
|
||||
*/
|
||||
|
||||
#include "curl_setup.h"
|
||||
@@ -82,6 +86,32 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w)
|
||||
|
||||
#if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES)
|
||||
|
||||
int curlx_win32_open(const char *filename, int oflag, ...)
|
||||
{
|
||||
int pmode = 0;
|
||||
|
||||
#ifdef _UNICODE
|
||||
int result = -1;
|
||||
wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename);
|
||||
#endif
|
||||
|
||||
va_list param;
|
||||
va_start(param, oflag);
|
||||
if(oflag & O_CREAT)
|
||||
pmode = va_arg(param, int);
|
||||
va_end(param);
|
||||
|
||||
#ifdef _UNICODE
|
||||
if(filename_w)
|
||||
result = _wopen(filename_w, oflag, pmode);
|
||||
free(filename_w);
|
||||
if(result != -1)
|
||||
return result;
|
||||
#endif
|
||||
|
||||
return (_open)(filename, oflag, pmode);
|
||||
}
|
||||
|
||||
FILE *curlx_win32_fopen(const char *filename, const char *mode)
|
||||
{
|
||||
#ifdef _UNICODE
|
||||
@@ -104,50 +134,38 @@ int curlx_win32_stat(const char *path, struct_stat *buffer)
|
||||
int result = -1;
|
||||
#ifdef _UNICODE
|
||||
wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
|
||||
if(path_w) {
|
||||
#if defined(USE_WIN32_SMALL_FILES)
|
||||
result = _wstat(path_w, buffer);
|
||||
#else
|
||||
result = _wstati64(path_w, buffer);
|
||||
#endif
|
||||
free(path_w);
|
||||
if(result != -1)
|
||||
return result;
|
||||
}
|
||||
#endif /* _UNICODE */
|
||||
|
||||
#if defined(USE_WIN32_SMALL_FILES)
|
||||
#if defined(_UNICODE)
|
||||
if(path_w)
|
||||
result = _wstat(path_w, buffer);
|
||||
else
|
||||
#endif /* _UNICODE */
|
||||
result = _stat(path, buffer);
|
||||
#else /* USE_WIN32_SMALL_FILES */
|
||||
#if defined(_UNICODE)
|
||||
if(path_w)
|
||||
result = _wstati64(path_w, buffer);
|
||||
else
|
||||
#endif /* _UNICODE */
|
||||
result = _stati64(path, buffer);
|
||||
#endif /* USE_WIN32_SMALL_FILES */
|
||||
|
||||
#ifdef _UNICODE
|
||||
free(path_w);
|
||||
result = _stat(path, buffer);
|
||||
#else
|
||||
result = _stati64(path, buffer);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int curlx_win32_access(const char *path, int mode)
|
||||
{
|
||||
int result = -1;
|
||||
#ifdef _UNICODE
|
||||
wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
|
||||
#endif /* _UNICODE */
|
||||
|
||||
#if defined(_UNICODE)
|
||||
if(path_w)
|
||||
result = _waccess(path_w, mode);
|
||||
else
|
||||
#endif /* _UNICODE */
|
||||
result = _access(path, mode);
|
||||
|
||||
#ifdef _UNICODE
|
||||
wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
|
||||
if(path_w) {
|
||||
int result = _waccess(path_w, mode);
|
||||
free(path_w);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
if(result != -1)
|
||||
return result;
|
||||
}
|
||||
#endif /* _UNICODE */
|
||||
return _access(path, mode);
|
||||
}
|
||||
|
||||
#endif /* USE_WIN32_LARGE_FILES || USE_WIN32_SMALL_FILES */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -31,7 +31,6 @@
|
||||
|
||||
wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8);
|
||||
char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
|
||||
|
||||
#endif /* WIN32 */
|
||||
|
||||
/*
|
||||
@@ -40,29 +39,23 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
|
||||
* preprocessor conditional directives needed by code using these
|
||||
* to differentiate UNICODE from non-UNICODE builds.
|
||||
*
|
||||
* When building with UNICODE defined, these two macros
|
||||
* curlx_convert_UTF8_to_tchar() and curlx_convert_tchar_to_UTF8()
|
||||
* return a pointer to a newly allocated memory area holding result.
|
||||
* When the result is no longer needed, allocated memory is intended
|
||||
* to be free'ed with curlx_unicodefree().
|
||||
* In the case of a non-UNICODE build the tchar strings are char strings that
|
||||
* are duplicated via strdup and remain in whatever the passed in encoding is,
|
||||
* which is assumed to be UTF-8 but may be other encoding. Therefore the
|
||||
* significance of the conversion functions is primarily for UNICODE builds.
|
||||
*
|
||||
* When building without UNICODE defined, this macros
|
||||
* curlx_convert_UTF8_to_tchar() and curlx_convert_tchar_to_UTF8()
|
||||
* return the pointer received as argument. curlx_unicodefree() does
|
||||
* no actual free'ing of this pointer it is simply set to NULL.
|
||||
* Allocated memory should be free'd with curlx_unicodefree().
|
||||
*
|
||||
* Note: Because these are curlx functions their memory usage is not tracked
|
||||
* by the curl memory tracker memdebug. You'll notice that curlx function-like
|
||||
* macros call free and strdup in parentheses, eg (strdup)(ptr), and that's to
|
||||
* ensure that the curl memdebug override macros do not replace them.
|
||||
*/
|
||||
|
||||
#if defined(UNICODE) && defined(WIN32)
|
||||
|
||||
#define curlx_convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr))
|
||||
#define curlx_convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr))
|
||||
#define curlx_unicodefree(ptr) \
|
||||
do { \
|
||||
if(ptr) { \
|
||||
(free)(ptr); \
|
||||
(ptr) = NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
typedef union {
|
||||
unsigned short *tchar_ptr;
|
||||
@@ -73,10 +66,8 @@ typedef union {
|
||||
|
||||
#else
|
||||
|
||||
#define curlx_convert_UTF8_to_tchar(ptr) (ptr)
|
||||
#define curlx_convert_tchar_to_UTF8(ptr) (ptr)
|
||||
#define curlx_unicodefree(ptr) \
|
||||
do {(ptr) = NULL;} while(0)
|
||||
#define curlx_convert_UTF8_to_tchar(ptr) (strdup)(ptr)
|
||||
#define curlx_convert_tchar_to_UTF8(ptr) (strdup)(ptr)
|
||||
|
||||
typedef union {
|
||||
char *tchar_ptr;
|
||||
@@ -87,4 +78,12 @@ typedef union {
|
||||
|
||||
#endif /* UNICODE && WIN32 */
|
||||
|
||||
#define curlx_unicodefree(ptr) \
|
||||
do { \
|
||||
if(ptr) { \
|
||||
(free)(ptr); \
|
||||
(ptr) = NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* HEADER_CURL_MULTIBYTE_H */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -34,13 +34,12 @@
|
||||
/* Please keep the SSL backend-specific #if branches in this order:
|
||||
|
||||
1. USE_OPENSSL
|
||||
2. USE_GNUTLS_NETTLE
|
||||
3. USE_GNUTLS
|
||||
4. USE_NSS
|
||||
5. USE_MBEDTLS
|
||||
6. USE_SECTRANSP
|
||||
7. USE_OS400CRYPTO
|
||||
8. USE_WIN32_CRYPTO
|
||||
2. USE_GNUTLS
|
||||
3. USE_NSS
|
||||
4. USE_MBEDTLS
|
||||
5. USE_SECTRANSP
|
||||
6. USE_OS400CRYPTO
|
||||
7. USE_WIN32_CRYPTO
|
||||
|
||||
This ensures that:
|
||||
- the same SSL branch gets activated throughout this source
|
||||
@@ -74,13 +73,9 @@
|
||||
# define DESKEY(x) &x
|
||||
# endif
|
||||
|
||||
#elif defined(USE_GNUTLS_NETTLE)
|
||||
|
||||
# include <nettle/des.h>
|
||||
|
||||
#elif defined(USE_GNUTLS)
|
||||
|
||||
# include <gcrypt.h>
|
||||
# include <nettle/des.h>
|
||||
|
||||
#elif defined(USE_NSS)
|
||||
|
||||
@@ -159,7 +154,7 @@ static void setup_des_key(const unsigned char *key_56,
|
||||
DES_set_key(&key, ks);
|
||||
}
|
||||
|
||||
#elif defined(USE_GNUTLS_NETTLE)
|
||||
#elif defined(USE_GNUTLS)
|
||||
|
||||
static void setup_des_key(const unsigned char *key_56,
|
||||
struct des_ctx *des)
|
||||
@@ -176,26 +171,6 @@ static void setup_des_key(const unsigned char *key_56,
|
||||
des_set_key(des, (const uint8_t *) key);
|
||||
}
|
||||
|
||||
#elif defined(USE_GNUTLS)
|
||||
|
||||
/*
|
||||
* Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
|
||||
*/
|
||||
static void setup_des_key(const unsigned char *key_56,
|
||||
gcry_cipher_hd_t *des)
|
||||
{
|
||||
char key[8];
|
||||
|
||||
/* Expand the 56-bit key to 64-bits */
|
||||
extend_key_56_to_64(key_56, key);
|
||||
|
||||
/* Set the key parity to odd */
|
||||
Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
|
||||
|
||||
/* Set the key */
|
||||
gcry_cipher_setkey(*des, key, sizeof(key));
|
||||
}
|
||||
|
||||
#elif defined(USE_NSS)
|
||||
|
||||
/*
|
||||
@@ -402,7 +377,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
|
||||
setup_des_key(keys + 14, DESKEY(ks));
|
||||
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16),
|
||||
DESKEY(ks), DES_ENCRYPT);
|
||||
#elif defined(USE_GNUTLS_NETTLE)
|
||||
#elif defined(USE_GNUTLS)
|
||||
struct des_ctx des;
|
||||
setup_des_key(keys, &des);
|
||||
des_encrypt(&des, 8, results, plaintext);
|
||||
@@ -410,23 +385,6 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
|
||||
des_encrypt(&des, 8, results + 8, plaintext);
|
||||
setup_des_key(keys + 14, &des);
|
||||
des_encrypt(&des, 8, results + 16, plaintext);
|
||||
#elif defined(USE_GNUTLS)
|
||||
gcry_cipher_hd_t des;
|
||||
|
||||
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
||||
setup_des_key(keys, &des);
|
||||
gcry_cipher_encrypt(des, results, 8, plaintext, 8);
|
||||
gcry_cipher_close(des);
|
||||
|
||||
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
||||
setup_des_key(keys + 7, &des);
|
||||
gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8);
|
||||
gcry_cipher_close(des);
|
||||
|
||||
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
||||
setup_des_key(keys + 14, &des);
|
||||
gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
|
||||
gcry_cipher_close(des);
|
||||
#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|
||||
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
|
||||
encrypt_des(plaintext, results, keys);
|
||||
@@ -473,24 +431,12 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
|
||||
setup_des_key(pw + 7, DESKEY(ks));
|
||||
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8),
|
||||
DESKEY(ks), DES_ENCRYPT);
|
||||
#elif defined(USE_GNUTLS_NETTLE)
|
||||
#elif defined(USE_GNUTLS)
|
||||
struct des_ctx des;
|
||||
setup_des_key(pw, &des);
|
||||
des_encrypt(&des, 8, lmbuffer, magic);
|
||||
setup_des_key(pw + 7, &des);
|
||||
des_encrypt(&des, 8, lmbuffer + 8, magic);
|
||||
#elif defined(USE_GNUTLS)
|
||||
gcry_cipher_hd_t des;
|
||||
|
||||
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
||||
setup_des_key(pw, &des);
|
||||
gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
|
||||
gcry_cipher_close(des);
|
||||
|
||||
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
||||
setup_des_key(pw + 7, &des);
|
||||
gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
|
||||
gcry_cipher_close(des);
|
||||
#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|
||||
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
|
||||
encrypt_des(magic, lmbuffer, pw);
|
||||
@@ -567,6 +513,56 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
|
||||
|
||||
#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI)
|
||||
|
||||
/* Timestamp in tenths of a microsecond since January 1, 1601 00:00:00 UTC. */
|
||||
struct ms_filetime {
|
||||
unsigned int dwLowDateTime;
|
||||
unsigned int dwHighDateTime;
|
||||
};
|
||||
|
||||
/* Convert a time_t to an MS FILETIME (MS-DTYP section 2.3.3). */
|
||||
static void time2filetime(struct ms_filetime *ft, time_t t)
|
||||
{
|
||||
#if SIZEOF_TIME_T > 4
|
||||
t = (t + CURL_OFF_T_C(11644473600)) * 10000000;
|
||||
ft->dwLowDateTime = (unsigned int) (t & 0xFFFFFFFF);
|
||||
ft->dwHighDateTime = (unsigned int) (t >> 32);
|
||||
#else
|
||||
unsigned int r, s;
|
||||
unsigned int i;
|
||||
|
||||
ft->dwLowDateTime = t & 0xFFFFFFFF;
|
||||
ft->dwHighDateTime = 0;
|
||||
|
||||
# ifndef HAVE_TIME_T_UNSIGNED
|
||||
/* Extend sign if needed. */
|
||||
if(ft->dwLowDateTime & 0x80000000)
|
||||
ft->dwHighDateTime = ~0;
|
||||
# endif
|
||||
|
||||
/* Bias seconds to Jan 1, 1601.
|
||||
134774 days = 11644473600 seconds = 0x2B6109100 */
|
||||
r = ft->dwLowDateTime;
|
||||
ft->dwLowDateTime = (ft->dwLowDateTime + 0xB6109100U) & 0xFFFFFFFF;
|
||||
ft->dwHighDateTime += ft->dwLowDateTime < r? 0x03: 0x02;
|
||||
|
||||
/* Convert to tenths of microseconds. */
|
||||
ft->dwHighDateTime *= 10000000;
|
||||
i = 32;
|
||||
do {
|
||||
i -= 8;
|
||||
s = ((ft->dwLowDateTime >> i) & 0xFF) * (10000000 - 1);
|
||||
r = (s << i) & 0xFFFFFFFF;
|
||||
s >>= 1; /* Split shift to avoid width overflow. */
|
||||
s >>= 31 - i;
|
||||
ft->dwLowDateTime = (ft->dwLowDateTime + r) & 0xFFFFFFFF;
|
||||
if(ft->dwLowDateTime < r)
|
||||
s++;
|
||||
ft->dwHighDateTime += s;
|
||||
} while(i);
|
||||
ft->dwHighDateTime &= 0xFFFFFFFF;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
|
||||
* (uppercase UserName + Domain) as the data
|
||||
*/
|
||||
@@ -640,22 +636,18 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
|
||||
unsigned int len = 0;
|
||||
unsigned char *ptr = NULL;
|
||||
unsigned char hmac_output[HMAC_MD5_LENGTH];
|
||||
curl_off_t tw;
|
||||
struct ms_filetime tw;
|
||||
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
#if CURL_SIZEOF_CURL_OFF_T < 8
|
||||
#error "this section needs 64bit support to work"
|
||||
#endif
|
||||
|
||||
/* Calculate the timestamp */
|
||||
#ifdef DEBUGBUILD
|
||||
char *force_timestamp = getenv("CURL_FORCETIME");
|
||||
if(force_timestamp)
|
||||
tw = CURL_OFF_T_C(11644473600) * 10000000;
|
||||
time2filetime(&tw, (time_t) 0);
|
||||
else
|
||||
#endif
|
||||
tw = ((curl_off_t)time(NULL) + CURL_OFF_T_C(11644473600)) * 10000000;
|
||||
time2filetime(&tw, time(NULL));
|
||||
|
||||
/* Calculate the response len */
|
||||
len = HMAC_MD5_LENGTH + NTLMv2_BLOB_LEN;
|
||||
@@ -667,13 +659,14 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
|
||||
|
||||
/* Create the BLOB structure */
|
||||
msnprintf((char *)ptr + HMAC_MD5_LENGTH, NTLMv2_BLOB_LEN,
|
||||
"%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */
|
||||
"%c%c%c%c", /* Reserved = 0 */
|
||||
"%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */
|
||||
"%c%c%c%c" /* Reserved = 0 */
|
||||
"%c%c%c%c%c%c%c%c", /* Timestamp */
|
||||
NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
|
||||
NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
|
||||
0, 0, 0, 0);
|
||||
0, 0, 0, 0,
|
||||
LONGQUARTET(tw.dwLowDateTime), LONGQUARTET(tw.dwHighDateTime));
|
||||
|
||||
Curl_write64_le(tw, ptr + 24);
|
||||
memcpy(ptr + 32, challenge_client, 8);
|
||||
memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -30,7 +30,6 @@
|
||||
then it must be initialized to be used by NTLM. */
|
||||
#if !defined(USE_OPENSSL) && \
|
||||
!defined(USE_WOLFSSL) && \
|
||||
!defined(USE_GNUTLS_NETTLE) && \
|
||||
!defined(USE_GNUTLS) && \
|
||||
defined(USE_NSS)
|
||||
#define NTLM_NEEDS_NSS_INIT
|
||||
@@ -48,19 +47,22 @@
|
||||
#define USE_NTRESPONSES
|
||||
|
||||
/* Define USE_NTLM2SESSION in order to make the type-3 message include the
|
||||
NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and
|
||||
MD5 support */
|
||||
#if defined(USE_NTRESPONSES) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
NTLM2Session response message, requires USE_NTRESPONSES defined to 1 */
|
||||
#if defined(USE_NTRESPONSES)
|
||||
#define USE_NTLM2SESSION
|
||||
#endif
|
||||
|
||||
/* Define USE_NTLM_V2 in order to allow the type-3 message to include the
|
||||
LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1
|
||||
and support for 64-bit integers. */
|
||||
#if defined(USE_NTRESPONSES) && (CURL_SIZEOF_CURL_OFF_T > 4)
|
||||
LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1 */
|
||||
#if defined(USE_NTRESPONSES)
|
||||
#define USE_NTLM_V2
|
||||
#endif
|
||||
|
||||
/* Helpers to generate function byte arguments in little endian order */
|
||||
#define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff))
|
||||
#define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \
|
||||
((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff))
|
||||
|
||||
void Curl_ntlm_core_lm_resp(const unsigned char *keys,
|
||||
const unsigned char *plaintext,
|
||||
unsigned char *results);
|
||||
|
||||
@@ -48,7 +48,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
|
||||
/* Check for /~/, indicating relative to the user's home directory */
|
||||
if(data->conn->handler->protocol & CURLPROTO_SCP) {
|
||||
real_path = malloc(working_path_len + 1);
|
||||
if(real_path == NULL) {
|
||||
if(!real_path) {
|
||||
free(working_path);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -62,7 +62,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
|
||||
if((working_path_len > 1) && (working_path[1] == '~')) {
|
||||
size_t homelen = strlen(homedir);
|
||||
real_path = malloc(homelen + working_path_len + 1);
|
||||
if(real_path == NULL) {
|
||||
if(!real_path) {
|
||||
free(working_path);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -78,7 +78,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
|
||||
}
|
||||
else {
|
||||
real_path = malloc(working_path_len + 1);
|
||||
if(real_path == NULL) {
|
||||
if(!real_path) {
|
||||
free(working_path);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -130,7 +130,7 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
|
||||
/* Allocate enough space for home directory and filename + separator */
|
||||
fullPathLength = strlen(cp) + strlen(homedir) + 2;
|
||||
*path = malloc(fullPathLength);
|
||||
if(*path == NULL)
|
||||
if(!*path)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Check for quoted filenames */
|
||||
@@ -169,7 +169,7 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
|
||||
else {
|
||||
/* Read to end of filename - either to whitespace or terminator */
|
||||
end = strpbrk(cp, WHITESPACE);
|
||||
if(end == NULL)
|
||||
if(!end)
|
||||
end = strchr(cp, '\0');
|
||||
/* return pointer to second parameter if it exists */
|
||||
*cpp = end + strspn(end, WHITESPACE);
|
||||
|
||||
@@ -79,6 +79,7 @@ const struct Curl_handler Curl_handler_rtmp = {
|
||||
rtmp_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_RTMP, /* defport */
|
||||
CURLPROTO_RTMP, /* protocol */
|
||||
CURLPROTO_RTMP, /* family */
|
||||
@@ -101,6 +102,7 @@ const struct Curl_handler Curl_handler_rtmpt = {
|
||||
rtmp_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_RTMPT, /* defport */
|
||||
CURLPROTO_RTMPT, /* protocol */
|
||||
CURLPROTO_RTMPT, /* family */
|
||||
@@ -123,6 +125,7 @@ const struct Curl_handler Curl_handler_rtmpe = {
|
||||
rtmp_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_RTMP, /* defport */
|
||||
CURLPROTO_RTMPE, /* protocol */
|
||||
CURLPROTO_RTMPE, /* family */
|
||||
@@ -145,6 +148,7 @@ const struct Curl_handler Curl_handler_rtmpte = {
|
||||
rtmp_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_RTMPT, /* defport */
|
||||
CURLPROTO_RTMPTE, /* protocol */
|
||||
CURLPROTO_RTMPTE, /* family */
|
||||
@@ -167,6 +171,7 @@ const struct Curl_handler Curl_handler_rtmps = {
|
||||
rtmp_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_RTMPS, /* defport */
|
||||
CURLPROTO_RTMPS, /* protocol */
|
||||
CURLPROTO_RTMP, /* family */
|
||||
@@ -189,6 +194,7 @@ const struct Curl_handler Curl_handler_rtmpts = {
|
||||
rtmp_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_RTMPS, /* defport */
|
||||
CURLPROTO_RTMPTS, /* protocol */
|
||||
CURLPROTO_RTMPT, /* family */
|
||||
@@ -204,7 +210,7 @@ static CURLcode rtmp_setup_connection(struct Curl_easy *data,
|
||||
|
||||
RTMP_Init(r);
|
||||
RTMP_SetBufferMS(r, DEF_BUFTIME);
|
||||
if(!RTMP_SetupURL(r, data->change.url)) {
|
||||
if(!RTMP_SetupURL(r, data->state.url)) {
|
||||
RTMP_Free(r);
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
|
||||
+192
-112
@@ -23,6 +23,8 @@
|
||||
* RFC2831 DIGEST-MD5 authentication
|
||||
* RFC4422 Simple Authentication and Security Layer (SASL)
|
||||
* RFC4616 PLAIN authentication
|
||||
* RFC5802 SCRAM-SHA-1 authentication
|
||||
* RFC7677 SCRAM-SHA-256 authentication
|
||||
* RFC6749 OAuth 2.0 Authorization Framework
|
||||
* RFC7628 A Set of SASL Mechanisms for OAuth
|
||||
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
|
||||
@@ -56,7 +58,7 @@
|
||||
static const struct {
|
||||
const char *name; /* Name */
|
||||
size_t len; /* Name length */
|
||||
unsigned int bit; /* Flag bit */
|
||||
unsigned short bit; /* Flag bit */
|
||||
} mechtable[] = {
|
||||
{ "LOGIN", 5, SASL_MECH_LOGIN },
|
||||
{ "PLAIN", 5, SASL_MECH_PLAIN },
|
||||
@@ -67,6 +69,8 @@ static const struct {
|
||||
{ "NTLM", 4, SASL_MECH_NTLM },
|
||||
{ "XOAUTH2", 7, SASL_MECH_XOAUTH2 },
|
||||
{ "OAUTHBEARER", 11, SASL_MECH_OAUTHBEARER },
|
||||
{ "SCRAM-SHA-1", 11, SASL_MECH_SCRAM_SHA_1 },
|
||||
{ "SCRAM-SHA-256",13, SASL_MECH_SCRAM_SHA_256 },
|
||||
{ ZERO_NULL, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -90,6 +94,13 @@ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_GSASL)
|
||||
/* Cleanup the GSASL structure */
|
||||
if(authused & (SASL_MECH_SCRAM_SHA_1 | SASL_MECH_SCRAM_SHA_256)) {
|
||||
Curl_auth_gsasl_cleanup(&conn->gsasl);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_NTLM)
|
||||
/* Cleanup the NTLM structure */
|
||||
if(authused == SASL_MECH_NTLM) {
|
||||
@@ -117,7 +128,8 @@ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
|
||||
*
|
||||
* Returns the SASL mechanism token or 0 if no match.
|
||||
*/
|
||||
unsigned int Curl_sasl_decode_mech(const char *ptr, size_t maxlen, size_t *len)
|
||||
unsigned short Curl_sasl_decode_mech(const char *ptr, size_t maxlen,
|
||||
size_t *len)
|
||||
{
|
||||
unsigned int i;
|
||||
char c;
|
||||
@@ -162,7 +174,7 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
|
||||
if(!strncmp(value, "*", len))
|
||||
sasl->prefmech = SASL_AUTH_DEFAULT;
|
||||
else {
|
||||
unsigned int mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
|
||||
unsigned short mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
|
||||
if(mechbit && mechlen == len)
|
||||
sasl->prefmech |= mechbit;
|
||||
else
|
||||
@@ -215,6 +227,7 @@ static void state(struct SASL *sasl, struct Curl_easy *data,
|
||||
"GSSAPI_NO_DATA",
|
||||
"OAUTH2",
|
||||
"OAUTH2_RESP",
|
||||
"GSASL",
|
||||
"CANCEL",
|
||||
"FINAL",
|
||||
/* LAST */
|
||||
@@ -230,6 +243,49 @@ static void state(struct SASL *sasl, struct Curl_easy *data,
|
||||
sasl->state = newstate;
|
||||
}
|
||||
|
||||
/* Get the SASL server message and convert it to binary. */
|
||||
static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
|
||||
struct bufref *out)
|
||||
{
|
||||
unsigned char *msg;
|
||||
size_t msglen;
|
||||
char *serverdata = NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
sasl->params->getmessage(data->state.buffer, &serverdata);
|
||||
if(!serverdata)
|
||||
result = CURLE_BAD_CONTENT_ENCODING;
|
||||
else if(!*serverdata || *serverdata == '=')
|
||||
Curl_bufref_set(out, NULL, 0, NULL);
|
||||
else {
|
||||
result = Curl_base64_decode(serverdata, &msg, &msglen);
|
||||
if(!result)
|
||||
Curl_bufref_set(out, msg, msglen, curl_free);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Encode the outgoing SASL message. */
|
||||
static CURLcode build_message(struct Curl_easy *data, struct bufref *msg)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
char *base64;
|
||||
size_t base64len;
|
||||
|
||||
if(!Curl_bufref_ptr(msg)) /* Empty mesage. */
|
||||
Curl_bufref_set(msg, "", 0, NULL);
|
||||
else if(!Curl_bufref_len(msg)) /* Explicit empty response. */
|
||||
Curl_bufref_set(msg, "=", 1, NULL);
|
||||
else {
|
||||
result = Curl_base64_encode(data, (const char *) Curl_bufref_ptr(msg),
|
||||
Curl_bufref_len(msg), &base64, &base64len);
|
||||
if(!result)
|
||||
Curl_bufref_set(msg, base64, base64len, curl_free);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_sasl_can_authenticate()
|
||||
*
|
||||
@@ -260,25 +316,21 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
|
||||
CURLcode result = CURLE_OK;
|
||||
unsigned int enabledmechs;
|
||||
const char *mech = NULL;
|
||||
char *resp = NULL;
|
||||
size_t len = 0;
|
||||
struct bufref resp;
|
||||
saslstate state1 = SASL_STOP;
|
||||
saslstate state2 = SASL_FINAL;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
|
||||
conn->host.name;
|
||||
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
|
||||
#else
|
||||
const char * const hostname = conn->host.name;
|
||||
const long int port = conn->remote_port;
|
||||
#endif
|
||||
const char * const hostname = SSL_HOST_NAME();
|
||||
const long int port = SSL_HOST_PORT();
|
||||
#if defined(USE_KERBEROS5) || defined(USE_NTLM)
|
||||
const char *service = data->set.str[STRING_SERVICE_NAME] ?
|
||||
data->set.str[STRING_SERVICE_NAME] :
|
||||
sasl->params->service;
|
||||
#endif
|
||||
const char *oauth_bearer = data->set.str[STRING_BEARER];
|
||||
struct bufref nullmsg;
|
||||
|
||||
Curl_bufref_init(&nullmsg);
|
||||
Curl_bufref_init(&resp);
|
||||
sasl->force_ir = force_ir; /* Latch for future use */
|
||||
sasl->authused = 0; /* No mechanism used yet */
|
||||
enabledmechs = sasl->authmechs & sasl->prefmech;
|
||||
@@ -292,8 +344,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
|
||||
sasl->authused = SASL_MECH_EXTERNAL;
|
||||
|
||||
if(force_ir || data->set.sasl_ir)
|
||||
result = Curl_auth_create_external_message(data, conn->user, &resp,
|
||||
&len);
|
||||
result = Curl_auth_create_external_message(conn->user, &resp);
|
||||
}
|
||||
else if(conn->bits.user_passwd) {
|
||||
#if defined(USE_KERBEROS5)
|
||||
@@ -309,10 +360,39 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
|
||||
result = Curl_auth_create_gssapi_user_message(data, conn->user,
|
||||
conn->passwd,
|
||||
service,
|
||||
data->conn->host.name,
|
||||
conn->host.name,
|
||||
sasl->mutual_auth,
|
||||
NULL, &conn->krb5,
|
||||
&resp, &len);
|
||||
&resp);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef USE_GSASL
|
||||
if((enabledmechs & SASL_MECH_SCRAM_SHA_256) &&
|
||||
Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_256,
|
||||
&conn->gsasl)) {
|
||||
mech = SASL_MECH_STRING_SCRAM_SHA_256;
|
||||
sasl->authused = SASL_MECH_SCRAM_SHA_256;
|
||||
state1 = SASL_GSASL;
|
||||
state2 = SASL_GSASL;
|
||||
|
||||
result = Curl_auth_gsasl_start(data, conn->user,
|
||||
conn->passwd, &conn->gsasl);
|
||||
if(result == CURLE_OK && (force_ir || data->set.sasl_ir))
|
||||
result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp);
|
||||
}
|
||||
else if((enabledmechs & SASL_MECH_SCRAM_SHA_1) &&
|
||||
Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_1,
|
||||
&conn->gsasl)) {
|
||||
mech = SASL_MECH_STRING_SCRAM_SHA_1;
|
||||
sasl->authused = SASL_MECH_SCRAM_SHA_1;
|
||||
state1 = SASL_GSASL;
|
||||
state2 = SASL_GSASL;
|
||||
|
||||
result = Curl_auth_gsasl_start(data, conn->user,
|
||||
conn->passwd, &conn->gsasl);
|
||||
if(result == CURLE_OK && (force_ir || data->set.sasl_ir))
|
||||
result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -342,8 +422,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
|
||||
conn->user, conn->passwd,
|
||||
service,
|
||||
hostname,
|
||||
&conn->ntlm, &resp,
|
||||
&len);
|
||||
&conn->ntlm, &resp);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -354,11 +433,11 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
|
||||
sasl->authused = SASL_MECH_OAUTHBEARER;
|
||||
|
||||
if(force_ir || data->set.sasl_ir)
|
||||
result = Curl_auth_create_oauth_bearer_message(data, conn->user,
|
||||
result = Curl_auth_create_oauth_bearer_message(conn->user,
|
||||
hostname,
|
||||
port,
|
||||
oauth_bearer,
|
||||
&resp, &len);
|
||||
&resp);
|
||||
}
|
||||
else if((enabledmechs & SASL_MECH_XOAUTH2) && oauth_bearer) {
|
||||
mech = SASL_MECH_STRING_XOAUTH2;
|
||||
@@ -366,9 +445,9 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
|
||||
sasl->authused = SASL_MECH_XOAUTH2;
|
||||
|
||||
if(force_ir || data->set.sasl_ir)
|
||||
result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
|
||||
result = Curl_auth_create_xoauth_bearer_message(conn->user,
|
||||
oauth_bearer,
|
||||
&resp, &len);
|
||||
&resp);
|
||||
}
|
||||
else if(enabledmechs & SASL_MECH_PLAIN) {
|
||||
mech = SASL_MECH_STRING_PLAIN;
|
||||
@@ -376,9 +455,9 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
|
||||
sasl->authused = SASL_MECH_PLAIN;
|
||||
|
||||
if(force_ir || data->set.sasl_ir)
|
||||
result = Curl_auth_create_plain_message(data, conn->sasl_authzid,
|
||||
result = Curl_auth_create_plain_message(conn->sasl_authzid,
|
||||
conn->user, conn->passwd,
|
||||
&resp, &len);
|
||||
&resp);
|
||||
}
|
||||
else if(enabledmechs & SASL_MECH_LOGIN) {
|
||||
mech = SASL_MECH_STRING_LOGIN;
|
||||
@@ -387,26 +466,29 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
|
||||
sasl->authused = SASL_MECH_LOGIN;
|
||||
|
||||
if(force_ir || data->set.sasl_ir)
|
||||
result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
|
||||
result = Curl_auth_create_login_message(conn->user, &resp);
|
||||
}
|
||||
}
|
||||
|
||||
if(!result && mech) {
|
||||
if(resp && sasl->params->maxirlen &&
|
||||
strlen(mech) + len > sasl->params->maxirlen) {
|
||||
free(resp);
|
||||
resp = NULL;
|
||||
}
|
||||
if(Curl_bufref_ptr(&resp))
|
||||
result = build_message(data, &resp);
|
||||
|
||||
if(sasl->params->maxirlen &&
|
||||
strlen(mech) + Curl_bufref_len(&resp) > sasl->params->maxirlen)
|
||||
Curl_bufref_free(&resp);
|
||||
|
||||
if(!result)
|
||||
result = sasl->params->sendauth(data, conn, mech,
|
||||
(const char *) Curl_bufref_ptr(&resp));
|
||||
|
||||
result = sasl->params->sendauth(data, conn, mech, resp);
|
||||
if(!result) {
|
||||
*progress = SASL_INPROGRESS;
|
||||
state(sasl, data, resp ? state2 : state1);
|
||||
state(sasl, data, Curl_bufref_ptr(&resp) ? state2 : state1);
|
||||
}
|
||||
}
|
||||
|
||||
free(resp);
|
||||
|
||||
Curl_bufref_free(&resp);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -421,29 +503,20 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
saslstate newstate = SASL_FINAL;
|
||||
char *resp = NULL;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
|
||||
conn->host.name;
|
||||
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
|
||||
#else
|
||||
const char * const hostname = conn->host.name;
|
||||
const long int port = conn->remote_port;
|
||||
#endif
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
char *chlg = NULL;
|
||||
size_t chlglen = 0;
|
||||
#endif
|
||||
struct bufref resp;
|
||||
const char * const hostname = SSL_HOST_NAME();
|
||||
const long int port = SSL_HOST_PORT();
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
|
||||
defined(USE_NTLM)
|
||||
const char *service = data->set.str[STRING_SERVICE_NAME] ?
|
||||
data->set.str[STRING_SERVICE_NAME] :
|
||||
sasl->params->service;
|
||||
char *serverdata;
|
||||
#endif
|
||||
size_t len = 0;
|
||||
const char *oauth_bearer = data->set.str[STRING_BEARER];
|
||||
struct bufref serverdata;
|
||||
|
||||
Curl_bufref_init(&serverdata);
|
||||
Curl_bufref_init(&resp);
|
||||
*progress = SASL_INPROGRESS;
|
||||
|
||||
if(sasl->state == SASL_FINAL) {
|
||||
@@ -466,42 +539,45 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
|
||||
*progress = SASL_DONE;
|
||||
return result;
|
||||
case SASL_PLAIN:
|
||||
result = Curl_auth_create_plain_message(data, conn->sasl_authzid,
|
||||
conn->user, conn->passwd,
|
||||
&resp, &len);
|
||||
result = Curl_auth_create_plain_message(conn->sasl_authzid,
|
||||
conn->user, conn->passwd, &resp);
|
||||
break;
|
||||
case SASL_LOGIN:
|
||||
result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
|
||||
result = Curl_auth_create_login_message(conn->user, &resp);
|
||||
newstate = SASL_LOGIN_PASSWD;
|
||||
break;
|
||||
case SASL_LOGIN_PASSWD:
|
||||
result = Curl_auth_create_login_message(data, conn->passwd, &resp, &len);
|
||||
result = Curl_auth_create_login_message(conn->passwd, &resp);
|
||||
break;
|
||||
case SASL_EXTERNAL:
|
||||
result = Curl_auth_create_external_message(data, conn->user, &resp, &len);
|
||||
result = Curl_auth_create_external_message(conn->user, &resp);
|
||||
break;
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
case SASL_CRAMMD5:
|
||||
sasl->params->getmessage(data->state.buffer, &serverdata);
|
||||
result = Curl_auth_decode_cram_md5_message(serverdata, &chlg, &chlglen);
|
||||
#ifdef USE_GSASL
|
||||
case SASL_GSASL:
|
||||
result = get_server_message(sasl, data, &serverdata);
|
||||
if(!result)
|
||||
result = Curl_auth_create_cram_md5_message(data, chlg, conn->user,
|
||||
conn->passwd, &resp, &len);
|
||||
free(chlg);
|
||||
result = Curl_auth_gsasl_token(data, &serverdata, &conn->gsasl, &resp);
|
||||
if(!result && Curl_bufref_len(&resp) > 0)
|
||||
newstate = SASL_GSASL;
|
||||
break;
|
||||
#endif
|
||||
case SASL_CRAMMD5:
|
||||
result = get_server_message(sasl, data, &serverdata);
|
||||
if(!result)
|
||||
result = Curl_auth_create_cram_md5_message(&serverdata, conn->user,
|
||||
conn->passwd, &resp);
|
||||
break;
|
||||
case SASL_DIGESTMD5:
|
||||
sasl->params->getmessage(data->state.buffer, &serverdata);
|
||||
result = Curl_auth_create_digest_md5_message(data, serverdata,
|
||||
conn->user, conn->passwd,
|
||||
service,
|
||||
&resp, &len);
|
||||
result = get_server_message(sasl, data, &serverdata);
|
||||
if(!result)
|
||||
result = Curl_auth_create_digest_md5_message(data, &serverdata,
|
||||
conn->user, conn->passwd,
|
||||
service, &resp);
|
||||
newstate = SASL_DIGESTMD5_RESP;
|
||||
break;
|
||||
case SASL_DIGESTMD5_RESP:
|
||||
resp = strdup("");
|
||||
if(!resp)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
/* Keep response NULL to output an empty line. */
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -511,18 +587,19 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
|
||||
result = Curl_auth_create_ntlm_type1_message(data,
|
||||
conn->user, conn->passwd,
|
||||
service, hostname,
|
||||
&conn->ntlm, &resp, &len);
|
||||
&conn->ntlm, &resp);
|
||||
newstate = SASL_NTLM_TYPE2MSG;
|
||||
break;
|
||||
case SASL_NTLM_TYPE2MSG:
|
||||
/* Decode the type-2 message */
|
||||
sasl->params->getmessage(data->state.buffer, &serverdata);
|
||||
result = Curl_auth_decode_ntlm_type2_message(data, serverdata,
|
||||
&conn->ntlm);
|
||||
result = get_server_message(sasl, data, &serverdata);
|
||||
if(!result)
|
||||
result = Curl_auth_decode_ntlm_type2_message(data, &serverdata,
|
||||
&conn->ntlm);
|
||||
if(!result)
|
||||
result = Curl_auth_create_ntlm_type3_message(data, conn->user,
|
||||
conn->passwd, &conn->ntlm,
|
||||
&resp, &len);
|
||||
&resp);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -531,55 +608,59 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
|
||||
result = Curl_auth_create_gssapi_user_message(data, conn->user,
|
||||
conn->passwd,
|
||||
service,
|
||||
data->conn->host.name,
|
||||
conn->host.name,
|
||||
sasl->mutual_auth, NULL,
|
||||
&conn->krb5,
|
||||
&resp, &len);
|
||||
&resp);
|
||||
newstate = SASL_GSSAPI_TOKEN;
|
||||
break;
|
||||
case SASL_GSSAPI_TOKEN:
|
||||
sasl->params->getmessage(data->state.buffer, &serverdata);
|
||||
if(sasl->mutual_auth) {
|
||||
/* Decode the user token challenge and create the optional response
|
||||
message */
|
||||
result = Curl_auth_create_gssapi_user_message(data, NULL, NULL,
|
||||
NULL, NULL,
|
||||
sasl->mutual_auth,
|
||||
serverdata, &conn->krb5,
|
||||
&resp, &len);
|
||||
newstate = SASL_GSSAPI_NO_DATA;
|
||||
result = get_server_message(sasl, data, &serverdata);
|
||||
if(!result) {
|
||||
if(sasl->mutual_auth) {
|
||||
/* Decode the user token challenge and create the optional response
|
||||
message */
|
||||
result = Curl_auth_create_gssapi_user_message(data, NULL, NULL,
|
||||
NULL, NULL,
|
||||
sasl->mutual_auth,
|
||||
&serverdata,
|
||||
&conn->krb5,
|
||||
&resp);
|
||||
newstate = SASL_GSSAPI_NO_DATA;
|
||||
}
|
||||
else
|
||||
/* Decode the security challenge and create the response message */
|
||||
result = Curl_auth_create_gssapi_security_message(data, &serverdata,
|
||||
&conn->krb5,
|
||||
&resp);
|
||||
}
|
||||
else
|
||||
/* Decode the security challenge and create the response message */
|
||||
result = Curl_auth_create_gssapi_security_message(data, serverdata,
|
||||
&conn->krb5,
|
||||
&resp, &len);
|
||||
break;
|
||||
case SASL_GSSAPI_NO_DATA:
|
||||
sasl->params->getmessage(data->state.buffer, &serverdata);
|
||||
/* Decode the security challenge and create the response message */
|
||||
result = Curl_auth_create_gssapi_security_message(data, serverdata,
|
||||
&conn->krb5,
|
||||
&resp, &len);
|
||||
result = get_server_message(sasl, data, &serverdata);
|
||||
if(!result)
|
||||
result = Curl_auth_create_gssapi_security_message(data, &serverdata,
|
||||
&conn->krb5,
|
||||
&resp);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SASL_OAUTH2:
|
||||
/* Create the authorisation message */
|
||||
if(sasl->authused == SASL_MECH_OAUTHBEARER) {
|
||||
result = Curl_auth_create_oauth_bearer_message(data, conn->user,
|
||||
result = Curl_auth_create_oauth_bearer_message(conn->user,
|
||||
hostname,
|
||||
port,
|
||||
oauth_bearer,
|
||||
&resp, &len);
|
||||
&resp);
|
||||
|
||||
/* Failures maybe sent by the server as continuations for OAUTHBEARER */
|
||||
newstate = SASL_OAUTH2_RESP;
|
||||
}
|
||||
else
|
||||
result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
|
||||
result = Curl_auth_create_xoauth_bearer_message(conn->user,
|
||||
oauth_bearer,
|
||||
&resp, &len);
|
||||
&resp);
|
||||
break;
|
||||
|
||||
case SASL_OAUTH2_RESP:
|
||||
@@ -591,11 +672,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
|
||||
return result;
|
||||
}
|
||||
else if(code == sasl->params->contcode) {
|
||||
/* Acknowledge the continuation by sending a 0x01 response base64
|
||||
encoded */
|
||||
resp = strdup("AQ==");
|
||||
if(!resp)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
/* Acknowledge the continuation by sending a 0x01 response. */
|
||||
Curl_bufref_set(&resp, "\x01", 1, NULL);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
@@ -609,15 +687,15 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
|
||||
sasl->authmechs ^= sasl->authused;
|
||||
|
||||
/* Start an alternative SASL authentication */
|
||||
result = Curl_sasl_start(sasl, data, conn, sasl->force_ir, progress);
|
||||
newstate = sasl->state; /* Use state from Curl_sasl_start() */
|
||||
break;
|
||||
return Curl_sasl_start(sasl, data, conn, sasl->force_ir, progress);
|
||||
default:
|
||||
failf(data, "Unsupported SASL authentication mechanism");
|
||||
result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */
|
||||
break;
|
||||
}
|
||||
|
||||
Curl_bufref_free(&serverdata);
|
||||
|
||||
switch(result) {
|
||||
case CURLE_BAD_CONTENT_ENCODING:
|
||||
/* Cancel dialog */
|
||||
@@ -625,8 +703,10 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
|
||||
newstate = SASL_CANCEL;
|
||||
break;
|
||||
case CURLE_OK:
|
||||
if(resp)
|
||||
result = sasl->params->sendcont(data, conn, resp);
|
||||
result = build_message(data, &resp);
|
||||
if(!result)
|
||||
result = sasl->params->sendcont(data, conn,
|
||||
(const char *) Curl_bufref_ptr(&resp));
|
||||
break;
|
||||
default:
|
||||
newstate = SASL_STOP; /* Stop on error */
|
||||
@@ -634,7 +714,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
|
||||
break;
|
||||
}
|
||||
|
||||
free(resp);
|
||||
Curl_bufref_free(&resp);
|
||||
|
||||
state(sasl, data, newstate);
|
||||
|
||||
|
||||
@@ -37,10 +37,12 @@ struct connectdata;
|
||||
#define SASL_MECH_NTLM (1 << 6)
|
||||
#define SASL_MECH_XOAUTH2 (1 << 7)
|
||||
#define SASL_MECH_OAUTHBEARER (1 << 8)
|
||||
#define SASL_MECH_SCRAM_SHA_1 (1 << 9)
|
||||
#define SASL_MECH_SCRAM_SHA_256 (1 << 10)
|
||||
|
||||
/* Authentication mechanism values */
|
||||
#define SASL_AUTH_NONE 0
|
||||
#define SASL_AUTH_ANY ~0U
|
||||
#define SASL_AUTH_ANY 0xffff
|
||||
#define SASL_AUTH_DEFAULT (SASL_AUTH_ANY & ~SASL_MECH_EXTERNAL)
|
||||
|
||||
/* Authentication mechanism strings */
|
||||
@@ -53,6 +55,8 @@ struct connectdata;
|
||||
#define SASL_MECH_STRING_NTLM "NTLM"
|
||||
#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2"
|
||||
#define SASL_MECH_STRING_OAUTHBEARER "OAUTHBEARER"
|
||||
#define SASL_MECH_STRING_SCRAM_SHA_1 "SCRAM-SHA-1"
|
||||
#define SASL_MECH_STRING_SCRAM_SHA_256 "SCRAM-SHA-256"
|
||||
|
||||
/* SASL machine states */
|
||||
typedef enum {
|
||||
@@ -71,6 +75,7 @@ typedef enum {
|
||||
SASL_GSSAPI_NO_DATA,
|
||||
SASL_OAUTH2,
|
||||
SASL_OAUTH2_RESP,
|
||||
SASL_GSASL,
|
||||
SASL_CANCEL,
|
||||
SASL_FINAL
|
||||
} saslstate;
|
||||
@@ -103,9 +108,9 @@ struct SASLproto {
|
||||
struct SASL {
|
||||
const struct SASLproto *params; /* Protocol dependent parameters */
|
||||
saslstate state; /* Current machine state */
|
||||
unsigned int authmechs; /* Accepted authentication mechanisms */
|
||||
unsigned int prefmech; /* Preferred authentication mechanism */
|
||||
unsigned int authused; /* Auth mechanism used for the connection */
|
||||
unsigned short authmechs; /* Accepted authentication mechanisms */
|
||||
unsigned short prefmech; /* Preferred authentication mechanism */
|
||||
unsigned short authused; /* Auth mechanism used for the connection */
|
||||
bool resetprefs; /* For URL auth option parsing. */
|
||||
bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */
|
||||
bool force_ir; /* Protocol always supports initial response */
|
||||
@@ -121,8 +126,8 @@ struct SASL {
|
||||
void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused);
|
||||
|
||||
/* Convert a mechanism name to a token */
|
||||
unsigned int Curl_sasl_decode_mech(const char *ptr,
|
||||
size_t maxlen, size_t *len);
|
||||
unsigned short Curl_sasl_decode_mech(const char *ptr,
|
||||
size_t maxlen, size_t *len);
|
||||
|
||||
/* Parse the URL login options */
|
||||
CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -54,6 +54,16 @@
|
||||
# ifndef NOGDI
|
||||
# define NOGDI
|
||||
# endif
|
||||
/* Detect Windows App environment which has a restricted access
|
||||
* to the Win32 APIs. */
|
||||
# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
|
||||
defined(WINAPI_FAMILY)
|
||||
# include <winapifamily.h>
|
||||
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
|
||||
!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
# define CURL_WINDOWS_APP
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -155,8 +165,6 @@
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#define CURL_SIZEOF_CURL_OFF_T SIZEOF_CURL_OFF_T
|
||||
|
||||
/*
|
||||
* Disable other protocols when http is the only one desired.
|
||||
*/
|
||||
@@ -243,7 +251,11 @@
|
||||
* performing this task will result in a synthesized IPv6 address.
|
||||
*/
|
||||
#if defined(__APPLE__) && !defined(USE_ARES)
|
||||
#include <TargetConditionals.h>
|
||||
#define USE_RESOLVE_ON_IPS 1
|
||||
# if defined(TARGET_OS_OSX) && TARGET_OS_OSX
|
||||
# define CURL_OSX_CALL_COPYPROXIES 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_LWIPSOCK
|
||||
@@ -350,8 +362,10 @@
|
||||
# define stat(fname,stp) curlx_win32_stat(fname, stp)
|
||||
# define struct_stat struct _stati64
|
||||
# define LSEEK_ERROR (__int64)-1
|
||||
# define open curlx_win32_open
|
||||
# define fopen(fname,mode) curlx_win32_fopen(fname, mode)
|
||||
# define access(fname,mode) curlx_win32_access(fname, mode)
|
||||
int curlx_win32_open(const char *filename, int oflag, ...);
|
||||
int curlx_win32_stat(const char *path, struct_stat *buffer);
|
||||
FILE *curlx_win32_fopen(const char *filename, const char *mode);
|
||||
int curlx_win32_access(const char *path, int mode);
|
||||
@@ -371,9 +385,11 @@
|
||||
# define fstat(fdes,stp) _fstat(fdes, stp)
|
||||
# define stat(fname,stp) curlx_win32_stat(fname, stp)
|
||||
# define struct_stat struct _stat
|
||||
# define open curlx_win32_open
|
||||
# define fopen(fname,mode) curlx_win32_fopen(fname, mode)
|
||||
# define access(fname,mode) curlx_win32_access(fname, mode)
|
||||
int curlx_win32_stat(const char *path, struct_stat *buffer);
|
||||
int curlx_win32_open(const char *filename, int oflag, ...);
|
||||
FILE *curlx_win32_fopen(const char *filename, const char *mode);
|
||||
int curlx_win32_access(const char *path, int mode);
|
||||
# endif
|
||||
@@ -423,7 +439,7 @@
|
||||
#if (SIZEOF_CURL_OFF_T == 4)
|
||||
# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF)
|
||||
#else
|
||||
/* assume CURL_SIZEOF_CURL_OFF_T == 8 */
|
||||
/* assume SIZEOF_CURL_OFF_T == 8 */
|
||||
# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF)
|
||||
#endif
|
||||
#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1))
|
||||
@@ -520,7 +536,6 @@
|
||||
# undef HAVE_GETADDRINFO_THREADSAFE
|
||||
# undef HAVE_FREEADDRINFO
|
||||
# undef HAVE_GETADDRINFO
|
||||
# undef HAVE_GETNAMEINFO
|
||||
# undef ENABLE_IPV6
|
||||
# endif
|
||||
#endif
|
||||
@@ -627,7 +642,7 @@ int netware_init(void);
|
||||
defined(USE_MBEDTLS) || \
|
||||
defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || \
|
||||
defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK) || \
|
||||
defined(USE_BEARSSL)
|
||||
defined(USE_BEARSSL) || defined(USE_RUSTLS)
|
||||
#define USE_SSL /* SSL support has been enabled */
|
||||
#endif
|
||||
|
||||
@@ -644,7 +659,7 @@ int netware_init(void);
|
||||
#endif
|
||||
|
||||
/* Single point where USE_NTLM definition might be defined */
|
||||
#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
|
||||
defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
|
||||
defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
|
||||
@@ -718,13 +733,19 @@ int netware_init(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Portable symbolic names for Winsock shutdown() mode flags.
|
||||
* shutdown() flags for systems that don't define them
|
||||
*/
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
# define SHUT_RD 0x00
|
||||
# define SHUT_WR 0x01
|
||||
# define SHUT_RDWR 0x02
|
||||
#ifndef SHUT_RD
|
||||
#define SHUT_RD 0x00
|
||||
#endif
|
||||
|
||||
#ifndef SHUT_WR
|
||||
#define SHUT_WR 0x01
|
||||
#endif
|
||||
|
||||
#ifndef SHUT_RDWR
|
||||
#define SHUT_RDWR 0x02
|
||||
#endif
|
||||
|
||||
/* Define S_ISREG if not defined by system headers, f.e. MSVC */
|
||||
@@ -775,20 +796,16 @@ endings either CRLF or LF so 't' is appropriate.
|
||||
# endif
|
||||
#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */
|
||||
|
||||
/* Detect Windows App environment which has a restricted access
|
||||
* to the Win32 APIs. */
|
||||
# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
|
||||
defined(WINAPI_FAMILY)
|
||||
# include <winapifamily.h>
|
||||
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
|
||||
!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
# define CURL_WINDOWS_APP
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* for systems that don't detect this in configure, use a sensible default */
|
||||
/* for systems that don't detect this in configure */
|
||||
#ifndef CURL_SA_FAMILY_T
|
||||
#define CURL_SA_FAMILY_T unsigned short
|
||||
# if defined(HAVE_SA_FAMILY_T)
|
||||
# define CURL_SA_FAMILY_T sa_family_t
|
||||
# elif defined(HAVE_ADDRESS_FAMILY)
|
||||
# define CURL_SA_FAMILY_T ADDRESS_FAMILY
|
||||
# else
|
||||
/* use a sensible default */
|
||||
# define CURL_SA_FAMILY_T unsigned short
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Some convenience macros to get the larger/smaller value out of two given.
|
||||
@@ -809,6 +826,10 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
|
||||
#define UNITTEST static
|
||||
#endif
|
||||
|
||||
#if defined(USE_NGHTTP2) || defined(USE_HYPER)
|
||||
#define USE_HTTP2
|
||||
#endif
|
||||
|
||||
#if defined(USE_NGTCP2) || defined(USE_QUICHE)
|
||||
#define ENABLE_QUIC
|
||||
#endif
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
@@ -55,13 +56,6 @@
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
#include <time.h>
|
||||
#endif
|
||||
#else
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -350,15 +344,6 @@ typedef int sig_atomic_t;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Default return type for signal handlers.
|
||||
*/
|
||||
|
||||
#ifndef RETSIGTYPE
|
||||
#define RETSIGTYPE void
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Macro used to include code only in debug builds.
|
||||
*/
|
||||
|
||||
@@ -89,6 +89,7 @@ const struct Curl_handler Curl_handler_dict = {
|
||||
ZERO_NULL, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_DICT, /* defport */
|
||||
CURLPROTO_DICT, /* protocol */
|
||||
CURLPROTO_DICT, /* family */
|
||||
@@ -214,14 +215,14 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
|
||||
}
|
||||
}
|
||||
|
||||
if((word == NULL) || (*word == (char)0)) {
|
||||
if(!word || (*word == (char)0)) {
|
||||
infof(data, "lookup word is missing\n");
|
||||
word = (char *)"default";
|
||||
}
|
||||
if((database == NULL) || (*database == (char)0)) {
|
||||
if(!database || (*database == (char)0)) {
|
||||
database = (char *)"!";
|
||||
}
|
||||
if((strategy == NULL) || (*strategy == (char)0)) {
|
||||
if(!strategy || (*strategy == (char)0)) {
|
||||
strategy = (char *)".";
|
||||
}
|
||||
|
||||
@@ -265,11 +266,11 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
|
||||
}
|
||||
}
|
||||
|
||||
if((word == NULL) || (*word == (char)0)) {
|
||||
if(!word || (*word == (char)0)) {
|
||||
infof(data, "lookup word is missing\n");
|
||||
word = (char *)"default";
|
||||
}
|
||||
if((database == NULL) || (*database == (char)0)) {
|
||||
if(!database || (*database == (char)0)) {
|
||||
database = (char *)"!";
|
||||
}
|
||||
|
||||
|
||||
+67
-58
@@ -207,10 +207,12 @@ static int doh_done(struct Curl_easy *doh, CURLcode result)
|
||||
}
|
||||
|
||||
#define ERROR_CHECK_SETOPT(x,y) \
|
||||
do { \
|
||||
result = curl_easy_setopt(doh, x, y); \
|
||||
if(result) \
|
||||
goto error; \
|
||||
do { \
|
||||
result = curl_easy_setopt(doh, x, y); \
|
||||
if(result && \
|
||||
result != CURLE_NOT_BUILT_IN && \
|
||||
result != CURLE_UNKNOWN_OPTION) \
|
||||
goto error; \
|
||||
} while(0)
|
||||
|
||||
static CURLcode dohprobe(struct Curl_easy *data,
|
||||
@@ -282,84 +284,93 @@ static CURLcode dohprobe(struct Curl_easy *data,
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS);
|
||||
#endif
|
||||
ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SHARE, data->share);
|
||||
if(data->set.err && data->set.err != stderr)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_STDERR, data->set.err);
|
||||
if(data->set.verbose)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
|
||||
if(data->set.no_signal)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L);
|
||||
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST,
|
||||
data->set.doh_verifyhost ? 2L : 0L);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER,
|
||||
data->set.doh_verifypeer ? 1L : 0L);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS,
|
||||
data->set.doh_verifystatus ? 1L : 0L);
|
||||
|
||||
/* Inherit *some* SSL options from the user's transfer. This is a
|
||||
best-guess as to which options are needed for compatibility. #3661 */
|
||||
best-guess as to which options are needed for compatibility. #3661
|
||||
|
||||
Note DOH does not inherit the user's proxy server so proxy SSL settings
|
||||
have no effect and are not inherited. If that changes then two new
|
||||
options should be added to check doh proxy insecure separately,
|
||||
CURLOPT_DOH_PROXY_SSL_VERIFYHOST and CURLOPT_DOH_PROXY_SSL_VERIFYPEER.
|
||||
*/
|
||||
if(data->set.ssl.falsestart)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_FALSESTART, 1L);
|
||||
if(data->set.ssl.primary.verifyhost)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, 2L);
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(data->set.proxy_ssl.primary.verifyhost)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYHOST, 2L);
|
||||
if(data->set.proxy_ssl.primary.verifypeer)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
|
||||
if(data->set.str[STRING_SSL_CAFILE_PROXY]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAINFO,
|
||||
data->set.str[STRING_SSL_CAFILE_PROXY]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CRLFILE_PROXY]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_CRLFILE,
|
||||
data->set.str[STRING_SSL_CRLFILE_PROXY]);
|
||||
}
|
||||
if(data->set.proxy_ssl.no_revoke)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
|
||||
else if(data->set.proxy_ssl.revoke_best_effort)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS,
|
||||
CURLSSLOPT_REVOKE_BEST_EFFORT);
|
||||
if(data->set.str[STRING_SSL_CAPATH_PROXY]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH,
|
||||
data->set.str[STRING_SSL_CAPATH_PROXY]);
|
||||
}
|
||||
#endif
|
||||
if(data->set.ssl.primary.verifypeer)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, 1L);
|
||||
if(data->set.ssl.primary.verifystatus)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, 1L);
|
||||
if(data->set.str[STRING_SSL_CAFILE_ORIG]) {
|
||||
if(data->set.str[STRING_SSL_CAFILE]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CAINFO,
|
||||
data->set.str[STRING_SSL_CAFILE_ORIG]);
|
||||
data->set.str[STRING_SSL_CAFILE]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CAPATH_ORIG]) {
|
||||
if(data->set.blobs[BLOB_CAINFO]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CAINFO_BLOB,
|
||||
data->set.blobs[BLOB_CAINFO]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CAPATH]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CAPATH,
|
||||
data->set.str[STRING_SSL_CAPATH_ORIG]);
|
||||
data->set.str[STRING_SSL_CAPATH]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CRLFILE_ORIG]) {
|
||||
if(data->set.str[STRING_SSL_CRLFILE]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CRLFILE,
|
||||
data->set.str[STRING_SSL_CRLFILE_ORIG]);
|
||||
data->set.str[STRING_SSL_CRLFILE]);
|
||||
}
|
||||
if(data->set.ssl.certinfo)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L);
|
||||
if(data->set.str[STRING_SSL_RANDOM_FILE]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_RANDOM_FILE,
|
||||
data->set.str[STRING_SSL_RANDOM_FILE]);
|
||||
data->set.str[STRING_SSL_RANDOM_FILE]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_EGDSOCKET]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_EGDSOCKET,
|
||||
data->set.str[STRING_SSL_EGDSOCKET]);
|
||||
data->set.str[STRING_SSL_EGDSOCKET]);
|
||||
}
|
||||
if(data->set.ssl.no_revoke)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
|
||||
else if(data->set.ssl.revoke_best_effort)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_REVOKE_BEST_EFFORT);
|
||||
if(data->set.ssl.fsslctx)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
|
||||
if(data->set.ssl.fsslctxp)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
|
||||
if(data->set.str[STRING_SSL_EC_CURVES]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_EC_CURVES,
|
||||
data->set.str[STRING_SSL_EC_CURVES]);
|
||||
data->set.str[STRING_SSL_EC_CURVES]);
|
||||
}
|
||||
|
||||
{
|
||||
long mask =
|
||||
(data->set.ssl.enable_beast ?
|
||||
CURLSSLOPT_ALLOW_BEAST : 0) |
|
||||
(data->set.ssl.no_revoke ?
|
||||
CURLSSLOPT_NO_REVOKE : 0) |
|
||||
(data->set.ssl.no_partialchain ?
|
||||
CURLSSLOPT_NO_PARTIALCHAIN : 0) |
|
||||
(data->set.ssl.revoke_best_effort ?
|
||||
CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
|
||||
(data->set.ssl.native_ca_store ?
|
||||
CURLSSLOPT_NATIVE_CA : 0) |
|
||||
(data->set.ssl.auto_client_cert ?
|
||||
CURLSSLOPT_AUTO_CLIENT_CERT : 0);
|
||||
|
||||
curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS, mask);
|
||||
}
|
||||
|
||||
doh->set.fmultidone = doh_done;
|
||||
doh->set.dohfor = data; /* identify for which transfer this is done */
|
||||
p->easy = doh;
|
||||
|
||||
/* add this transfer to the multi handle */
|
||||
/* DOH private_data must be null because the user must have a way to
|
||||
distinguish their transfer's handle from DOH handles in user
|
||||
callbacks (ie SSL CTX callback). */
|
||||
DEBUGASSERT(!data->set.private_data);
|
||||
|
||||
if(curl_multi_add_handle(multi, doh))
|
||||
goto error;
|
||||
}
|
||||
@@ -409,17 +420,15 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
|
||||
if(!dohp->headers)
|
||||
goto error;
|
||||
|
||||
if(conn->ip_version != CURL_IPRESOLVE_V6) {
|
||||
/* create IPv4 DOH request */
|
||||
result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4],
|
||||
DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
|
||||
data->multi, dohp->headers);
|
||||
if(result)
|
||||
goto error;
|
||||
dohp->pending++;
|
||||
}
|
||||
/* create IPv4 DOH request */
|
||||
result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4],
|
||||
DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
|
||||
data->multi, dohp->headers);
|
||||
if(result)
|
||||
goto error;
|
||||
dohp->pending++;
|
||||
|
||||
if(conn->ip_version != CURL_IPRESOLVE_V4) {
|
||||
if(Curl_ipv6works(data)) {
|
||||
/* create IPv6 DOH request */
|
||||
result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6],
|
||||
DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2020, 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -74,7 +74,7 @@ int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save);
|
||||
#define DYN_DOH_CNAME 256
|
||||
#define DYN_PAUSE_BUFFER (64 * 1024 * 1024)
|
||||
#define DYN_HAXPROXY 2048
|
||||
#define DYN_HTTP_REQUEST (128*1024)
|
||||
#define DYN_HTTP_REQUEST (1024*1024)
|
||||
#define DYN_H2_HEADERS (128*1024)
|
||||
#define DYN_H2_TRAILERS (128*1024)
|
||||
#define DYN_APRINTF 8000000
|
||||
|
||||
+24
-34
@@ -789,7 +789,6 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
|
||||
/* duplicate all blobs */
|
||||
for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
|
||||
result = Curl_setblobopt(&dst->set.blobs[j], src->set.blobs[j]);
|
||||
/* Curl_setstropt return CURLE_BAD_FUNCTION_ARGUMENT with blob */
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@@ -810,7 +809,7 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
|
||||
result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost);
|
||||
|
||||
if(src->set.resolve)
|
||||
dst->change.resolve = dst->set.resolve;
|
||||
dst->state.resolve = dst->set.resolve;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -858,25 +857,25 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
|
||||
}
|
||||
|
||||
/* duplicate all values in 'change' */
|
||||
if(data->change.cookielist) {
|
||||
outcurl->change.cookielist =
|
||||
Curl_slist_duplicate(data->change.cookielist);
|
||||
if(!outcurl->change.cookielist)
|
||||
if(data->state.cookielist) {
|
||||
outcurl->state.cookielist =
|
||||
Curl_slist_duplicate(data->state.cookielist);
|
||||
if(!outcurl->state.cookielist)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if(data->change.url) {
|
||||
outcurl->change.url = strdup(data->change.url);
|
||||
if(!outcurl->change.url)
|
||||
if(data->state.url) {
|
||||
outcurl->state.url = strdup(data->state.url);
|
||||
if(!outcurl->state.url)
|
||||
goto fail;
|
||||
outcurl->change.url_alloc = TRUE;
|
||||
outcurl->state.url_alloc = TRUE;
|
||||
}
|
||||
|
||||
if(data->change.referer) {
|
||||
outcurl->change.referer = strdup(data->change.referer);
|
||||
if(!outcurl->change.referer)
|
||||
if(data->state.referer) {
|
||||
outcurl->state.referer = strdup(data->state.referer);
|
||||
if(!outcurl->state.referer)
|
||||
goto fail;
|
||||
outcurl->change.referer_alloc = TRUE;
|
||||
outcurl->state.referer_alloc = TRUE;
|
||||
}
|
||||
|
||||
/* Reinitialize an SSL engine for the new handle
|
||||
@@ -895,7 +894,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
|
||||
(void)Curl_altsvc_load(outcurl->asi, outcurl->set.str[STRING_ALTSVC]);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_HSTS
|
||||
#ifndef CURL_DISABLE_HSTS
|
||||
if(data->hsts) {
|
||||
outcurl->hsts = Curl_hsts_init();
|
||||
if(!outcurl->hsts)
|
||||
@@ -947,12 +946,12 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
|
||||
fail:
|
||||
|
||||
if(outcurl) {
|
||||
curl_slist_free_all(outcurl->change.cookielist);
|
||||
outcurl->change.cookielist = NULL;
|
||||
curl_slist_free_all(outcurl->state.cookielist);
|
||||
outcurl->state.cookielist = NULL;
|
||||
Curl_safefree(outcurl->state.buffer);
|
||||
Curl_dyn_free(&outcurl->state.headerb);
|
||||
Curl_safefree(outcurl->change.url);
|
||||
Curl_safefree(outcurl->change.referer);
|
||||
Curl_safefree(outcurl->state.url);
|
||||
Curl_safefree(outcurl->state.referer);
|
||||
Curl_altsvc_cleanup(&outcurl->asi);
|
||||
Curl_hsts_cleanup(&outcurl->hsts);
|
||||
Curl_freeset(outcurl);
|
||||
@@ -1034,8 +1033,8 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
||||
|
||||
/* Unpause parts in active mime tree. */
|
||||
if((k->keepon & ~newstate & KEEP_SEND_PAUSE) &&
|
||||
(data->mstate == CURLM_STATE_PERFORM ||
|
||||
data->mstate == CURLM_STATE_TOOFAST) &&
|
||||
(data->mstate == MSTATE_PERFORMING ||
|
||||
data->mstate == MSTATE_RATELIMITING) &&
|
||||
data->state.fread_func == (curl_read_callback) Curl_mime_read) {
|
||||
Curl_mime_unpause(data->state.in);
|
||||
}
|
||||
@@ -1052,8 +1051,6 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
||||
unsigned int i;
|
||||
unsigned int count = data->state.tempcount;
|
||||
struct tempbuf writebuf[3]; /* there can only be three */
|
||||
struct connectdata *conn = data->conn;
|
||||
struct Curl_easy *saved_data = NULL;
|
||||
|
||||
/* copy the structs to allow for immediate re-pausing */
|
||||
for(i = 0; i < data->state.tempcount; i++) {
|
||||
@@ -1062,12 +1059,6 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
||||
}
|
||||
data->state.tempcount = 0;
|
||||
|
||||
/* set the connection's current owner */
|
||||
if(conn->data != data) {
|
||||
saved_data = conn->data;
|
||||
conn->data = data;
|
||||
}
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
/* even if one function returns error, this loops through and frees
|
||||
all buffers */
|
||||
@@ -1078,10 +1069,6 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
||||
Curl_dyn_free(&writebuf[i].b);
|
||||
}
|
||||
|
||||
/* recover previous owner of the connection */
|
||||
if(saved_data)
|
||||
conn->data = saved_data;
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@@ -1117,7 +1104,7 @@ static CURLcode easy_connection(struct Curl_easy *data,
|
||||
curl_socket_t *sfd,
|
||||
struct connectdata **connp)
|
||||
{
|
||||
if(data == NULL)
|
||||
if(!data)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
/* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */
|
||||
@@ -1183,6 +1170,7 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
|
||||
CURLcode result;
|
||||
ssize_t n1;
|
||||
struct connectdata *c = NULL;
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
if(Curl_is_in_callback(data))
|
||||
return CURLE_RECURSIVE_API_CALL;
|
||||
@@ -1197,7 +1185,9 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
|
||||
Curl_attach_connnection(data, c);
|
||||
|
||||
*n = 0;
|
||||
sigpipe_ignore(data, &pipe_st);
|
||||
result = Curl_write(data, sfd, buffer, buflen, &n1);
|
||||
sigpipe_restore(&pipe_st);
|
||||
|
||||
if(n1 == -1)
|
||||
return CURLE_SEND_ERROR;
|
||||
|
||||
@@ -38,6 +38,7 @@ struct curl_easyoption Curl_easyopts[] = {
|
||||
{"AWS_SIGV4", CURLOPT_AWS_SIGV4, CURLOT_STRING, 0},
|
||||
{"BUFFERSIZE", CURLOPT_BUFFERSIZE, CURLOT_LONG, 0},
|
||||
{"CAINFO", CURLOPT_CAINFO, CURLOT_STRING, 0},
|
||||
{"CAINFO_BLOB", CURLOPT_CAINFO_BLOB, CURLOT_BLOB, 0},
|
||||
{"CAPATH", CURLOPT_CAPATH, CURLOT_STRING, 0},
|
||||
{"CERTINFO", CURLOPT_CERTINFO, CURLOT_LONG, 0},
|
||||
{"CHUNK_BGN_FUNCTION", CURLOPT_CHUNK_BGN_FUNCTION, CURLOT_FUNCTION, 0},
|
||||
@@ -78,6 +79,9 @@ struct curl_easyoption Curl_easyopts[] = {
|
||||
{"DNS_SERVERS", CURLOPT_DNS_SERVERS, CURLOT_STRING, 0},
|
||||
{"DNS_SHUFFLE_ADDRESSES", CURLOPT_DNS_SHUFFLE_ADDRESSES, CURLOT_LONG, 0},
|
||||
{"DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOT_LONG, 0},
|
||||
{"DOH_SSL_VERIFYHOST", CURLOPT_DOH_SSL_VERIFYHOST, CURLOT_LONG, 0},
|
||||
{"DOH_SSL_VERIFYPEER", CURLOPT_DOH_SSL_VERIFYPEER, CURLOT_LONG, 0},
|
||||
{"DOH_SSL_VERIFYSTATUS", CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOT_LONG, 0},
|
||||
{"DOH_URL", CURLOPT_DOH_URL, CURLOT_STRING, 0},
|
||||
{"EGDSOCKET", CURLOPT_EGDSOCKET, CURLOT_STRING, 0},
|
||||
{"ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, CURLOT_FLAG_ALIAS},
|
||||
@@ -202,6 +206,7 @@ struct curl_easyoption Curl_easyopts[] = {
|
||||
{"PROXYUSERNAME", CURLOPT_PROXYUSERNAME, CURLOT_STRING, 0},
|
||||
{"PROXYUSERPWD", CURLOPT_PROXYUSERPWD, CURLOT_STRING, 0},
|
||||
{"PROXY_CAINFO", CURLOPT_PROXY_CAINFO, CURLOT_STRING, 0},
|
||||
{"PROXY_CAINFO_BLOB", CURLOPT_PROXY_CAINFO_BLOB, CURLOT_BLOB, 0},
|
||||
{"PROXY_CAPATH", CURLOPT_PROXY_CAPATH, CURLOT_STRING, 0},
|
||||
{"PROXY_CRLFILE", CURLOPT_PROXY_CRLFILE, CURLOT_STRING, 0},
|
||||
{"PROXY_ISSUERCERT", CURLOPT_PROXY_ISSUERCERT, CURLOT_STRING, 0},
|
||||
@@ -349,6 +354,6 @@ struct curl_easyoption Curl_easyopts[] = {
|
||||
*/
|
||||
int Curl_easyopts_check(void)
|
||||
{
|
||||
return ((CURLOPT_LASTENTRY%10000) != (305 + 1));
|
||||
return ((CURLOPT_LASTENTRY%10000) != (310 + 1));
|
||||
}
|
||||
#endif
|
||||
|
||||
+24
-16
@@ -111,6 +111,7 @@ const struct Curl_handler Curl_handler_file = {
|
||||
file_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
0, /* defport */
|
||||
CURLPROTO_FILE, /* protocol */
|
||||
CURLPROTO_FILE, /* family */
|
||||
@@ -410,19 +411,21 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
|
||||
struct tm buffer;
|
||||
const struct tm *tm = &buffer;
|
||||
char header[80];
|
||||
int headerlen;
|
||||
char accept_ranges[24]= { "Accept-ranges: bytes\r\n" };
|
||||
if(expected_size >= 0) {
|
||||
msnprintf(header, sizeof(header),
|
||||
headerlen = msnprintf(header, sizeof(header),
|
||||
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
|
||||
expected_size);
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0);
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER, header, headerlen);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER,
|
||||
(char *)"Accept-ranges: bytes\r\n", 0);
|
||||
if(result)
|
||||
return result;
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER,
|
||||
accept_ranges, strlen(accept_ranges));
|
||||
if(result != CURLE_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
filetime = (time_t)statbuf.st_mtime;
|
||||
result = Curl_gmtime(filetime, &buffer);
|
||||
@@ -430,7 +433,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
|
||||
return result;
|
||||
|
||||
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
|
||||
msnprintf(header, sizeof(header),
|
||||
headerlen = msnprintf(header, sizeof(header),
|
||||
"Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
|
||||
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
|
||||
tm->tm_mday,
|
||||
@@ -440,7 +443,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
|
||||
tm->tm_min,
|
||||
tm->tm_sec,
|
||||
data->set.opt_no_body ? "": "\r\n");
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0);
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER, header, headerlen);
|
||||
if(result)
|
||||
return result;
|
||||
/* set the file size to make it available post transfer */
|
||||
@@ -464,18 +467,23 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
|
||||
data->state.resume_from += (curl_off_t)statbuf.st_size;
|
||||
}
|
||||
|
||||
if(data->state.resume_from <= expected_size)
|
||||
expected_size -= data->state.resume_from;
|
||||
else {
|
||||
failf(data, "failed to resume file:// transfer");
|
||||
return CURLE_BAD_DOWNLOAD_RESUME;
|
||||
if(data->state.resume_from > 0) {
|
||||
/* We check explicitly if we have a start offset, because
|
||||
* expected_size may be -1 if we don't know how large the file is,
|
||||
* in which case we should not adjust it. */
|
||||
if(data->state.resume_from <= expected_size)
|
||||
expected_size -= data->state.resume_from;
|
||||
else {
|
||||
failf(data, "failed to resume file:// transfer");
|
||||
return CURLE_BAD_DOWNLOAD_RESUME;
|
||||
}
|
||||
}
|
||||
|
||||
/* A high water mark has been specified so we obey... */
|
||||
if(data->req.maxdownload > 0)
|
||||
expected_size = data->req.maxdownload;
|
||||
|
||||
if(!fstated || (expected_size == 0))
|
||||
if(!fstated || (expected_size <= 0))
|
||||
size_known = FALSE;
|
||||
else
|
||||
size_known = TRUE;
|
||||
@@ -484,7 +492,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
|
||||
this is both more efficient than the former call to download() and
|
||||
it avoids problems with select() and recv() on file descriptors
|
||||
in Winsock */
|
||||
if(fstated)
|
||||
if(size_known)
|
||||
Curl_pgrsSetDownloadSize(data, expected_size);
|
||||
|
||||
if(data->state.resume_from) {
|
||||
|
||||
+70
-51
@@ -175,6 +175,7 @@ const struct Curl_handler Curl_handler_ftp = {
|
||||
ftp_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_FTP, /* defport */
|
||||
CURLPROTO_FTP, /* protocol */
|
||||
CURLPROTO_FTP, /* family */
|
||||
@@ -205,6 +206,7 @@ const struct Curl_handler Curl_handler_ftps = {
|
||||
ftp_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_FTPS, /* defport */
|
||||
CURLPROTO_FTPS, /* protocol */
|
||||
CURLPROTO_FTP, /* family */
|
||||
@@ -1090,7 +1092,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
||||
else
|
||||
res = NULL; /* failure! */
|
||||
|
||||
if(res == NULL) {
|
||||
if(!res) {
|
||||
failf(data, "failed to resolve the address provided to PORT: %s", host);
|
||||
free(addr);
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
@@ -1357,7 +1359,7 @@ static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data)
|
||||
struct FTP *ftp = data->req.p.ftp;
|
||||
struct connectdata *conn = data->conn;
|
||||
|
||||
if(ftp->transfer != FTPTRANSFER_BODY) {
|
||||
if(ftp->transfer != PPTRANSFER_BODY) {
|
||||
/* doesn't transfer any data */
|
||||
|
||||
/* still possibly do PRE QUOTE jobs */
|
||||
@@ -1378,7 +1380,7 @@ static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data)
|
||||
result = Curl_pp_sendf(data, &ftpc->pp, "PRET %s",
|
||||
data->set.str[STRING_CUSTOMREQUEST]?
|
||||
data->set.str[STRING_CUSTOMREQUEST]:
|
||||
(data->set.ftp_list_only?"NLST":"LIST"));
|
||||
(data->state.list_only?"NLST":"LIST"));
|
||||
else if(data->set.upload)
|
||||
result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s",
|
||||
conn->proto.ftpc.file);
|
||||
@@ -1401,7 +1403,7 @@ static CURLcode ftp_state_rest(struct Curl_easy *data,
|
||||
struct FTP *ftp = data->req.p.ftp;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
|
||||
if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) {
|
||||
if((ftp->transfer != PPTRANSFER_BODY) && ftpc->file) {
|
||||
/* if a "head"-like request is being made (on a file) */
|
||||
|
||||
/* Determine if server can respond to REST command and therefore
|
||||
@@ -1423,7 +1425,7 @@ static CURLcode ftp_state_size(struct Curl_easy *data,
|
||||
struct FTP *ftp = data->req.p.ftp;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
|
||||
if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) {
|
||||
if((ftp->transfer == PPTRANSFER_INFO) && ftpc->file) {
|
||||
/* if a "head"-like request is being made (on a file) */
|
||||
|
||||
/* we know ftpc->file is a valid pointer to a file name */
|
||||
@@ -1485,7 +1487,7 @@ static CURLcode ftp_state_list(struct Curl_easy *data)
|
||||
cmd = aprintf("%s%s%s",
|
||||
data->set.str[STRING_CUSTOMREQUEST]?
|
||||
data->set.str[STRING_CUSTOMREQUEST]:
|
||||
(data->set.ftp_list_only?"NLST":"LIST"),
|
||||
(data->state.list_only?"NLST":"LIST"),
|
||||
lstArg? " ": "",
|
||||
lstArg? lstArg: "");
|
||||
free(lstArg);
|
||||
@@ -1525,17 +1527,17 @@ static CURLcode ftp_state_type(struct Curl_easy *data)
|
||||
information. Which in FTP can't be much more than the file size and
|
||||
date. */
|
||||
if(data->set.opt_no_body && ftpc->file &&
|
||||
ftp_need_type(conn, data->set.prefer_ascii)) {
|
||||
ftp_need_type(conn, data->state.prefer_ascii)) {
|
||||
/* The SIZE command is _not_ RFC 959 specified, and therefore many servers
|
||||
may not support it! It is however the only way we have to get a file's
|
||||
size! */
|
||||
|
||||
ftp->transfer = FTPTRANSFER_INFO;
|
||||
ftp->transfer = PPTRANSFER_INFO;
|
||||
/* this means no actual transfer will be made */
|
||||
|
||||
/* Some servers return different sizes for different modes, and thus we
|
||||
must set the proper type before we check the size */
|
||||
result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_TYPE);
|
||||
result = ftp_nb_type(data, conn, data->state.prefer_ascii, FTP_TYPE);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@@ -1578,6 +1580,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
|
||||
struct connectdata *conn = data->conn;
|
||||
struct FTP *ftp = data->req.p.ftp;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
bool append = data->set.remote_append;
|
||||
|
||||
if((data->state.resume_from && !sizechecked) ||
|
||||
((data->state.resume_from > 0) && sizechecked)) {
|
||||
@@ -1604,7 +1607,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
/* enable append */
|
||||
data->set.ftp_append = TRUE;
|
||||
append = TRUE;
|
||||
|
||||
/* Let's read off the proper amount of bytes from the input. */
|
||||
if(conn->seek_func) {
|
||||
@@ -1652,7 +1655,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
|
||||
|
||||
/* Set ->transfer so that we won't get any error in
|
||||
* ftp_done() because we didn't transfer anything! */
|
||||
ftp->transfer = FTPTRANSFER_NONE;
|
||||
ftp->transfer = PPTRANSFER_NONE;
|
||||
|
||||
state(data, FTP_STOP);
|
||||
return CURLE_OK;
|
||||
@@ -1661,8 +1664,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
|
||||
/* we've passed, proceed as normal */
|
||||
} /* resume_from */
|
||||
|
||||
result = Curl_pp_sendf(data, &ftpc->pp,
|
||||
data->set.ftp_append?"APPE %s":"STOR %s",
|
||||
result = Curl_pp_sendf(data, &ftpc->pp, append?"APPE %s":"STOR %s",
|
||||
ftpc->file);
|
||||
if(!result)
|
||||
state(data, FTP_STOR);
|
||||
@@ -1739,7 +1741,7 @@ static CURLcode ftp_state_quote(struct Curl_easy *data,
|
||||
result = ftp_state_cwd(data, conn);
|
||||
break;
|
||||
case FTP_RETR_PREQUOTE:
|
||||
if(ftp->transfer != FTPTRANSFER_BODY)
|
||||
if(ftp->transfer != PPTRANSFER_BODY)
|
||||
state(data, FTP_STOP);
|
||||
else {
|
||||
if(ftpc->known_filesize != -1) {
|
||||
@@ -1747,13 +1749,19 @@ static CURLcode ftp_state_quote(struct Curl_easy *data,
|
||||
result = ftp_state_retr(data, ftpc->known_filesize);
|
||||
}
|
||||
else {
|
||||
if(data->set.ignorecl) {
|
||||
/* This code is to support download of growing files. It prevents
|
||||
the state machine from requesting the file size from the
|
||||
server. With an unknown file size the download continues until
|
||||
the server terminates it, otherwise the client stops if the
|
||||
received byte count exceeds the reported file size. Set option
|
||||
CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/
|
||||
if(data->set.ignorecl || data->state.prefer_ascii) {
|
||||
/* 'ignorecl' is used to support download of growing files. It
|
||||
prevents the state machine from requesting the file size from
|
||||
the server. With an unknown file size the download continues
|
||||
until the server terminates it, otherwise the client stops if
|
||||
the received byte count exceeds the reported file size. Set
|
||||
option CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this
|
||||
behavior.
|
||||
|
||||
In addition: asking for the size for 'TYPE A' transfers is not
|
||||
constructive since servers don't report the converted size. So
|
||||
skip it.
|
||||
*/
|
||||
result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
|
||||
if(!result)
|
||||
state(data, FTP_RETR);
|
||||
@@ -2092,6 +2100,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
|
||||
data->set.get_filetime &&
|
||||
(data->info.filetime >= 0) ) {
|
||||
char headerbuf[128];
|
||||
int headerbuflen;
|
||||
time_t filetime = data->info.filetime;
|
||||
struct tm buffer;
|
||||
const struct tm *tm = &buffer;
|
||||
@@ -2101,7 +2110,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
|
||||
return result;
|
||||
|
||||
/* format: "Tue, 15 Nov 1994 12:45:26" */
|
||||
msnprintf(headerbuf, sizeof(headerbuf),
|
||||
headerbuflen = msnprintf(headerbuf, sizeof(headerbuf),
|
||||
"Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
|
||||
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
|
||||
tm->tm_mday,
|
||||
@@ -2110,7 +2119,8 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
|
||||
tm->tm_hour,
|
||||
tm->tm_min,
|
||||
tm->tm_sec);
|
||||
result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf, 0);
|
||||
result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf,
|
||||
headerbuflen);
|
||||
if(result)
|
||||
return result;
|
||||
} /* end of a ridiculous amount of conditionals */
|
||||
@@ -2133,7 +2143,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
|
||||
default:
|
||||
if(data->info.filetime <= data->set.timevalue) {
|
||||
infof(data, "The requested document is not new enough\n");
|
||||
ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
|
||||
ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
|
||||
data->info.timecond = TRUE;
|
||||
state(data, FTP_STOP);
|
||||
return CURLE_OK;
|
||||
@@ -2142,7 +2152,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
|
||||
case CURL_TIMECOND_IFUNMODSINCE:
|
||||
if(data->info.filetime > data->set.timevalue) {
|
||||
infof(data, "The requested document is not old enough\n");
|
||||
ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
|
||||
ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
|
||||
data->info.timecond = TRUE;
|
||||
state(data, FTP_STOP);
|
||||
return CURLE_OK;
|
||||
@@ -2250,7 +2260,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
|
||||
|
||||
/* Set ->transfer so that we won't get any error in ftp_done()
|
||||
* because we didn't transfer the any file */
|
||||
ftp->transfer = FTPTRANSFER_NONE;
|
||||
ftp->transfer = PPTRANSFER_NONE;
|
||||
state(data, FTP_STOP);
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -2303,17 +2313,21 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
|
||||
|
||||
}
|
||||
else if(ftpcode == 550) { /* "No such file or directory" */
|
||||
failf(data, "The file does not exist");
|
||||
return CURLE_REMOTE_FILE_NOT_FOUND;
|
||||
/* allow a SIZE failure for (resumed) uploads, when probing what command
|
||||
to use */
|
||||
if(instate != FTP_STOR_SIZE) {
|
||||
failf(data, "The file does not exist");
|
||||
return CURLE_REMOTE_FILE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
if(instate == FTP_SIZE) {
|
||||
#ifdef CURL_FTP_HTTPSTYLE_HEAD
|
||||
if(-1 != filesize) {
|
||||
char clbuf[128];
|
||||
msnprintf(clbuf, sizeof(clbuf),
|
||||
int clbuflen = msnprintf(clbuf, sizeof(clbuf),
|
||||
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
|
||||
result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, 0);
|
||||
result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, clbuflen);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@@ -2347,7 +2361,8 @@ static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
|
||||
#ifdef CURL_FTP_HTTPSTYLE_HEAD
|
||||
if(ftpcode == 350) {
|
||||
char buffer[24]= { "Accept-ranges: bytes\r\n" };
|
||||
result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer, 0);
|
||||
result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer,
|
||||
strlen(buffer));
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@@ -2448,7 +2463,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
|
||||
*/
|
||||
|
||||
if((instate != FTP_LIST) &&
|
||||
!data->set.prefer_ascii &&
|
||||
!data->state.prefer_ascii &&
|
||||
(ftp->downloadsize < 1)) {
|
||||
/*
|
||||
* It seems directory listings either don't show the size or very
|
||||
@@ -2476,7 +2491,8 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
|
||||
bytes--;
|
||||
}
|
||||
/* if we have nothing but digits: */
|
||||
if(bytes++) {
|
||||
if(bytes) {
|
||||
++bytes;
|
||||
/* get the number! */
|
||||
(void)curlx_strtoofft(bytes, NULL, 0, &size);
|
||||
}
|
||||
@@ -2487,7 +2503,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
|
||||
|
||||
if(size > data->req.maxdownload && data->req.maxdownload > 0)
|
||||
size = data->req.size = data->req.maxdownload;
|
||||
else if((instate != FTP_LIST) && (data->set.prefer_ascii))
|
||||
else if((instate != FTP_LIST) && (data->state.prefer_ascii))
|
||||
size = -1; /* kludge for servers that understate ASCII mode file size */
|
||||
|
||||
infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n",
|
||||
@@ -2521,7 +2537,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
|
||||
else {
|
||||
if((instate == FTP_LIST) && (ftpcode == 450)) {
|
||||
/* simply no matching files in the dir listing */
|
||||
ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */
|
||||
ftp->transfer = PPTRANSFER_NONE; /* don't download anything */
|
||||
state(data, FTP_STOP); /* this phase is over */
|
||||
}
|
||||
else {
|
||||
@@ -3291,7 +3307,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
|
||||
close_secondarysocket(data, conn);
|
||||
}
|
||||
|
||||
if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid &&
|
||||
if(!result && (ftp->transfer == PPTRANSFER_BODY) && ftpc->ctl_valid &&
|
||||
pp->pending_resp && !premature) {
|
||||
/*
|
||||
* Let's see what the server says about the transfer we just performed,
|
||||
@@ -3314,8 +3330,10 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
|
||||
connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */
|
||||
}
|
||||
|
||||
if(result)
|
||||
if(result) {
|
||||
Curl_safefree(ftp->pathalloc);
|
||||
return result;
|
||||
}
|
||||
|
||||
if(ftpc->dont_check && data->req.maxdownload > 0) {
|
||||
/* we have just sent ABOR and there is no reliable way to check if it was
|
||||
@@ -3351,7 +3369,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
|
||||
if((-1 != data->state.infilesize) &&
|
||||
(data->state.infilesize != data->req.writebytecount) &&
|
||||
!data->set.crlf &&
|
||||
(ftp->transfer == FTPTRANSFER_BODY)) {
|
||||
(ftp->transfer == PPTRANSFER_BODY)) {
|
||||
failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
|
||||
" out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
|
||||
data->req.bytecount, data->state.infilesize);
|
||||
@@ -3383,7 +3401,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
|
||||
}
|
||||
|
||||
/* clear these for next connection */
|
||||
ftp->transfer = FTPTRANSFER_BODY;
|
||||
ftp->transfer = PPTRANSFER_BODY;
|
||||
ftpc->dont_check = FALSE;
|
||||
|
||||
/* Send any post-transfer QUOTE strings? */
|
||||
@@ -3594,7 +3612,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
|
||||
*completep = 0;
|
||||
}
|
||||
|
||||
if(ftp->transfer <= FTPTRANSFER_INFO) {
|
||||
if(ftp->transfer <= PPTRANSFER_INFO) {
|
||||
/* a transfer is about to take place, or if not a file name was given
|
||||
so we'll do a SIZE on it later and then we need the right TYPE first */
|
||||
|
||||
@@ -3620,7 +3638,8 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
|
||||
}
|
||||
}
|
||||
else if(data->set.upload) {
|
||||
result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_STOR_TYPE);
|
||||
result = ftp_nb_type(data, conn, data->state.prefer_ascii,
|
||||
FTP_STOR_TYPE);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
@@ -3641,13 +3660,13 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
|
||||
|
||||
if(result)
|
||||
;
|
||||
else if(data->set.ftp_list_only || !ftpc->file) {
|
||||
else if(data->state.list_only || !ftpc->file) {
|
||||
/* The specified path ends with a slash, and therefore we think this
|
||||
is a directory that is requested, use LIST. But before that we
|
||||
need to set ASCII transfer mode. */
|
||||
|
||||
/* But only if a body transfer was requested. */
|
||||
if(ftp->transfer == FTPTRANSFER_BODY) {
|
||||
if(ftp->transfer == PPTRANSFER_BODY) {
|
||||
result = ftp_nb_type(data, conn, TRUE, FTP_LIST_TYPE);
|
||||
if(result)
|
||||
return result;
|
||||
@@ -3655,7 +3674,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
|
||||
/* otherwise just fall through */
|
||||
}
|
||||
else {
|
||||
result = ftp_nb_type(data, conn, data->set.prefer_ascii,
|
||||
result = ftp_nb_type(data, conn, data->state.prefer_ascii,
|
||||
FTP_RETR_TYPE);
|
||||
if(result)
|
||||
return result;
|
||||
@@ -3703,7 +3722,7 @@ CURLcode ftp_perform(struct Curl_easy *data,
|
||||
if(data->set.opt_no_body) {
|
||||
/* requested no body means no transfer... */
|
||||
struct FTP *ftp = data->req.p.ftp;
|
||||
ftp->transfer = FTPTRANSFER_INFO;
|
||||
ftp->transfer = PPTRANSFER_INFO;
|
||||
}
|
||||
|
||||
*dophase_done = FALSE; /* not done yet */
|
||||
@@ -4194,7 +4213,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
|
||||
ftpc->file = NULL; /* instead of point to a zero byte,
|
||||
we make it a NULL pointer */
|
||||
|
||||
if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) {
|
||||
if(data->set.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) {
|
||||
/* We need a file name when uploading. Return error! */
|
||||
failf(data, "Uploading to a URL without a file name!");
|
||||
free(rawPath);
|
||||
@@ -4242,7 +4261,7 @@ static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)
|
||||
}
|
||||
}
|
||||
|
||||
if(ftp->transfer != FTPTRANSFER_BODY)
|
||||
if(ftp->transfer != PPTRANSFER_BODY)
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
else if(!connected)
|
||||
@@ -4346,23 +4365,23 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
|
||||
|
||||
switch(command) {
|
||||
case 'A': /* ASCII mode */
|
||||
data->set.prefer_ascii = TRUE;
|
||||
data->state.prefer_ascii = TRUE;
|
||||
break;
|
||||
|
||||
case 'D': /* directory mode */
|
||||
data->set.ftp_list_only = TRUE;
|
||||
data->state.list_only = TRUE;
|
||||
break;
|
||||
|
||||
case 'I': /* binary mode */
|
||||
default:
|
||||
/* switch off ASCII */
|
||||
data->set.prefer_ascii = FALSE;
|
||||
data->state.prefer_ascii = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* get some initial data into the ftp struct */
|
||||
ftp->transfer = FTPTRANSFER_BODY;
|
||||
ftp->transfer = PPTRANSFER_BODY;
|
||||
ftp->downloadsize = 0;
|
||||
conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
|
||||
|
||||
|
||||
@@ -424,7 +424,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
endptr++;
|
||||
while(ISDIGIT(*endptr))
|
||||
endptr++;
|
||||
if(*endptr != 0) {
|
||||
if(*endptr) {
|
||||
parser->error = CURLE_FTP_BAD_FILE_LIST;
|
||||
goto fail;
|
||||
}
|
||||
@@ -966,7 +966,6 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
else if(c == '\n') {
|
||||
parser->offsets.filename = parser->item_offset;
|
||||
finfo->b_data[finfo->b_used - 1] = 0;
|
||||
parser->offsets.filename = parser->item_offset;
|
||||
result = ftp_pl_insert_finfo(data, infop);
|
||||
if(result) {
|
||||
parser->error = result;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -94,7 +94,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
|
||||
{
|
||||
switch(info) {
|
||||
case CURLINFO_EFFECTIVE_URL:
|
||||
*param_charp = data->change.url?data->change.url:(char *)"";
|
||||
*param_charp = data->state.url?data->state.url:(char *)"";
|
||||
break;
|
||||
case CURLINFO_EFFECTIVE_METHOD: {
|
||||
const char *m = data->set.str[STRING_CUSTOMREQUEST];
|
||||
@@ -145,6 +145,10 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
|
||||
option had been enabled! */
|
||||
*param_charp = data->info.wouldredirect;
|
||||
break;
|
||||
case CURLINFO_REFERER:
|
||||
/* Return the referrer header for this request, or NULL if unset */
|
||||
*param_charp = data->state.referer;
|
||||
break;
|
||||
case CURLINFO_PRIMARY_IP:
|
||||
/* Return the ip address of the most recent (primary) connection */
|
||||
*param_charp = data->info.conn_primary_ip;
|
||||
@@ -235,7 +239,7 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
|
||||
break;
|
||||
#endif
|
||||
case CURLINFO_REDIRECT_COUNT:
|
||||
*param_longp = data->set.followlocation;
|
||||
*param_longp = data->state.followlocation;
|
||||
break;
|
||||
case CURLINFO_HTTPAUTH_AVAIL:
|
||||
lptr.to_long = param_longp;
|
||||
|
||||
@@ -74,6 +74,7 @@ const struct Curl_handler Curl_handler_gopher = {
|
||||
ZERO_NULL, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_GOPHER, /* defport */
|
||||
CURLPROTO_GOPHER, /* protocol */
|
||||
CURLPROTO_GOPHER, /* family */
|
||||
@@ -97,6 +98,7 @@ const struct Curl_handler Curl_handler_gophers = {
|
||||
ZERO_NULL, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_GOPHER, /* defport */
|
||||
CURLPROTO_GOPHERS, /* protocol */
|
||||
CURLPROTO_GOPHER, /* family */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -245,7 +245,7 @@ Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user,
|
||||
struct Curl_hash_element *he = le->ptr;
|
||||
lnext = le->next;
|
||||
/* ask the callback function if we shall remove this entry or not */
|
||||
if(comp == NULL || comp(user, he->ptr)) {
|
||||
if(!comp || comp(user, he->ptr)) {
|
||||
Curl_llist_remove(list, le, (void *) h);
|
||||
--h->size; /* one less entry in the hash now */
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -81,7 +81,7 @@ static int hostmatch(char *hostname, char *pattern)
|
||||
pattern[len-1] = 0;
|
||||
|
||||
pattern_wildcard = strchr(pattern, '*');
|
||||
if(pattern_wildcard == NULL)
|
||||
if(!pattern_wildcard)
|
||||
return strcasecompare(pattern, hostname) ?
|
||||
CURL_HOST_MATCH : CURL_HOST_NOMATCH;
|
||||
|
||||
@@ -97,7 +97,7 @@ static int hostmatch(char *hostname, char *pattern)
|
||||
match. */
|
||||
wildcard_enabled = 1;
|
||||
pattern_label_end = strchr(pattern, '.');
|
||||
if(pattern_label_end == NULL || strchr(pattern_label_end + 1, '.') == NULL ||
|
||||
if(!pattern_label_end || strchr(pattern_label_end + 1, '.') == NULL ||
|
||||
pattern_wildcard > pattern_label_end ||
|
||||
strncasecompare(pattern, "xn--", 4)) {
|
||||
wildcard_enabled = 0;
|
||||
@@ -107,7 +107,7 @@ static int hostmatch(char *hostname, char *pattern)
|
||||
CURL_HOST_MATCH : CURL_HOST_NOMATCH;
|
||||
|
||||
hostname_label_end = strchr(hostname, '.');
|
||||
if(hostname_label_end == NULL ||
|
||||
if(!hostname_label_end ||
|
||||
!strcasecompare(pattern_label_end, hostname_label_end))
|
||||
return CURL_HOST_NOMATCH;
|
||||
|
||||
|
||||
@@ -68,6 +68,10 @@
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
|
||||
#include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
|
||||
#endif
|
||||
|
||||
#if defined(CURLRES_SYNCH) && \
|
||||
defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP)
|
||||
/* alarm-based timeouts can only be used with all the dependencies satisfied */
|
||||
@@ -269,7 +273,7 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
|
||||
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
|
||||
|
||||
/* No entry found in cache, check if we might have a wildcard entry */
|
||||
if(!dns && data->change.wildcard_resolve) {
|
||||
if(!dns && data->state.wildcard_resolve) {
|
||||
create_hostcache_id("*", port, entry_id, sizeof(entry_id));
|
||||
entry_len = strlen(entry_id);
|
||||
|
||||
@@ -466,10 +470,6 @@ Curl_cache_addr(struct Curl_easy *data,
|
||||
* function is used. You MUST call Curl_resolv_unlock() later (when you're
|
||||
* done using this struct) to decrease the counter again.
|
||||
*
|
||||
* In debug mode, we specifically test for an interface name "LocalHost"
|
||||
* and resolve "localhost" instead as a means to permit test cases
|
||||
* to connect to a local test server with any host name.
|
||||
*
|
||||
* Return codes:
|
||||
*
|
||||
* CURLRESOLV_ERROR (-1) = error, no pointer
|
||||
@@ -520,13 +520,32 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
|
||||
if(data->set.resolver_start) {
|
||||
int st;
|
||||
Curl_set_in_callback(data, true);
|
||||
st = data->set.resolver_start(data->state.async.resolver, NULL,
|
||||
data->set.resolver_start_client);
|
||||
st = data->set.resolver_start(
|
||||
#ifdef USE_CURL_ASYNC
|
||||
data->state.async.resolver,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
NULL,
|
||||
data->set.resolver_start_client);
|
||||
Curl_set_in_callback(data, false);
|
||||
if(st)
|
||||
return CURLRESOLV_ERROR;
|
||||
}
|
||||
|
||||
#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
|
||||
/*
|
||||
* The automagic conversion from IPv4 literals to IPv6 literals only works
|
||||
* if the SCDynamicStoreCopyProxies system function gets called first. As
|
||||
* Curl currently doesn't support system-wide HTTP proxies, we therefore
|
||||
* don't use any value this function might return.
|
||||
*
|
||||
* This function is only available on a macOS and is not needed for
|
||||
* IPv4-only builds, hence the conditions above.
|
||||
*/
|
||||
SCDynamicStoreCopyProxies(NULL);
|
||||
#endif
|
||||
|
||||
#ifndef USE_RESOLVE_ON_IPS
|
||||
/* First check if this is an IPv4 address string */
|
||||
if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
|
||||
@@ -572,13 +591,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
|
||||
/* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
|
||||
non-zero value indicating that we need to wait for the response to
|
||||
the resolve call */
|
||||
addr = Curl_getaddrinfo(data,
|
||||
#ifdef DEBUGBUILD
|
||||
(data->set.str[STRING_DEVICE]
|
||||
&& !strcmp(data->set.str[STRING_DEVICE],
|
||||
"LocalHost"))?"localhost":
|
||||
#endif
|
||||
hostname, port, &respwait);
|
||||
addr = Curl_getaddrinfo(data, hostname, port, &respwait);
|
||||
}
|
||||
}
|
||||
if(!addr) {
|
||||
@@ -625,7 +638,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
|
||||
* within a signal handler which is nonportable and could lead to problems.
|
||||
*/
|
||||
static
|
||||
RETSIGTYPE alarmfunc(int sig)
|
||||
void alarmfunc(int sig)
|
||||
{
|
||||
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
|
||||
(void)sig;
|
||||
@@ -872,9 +885,9 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
|
||||
int port = 0;
|
||||
|
||||
/* Default is no wildcard found */
|
||||
data->change.wildcard_resolve = false;
|
||||
data->state.wildcard_resolve = false;
|
||||
|
||||
for(hostp = data->change.resolve; hostp; hostp = hostp->next) {
|
||||
for(hostp = data->state.resolve; hostp; hostp = hostp->next) {
|
||||
char entry_id[MAX_HOSTCACHE_LEN];
|
||||
if(!hostp->data)
|
||||
continue;
|
||||
@@ -1055,11 +1068,11 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
|
||||
if(hostname[0] == '*' && hostname[1] == '\0') {
|
||||
infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks\n",
|
||||
hostname, port);
|
||||
data->change.wildcard_resolve = true;
|
||||
data->state.wildcard_resolve = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
data->change.resolve = NULL; /* dealt with now */
|
||||
data->state.resolve = NULL; /* dealt with now */
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -1102,10 +1115,12 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
|
||||
CURLcode result;
|
||||
struct connectdata *conn = data->conn;
|
||||
|
||||
#ifdef USE_CURL_ASYNC
|
||||
if(data->state.async.dns) {
|
||||
conn->dns_entry = data->state.async.dns;
|
||||
data->state.async.dns = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
result = Curl_setup_conn(data, protocol_done);
|
||||
|
||||
@@ -1116,3 +1131,34 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_resolver_error() calls failf() with the appropriate message after a
|
||||
* resolve error
|
||||
*/
|
||||
|
||||
#ifdef USE_CURL_ASYNC
|
||||
CURLcode Curl_resolver_error(struct Curl_easy *data)
|
||||
{
|
||||
const char *host_or_proxy;
|
||||
CURLcode result;
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
struct connectdata *conn = data->conn;
|
||||
if(conn->bits.httpproxy) {
|
||||
host_or_proxy = "proxy";
|
||||
result = CURLE_COULDNT_RESOLVE_PROXY;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
host_or_proxy = "host";
|
||||
result = CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
|
||||
failf(data, "Could not resolve %s: %s", host_or_proxy,
|
||||
data->state.async.hostname);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif /* USE_CURL_ASYNC */
|
||||
|
||||
@@ -136,15 +136,6 @@ void Curl_hostcache_prune(struct Curl_easy *data);
|
||||
/* Return # of addresses in a Curl_addrinfo struct */
|
||||
int Curl_num_addresses(const struct Curl_addrinfo *addr);
|
||||
|
||||
#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
|
||||
int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
|
||||
GETNAMEINFO_TYPE_ARG2 salen,
|
||||
char *host, GETNAMEINFO_TYPE_ARG46 hostlen,
|
||||
char *serv, GETNAMEINFO_TYPE_ARG46 servlen,
|
||||
GETNAMEINFO_TYPE_ARG7 flags,
|
||||
int line, const char *source);
|
||||
#endif
|
||||
|
||||
/* IPv4 threadsafe resolve function used for synch and asynch builds */
|
||||
struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
|
||||
|
||||
@@ -245,4 +236,5 @@ CURLcode Curl_resolv_check(struct Curl_easy *data,
|
||||
int Curl_resolv_getsock(struct Curl_easy *data,
|
||||
curl_socket_t *socks);
|
||||
|
||||
CURLcode Curl_resolver_error(struct Curl_easy *data);
|
||||
#endif /* HEADER_CURL_HOSTIP_H */
|
||||
|
||||
@@ -140,26 +140,13 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
|
||||
#ifndef USE_RESOLVE_ON_IPS
|
||||
char addrbuf[128];
|
||||
#endif
|
||||
int pf;
|
||||
int pf = PF_INET;
|
||||
|
||||
*waitp = 0; /* synchronous response only */
|
||||
|
||||
/* Check if a limited name resolve has been requested */
|
||||
switch(data->set.ipver) {
|
||||
case CURL_IPRESOLVE_V4:
|
||||
pf = PF_INET;
|
||||
break;
|
||||
case CURL_IPRESOLVE_V6:
|
||||
pf = PF_INET6;
|
||||
break;
|
||||
default:
|
||||
if(Curl_ipv6works(data))
|
||||
/* The stack seems to be IPv6-enabled */
|
||||
pf = PF_UNSPEC;
|
||||
break;
|
||||
}
|
||||
|
||||
if((pf != PF_INET) && !Curl_ipv6works(data))
|
||||
/* The stack seems to be a non-IPv6 one */
|
||||
pf = PF_INET;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = pf;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
*/
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS)
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS)
|
||||
#include <curl/curl.h>
|
||||
#include "urldata.h"
|
||||
#include "llist.h"
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "parsedate.h"
|
||||
#include "rand.h"
|
||||
#include "rename.h"
|
||||
#include "strtoofft.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
@@ -46,8 +47,6 @@
|
||||
#define MAX_HSTS_LINE 4095
|
||||
#define MAX_HSTS_HOSTLEN 256
|
||||
#define MAX_HSTS_HOSTLENSTR "256"
|
||||
#define MAX_HSTS_SUBLEN 4
|
||||
#define MAX_HSTS_SUBLENSTR "4"
|
||||
#define MAX_HSTS_DATELEN 64
|
||||
#define MAX_HSTS_DATELENSTR "64"
|
||||
|
||||
@@ -60,7 +59,10 @@ static time_t debugtime(void *unused)
|
||||
char *timestr = getenv("CURL_TIME");
|
||||
(void)unused;
|
||||
if(timestr) {
|
||||
unsigned long val = strtol(timestr, NULL, 10) + deltatime;
|
||||
curl_off_t val;
|
||||
(void)curlx_strtoofft(timestr, NULL, 10, &val);
|
||||
|
||||
val += (curl_off_t)deltatime;
|
||||
return (time_t)val;
|
||||
}
|
||||
return time(NULL);
|
||||
@@ -276,7 +278,7 @@ static CURLcode hsts_push(struct Curl_easy *data,
|
||||
e.namelen = strlen(sts->host);
|
||||
e.includeSubDomains = sts->includeSubDomains;
|
||||
|
||||
result = Curl_gmtime(sts->expires, &stamp);
|
||||
result = Curl_gmtime((time_t)sts->expires, &stamp);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
@@ -296,7 +298,7 @@ static CURLcode hsts_push(struct Curl_easy *data,
|
||||
static CURLcode hsts_out(struct stsentry *sts, FILE *fp)
|
||||
{
|
||||
struct tm stamp;
|
||||
CURLcode result = Curl_gmtime(sts->expires, &stamp);
|
||||
CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
@@ -441,7 +443,10 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
|
||||
expires = Curl_getdate_capped(e.expire);
|
||||
else
|
||||
expires = TIME_T_MAX; /* the end of time */
|
||||
result = hsts_create(h, e.name, e.includeSubDomains, expires);
|
||||
result = hsts_create(h, e.name,
|
||||
/* bitfield to bool conversion: */
|
||||
e.includeSubDomains ? TRUE : FALSE,
|
||||
expires);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@@ -519,4 +524,4 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h)
|
||||
return hsts_pull(data, h);
|
||||
}
|
||||
|
||||
#endif /* CURL_DISABLE_HTTP || USE_HSTS */
|
||||
#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2020 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -23,7 +23,7 @@
|
||||
***************************************************************************/
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS)
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS)
|
||||
#include <curl/curl.h>
|
||||
#include "llist.h"
|
||||
|
||||
@@ -35,7 +35,7 @@ struct stsentry {
|
||||
struct Curl_llist_element node;
|
||||
const char *host;
|
||||
bool includeSubDomains;
|
||||
time_t expires; /* the timestamp of this entry's expiry */
|
||||
curl_off_t expires; /* the timestamp of this entry's expiry */
|
||||
};
|
||||
|
||||
/* The HSTS cache. Needs to be able to tailmatch host names. */
|
||||
@@ -61,5 +61,5 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data,
|
||||
#define Curl_hsts_cleanup(x)
|
||||
#define Curl_hsts_loadcb(x,y)
|
||||
#define Curl_hsts_save(x,y,z)
|
||||
#endif /* CURL_DISABLE_HTTP || USE_HSTS */
|
||||
#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */
|
||||
#endif /* HEADER_CURL_HSTS_H */
|
||||
|
||||
+150
-71
@@ -133,6 +133,7 @@ const struct Curl_handler Curl_handler_http = {
|
||||
ZERO_NULL, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_HTTP, /* defport */
|
||||
CURLPROTO_HTTP, /* protocol */
|
||||
CURLPROTO_HTTP, /* family */
|
||||
@@ -160,6 +161,7 @@ const struct Curl_handler Curl_handler_https = {
|
||||
ZERO_NULL, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_HTTPS, /* defport */
|
||||
CURLPROTO_HTTPS, /* protocol */
|
||||
CURLPROTO_HTTP, /* family */
|
||||
@@ -183,7 +185,7 @@ static CURLcode http_setup_conn(struct Curl_easy *data,
|
||||
Curl_mime_initpart(&http->form, data);
|
||||
data->req.p.http = http;
|
||||
|
||||
if(data->set.httpversion == CURL_HTTP_VERSION_3) {
|
||||
if(data->state.httpwant == CURL_HTTP_VERSION_3) {
|
||||
if(conn->handler->flags & PROTOPT_SSL)
|
||||
/* Only go HTTP/3 directly on HTTPS URLs. It needs a UDP socket and does
|
||||
the QUIC dance. */
|
||||
@@ -298,26 +300,27 @@ static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
|
||||
{
|
||||
size_t size = 0;
|
||||
char *authorization = NULL;
|
||||
struct connectdata *conn = data->conn;
|
||||
char **userp;
|
||||
const char *user;
|
||||
const char *pwd;
|
||||
CURLcode result;
|
||||
char *out;
|
||||
|
||||
/* credentials are unique per transfer for HTTP, do not use the ones for the
|
||||
connection */
|
||||
if(proxy) {
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
userp = &data->state.aptr.proxyuserpwd;
|
||||
user = conn->http_proxy.user;
|
||||
pwd = conn->http_proxy.passwd;
|
||||
user = data->state.aptr.proxyuser;
|
||||
pwd = data->state.aptr.proxypasswd;
|
||||
#else
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
userp = &data->state.aptr.userpwd;
|
||||
user = conn->user;
|
||||
pwd = conn->passwd;
|
||||
user = data->state.aptr.user;
|
||||
pwd = data->state.aptr.passwd;
|
||||
}
|
||||
|
||||
out = aprintf("%s:%s", user, pwd ? pwd : "");
|
||||
@@ -595,7 +598,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
|
||||
conn->httpversion > 11) {
|
||||
infof(data, "Forcing HTTP/1.1 for NTLM");
|
||||
connclose(conn, "Force HTTP/1.1 connection");
|
||||
data->set.httpversion = CURL_HTTP_VERSION_1_1;
|
||||
data->state.httpwant = CURL_HTTP_VERSION_1_1;
|
||||
}
|
||||
}
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@@ -621,7 +624,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
|
||||
we must make sure to free it before allocating a new one. As figured
|
||||
out in bug #2284386 */
|
||||
Curl_safefree(data->req.newurl);
|
||||
data->req.newurl = strdup(data->change.url); /* clone URL */
|
||||
data->req.newurl = strdup(data->state.url); /* clone URL */
|
||||
if(!data->req.newurl)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -634,7 +637,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
|
||||
we didn't try HEAD or GET */
|
||||
if((data->state.httpreq != HTTPREQ_GET) &&
|
||||
(data->state.httpreq != HTTPREQ_HEAD)) {
|
||||
data->req.newurl = strdup(data->change.url); /* clone URL */
|
||||
data->req.newurl = strdup(data->state.url); /* clone URL */
|
||||
if(!data->req.newurl)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
data->state.authhost.done = TRUE;
|
||||
@@ -709,7 +712,6 @@ output_auth_headers(struct Curl_easy *data,
|
||||
if(authstatus->picked == CURLAUTH_DIGEST) {
|
||||
auth = "Digest";
|
||||
result = Curl_output_digest(data,
|
||||
conn,
|
||||
proxy,
|
||||
(const unsigned char *)request,
|
||||
(const unsigned char *)path);
|
||||
@@ -740,7 +742,7 @@ output_auth_headers(struct Curl_easy *data,
|
||||
if(authstatus->picked == CURLAUTH_BEARER) {
|
||||
/* Bearer */
|
||||
if((!proxy && data->set.str[STRING_BEARER] &&
|
||||
!Curl_checkheaders(data, "Authorization:"))) {
|
||||
!Curl_checkheaders(data, "Authorization"))) {
|
||||
auth = "Bearer";
|
||||
result = http_output_bearer(data);
|
||||
if(result)
|
||||
@@ -756,11 +758,14 @@ output_auth_headers(struct Curl_easy *data,
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
infof(data, "%s auth using %s with user '%s'\n",
|
||||
proxy ? "Proxy" : "Server", auth,
|
||||
proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") :
|
||||
(conn->user ? conn->user : ""));
|
||||
proxy ? (data->state.aptr.proxyuser ?
|
||||
data->state.aptr.proxyuser : "") :
|
||||
(data->state.aptr.user ?
|
||||
data->state.aptr.user : ""));
|
||||
#else
|
||||
infof(data, "Server auth using %s with user '%s'\n",
|
||||
auth, conn->user ? conn->user : "");
|
||||
auth, data->state.aptr.user ?
|
||||
data->state.aptr.user : "");
|
||||
#endif
|
||||
authstatus->multipass = (!authstatus->done) ? TRUE : FALSE;
|
||||
}
|
||||
@@ -871,13 +876,17 @@ Curl_http_output_auth(struct Curl_easy *data,
|
||||
#else
|
||||
/* when disabled */
|
||||
CURLcode
|
||||
Curl_http_output_auth(struct connectdata *conn,
|
||||
Curl_http_output_auth(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
const char *request,
|
||||
Curl_HttpReq httpreq,
|
||||
const char *path,
|
||||
bool proxytunnel)
|
||||
{
|
||||
(void)data;
|
||||
(void)conn;
|
||||
(void)request;
|
||||
(void)httpreq;
|
||||
(void)path;
|
||||
(void)proxytunnel;
|
||||
return CURLE_OK;
|
||||
@@ -890,6 +899,11 @@ Curl_http_output_auth(struct connectdata *conn,
|
||||
* proxy CONNECT loop.
|
||||
*/
|
||||
|
||||
static int is_valid_auth_separator(char ch)
|
||||
{
|
||||
return ch == '\0' || ch == ',' || ISSPACE(ch);
|
||||
}
|
||||
|
||||
CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
const char *auth) /* the first non-space */
|
||||
{
|
||||
@@ -933,7 +947,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
|
||||
while(*auth) {
|
||||
#ifdef USE_SPNEGO
|
||||
if(checkprefix("Negotiate", auth)) {
|
||||
if(checkprefix("Negotiate", auth) && is_valid_auth_separator(auth[9])) {
|
||||
if((authp->avail & CURLAUTH_NEGOTIATE) ||
|
||||
Curl_auth_is_spnego_supported()) {
|
||||
*availp |= CURLAUTH_NEGOTIATE;
|
||||
@@ -943,7 +957,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
CURLcode result = Curl_input_negotiate(data, conn, proxy, auth);
|
||||
if(!result) {
|
||||
DEBUGASSERT(!data->req.newurl);
|
||||
data->req.newurl = strdup(data->change.url);
|
||||
data->req.newurl = strdup(data->state.url);
|
||||
if(!data->req.newurl)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
data->state.authproblem = FALSE;
|
||||
@@ -959,7 +973,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
#endif
|
||||
#ifdef USE_NTLM
|
||||
/* NTLM support requires the SSL crypto libs */
|
||||
if(checkprefix("NTLM", auth)) {
|
||||
if(checkprefix("NTLM", auth) && is_valid_auth_separator(auth[4])) {
|
||||
if((authp->avail & CURLAUTH_NTLM) ||
|
||||
(authp->avail & CURLAUTH_NTLM_WB) ||
|
||||
Curl_auth_is_ntlm_supported()) {
|
||||
@@ -997,7 +1011,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
else
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
if(checkprefix("Digest", auth)) {
|
||||
if(checkprefix("Digest", auth) && is_valid_auth_separator(auth[6])) {
|
||||
if((authp->avail & CURLAUTH_DIGEST) != 0)
|
||||
infof(data, "Ignoring duplicate digest auth header.\n");
|
||||
else if(Curl_auth_is_digest_supported()) {
|
||||
@@ -1019,7 +1033,8 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(checkprefix("Basic", auth)) {
|
||||
if(checkprefix("Basic", auth) &&
|
||||
is_valid_auth_separator(auth[5])) {
|
||||
*availp |= CURLAUTH_BASIC;
|
||||
authp->avail |= CURLAUTH_BASIC;
|
||||
if(authp->picked == CURLAUTH_BASIC) {
|
||||
@@ -1032,7 +1047,8 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
}
|
||||
}
|
||||
else
|
||||
if(checkprefix("Bearer", auth)) {
|
||||
if(checkprefix("Bearer", auth) &&
|
||||
is_valid_auth_separator(auth[6])) {
|
||||
*availp |= CURLAUTH_BEARER;
|
||||
authp->avail |= CURLAUTH_BEARER;
|
||||
if(authp->picked == CURLAUTH_BEARER) {
|
||||
@@ -1087,6 +1103,14 @@ static bool http_should_fail(struct Curl_easy *data)
|
||||
if(httpcode < 400)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
** A 416 response to a resume request is presumably because the file is
|
||||
** already completely downloaded and thus not actually a fail.
|
||||
*/
|
||||
if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
|
||||
httpcode == 416)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
** Any code >= 400 that's not 401 or 407 is always
|
||||
** a terminal error
|
||||
@@ -1152,7 +1176,12 @@ static size_t readmoredata(char *buffer,
|
||||
/* make sure that a HTTP request is never sent away chunked! */
|
||||
data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
|
||||
|
||||
if(http->postsize <= (curl_off_t)fullsize) {
|
||||
if(data->set.max_send_speed &&
|
||||
(data->set.max_send_speed < http->postsize))
|
||||
/* speed limit */
|
||||
fullsize = (size_t)data->set.max_send_speed;
|
||||
|
||||
else if(http->postsize <= (curl_off_t)fullsize) {
|
||||
memcpy(buffer, http->postdata, (size_t)http->postsize);
|
||||
fullsize = (size_t)http->postsize;
|
||||
|
||||
@@ -1192,7 +1221,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
|
||||
counter */
|
||||
curl_off_t *bytes_written,
|
||||
/* how much of the buffer contains body data */
|
||||
size_t included_body_bytes,
|
||||
curl_off_t included_body_bytes,
|
||||
int socketindex)
|
||||
{
|
||||
ssize_t amount;
|
||||
@@ -1215,10 +1244,10 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
|
||||
ptr = Curl_dyn_ptr(in);
|
||||
size = Curl_dyn_len(in);
|
||||
|
||||
headersize = size - included_body_bytes; /* the initial part that isn't body
|
||||
is header */
|
||||
headersize = size - (size_t)included_body_bytes; /* the initial part that
|
||||
isn't body is header */
|
||||
|
||||
DEBUGASSERT(size > included_body_bytes);
|
||||
DEBUGASSERT(size > (size_t)included_body_bytes);
|
||||
|
||||
result = Curl_convert_to_network(data, ptr, headersize);
|
||||
/* Curl_convert_to_network calls failf if unsuccessful */
|
||||
@@ -1234,13 +1263,17 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
|
||||
#endif
|
||||
)
|
||||
&& conn->httpversion != 20) {
|
||||
/* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
|
||||
when we speak HTTPS, as if only a fraction of it is sent now, this data
|
||||
needs to fit into the normal read-callback buffer later on and that
|
||||
buffer is using this size.
|
||||
/* Make sure this doesn't send more body bytes than what the max send
|
||||
speed says. The request bytes do not count to the max speed.
|
||||
*/
|
||||
|
||||
sendsize = CURLMIN(size, CURL_MAX_WRITE_SIZE);
|
||||
if(data->set.max_send_speed &&
|
||||
(included_body_bytes > data->set.max_send_speed)) {
|
||||
curl_off_t overflow = included_body_bytes - data->set.max_send_speed;
|
||||
DEBUGASSERT((size_t)overflow < size);
|
||||
sendsize = size - (size_t)overflow;
|
||||
}
|
||||
else
|
||||
sendsize = size;
|
||||
|
||||
/* OpenSSL is very picky and we must send the SAME buffer pointer to the
|
||||
library when we attempt to re-send this buffer. Sending the same data
|
||||
@@ -1254,6 +1287,14 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
|
||||
Curl_dyn_free(in);
|
||||
return result;
|
||||
}
|
||||
/* We never send more than upload_buffer_size bytes in one single chunk
|
||||
when we speak HTTPS, as if only a fraction of it is sent now, this data
|
||||
needs to fit into the normal read-callback buffer later on and that
|
||||
buffer is using this size.
|
||||
*/
|
||||
if(sendsize > (size_t)data->set.upload_buffer_size)
|
||||
sendsize = (size_t)data->set.upload_buffer_size;
|
||||
|
||||
memcpy(data->state.ulbuf, ptr, sendsize);
|
||||
ptr = data->state.ulbuf;
|
||||
}
|
||||
@@ -1272,7 +1313,19 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
|
||||
}
|
||||
else
|
||||
#endif
|
||||
sendsize = size;
|
||||
{
|
||||
/* Make sure this doesn't send more body bytes than what the max send
|
||||
speed says. The request bytes do not count to the max speed.
|
||||
*/
|
||||
if(data->set.max_send_speed &&
|
||||
(included_body_bytes > data->set.max_send_speed)) {
|
||||
curl_off_t overflow = included_body_bytes - data->set.max_send_speed;
|
||||
DEBUGASSERT((size_t)overflow < size);
|
||||
sendsize = size - (size_t)overflow;
|
||||
}
|
||||
else
|
||||
sendsize = size;
|
||||
}
|
||||
}
|
||||
|
||||
result = Curl_write(data, sockfd, ptr, sendsize, &amount);
|
||||
@@ -1500,7 +1553,7 @@ static CURLcode add_haproxy_protocol_header(struct Curl_easy *data)
|
||||
|
||||
msnprintf(proxy_header,
|
||||
sizeof(proxy_header),
|
||||
"PROXY %s %s %s %li %li\r\n",
|
||||
"PROXY %s %s %s %i %i\r\n",
|
||||
tcp_version,
|
||||
data->info.conn_local_ip,
|
||||
data->info.conn_primary_ip,
|
||||
@@ -1548,7 +1601,7 @@ static int https_getsock(struct Curl_easy *data,
|
||||
{
|
||||
(void)data;
|
||||
if(conn->handler->flags & PROTOPT_SSL)
|
||||
return Curl_ssl_getsock(conn, socks);
|
||||
return Curl_ssl->getsock(conn, socks);
|
||||
return GETSOCK_BLANK;
|
||||
}
|
||||
#endif /* USE_SSL */
|
||||
@@ -1621,11 +1674,11 @@ static bool use_http_1_1plus(const struct Curl_easy *data,
|
||||
{
|
||||
if((data->state.httpversion == 10) || (conn->httpversion == 10))
|
||||
return FALSE;
|
||||
if((data->set.httpversion == CURL_HTTP_VERSION_1_0) &&
|
||||
if((data->state.httpwant == CURL_HTTP_VERSION_1_0) &&
|
||||
(conn->httpversion <= 10))
|
||||
return FALSE;
|
||||
return ((data->set.httpversion == CURL_HTTP_VERSION_NONE) ||
|
||||
(data->set.httpversion >= CURL_HTTP_VERSION_1_1));
|
||||
return ((data->state.httpwant == CURL_HTTP_VERSION_NONE) ||
|
||||
(data->state.httpwant >= CURL_HTTP_VERSION_1_1));
|
||||
}
|
||||
|
||||
#ifndef USE_HYPER
|
||||
@@ -1633,7 +1686,7 @@ static const char *get_http_string(const struct Curl_easy *data,
|
||||
const struct connectdata *conn)
|
||||
{
|
||||
#ifdef ENABLE_QUIC
|
||||
if((data->set.httpversion == CURL_HTTP_VERSION_3) ||
|
||||
if((data->state.httpwant == CURL_HTTP_VERSION_3) ||
|
||||
(conn->httpversion == 30))
|
||||
return "3";
|
||||
#endif
|
||||
@@ -1698,7 +1751,7 @@ CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
|
||||
|
||||
if(
|
||||
#ifdef CURL_DO_LINEEND_CONV
|
||||
(handle->set.prefer_ascii) ||
|
||||
(handle->state.prefer_ascii) ||
|
||||
#endif
|
||||
(handle->set.crlf)) {
|
||||
/* \n will become \r\n later on */
|
||||
@@ -1960,10 +2013,10 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
|
||||
}
|
||||
#else
|
||||
/* disabled */
|
||||
CURLcode Curl_add_timecondition(const struct connectdata *conn,
|
||||
CURLcode Curl_add_timecondition(struct Curl_easy *data,
|
||||
struct dynbuf *req)
|
||||
{
|
||||
(void)conn;
|
||||
(void)data;
|
||||
(void)req;
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -2174,7 +2227,7 @@ CURLcode Curl_http_target(struct Curl_easy *data,
|
||||
/* Extract the URL to use in the request. Store in STRING_TEMP_URL for
|
||||
clean-up reasons if the function returns before the free() further
|
||||
down. */
|
||||
uc = curl_url_get(h, CURLUPART_URL, &url, 0);
|
||||
uc = curl_url_get(h, CURLUPART_URL, &url, CURLU_NO_DEFAULT_PORT);
|
||||
if(uc) {
|
||||
curl_url_cleanup(h);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
@@ -2205,7 +2258,7 @@ CURLcode Curl_http_target(struct Curl_easy *data,
|
||||
}
|
||||
if(!type) {
|
||||
result = Curl_dyn_addf(r, ";type=%c",
|
||||
data->set.prefer_ascii ? 'a' : 'i');
|
||||
data->state.prefer_ascii ? 'a' : 'i');
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@@ -2614,8 +2667,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
/* issue the request */
|
||||
result = Curl_buffer_send(r, data, &data->info.request_size,
|
||||
(size_t)included_body, FIRSTSOCKET);
|
||||
result = Curl_buffer_send(r, data, &data->info.request_size, included_body,
|
||||
FIRSTSOCKET);
|
||||
|
||||
if(result)
|
||||
failf(data, "Failed sending HTTP POST request");
|
||||
@@ -2946,7 +2999,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
default:
|
||||
/* Check if user wants to use HTTP/2 with clear TCP*/
|
||||
#ifdef USE_NGHTTP2
|
||||
if(data->set.httpversion == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
|
||||
if(data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
|
||||
/* We don't support HTTP/2 proxies yet. Also it's debatable
|
||||
@@ -3002,8 +3055,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
}
|
||||
|
||||
Curl_safefree(data->state.aptr.ref);
|
||||
if(data->change.referer && !Curl_checkheaders(data, "Referer")) {
|
||||
data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
|
||||
if(data->state.referer && !Curl_checkheaders(data, "Referer")) {
|
||||
data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
|
||||
if(!data->state.aptr.ref)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -3016,10 +3069,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
if(!data->state.aptr.accept_encoding)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
else
|
||||
Curl_safefree(data->state.aptr.accept_encoding);
|
||||
data->state.aptr.accept_encoding = NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
/* we only consider transfer-encoding magic if libz support is built-in */
|
||||
@@ -3071,6 +3122,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
/* initialize a dynamic send-buffer */
|
||||
Curl_dyn_init(&req, DYN_HTTP_REQUEST);
|
||||
|
||||
/* make sure the header buffer is reset - if there are leftovers from a
|
||||
previous transfer */
|
||||
Curl_dyn_reset(&data->state.headerb);
|
||||
|
||||
/* add the main request stuff */
|
||||
/* GET/HEAD/POST/PUT */
|
||||
result = Curl_dyn_addf(&req, "%s ", request);
|
||||
@@ -3124,7 +3179,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
*data->set.str[STRING_ENCODING] &&
|
||||
data->state.aptr.accept_encoding)?
|
||||
data->state.aptr.accept_encoding:"",
|
||||
(data->change.referer && data->state.aptr.ref)?
|
||||
(data->state.referer && data->state.aptr.ref)?
|
||||
data->state.aptr.ref:"" /* Referer: <data> */,
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
(conn->bits.httpproxy &&
|
||||
@@ -3152,10 +3207,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
|
||||
if(!(conn->handler->flags&PROTOPT_SSL) &&
|
||||
conn->httpversion != 20 &&
|
||||
(data->set.httpversion == CURL_HTTP_VERSION_2)) {
|
||||
(data->state.httpwant == CURL_HTTP_VERSION_2)) {
|
||||
/* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
|
||||
over SSL */
|
||||
result = Curl_http2_request_upgrade(&req, conn);
|
||||
result = Curl_http2_request_upgrade(&req, data);
|
||||
if(result) {
|
||||
Curl_dyn_free(&req);
|
||||
return result;
|
||||
@@ -3333,7 +3388,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
|
||||
if(!k->http_bodyless &&
|
||||
!data->set.ignorecl && checkprefix("Content-Length:", headp)) {
|
||||
curl_off_t contentlength;
|
||||
CURLofft offt = curlx_strtoofft(headp + 15, NULL, 10, &contentlength);
|
||||
CURLofft offt = curlx_strtoofft(headp + strlen("Content-Length:"),
|
||||
NULL, 10, &contentlength);
|
||||
|
||||
if(offt == CURL_OFFT_OK) {
|
||||
if(data->set.max_filesize &&
|
||||
@@ -3432,7 +3488,9 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
|
||||
* of chunks, and a chunk-data set to zero signals the
|
||||
* end-of-chunks. */
|
||||
|
||||
result = Curl_build_unencoding_stack(data, headp + 18, TRUE);
|
||||
result = Curl_build_unencoding_stack(data,
|
||||
headp + strlen("Transfer-Encoding:"),
|
||||
TRUE);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@@ -3445,17 +3503,20 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
|
||||
* 2616). zlib cannot handle compress. However, errors are
|
||||
* handled further down when the response body is processed
|
||||
*/
|
||||
result = Curl_build_unencoding_stack(data, headp + 17, FALSE);
|
||||
result = Curl_build_unencoding_stack(data,
|
||||
headp + strlen("Content-Encoding:"),
|
||||
FALSE);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
else if(checkprefix("Retry-After:", headp)) {
|
||||
/* Retry-After = HTTP-date / delay-seconds */
|
||||
curl_off_t retry_after = 0; /* zero for unknown or "now" */
|
||||
time_t date = Curl_getdate_capped(&headp[12]);
|
||||
time_t date = Curl_getdate_capped(headp + strlen("Retry-After:"));
|
||||
if(-1 == date) {
|
||||
/* not a date, try it as a decimal number */
|
||||
(void)curlx_strtoofft(&headp[12], NULL, 10, &retry_after);
|
||||
(void)curlx_strtoofft(headp + strlen("Retry-After:"),
|
||||
NULL, 10, &retry_after);
|
||||
}
|
||||
else
|
||||
/* convert date to number of seconds into the future */
|
||||
@@ -3474,7 +3535,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
|
||||
The forth means the requested range was unsatisfied.
|
||||
*/
|
||||
|
||||
char *ptr = headp + 14;
|
||||
char *ptr = headp + strlen("Content-Range:");
|
||||
|
||||
/* Move forward until first digit or asterisk */
|
||||
while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
|
||||
@@ -3497,7 +3558,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
|
||||
CURL_LOCK_ACCESS_SINGLE);
|
||||
Curl_cookie_add(data,
|
||||
data->cookies, TRUE, FALSE, headp + 11,
|
||||
data->cookies, TRUE, FALSE,
|
||||
headp + strlen("Set-Cookie:"),
|
||||
/* If there is a custom-set Host: name, use it
|
||||
here, or else use real peer host name. */
|
||||
data->state.aptr.cookiehost?
|
||||
@@ -3532,7 +3594,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
|
||||
return result;
|
||||
}
|
||||
#ifdef USE_SPNEGO
|
||||
else if(checkprefix("Persistent-Auth", headp)) {
|
||||
else if(checkprefix("Persistent-Auth:", headp)) {
|
||||
struct negotiatedata *negdata = &conn->negotiate;
|
||||
struct auth *authp = &data->state.authhost;
|
||||
if(authp->picked == CURLAUTH_NEGOTIATE) {
|
||||
@@ -3576,13 +3638,13 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_HSTS
|
||||
#ifndef CURL_DISABLE_HSTS
|
||||
/* If enabled, the header is incoming and this is over HTTPS */
|
||||
else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) &&
|
||||
(conn->handler->flags & PROTOPT_SSL)) {
|
||||
CURLcode check =
|
||||
Curl_hsts_parse(data->hsts, data->state.up.hostname,
|
||||
&headp[ sizeof("Strict-Transport-Security:") -1 ]);
|
||||
headp + strlen("Strict-Transport-Security:"));
|
||||
if(check)
|
||||
infof(data, "Illegal STS header skipped\n");
|
||||
#ifdef DEBUGBUILD
|
||||
@@ -3606,7 +3668,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
|
||||
/* the ALPN of the current request */
|
||||
enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
|
||||
result = Curl_altsvc_parse(data, data->asi,
|
||||
&headp[ strlen("Alt-Svc:") ],
|
||||
headp + strlen("Alt-Svc:"),
|
||||
id, conn->host.name,
|
||||
curlx_uitous(conn->remote_port));
|
||||
if(result)
|
||||
@@ -3995,7 +4057,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
infof(data, "Got 417 while waiting for a 100\n");
|
||||
data->state.disableexpect = TRUE;
|
||||
DEBUGASSERT(!data->req.newurl);
|
||||
data->req.newurl = strdup(data->change.url);
|
||||
data->req.newurl = strdup(data->state.url);
|
||||
Curl_done_sending(data, k);
|
||||
}
|
||||
else if(data->set.http_keep_sending_on_error) {
|
||||
@@ -4144,10 +4206,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
*/
|
||||
char separator;
|
||||
char twoorthree[2];
|
||||
int httpversion = 0;
|
||||
nc = sscanf(HEADER1,
|
||||
" HTTP/%1d.%1d%c%3d",
|
||||
&httpversion_major,
|
||||
&conn->httpversion,
|
||||
&httpversion,
|
||||
&separator,
|
||||
&k->httpcode);
|
||||
|
||||
@@ -4159,7 +4222,23 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
if((nc == 4) && (' ' == separator)) {
|
||||
conn->httpversion += 10 * httpversion_major;
|
||||
httpversion += 10 * httpversion_major;
|
||||
switch(httpversion) {
|
||||
case 10:
|
||||
case 11:
|
||||
#if defined(USE_NGHTTP2) || defined(USE_HYPER)
|
||||
case 20:
|
||||
#endif
|
||||
#if defined(ENABLE_QUIC)
|
||||
case 30:
|
||||
#endif
|
||||
conn->httpversion = (unsigned char)httpversion;
|
||||
break;
|
||||
default:
|
||||
failf(data, "Unsupported HTTP version (%u.%d) in response",
|
||||
httpversion/10, httpversion%10);
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
}
|
||||
|
||||
if(k->upgr101 == UPGR101_RECEIVED) {
|
||||
/* supposedly upgraded to http2 now */
|
||||
@@ -4200,14 +4279,14 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
}
|
||||
else if(conn->handler->protocol & CURLPROTO_RTSP) {
|
||||
char separator;
|
||||
int rtspversion;
|
||||
nc = sscanf(HEADER1,
|
||||
" RTSP/%1d.%1d%c%3d",
|
||||
&rtspversion_major,
|
||||
&conn->rtspversion,
|
||||
&rtspversion,
|
||||
&separator,
|
||||
&k->httpcode);
|
||||
if((nc == 4) && (' ' == separator)) {
|
||||
conn->rtspversion += 10 * rtspversion_major;
|
||||
conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -58,7 +58,7 @@ char *Curl_checkProxyheaders(struct Curl_easy *data,
|
||||
CURLcode Curl_buffer_send(struct dynbuf *in,
|
||||
struct Curl_easy *data,
|
||||
curl_off_t *bytes_written,
|
||||
size_t included_body_bytes,
|
||||
curl_off_t included_body_bytes,
|
||||
int socketindex);
|
||||
#else
|
||||
#define Curl_buffer_send(a,b,c,d,e) CURLE_OK
|
||||
@@ -184,8 +184,7 @@ struct HTTP {
|
||||
enum {
|
||||
HTTPSEND_NADA, /* init */
|
||||
HTTPSEND_REQUEST, /* sending a request */
|
||||
HTTPSEND_BODY, /* sending body */
|
||||
HTTPSEND_LAST /* never use this */
|
||||
HTTPSEND_BODY /* sending body */
|
||||
} sending;
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
@@ -211,6 +210,7 @@ struct HTTP {
|
||||
char **push_headers; /* allocated array */
|
||||
size_t push_headers_used; /* number of entries filled in */
|
||||
size_t push_headers_alloc; /* number of entries allocated */
|
||||
uint32_t error; /* HTTP/2 stream error code */
|
||||
#endif
|
||||
#if defined(USE_NGHTTP2) || defined(USE_NGHTTP3)
|
||||
bool closed; /* TRUE on HTTP2 stream close */
|
||||
@@ -251,9 +251,16 @@ struct h2settings {
|
||||
struct http_conn {
|
||||
#ifdef USE_NGHTTP2
|
||||
#define H2_BINSETTINGS_LEN 80
|
||||
nghttp2_session *h2;
|
||||
uint8_t binsettings[H2_BINSETTINGS_LEN];
|
||||
size_t binlen; /* length of the binsettings data */
|
||||
|
||||
/* We associate the connnectdata struct with the connection, but we need to
|
||||
make sure we can identify the current "driving" transfer. This is a
|
||||
work-around for the lack of nghttp2_session_set_user_data() in older
|
||||
nghttp2 versions that we want to support. (Added in 1.31.0) */
|
||||
struct Curl_easy *trnsfr;
|
||||
|
||||
nghttp2_session *h2;
|
||||
Curl_send *send_underlying; /* underlying send Curl_send callback */
|
||||
Curl_recv *recv_underlying; /* underlying recv Curl_recv callback */
|
||||
char *inbuf; /* buffer to receive data from underlying socket */
|
||||
@@ -274,7 +281,6 @@ struct http_conn {
|
||||
/* list of settings that will be sent */
|
||||
nghttp2_settings_entry local_settings[3];
|
||||
size_t local_settings_num;
|
||||
uint32_t error_code; /* HTTP/2 error code */
|
||||
#else
|
||||
int unused; /* prevent a compiler warning */
|
||||
#endif
|
||||
|
||||
+138
-81
@@ -211,6 +211,24 @@ static bool http2_connisdead(struct Curl_easy *data, struct connectdata *conn)
|
||||
return dead;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the transfer that is currently using this HTTP/2 connection.
|
||||
*/
|
||||
static void set_transfer(struct http_conn *c,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
c->trnsfr = data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the transfer that is currently using this HTTP/2 connection.
|
||||
*/
|
||||
static struct Curl_easy *get_transfer(struct http_conn *c)
|
||||
{
|
||||
DEBUGASSERT(c && c->trnsfr);
|
||||
return c->trnsfr;
|
||||
}
|
||||
|
||||
static unsigned int http2_conncheck(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
unsigned int checks_to_perform)
|
||||
@@ -247,6 +265,7 @@ static unsigned int http2_conncheck(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
if(send_frames) {
|
||||
set_transfer(c, data); /* set the transfer */
|
||||
rc = nghttp2_session_send(c->h2);
|
||||
if(rc)
|
||||
failf(data, "nghttp2_session_send() failed: %s(%d)",
|
||||
@@ -269,6 +288,7 @@ void Curl_http2_setup_req(struct Curl_easy *data)
|
||||
http->mem = NULL;
|
||||
http->len = 0;
|
||||
http->memlen = 0;
|
||||
http->error = NGHTTP2_NO_ERROR;
|
||||
}
|
||||
|
||||
/* called from http_setup_conn */
|
||||
@@ -276,7 +296,6 @@ void Curl_http2_setup_conn(struct connectdata *conn)
|
||||
{
|
||||
conn->proto.httpc.settings.max_concurrent_streams =
|
||||
DEFAULT_MAX_CONCURRENT_STREAMS;
|
||||
conn->proto.httpc.error_code = NGHTTP2_NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -300,6 +319,7 @@ static const struct Curl_handler Curl_handler_http2 = {
|
||||
http2_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
http2_conncheck, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_HTTP, /* defport */
|
||||
CURLPROTO_HTTP, /* protocol */
|
||||
CURLPROTO_HTTP, /* family */
|
||||
@@ -322,6 +342,7 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
|
||||
http2_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
http2_conncheck, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_HTTP, /* defport */
|
||||
CURLPROTO_HTTPS, /* protocol */
|
||||
CURLPROTO_HTTP, /* family */
|
||||
@@ -349,6 +370,7 @@ static ssize_t send_callback(nghttp2_session *h2,
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
struct http_conn *c = &conn->proto.httpc;
|
||||
struct Curl_easy *data = get_transfer(c);
|
||||
ssize_t written;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
@@ -359,7 +381,7 @@ static ssize_t send_callback(nghttp2_session *h2,
|
||||
/* called before setup properly! */
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
|
||||
written = ((Curl_send*)c->send_underlying)(conn->data, FIRSTSOCKET,
|
||||
written = ((Curl_send*)c->send_underlying)(data, FIRSTSOCKET,
|
||||
mem, length, &result);
|
||||
|
||||
if(result == CURLE_AGAIN) {
|
||||
@@ -367,7 +389,7 @@ static ssize_t send_callback(nghttp2_session *h2,
|
||||
}
|
||||
|
||||
if(written == -1) {
|
||||
failf(conn->data, "Failed sending HTTP2 data");
|
||||
failf(data, "Failed sending HTTP2 data");
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
@@ -479,38 +501,48 @@ static int set_transfer_url(struct Curl_easy *data,
|
||||
const char *v;
|
||||
CURLU *u = curl_url();
|
||||
CURLUcode uc;
|
||||
char *url;
|
||||
char *url = NULL;
|
||||
int rc = 0;
|
||||
|
||||
v = curl_pushheader_byname(hp, ":scheme");
|
||||
if(v) {
|
||||
uc = curl_url_set(u, CURLUPART_SCHEME, v, 0);
|
||||
if(uc)
|
||||
return 1;
|
||||
if(uc) {
|
||||
rc = 1;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
v = curl_pushheader_byname(hp, ":authority");
|
||||
if(v) {
|
||||
uc = curl_url_set(u, CURLUPART_HOST, v, 0);
|
||||
if(uc)
|
||||
return 2;
|
||||
if(uc) {
|
||||
rc = 2;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
v = curl_pushheader_byname(hp, ":path");
|
||||
if(v) {
|
||||
uc = curl_url_set(u, CURLUPART_PATH, v, 0);
|
||||
if(uc)
|
||||
return 3;
|
||||
if(uc) {
|
||||
rc = 3;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
uc = curl_url_get(u, CURLUPART_URL, &url, 0);
|
||||
if(uc)
|
||||
return 4;
|
||||
rc = 4;
|
||||
fail:
|
||||
curl_url_cleanup(u);
|
||||
if(rc)
|
||||
return rc;
|
||||
|
||||
if(data->change.url_alloc)
|
||||
free(data->change.url);
|
||||
data->change.url_alloc = TRUE;
|
||||
data->change.url = url;
|
||||
if(data->state.url_alloc)
|
||||
free(data->state.url);
|
||||
data->state.url_alloc = TRUE;
|
||||
data->state.url = url;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -551,6 +583,7 @@ static int push_promise(struct Curl_easy *data,
|
||||
|
||||
rv = set_transfer_url(newhandle, &heads);
|
||||
if(rv) {
|
||||
(void)Curl_close(&newhandle);
|
||||
rv = CURL_PUSH_DENY;
|
||||
goto fail;
|
||||
}
|
||||
@@ -633,6 +666,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
struct http_conn *httpc = &conn->proto.httpc;
|
||||
struct Curl_easy *data_s = NULL;
|
||||
struct HTTP *stream = NULL;
|
||||
struct Curl_easy *data = get_transfer(httpc);
|
||||
int rv;
|
||||
size_t left, ncopy;
|
||||
int32_t stream_id = frame->hd.stream_id;
|
||||
@@ -642,30 +676,30 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
/* stream ID zero is for connection-oriented stuff */
|
||||
if(frame->hd.type == NGHTTP2_SETTINGS) {
|
||||
uint32_t max_conn = httpc->settings.max_concurrent_streams;
|
||||
H2BUGF(infof(conn->data, "Got SETTINGS\n"));
|
||||
H2BUGF(infof(data, "Got SETTINGS\n"));
|
||||
httpc->settings.max_concurrent_streams =
|
||||
nghttp2_session_get_remote_settings(
|
||||
session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
|
||||
httpc->settings.enable_push =
|
||||
nghttp2_session_get_remote_settings(
|
||||
session, NGHTTP2_SETTINGS_ENABLE_PUSH);
|
||||
H2BUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n",
|
||||
H2BUGF(infof(data, "MAX_CONCURRENT_STREAMS == %d\n",
|
||||
httpc->settings.max_concurrent_streams));
|
||||
H2BUGF(infof(conn->data, "ENABLE_PUSH == %s\n",
|
||||
H2BUGF(infof(data, "ENABLE_PUSH == %s\n",
|
||||
httpc->settings.enable_push?"TRUE":"false"));
|
||||
if(max_conn != httpc->settings.max_concurrent_streams) {
|
||||
/* only signal change if the value actually changed */
|
||||
infof(conn->data,
|
||||
infof(data,
|
||||
"Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n",
|
||||
httpc->settings.max_concurrent_streams);
|
||||
multi_connchanged(conn->data->multi);
|
||||
multi_connchanged(data->multi);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
|
||||
if(!data_s) {
|
||||
H2BUGF(infof(conn->data,
|
||||
H2BUGF(infof(data,
|
||||
"No Curl_easy associated with stream: %x\n",
|
||||
stream_id));
|
||||
return 0;
|
||||
@@ -733,14 +767,9 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
stream->memlen += ncopy;
|
||||
|
||||
drain_this(data_s, httpc);
|
||||
{
|
||||
/* get the pointer from userp again since it was re-assigned above */
|
||||
struct connectdata *conn_s = (struct connectdata *)userp;
|
||||
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(conn_s->data != data_s)
|
||||
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
|
||||
}
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(get_transfer(httpc) != data_s)
|
||||
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
|
||||
break;
|
||||
case NGHTTP2_PUSH_PROMISE:
|
||||
rv = push_promise(data_s, conn, &frame->push_promise);
|
||||
@@ -768,15 +797,15 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
|
||||
static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const uint8_t *data, size_t len, void *userp)
|
||||
const uint8_t *mem, size_t len, void *userp)
|
||||
{
|
||||
struct HTTP *stream;
|
||||
struct Curl_easy *data_s;
|
||||
size_t nread;
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
struct http_conn *httpc = &conn->proto.httpc;
|
||||
(void)session;
|
||||
(void)flags;
|
||||
(void)data;
|
||||
|
||||
DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
|
||||
|
||||
@@ -792,7 +821,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
|
||||
nread = CURLMIN(stream->len, len);
|
||||
memcpy(&stream->mem[stream->memlen], data, nread);
|
||||
memcpy(&stream->mem[stream->memlen], mem, nread);
|
||||
|
||||
stream->len -= nread;
|
||||
stream->memlen += nread;
|
||||
@@ -800,7 +829,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
|
||||
drain_this(data_s, &conn->proto.httpc);
|
||||
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(conn->data != data_s)
|
||||
if(get_transfer(httpc) != data_s)
|
||||
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
|
||||
|
||||
H2BUGF(infof(data_s, "%zu data received for stream %u "
|
||||
@@ -810,7 +839,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
|
||||
stream->memlen));
|
||||
|
||||
if(nread < len) {
|
||||
stream->pausedata = data + nread;
|
||||
stream->pausedata = mem + nread;
|
||||
stream->pauselen = len - nread;
|
||||
H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
|
||||
", stream %u\n",
|
||||
@@ -822,7 +851,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
|
||||
|
||||
/* pause execution of nghttp2 if we received data for another handle
|
||||
in order to process them first. */
|
||||
if(conn->data != data_s) {
|
||||
if(get_transfer(httpc) != data_s) {
|
||||
data_s->conn->proto.httpc.pause_stream_id = stream_id;
|
||||
|
||||
return NGHTTP2_ERR_PAUSE;
|
||||
@@ -861,7 +890,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
|
||||
httpc = &conn->proto.httpc;
|
||||
drain_this(data_s, httpc);
|
||||
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
|
||||
httpc->error_code = error_code;
|
||||
stream->error = error_code;
|
||||
|
||||
/* remove the entry from the hash as the stream is now gone */
|
||||
rv = nghttp2_session_set_stream_user_data(session, stream_id, 0);
|
||||
@@ -944,6 +973,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
struct Curl_easy *data_s;
|
||||
int32_t stream_id = frame->hd.stream_id;
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
struct http_conn *httpc = &conn->proto.httpc;
|
||||
CURLcode result;
|
||||
(void)flags;
|
||||
|
||||
@@ -1049,7 +1079,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
if(result)
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(conn->data != data_s)
|
||||
if(get_transfer(httpc) != data_s)
|
||||
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
|
||||
|
||||
H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
|
||||
@@ -1073,7 +1103,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
if(result)
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(conn->data != data_s)
|
||||
if(get_transfer(httpc) != data_s)
|
||||
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
|
||||
|
||||
H2BUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
|
||||
@@ -1138,27 +1168,27 @@ static int error_callback(nghttp2_session *session,
|
||||
size_t len,
|
||||
void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
(void)session;
|
||||
infof(conn->data, "http2 error: %.*s\n", len, msg);
|
||||
(void)msg;
|
||||
(void)len;
|
||||
(void)userp;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void populate_settings(struct connectdata *conn,
|
||||
static void populate_settings(struct Curl_easy *data,
|
||||
struct http_conn *httpc)
|
||||
{
|
||||
nghttp2_settings_entry *iv = httpc->local_settings;
|
||||
DEBUGASSERT(conn->data);
|
||||
|
||||
iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
|
||||
iv[0].value = Curl_multi_max_concurrent_streams(conn->data->multi);
|
||||
iv[0].value = Curl_multi_max_concurrent_streams(data->multi);
|
||||
|
||||
iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
|
||||
iv[1].value = HTTP2_HUGE_WINDOW_SIZE;
|
||||
|
||||
iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
|
||||
iv[2].value = conn->data->multi->push_cb != NULL;
|
||||
iv[2].value = data->multi->push_cb != NULL;
|
||||
|
||||
httpc->local_settings_num = 3;
|
||||
}
|
||||
@@ -1187,6 +1217,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
|
||||
|
||||
if(premature) {
|
||||
/* RST_STREAM */
|
||||
set_transfer(httpc, data); /* set the transfer */
|
||||
if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE,
|
||||
http->stream_id, NGHTTP2_STREAM_CLOSED))
|
||||
(void)nghttp2_session_send(httpc->h2);
|
||||
@@ -1209,6 +1240,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
|
||||
http->stream_id);
|
||||
DEBUGASSERT(0);
|
||||
}
|
||||
set_transfer(httpc, NULL);
|
||||
http->stream_id = 0;
|
||||
}
|
||||
}
|
||||
@@ -1223,7 +1255,7 @@ static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn)
|
||||
nghttp2_session_callbacks *callbacks;
|
||||
|
||||
conn->proto.httpc.inbuf = malloc(H2_BUFSIZE);
|
||||
if(conn->proto.httpc.inbuf == NULL)
|
||||
if(!conn->proto.httpc.inbuf)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
rc = nghttp2_session_callbacks_new(&callbacks);
|
||||
@@ -1269,18 +1301,18 @@ static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn)
|
||||
* Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
|
||||
*/
|
||||
CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
|
||||
struct connectdata *conn)
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
CURLcode result;
|
||||
ssize_t binlen;
|
||||
char *base64;
|
||||
size_t blen;
|
||||
struct Curl_easy *data = conn->data;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct SingleRequest *k = &data->req;
|
||||
uint8_t *binsettings = conn->proto.httpc.binsettings;
|
||||
struct http_conn *httpc = &conn->proto.httpc;
|
||||
|
||||
populate_settings(conn, httpc);
|
||||
populate_settings(data, httpc);
|
||||
|
||||
/* this returns number of bytes it wrote */
|
||||
binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
|
||||
@@ -1338,6 +1370,7 @@ static int h2_process_pending_input(struct Curl_easy *data,
|
||||
nread = httpc->inbuflen - httpc->nread_inbuf;
|
||||
inbuf = httpc->inbuf + httpc->nread_inbuf;
|
||||
|
||||
set_transfer(httpc, data); /* set the transfer */
|
||||
rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
|
||||
if(rv < 0) {
|
||||
failf(data,
|
||||
@@ -1363,7 +1396,7 @@ static int h2_process_pending_input(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
rv = h2_session_send(data, httpc->h2);
|
||||
if(rv != 0) {
|
||||
if(rv) {
|
||||
*err = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
}
|
||||
@@ -1377,9 +1410,10 @@ static int h2_process_pending_input(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
if(should_close_session(httpc)) {
|
||||
struct HTTP *stream = data->req.p.http;
|
||||
H2BUGF(infof(data,
|
||||
"h2_process_pending_input: nothing to do in this session\n"));
|
||||
if(httpc->error_code)
|
||||
if(stream->error)
|
||||
*err = CURLE_HTTP2;
|
||||
else {
|
||||
/* not an error per se, but should still close the connection */
|
||||
@@ -1402,9 +1436,7 @@ CURLcode Curl_http2_done_sending(struct Curl_easy *data,
|
||||
if((conn->handler == &Curl_handler_http2_ssl) ||
|
||||
(conn->handler == &Curl_handler_http2)) {
|
||||
/* make sure this is only attempted for HTTP/2 transfers */
|
||||
|
||||
struct HTTP *stream = data->req.p.http;
|
||||
|
||||
struct http_conn *httpc = &conn->proto.httpc;
|
||||
nghttp2_session *h2 = httpc->h2;
|
||||
|
||||
@@ -1426,13 +1458,15 @@ CURLcode Curl_http2_done_sending(struct Curl_easy *data,
|
||||
|
||||
H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)\n", data));
|
||||
|
||||
/* re-set KEEP_SEND to make sure we are called again */
|
||||
k->keepon |= KEEP_SEND;
|
||||
|
||||
/* and attempt to send the pending frames */
|
||||
rv = h2_session_send(data, h2);
|
||||
if(rv != 0)
|
||||
if(rv)
|
||||
result = CURLE_SEND_ERROR;
|
||||
|
||||
if(nghttp2_session_want_write(h2)) {
|
||||
/* re-set KEEP_SEND to make sure we are called again */
|
||||
k->keepon |= KEEP_SEND;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -1460,7 +1494,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
|
||||
|
||||
/* Reset to FALSE to prevent infinite loop in readwrite_data function. */
|
||||
stream->closed = FALSE;
|
||||
if(httpc->error_code == NGHTTP2_REFUSED_STREAM) {
|
||||
if(stream->error == NGHTTP2_REFUSED_STREAM) {
|
||||
H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n",
|
||||
stream->stream_id));
|
||||
connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */
|
||||
@@ -1468,10 +1502,10 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
|
||||
*err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
|
||||
return -1;
|
||||
}
|
||||
else if(httpc->error_code != NGHTTP2_NO_ERROR) {
|
||||
else if(stream->error != NGHTTP2_NO_ERROR) {
|
||||
failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
|
||||
stream->stream_id, nghttp2_http2_strerror(httpc->error_code),
|
||||
httpc->error_code);
|
||||
stream->stream_id, nghttp2_http2_strerror(stream->error),
|
||||
stream->error);
|
||||
*err = CURLE_HTTP2_STREAM;
|
||||
return -1;
|
||||
}
|
||||
@@ -1542,6 +1576,8 @@ static int h2_session_send(struct Curl_easy *data,
|
||||
nghttp2_session *h2)
|
||||
{
|
||||
struct HTTP *stream = data->req.p.http;
|
||||
struct http_conn *httpc = &data->conn->proto.httpc;
|
||||
set_transfer(httpc, data);
|
||||
if((data->set.stream_weight != data->state.stream_weight) ||
|
||||
(data->set.stream_depends_e != data->state.stream_depends_e) ||
|
||||
(data->set.stream_depends_on != data->state.stream_depends_on) ) {
|
||||
@@ -1585,6 +1621,10 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(stream->closed)
|
||||
/* closed overrides paused */
|
||||
return http2_handle_stream_close(conn, data, stream, err);
|
||||
|
||||
/* Nullify here because we call nghttp2_session_send() and they
|
||||
might refer to the old buffer. */
|
||||
stream->upload_mem = NULL;
|
||||
@@ -1707,6 +1747,17 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
|
||||
}
|
||||
|
||||
if(nread == 0) {
|
||||
if(!stream->closed) {
|
||||
/* This will happen when the server or proxy server is SIGKILLed
|
||||
during data transfer. We should emit an error since our data
|
||||
received may be incomplete. */
|
||||
failf(data, "HTTP/2 stream %d was not closed cleanly before"
|
||||
" end of the underlying stream",
|
||||
stream->stream_id);
|
||||
*err = CURLE_HTTP2_STREAM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
H2BUGF(infof(data, "end of stream\n"));
|
||||
*err = CURLE_OK;
|
||||
return 0;
|
||||
@@ -1725,7 +1776,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
|
||||
nread));
|
||||
}
|
||||
|
||||
if(h2_process_pending_input(data, httpc, err) != 0)
|
||||
if(h2_process_pending_input(data, httpc, err))
|
||||
return -1;
|
||||
}
|
||||
if(stream->memlen) {
|
||||
@@ -1750,7 +1801,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
|
||||
return retlen;
|
||||
}
|
||||
if(stream->closed)
|
||||
return 0;
|
||||
return http2_handle_stream_close(conn, data, stream, err);
|
||||
*err = CURLE_AGAIN;
|
||||
H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n",
|
||||
stream->stream_id));
|
||||
@@ -1925,7 +1976,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
|
||||
more space. */
|
||||
nheader += 1;
|
||||
nva = malloc(sizeof(nghttp2_nv) * nheader);
|
||||
if(nva == NULL) {
|
||||
if(!nva) {
|
||||
*err = CURLE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
@@ -2048,7 +2099,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
|
||||
}
|
||||
|
||||
/* :authority must come before non-pseudo header fields */
|
||||
if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) {
|
||||
if(authority_idx && authority_idx != AUTHORITY_DST_IDX) {
|
||||
nghttp2_nv authority = nva[authority_idx];
|
||||
for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) {
|
||||
nva[i] = nva[i - 1];
|
||||
@@ -2117,10 +2168,8 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
|
||||
stream_id, (void *)data);
|
||||
stream->stream_id = stream_id;
|
||||
|
||||
/* this does not call h2_session_send() since there can not have been any
|
||||
* priority update since the nghttp2_submit_request() call above */
|
||||
rv = nghttp2_session_send(h2);
|
||||
if(rv != 0) {
|
||||
rv = h2_session_send(data, h2);
|
||||
if(rv) {
|
||||
H2BUGF(infof(data,
|
||||
"http2_send() nghttp2_session_send error (%s)%d\n",
|
||||
nghttp2_strerror(rv), rv));
|
||||
@@ -2226,10 +2275,10 @@ CURLcode Curl_http2_switched(struct Curl_easy *data,
|
||||
/* stream 1 is opened implicitly on upgrade */
|
||||
stream->stream_id = 1;
|
||||
/* queue SETTINGS frame (again) */
|
||||
rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings,
|
||||
httpc->binlen, NULL);
|
||||
if(rv != 0) {
|
||||
failf(data, "nghttp2_session_upgrade() failed: %s(%d)",
|
||||
rv = nghttp2_session_upgrade2(httpc->h2, httpc->binsettings, httpc->binlen,
|
||||
data->state.httpreq == HTTPREQ_HEAD, NULL);
|
||||
if(rv) {
|
||||
failf(data, "nghttp2_session_upgrade2() failed: %s(%d)",
|
||||
nghttp2_strerror(rv), rv);
|
||||
return CURLE_HTTP2;
|
||||
}
|
||||
@@ -2244,14 +2293,14 @@ CURLcode Curl_http2_switched(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
else {
|
||||
populate_settings(conn, httpc);
|
||||
populate_settings(data, httpc);
|
||||
|
||||
/* stream ID is unknown at this point */
|
||||
stream->stream_id = -1;
|
||||
rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE,
|
||||
httpc->local_settings,
|
||||
httpc->local_settings_num);
|
||||
if(rv != 0) {
|
||||
if(rv) {
|
||||
failf(data, "nghttp2_submit_settings() failed: %s(%d)",
|
||||
nghttp2_strerror(rv), rv);
|
||||
return CURLE_HTTP2;
|
||||
@@ -2260,7 +2309,7 @@ CURLcode Curl_http2_switched(struct Curl_easy *data,
|
||||
|
||||
rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0,
|
||||
HTTP2_HUGE_WINDOW_SIZE);
|
||||
if(rv != 0) {
|
||||
if(rv) {
|
||||
failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
|
||||
nghttp2_strerror(rv), rv);
|
||||
return CURLE_HTTP2;
|
||||
@@ -2288,8 +2337,15 @@ CURLcode Curl_http2_switched(struct Curl_easy *data,
|
||||
|
||||
DEBUGASSERT(httpc->nread_inbuf == 0);
|
||||
|
||||
if(-1 == h2_process_pending_input(data, httpc, &result))
|
||||
return CURLE_HTTP2;
|
||||
/* Good enough to call it an end once the remaining payload is copied to the
|
||||
* connection buffer.
|
||||
* Some servers (e.g. nghttpx v1.43.0) may fulfill stream 1 immediately
|
||||
* following the protocol switch other than waiting for the client-side
|
||||
* connection preface. If h2_process_pending_input is invoked here to parse
|
||||
* the remaining payload, stream 1 would be marked as closed too early and
|
||||
* thus ignored in http2_recv (following 252790c53).
|
||||
* The logic in lib/http.c and lib/transfer.c guarantees a following
|
||||
* http2_recv would be invoked very soon. */
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -2299,7 +2355,8 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause)
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(data->conn);
|
||||
/* if it isn't HTTP/2, we're done */
|
||||
if(!data->conn->proto.httpc.h2)
|
||||
if(!(data->conn->handler->protocol & PROTO_FAMILY_HTTP) ||
|
||||
!data->conn->proto.httpc.h2)
|
||||
return CURLE_OK;
|
||||
#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
|
||||
else {
|
||||
@@ -2423,10 +2480,10 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
|
||||
|
||||
/* Only call this function for a transfer that already got a HTTP/2
|
||||
CURLE_HTTP2_STREAM error! */
|
||||
bool Curl_h2_http_1_1_error(struct connectdata *conn)
|
||||
bool Curl_h2_http_1_1_error(struct Curl_easy *data)
|
||||
{
|
||||
struct http_conn *httpc = &conn->proto.httpc;
|
||||
return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED);
|
||||
struct HTTP *stream = data->req.p.http;
|
||||
return (stream->error == NGHTTP2_HTTP_1_1_REQUIRED);
|
||||
}
|
||||
|
||||
#else /* !USE_NGHTTP2 */
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
/* value for MAX_CONCURRENT_STREAMS we use until we get an updated setting
|
||||
from the peer */
|
||||
#define DEFAULT_MAX_CONCURRENT_STREAMS 13
|
||||
#define DEFAULT_MAX_CONCURRENT_STREAMS 100
|
||||
|
||||
/*
|
||||
* Store nghttp2 version info in this buffer, Prefix with a space. Return
|
||||
@@ -43,7 +43,7 @@ CURLcode Curl_http2_init(struct connectdata *conn);
|
||||
void Curl_http2_init_state(struct UrlState *state);
|
||||
void Curl_http2_init_userset(struct UserDefined *set);
|
||||
CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
|
||||
struct connectdata *conn);
|
||||
struct Curl_easy *data);
|
||||
CURLcode Curl_http2_setup(struct Curl_easy *data, struct connectdata *conn);
|
||||
CURLcode Curl_http2_switched(struct Curl_easy *data,
|
||||
const char *ptr, size_t nread);
|
||||
@@ -62,7 +62,7 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
|
||||
CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause);
|
||||
|
||||
/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */
|
||||
bool Curl_h2_http_1_1_error(struct connectdata *conn);
|
||||
bool Curl_h2_http_1_1_error(struct Curl_easy *data);
|
||||
#else /* USE_NGHTTP2 */
|
||||
#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
|
||||
#define Curl_http2_setup(x,y) CURLE_UNSUPPORTED_PROTOCOL
|
||||
|
||||
@@ -99,8 +99,8 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
|
||||
char *request_type = NULL;
|
||||
char *credential_scope = NULL;
|
||||
char *str_to_sign = NULL;
|
||||
const char *user = conn->user ? conn->user : "";
|
||||
const char *passwd = conn->passwd ? conn->passwd : "";
|
||||
const char *user = data->state.aptr.user ? data->state.aptr.user : "";
|
||||
const char *passwd = data->state.aptr.passwd ? data->state.aptr.passwd : "";
|
||||
char *secret = NULL;
|
||||
unsigned char tmp_sign0[32] = {0};
|
||||
unsigned char tmp_sign1[32] = {0};
|
||||
|
||||
@@ -56,7 +56,7 @@ CURLcode Curl_input_digest(struct Curl_easy *data,
|
||||
digest = &data->state.digest;
|
||||
}
|
||||
|
||||
if(!checkprefix("Digest", header))
|
||||
if(!checkprefix("Digest", header) || !ISSPACE(header[6]))
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
|
||||
header += strlen("Digest");
|
||||
@@ -67,7 +67,6 @@ CURLcode Curl_input_digest(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
CURLcode Curl_output_digest(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool proxy,
|
||||
const unsigned char *request,
|
||||
const unsigned char *uripath)
|
||||
@@ -97,16 +96,16 @@ CURLcode Curl_output_digest(struct Curl_easy *data,
|
||||
#else
|
||||
digest = &data->state.proxydigest;
|
||||
allocuserpwd = &data->state.aptr.proxyuserpwd;
|
||||
userp = conn->http_proxy.user;
|
||||
passwdp = conn->http_proxy.passwd;
|
||||
userp = data->state.aptr.proxyuser;
|
||||
passwdp = data->state.aptr.proxypasswd;
|
||||
authp = &data->state.authproxy;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
digest = &data->state.digest;
|
||||
allocuserpwd = &data->state.aptr.userpwd;
|
||||
userp = conn->user;
|
||||
passwdp = conn->passwd;
|
||||
userp = data->state.aptr.user;
|
||||
passwdp = data->state.aptr.passwd;
|
||||
authp = &data->state.authhost;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ CURLcode Curl_input_digest(struct Curl_easy *data,
|
||||
|
||||
/* this is for creating digest header output */
|
||||
CURLcode Curl_output_digest(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool proxy,
|
||||
const unsigned char *request,
|
||||
const unsigned char *uripath);
|
||||
|
||||
@@ -179,7 +179,7 @@ CURLcode Curl_output_negotiate(struct Curl_easy *data,
|
||||
|
||||
free(base64);
|
||||
|
||||
if(userp == NULL) {
|
||||
if(!userp) {
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "http_ntlm.h"
|
||||
#include "curl_ntlm_core.h"
|
||||
#include "curl_ntlm_wb.h"
|
||||
#include "curl_base64.h"
|
||||
#include "vauth/vauth.h"
|
||||
#include "url.h"
|
||||
|
||||
@@ -80,7 +81,18 @@ CURLcode Curl_input_ntlm(struct Curl_easy *data,
|
||||
header++;
|
||||
|
||||
if(*header) {
|
||||
result = Curl_auth_decode_ntlm_type2_message(data, header, ntlm);
|
||||
unsigned char *hdr;
|
||||
size_t hdrlen;
|
||||
|
||||
result = Curl_base64_decode(header, &hdr, &hdrlen);
|
||||
if(!result) {
|
||||
struct bufref hdrbuf;
|
||||
|
||||
Curl_bufref_init(&hdrbuf);
|
||||
Curl_bufref_set(&hdrbuf, hdr, hdrlen, curl_free);
|
||||
result = Curl_auth_decode_ntlm_type2_message(data, &hdrbuf, ntlm);
|
||||
Curl_bufref_free(&hdrbuf);
|
||||
}
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
@@ -116,7 +128,8 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
|
||||
{
|
||||
char *base64 = NULL;
|
||||
size_t len = 0;
|
||||
CURLcode result;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct bufref ntlmmsg;
|
||||
|
||||
/* point to the address of the pointer that holds the string to send to the
|
||||
server, which is for a plain host or for a HTTP proxy */
|
||||
@@ -140,10 +153,10 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
|
||||
if(proxy) {
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
allocuserpwd = &data->state.aptr.proxyuserpwd;
|
||||
userp = conn->http_proxy.user;
|
||||
passwdp = conn->http_proxy.passwd;
|
||||
userp = data->state.aptr.proxyuser;
|
||||
passwdp = data->state.aptr.proxypasswd;
|
||||
service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
|
||||
data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
|
||||
data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
|
||||
hostname = conn->http_proxy.host.name;
|
||||
ntlm = &conn->proxyntlm;
|
||||
state = &conn->proxy_ntlm_state;
|
||||
@@ -154,10 +167,10 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
|
||||
}
|
||||
else {
|
||||
allocuserpwd = &data->state.aptr.userpwd;
|
||||
userp = conn->user;
|
||||
passwdp = conn->passwd;
|
||||
userp = data->state.aptr.user;
|
||||
passwdp = data->state.aptr.passwd;
|
||||
service = data->set.str[STRING_SERVICE_NAME] ?
|
||||
data->set.str[STRING_SERVICE_NAME] : "HTTP";
|
||||
data->set.str[STRING_SERVICE_NAME] : "HTTP";
|
||||
hostname = conn->host.name;
|
||||
ntlm = &conn->ntlm;
|
||||
state = &conn->http_ntlm_state;
|
||||
@@ -173,10 +186,10 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
|
||||
passwdp = "";
|
||||
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
if(s_hSecDll == NULL) {
|
||||
if(!s_hSecDll) {
|
||||
/* not thread safe and leaks - use curl_global_init() to avoid */
|
||||
CURLcode err = Curl_sspi_global_init();
|
||||
if(s_hSecDll == NULL)
|
||||
if(!s_hSecDll)
|
||||
return err;
|
||||
}
|
||||
#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
|
||||
@@ -184,50 +197,52 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Curl_bufref_init(&ntlmmsg);
|
||||
switch(*state) {
|
||||
case NTLMSTATE_TYPE1:
|
||||
default: /* for the weird cases we (re)start here */
|
||||
/* Create a type-1 message */
|
||||
result = Curl_auth_create_ntlm_type1_message(data, userp, passwdp,
|
||||
service, hostname,
|
||||
ntlm, &base64,
|
||||
&len);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(base64) {
|
||||
free(*allocuserpwd);
|
||||
*allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
|
||||
proxy ? "Proxy-" : "",
|
||||
base64);
|
||||
free(base64);
|
||||
if(!*allocuserpwd)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
|
||||
ntlm, &ntlmmsg);
|
||||
if(!result) {
|
||||
DEBUGASSERT(Curl_bufref_len(&ntlmmsg) != 0);
|
||||
result = Curl_base64_encode(data,
|
||||
(const char *) Curl_bufref_ptr(&ntlmmsg),
|
||||
Curl_bufref_len(&ntlmmsg), &base64, &len);
|
||||
if(!result) {
|
||||
free(*allocuserpwd);
|
||||
*allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
|
||||
proxy ? "Proxy-" : "",
|
||||
base64);
|
||||
free(base64);
|
||||
if(!*allocuserpwd)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NTLMSTATE_TYPE2:
|
||||
/* We already received the type-2 message, create a type-3 message */
|
||||
result = Curl_auth_create_ntlm_type3_message(data, userp, passwdp,
|
||||
ntlm, &base64, &len);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(base64) {
|
||||
free(*allocuserpwd);
|
||||
*allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
|
||||
proxy ? "Proxy-" : "",
|
||||
base64);
|
||||
free(base64);
|
||||
if(!*allocuserpwd)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
|
||||
|
||||
*state = NTLMSTATE_TYPE3; /* we send a type-3 */
|
||||
authp->done = TRUE;
|
||||
ntlm, &ntlmmsg);
|
||||
if(!result && Curl_bufref_len(&ntlmmsg)) {
|
||||
result = Curl_base64_encode(data,
|
||||
(const char *) Curl_bufref_ptr(&ntlmmsg),
|
||||
Curl_bufref_len(&ntlmmsg), &base64, &len);
|
||||
if(!result) {
|
||||
free(*allocuserpwd);
|
||||
*allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
|
||||
proxy ? "Proxy-" : "",
|
||||
base64);
|
||||
free(base64);
|
||||
if(!*allocuserpwd)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
else {
|
||||
*state = NTLMSTATE_TYPE3; /* we send a type-3 */
|
||||
authp->done = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -241,8 +256,9 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
|
||||
authp->done = TRUE;
|
||||
break;
|
||||
}
|
||||
Curl_bufref_free(&ntlmmsg);
|
||||
|
||||
return CURLE_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Curl_http_auth_cleanup_ntlm(struct connectdata *conn)
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#include "connect.h"
|
||||
#include "curlx.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "transfer.h"
|
||||
#include "multiif.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
@@ -88,29 +90,12 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex)
|
||||
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
/* for [protocol] tunneled through HTTP proxy */
|
||||
struct HTTP http_proxy;
|
||||
void *prot_save;
|
||||
const char *hostname;
|
||||
int remote_port;
|
||||
CURLcode result;
|
||||
|
||||
/* BLOCKING */
|
||||
/* We want "seamless" operations through HTTP proxy tunnel */
|
||||
|
||||
/* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
|
||||
* member conn->proto.http; we want [protocol] through HTTP and we have
|
||||
* to change the member temporarily for connecting to the HTTP
|
||||
* proxy. After Curl_proxyCONNECT we have to set back the member to the
|
||||
* original pointer
|
||||
*
|
||||
* This function might be called several times in the multi interface case
|
||||
* if the proxy's CONNECT response is not instant.
|
||||
*/
|
||||
prot_save = data->req.p.http;
|
||||
memset(&http_proxy, 0, sizeof(http_proxy));
|
||||
data->req.p.http = &http_proxy;
|
||||
connkeep(conn, "HTTP proxy CONNECT");
|
||||
|
||||
/* for the secondary socket (FTP), use the "connect to host"
|
||||
* but ignore the "connect to port" (use the secondary port)
|
||||
*/
|
||||
@@ -128,8 +113,8 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex)
|
||||
remote_port = conn->conn_to_port;
|
||||
else
|
||||
remote_port = conn->remote_port;
|
||||
|
||||
result = Curl_proxyCONNECT(data, sockindex, hostname, remote_port);
|
||||
data->req.p.http = prot_save;
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
Curl_safefree(data->state.aptr.proxyuserpwd);
|
||||
@@ -153,18 +138,53 @@ bool Curl_connect_ongoing(struct connectdata *conn)
|
||||
(conn->connect_state->tunnel_state != TUNNEL_COMPLETE);
|
||||
}
|
||||
|
||||
/* when we've sent a CONNECT to a proxy, we should rather either wait for the
|
||||
socket to become readable to be able to get the response headers or if
|
||||
we're still sending the request, wait for write. */
|
||||
int Curl_connect_getsock(struct connectdata *conn)
|
||||
{
|
||||
struct HTTP *http;
|
||||
DEBUGASSERT(conn);
|
||||
DEBUGASSERT(conn->connect_state);
|
||||
http = &conn->connect_state->http_proxy;
|
||||
|
||||
if(http->sending)
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
|
||||
return GETSOCK_READSOCK(0);
|
||||
}
|
||||
|
||||
static CURLcode connect_init(struct Curl_easy *data, bool reinit)
|
||||
{
|
||||
struct http_connect_state *s;
|
||||
struct connectdata *conn = data->conn;
|
||||
if(!reinit) {
|
||||
CURLcode result;
|
||||
DEBUGASSERT(!conn->connect_state);
|
||||
/* we might need the upload buffer for streaming a partial request */
|
||||
result = Curl_get_upload_buffer(data);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
s = calloc(1, sizeof(struct http_connect_state));
|
||||
if(!s)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
infof(data, "allocate connect buffer!\n");
|
||||
conn->connect_state = s;
|
||||
Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
|
||||
|
||||
/* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
|
||||
* member conn->proto.http; we want [protocol] through HTTP and we have
|
||||
* to change the member temporarily for connecting to the HTTP
|
||||
* proxy. After Curl_proxyCONNECT we have to set back the member to the
|
||||
* original pointer
|
||||
*
|
||||
* This function might be called several times in the multi interface case
|
||||
* if the proxy's CONNECT response is not instant.
|
||||
*/
|
||||
s->prot_save = data->req.p.http;
|
||||
data->req.p.http = &s->http_proxy;
|
||||
connkeep(conn, "HTTP proxy CONNECT");
|
||||
}
|
||||
else {
|
||||
DEBUGASSERT(conn->connect_state);
|
||||
@@ -184,6 +204,10 @@ static void connect_done(struct Curl_easy *data)
|
||||
struct http_connect_state *s = conn->connect_state;
|
||||
s->tunnel_state = TUNNEL_COMPLETE;
|
||||
Curl_dyn_free(&s->rcvbuf);
|
||||
Curl_dyn_free(&s->req);
|
||||
|
||||
/* retore the protocol pointer */
|
||||
data->req.p.http = s->prot_save;
|
||||
infof(data, "CONNECT phase completed!\n");
|
||||
}
|
||||
|
||||
@@ -231,6 +255,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
|
||||
struct connectdata *conn = data->conn;
|
||||
curl_socket_t tunnelsocket = conn->sock[sockindex];
|
||||
struct http_connect_state *s = conn->connect_state;
|
||||
struct HTTP *http = data->req.p.http;
|
||||
char *linep;
|
||||
size_t perline;
|
||||
|
||||
@@ -246,7 +271,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
|
||||
timediff_t check;
|
||||
if(TUNNEL_INIT == s->tunnel_state) {
|
||||
/* BEGIN CONNECT PHASE */
|
||||
struct dynbuf req;
|
||||
struct dynbuf *req = &s->req;
|
||||
char *hostheader = NULL;
|
||||
char *host = NULL;
|
||||
|
||||
@@ -259,8 +284,8 @@ static CURLcode CONNECT(struct Curl_easy *data,
|
||||
free(data->req.newurl);
|
||||
data->req.newurl = NULL;
|
||||
|
||||
/* initialize a dynamic send-buffer */
|
||||
Curl_dyn_init(&req, DYN_HTTP_REQUEST);
|
||||
/* initialize send-buffer */
|
||||
Curl_dyn_init(req, DYN_HTTP_REQUEST);
|
||||
|
||||
result = CONNECT_host(data, conn,
|
||||
hostname, remote_port, &hostheader, &host);
|
||||
@@ -285,7 +310,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
|
||||
useragent = data->state.aptr.uagent;
|
||||
|
||||
result =
|
||||
Curl_dyn_addf(&req,
|
||||
Curl_dyn_addf(req,
|
||||
"CONNECT %s HTTP/%s\r\n"
|
||||
"%s" /* Host: */
|
||||
"%s" /* Proxy-Authorization */
|
||||
@@ -300,16 +325,15 @@ static CURLcode CONNECT(struct Curl_easy *data,
|
||||
proxyconn);
|
||||
|
||||
if(!result)
|
||||
result = Curl_add_custom_headers(data, TRUE, &req);
|
||||
result = Curl_add_custom_headers(data, TRUE, req);
|
||||
|
||||
if(!result)
|
||||
/* CRLF terminate the request */
|
||||
result = Curl_dyn_add(&req, "\r\n");
|
||||
result = Curl_dyn_add(req, "\r\n");
|
||||
|
||||
if(!result) {
|
||||
/* Send the connect request to the proxy */
|
||||
/* BLOCKING */
|
||||
result = Curl_buffer_send(&req, data, &data->info.request_size, 0,
|
||||
result = Curl_buffer_send(req, data, &data->info.request_size, 0,
|
||||
sockindex);
|
||||
}
|
||||
if(result)
|
||||
@@ -317,7 +341,6 @@ static CURLcode CONNECT(struct Curl_easy *data,
|
||||
}
|
||||
free(host);
|
||||
free(hostheader);
|
||||
Curl_dyn_free(&req);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
@@ -330,12 +353,42 @@ static CURLcode CONNECT(struct Curl_easy *data,
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
|
||||
if(!Curl_conn_data_pending(conn, sockindex))
|
||||
if(!Curl_conn_data_pending(conn, sockindex) && !http->sending)
|
||||
/* return so we'll be called again polling-style */
|
||||
return CURLE_OK;
|
||||
|
||||
/* at this point, the tunnel_connecting phase is over. */
|
||||
|
||||
if(http->sending == HTTPSEND_REQUEST) {
|
||||
if(!s->nsend) {
|
||||
size_t fillcount;
|
||||
k->upload_fromhere = data->state.ulbuf;
|
||||
result = Curl_fillreadbuffer(data, data->set.upload_buffer_size,
|
||||
&fillcount);
|
||||
if(result)
|
||||
return result;
|
||||
s->nsend = fillcount;
|
||||
}
|
||||
if(s->nsend) {
|
||||
ssize_t bytes_written;
|
||||
/* write to socket (send away data) */
|
||||
result = Curl_write(data,
|
||||
conn->writesockfd, /* socket to send to */
|
||||
k->upload_fromhere, /* buffer pointer */
|
||||
s->nsend, /* buffer size */
|
||||
&bytes_written); /* actually sent */
|
||||
|
||||
if(!result)
|
||||
/* send to debug callback! */
|
||||
result = Curl_debug(data, CURLINFO_HEADER_OUT,
|
||||
k->upload_fromhere, bytes_written);
|
||||
|
||||
s->nsend -= bytes_written;
|
||||
k->upload_fromhere += bytes_written;
|
||||
return result;
|
||||
}
|
||||
/* if nothing left to send, continue */
|
||||
}
|
||||
{ /* READING RESPONSE PHASE */
|
||||
int error = SELECT_OK;
|
||||
|
||||
@@ -358,7 +411,8 @@ static CURLcode CONNECT(struct Curl_easy *data,
|
||||
break;
|
||||
}
|
||||
else if(gotbytes <= 0) {
|
||||
if(data->set.proxyauth && data->state.authproxy.avail) {
|
||||
if(data->set.proxyauth && data->state.authproxy.avail &&
|
||||
data->state.aptr.proxyuserpwd) {
|
||||
/* proxy auth was requested and there was proxy auth available,
|
||||
then deem this as "mere" proxy disconnect */
|
||||
conn->bits.proxy_connect_closed = TRUE;
|
||||
@@ -759,7 +813,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
|
||||
if((conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) &&
|
||||
(HYPERE_OK != hyper_request_set_version(req,
|
||||
HYPER_HTTP_VERSION_1_0))) {
|
||||
failf(data, "error settting HTTP version");
|
||||
failf(data, "error setting HTTP version");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,15 +38,39 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex);
|
||||
|
||||
bool Curl_connect_complete(struct connectdata *conn);
|
||||
bool Curl_connect_ongoing(struct connectdata *conn);
|
||||
int Curl_connect_getsock(struct connectdata *conn);
|
||||
|
||||
#else
|
||||
#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN
|
||||
#define Curl_proxy_connect(x,y) CURLE_OK
|
||||
#define Curl_connect_complete(x) CURLE_OK
|
||||
#define Curl_connect_ongoing(x) FALSE
|
||||
#define Curl_connect_getsock(x) 0
|
||||
#endif
|
||||
|
||||
void Curl_connect_free(struct Curl_easy *data);
|
||||
void Curl_connect_done(struct Curl_easy *data);
|
||||
|
||||
/* struct for HTTP CONNECT state data */
|
||||
struct http_connect_state {
|
||||
struct HTTP http_proxy;
|
||||
struct HTTP *prot_save;
|
||||
struct dynbuf rcvbuf;
|
||||
struct dynbuf req;
|
||||
size_t nsend;
|
||||
enum keeponval {
|
||||
KEEPON_DONE,
|
||||
KEEPON_CONNECT,
|
||||
KEEPON_IGNORE
|
||||
} keepon;
|
||||
curl_off_t cl; /* size of content to read and ignore */
|
||||
enum {
|
||||
TUNNEL_INIT, /* init/default/no tunnel state */
|
||||
TUNNEL_CONNECT, /* CONNECT has been sent off */
|
||||
TUNNEL_COMPLETE /* CONNECT response received completely */
|
||||
} tunnel_state;
|
||||
BIT(chunked_encoding);
|
||||
BIT(close_connection);
|
||||
};
|
||||
|
||||
#endif /* HEADER_CURL_HTTP_PROXY_H */
|
||||
|
||||
@@ -136,6 +136,7 @@ const struct Curl_handler Curl_handler_imap = {
|
||||
imap_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_IMAP, /* defport */
|
||||
CURLPROTO_IMAP, /* protocol */
|
||||
CURLPROTO_IMAP, /* family */
|
||||
@@ -164,6 +165,7 @@ const struct Curl_handler Curl_handler_imaps = {
|
||||
imap_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_IMAPS, /* defport */
|
||||
CURLPROTO_IMAPS, /* protocol */
|
||||
CURLPROTO_IMAP, /* family */
|
||||
@@ -919,7 +921,7 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data,
|
||||
/* Do we have a SASL based authentication mechanism? */
|
||||
else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) {
|
||||
size_t llen;
|
||||
unsigned int mechbit;
|
||||
unsigned short mechbit;
|
||||
|
||||
line += 5;
|
||||
wordlen -= 5;
|
||||
@@ -1519,7 +1521,7 @@ static CURLcode imap_done(struct Curl_easy *data, CURLcode status,
|
||||
Curl_safefree(imap->custom_params);
|
||||
|
||||
/* Clear the transfer mode for the next request */
|
||||
imap->transfer = FTPTRANSFER_BODY;
|
||||
imap->transfer = PPTRANSFER_BODY;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1545,7 +1547,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
|
||||
|
||||
if(data->set.opt_no_body) {
|
||||
/* Requested no body means no transfer */
|
||||
imap->transfer = FTPTRANSFER_INFO;
|
||||
imap->transfer = PPTRANSFER_INFO;
|
||||
}
|
||||
|
||||
*dophase_done = FALSE; /* not done yet */
|
||||
@@ -1667,7 +1669,7 @@ static CURLcode imap_dophase_done(struct Curl_easy *data, bool connected)
|
||||
|
||||
(void)connected;
|
||||
|
||||
if(imap->transfer != FTPTRANSFER_BODY)
|
||||
if(imap->transfer != PPTRANSFER_BODY)
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 1996-2019 Internet Software Consortium.
|
||||
* Copyright (C) 1996-2021 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -134,7 +134,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
|
||||
|
||||
/* Are we following an initial run of 0x00s or any real hex?
|
||||
*/
|
||||
if(i != 0)
|
||||
if(i)
|
||||
*tp++ = ':';
|
||||
|
||||
/* Is this address an encapsulated IPv4?
|
||||
|
||||
@@ -159,16 +159,6 @@ krb5_decode(void *app_data, void *buf, int len,
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
krb5_overhead(void *app_data, int level, int len)
|
||||
{
|
||||
/* no arguments are used */
|
||||
(void)app_data;
|
||||
(void)level;
|
||||
(void)len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
krb5_encode(void *app_data, const void *from, int length, int level, void **to)
|
||||
{
|
||||
@@ -305,7 +295,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
|
||||
break;
|
||||
}
|
||||
|
||||
if(output_buffer.length != 0) {
|
||||
if(output_buffer.length) {
|
||||
char *cmd;
|
||||
|
||||
result = Curl_base64_encode(data, (char *)output_buffer.value,
|
||||
@@ -392,7 +382,7 @@ static struct Curl_sec_client_mech Curl_krb5_client_mech = {
|
||||
krb5_auth,
|
||||
krb5_end,
|
||||
krb5_check_prot,
|
||||
krb5_overhead,
|
||||
|
||||
krb5_encode,
|
||||
krb5_decode
|
||||
};
|
||||
@@ -412,7 +402,7 @@ name_to_level(const char *name)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++)
|
||||
if(checkprefix(name, level_names[i].name))
|
||||
if(curl_strequal(name, level_names[i].name))
|
||||
return level_names[i].level;
|
||||
return PROT_NONE;
|
||||
}
|
||||
@@ -657,8 +647,6 @@ static ssize_t sec_write(struct Curl_easy *data, struct connectdata *conn,
|
||||
{
|
||||
ssize_t tx = 0, len = conn->buffer_size;
|
||||
|
||||
len -= conn->mech->overhead(conn->app_data, conn->data_prot,
|
||||
curlx_sztosi(len));
|
||||
if(len <= 0)
|
||||
len = length;
|
||||
while(length) {
|
||||
@@ -760,7 +748,7 @@ static int sec_set_protection_level(struct Curl_easy *data)
|
||||
|
||||
if(level) {
|
||||
char *pbsz;
|
||||
static unsigned int buffer_size = 1 << 20; /* 1048576 */
|
||||
unsigned int buffer_size = 1 << 20; /* 1048576 */
|
||||
|
||||
code = ftp_send_command(data, "PBSZ %u", buffer_size);
|
||||
if(code < 0)
|
||||
@@ -817,7 +805,7 @@ static CURLcode choose_mech(struct Curl_easy *data, struct connectdata *conn)
|
||||
const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech;
|
||||
|
||||
tmp_allocation = realloc(conn->app_data, mech->size);
|
||||
if(tmp_allocation == NULL) {
|
||||
if(!tmp_allocation) {
|
||||
failf(data, "Failed realloc of size %zu", mech->size);
|
||||
mech = NULL;
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
+26
-14
@@ -149,6 +149,7 @@ const struct Curl_handler Curl_handler_ldap = {
|
||||
ZERO_NULL, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_LDAP, /* defport */
|
||||
CURLPROTO_LDAP, /* protocol */
|
||||
CURLPROTO_LDAP, /* family */
|
||||
@@ -176,6 +177,7 @@ const struct Curl_handler Curl_handler_ldaps = {
|
||||
ZERO_NULL, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_LDAPS, /* defport */
|
||||
CURLPROTO_LDAPS, /* protocol */
|
||||
CURLPROTO_LDAP, /* family */
|
||||
@@ -296,14 +298,14 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
||||
*done = TRUE; /* unconditionally */
|
||||
infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n",
|
||||
LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
|
||||
infof(data, "LDAP local: %s\n", data->change.url);
|
||||
infof(data, "LDAP local: %s\n", data->state.url);
|
||||
|
||||
#ifdef HAVE_LDAP_URL_PARSE
|
||||
rc = ldap_url_parse(data->change.url, &ludp);
|
||||
rc = ldap_url_parse(data->state.url, &ludp);
|
||||
#else
|
||||
rc = _ldap_url_parse(data, conn, &ludp);
|
||||
#endif
|
||||
if(rc != 0) {
|
||||
if(rc) {
|
||||
failf(data, "LDAP local: %s", ldap_err2string(rc));
|
||||
result = CURLE_LDAP_INVALID_URL;
|
||||
goto quit;
|
||||
@@ -387,7 +389,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
||||
goto quit;
|
||||
}
|
||||
server = ldapssl_init(host, (int)conn->port, 1);
|
||||
if(server == NULL) {
|
||||
if(!server) {
|
||||
failf(data, "LDAP local: Cannot connect to %s:%ld",
|
||||
conn->host.dispname, conn->port);
|
||||
result = CURLE_COULDNT_CONNECT;
|
||||
@@ -428,7 +430,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
||||
goto quit;
|
||||
}
|
||||
server = ldap_init(host, (int)conn->port);
|
||||
if(server == NULL) {
|
||||
if(!server) {
|
||||
failf(data, "LDAP local: Cannot connect to %s:%ld",
|
||||
conn->host.dispname, conn->port);
|
||||
result = CURLE_COULDNT_CONNECT;
|
||||
@@ -464,7 +466,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
||||
}
|
||||
else {
|
||||
server = ldap_init(host, (int)conn->port);
|
||||
if(server == NULL) {
|
||||
if(!server) {
|
||||
failf(data, "LDAP local: Cannot connect to %s:%ld",
|
||||
conn->host.dispname, conn->port);
|
||||
result = CURLE_COULDNT_CONNECT;
|
||||
@@ -477,7 +479,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
||||
#else
|
||||
rc = ldap_simple_bind_s(server, user, passwd);
|
||||
#endif
|
||||
if(!ldap_ssl && rc != 0) {
|
||||
if(!ldap_ssl && rc) {
|
||||
ldap_proto = LDAP_VERSION2;
|
||||
ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
|
||||
#ifdef USE_WIN32_LDAP
|
||||
@@ -486,7 +488,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
||||
rc = ldap_simple_bind_s(server, user, passwd);
|
||||
#endif
|
||||
}
|
||||
if(rc != 0) {
|
||||
if(rc) {
|
||||
#ifdef USE_WIN32_LDAP
|
||||
failf(data, "LDAP local: bind via ldap_win_bind %s",
|
||||
ldap_err2string(rc));
|
||||
@@ -501,7 +503,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
||||
rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope,
|
||||
ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg);
|
||||
|
||||
if(rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) {
|
||||
if(rc && rc != LDAP_SIZELIMIT_EXCEEDED) {
|
||||
failf(data, "LDAP remote: %s", ldap_err2string(rc));
|
||||
result = CURLE_LDAP_SEARCH_FAILED;
|
||||
goto quit;
|
||||
@@ -581,7 +583,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
#else
|
||||
char *attr = attribute;
|
||||
#endif
|
||||
@@ -875,7 +877,7 @@ static int _ldap_url_parse2(struct Curl_easy *data,
|
||||
ludp->lud_dn = curlx_convert_UTF8_to_tchar(unescaped);
|
||||
|
||||
/* Free the unescaped string as we are done with it */
|
||||
curlx_unicodefree(unescaped);
|
||||
free(unescaped);
|
||||
|
||||
if(!ludp->lud_dn) {
|
||||
rc = LDAP_NO_MEMORY;
|
||||
@@ -943,7 +945,7 @@ static int _ldap_url_parse2(struct Curl_easy *data,
|
||||
ludp->lud_attrs[i] = curlx_convert_UTF8_to_tchar(unescaped);
|
||||
|
||||
/* Free the unescaped string as we are done with it */
|
||||
curlx_unicodefree(unescaped);
|
||||
free(unescaped);
|
||||
|
||||
if(!ludp->lud_attrs[i]) {
|
||||
free(attributes);
|
||||
@@ -1010,7 +1012,7 @@ static int _ldap_url_parse2(struct Curl_easy *data,
|
||||
ludp->lud_filter = curlx_convert_UTF8_to_tchar(unescaped);
|
||||
|
||||
/* Free the unescaped string as we are done with it */
|
||||
curlx_unicodefree(unescaped);
|
||||
free(unescaped);
|
||||
|
||||
if(!ludp->lud_filter) {
|
||||
rc = LDAP_NO_MEMORY;
|
||||
@@ -1061,13 +1063,23 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp)
|
||||
if(!ludp)
|
||||
return;
|
||||
|
||||
#if defined(USE_WIN32_LDAP)
|
||||
curlx_unicodefree(ludp->lud_dn);
|
||||
curlx_unicodefree(ludp->lud_filter);
|
||||
#else
|
||||
free(ludp->lud_dn);
|
||||
free(ludp->lud_filter);
|
||||
#endif
|
||||
|
||||
if(ludp->lud_attrs) {
|
||||
size_t i;
|
||||
for(i = 0; i < ludp->lud_attrs_dups; i++)
|
||||
for(i = 0; i < ludp->lud_attrs_dups; i++) {
|
||||
#if defined(USE_WIN32_LDAP)
|
||||
curlx_unicodefree(ludp->lud_attrs[i]);
|
||||
#else
|
||||
free(ludp->lud_attrs[i]);
|
||||
#endif
|
||||
}
|
||||
free(ludp->lud_attrs);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -94,13 +94,13 @@ Curl_llist_remove(struct Curl_llist *list, struct Curl_llist_element *e,
|
||||
void *user)
|
||||
{
|
||||
void *ptr;
|
||||
if(e == NULL || list->size == 0)
|
||||
if(!e || list->size == 0)
|
||||
return;
|
||||
|
||||
if(e == list->head) {
|
||||
list->head = e->next;
|
||||
|
||||
if(list->head == NULL)
|
||||
if(!list->head)
|
||||
list->tail = NULL;
|
||||
else
|
||||
e->next->prev = NULL;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -44,7 +44,7 @@
|
||||
#endif
|
||||
#endif /* USE_MBEDTLS */
|
||||
|
||||
#if defined(USE_GNUTLS_NETTLE)
|
||||
#if defined(USE_GNUTLS)
|
||||
|
||||
#include <nettle/md4.h>
|
||||
|
||||
@@ -70,33 +70,6 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
|
||||
md4_digest(ctx, MD4_DIGEST_SIZE, result);
|
||||
}
|
||||
|
||||
#elif defined(USE_GNUTLS)
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "curl_memory.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
typedef gcry_md_hd_t MD4_CTX;
|
||||
|
||||
static void MD4_Init(MD4_CTX *ctx)
|
||||
{
|
||||
gcry_md_open(ctx, GCRY_MD_MD4, 0);
|
||||
}
|
||||
|
||||
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
|
||||
{
|
||||
gcry_md_write(*ctx, data, size);
|
||||
}
|
||||
|
||||
static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
|
||||
{
|
||||
memcpy(result, gcry_md_read(*ctx, 0), MD4_DIGEST_LENGTH);
|
||||
gcry_md_close(*ctx);
|
||||
}
|
||||
|
||||
#elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
|
||||
/* When OpenSSL is available we use the MD4-functions from OpenSSL */
|
||||
#include <openssl/md4.h>
|
||||
@@ -201,7 +174,7 @@ static void MD4_Init(MD4_CTX *ctx)
|
||||
|
||||
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
|
||||
{
|
||||
if(ctx->data == NULL) {
|
||||
if(!ctx->data) {
|
||||
ctx->data = malloc(size);
|
||||
if(ctx->data != NULL) {
|
||||
memcpy(ctx->data, data, size);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -38,7 +38,7 @@
|
||||
#endif
|
||||
#endif /* USE_MBEDTLS */
|
||||
|
||||
#if defined(USE_GNUTLS_NETTLE)
|
||||
#if defined(USE_GNUTLS)
|
||||
|
||||
#include <nettle/md5.h>
|
||||
#include "curl_memory.h"
|
||||
@@ -64,33 +64,6 @@ static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
|
||||
md5_digest(ctx, 16, digest);
|
||||
}
|
||||
|
||||
#elif defined(USE_GNUTLS)
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
typedef gcry_md_hd_t MD5_CTX;
|
||||
|
||||
static void MD5_Init(MD5_CTX *ctx)
|
||||
{
|
||||
gcry_md_open(ctx, GCRY_MD_MD5, 0);
|
||||
}
|
||||
|
||||
static void MD5_Update(MD5_CTX *ctx,
|
||||
const unsigned char *input,
|
||||
unsigned int inputLen)
|
||||
{
|
||||
gcry_md_write(*ctx, input, inputLen);
|
||||
}
|
||||
|
||||
static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
|
||||
{
|
||||
memcpy(digest, gcry_md_read(*ctx, 0), 16);
|
||||
gcry_md_close(*ctx);
|
||||
}
|
||||
|
||||
#elif defined(USE_OPENSSL) && !defined(USE_AMISSL)
|
||||
/* When OpenSSL is available we use the MD5-function from OpenSSL */
|
||||
#include <openssl/md5.h>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -55,9 +55,24 @@ struct memdebug {
|
||||
*/
|
||||
|
||||
FILE *curl_dbg_logfile = NULL;
|
||||
static bool registered_cleanup = FALSE; /* atexit registered cleanup */
|
||||
static bool memlimit = FALSE; /* enable memory limit */
|
||||
static long memsize = 0; /* set number of mallocs allowed */
|
||||
|
||||
/* LeakSantizier (LSAN) calls _exit() instead of exit() when a leak is detected
|
||||
on exit so the logfile must be closed explicitly or data could be lost.
|
||||
Though _exit() does not call atexit handlers such as this, LSAN's call to
|
||||
_exit() comes after the atexit handlers are called. curl/curl#6620 */
|
||||
static void curl_dbg_cleanup(void)
|
||||
{
|
||||
if(curl_dbg_logfile &&
|
||||
curl_dbg_logfile != stderr &&
|
||||
curl_dbg_logfile != stdout) {
|
||||
fclose(curl_dbg_logfile);
|
||||
}
|
||||
curl_dbg_logfile = NULL;
|
||||
}
|
||||
|
||||
/* this sets the log file name */
|
||||
void curl_dbg_memdebug(const char *logname)
|
||||
{
|
||||
@@ -72,6 +87,8 @@ void curl_dbg_memdebug(const char *logname)
|
||||
setbuf(curl_dbg_logfile, (char *)NULL);
|
||||
#endif
|
||||
}
|
||||
if(!registered_cleanup)
|
||||
registered_cleanup = !atexit(curl_dbg_cleanup);
|
||||
}
|
||||
|
||||
/* This function sets the number of malloc() calls that should return
|
||||
@@ -91,15 +108,13 @@ static bool countcheck(const char *func, int line, const char *source)
|
||||
should not be made */
|
||||
if(memlimit && source) {
|
||||
if(!memsize) {
|
||||
if(source) {
|
||||
/* log to file */
|
||||
curl_dbg_log("LIMIT %s:%d %s reached memlimit\n",
|
||||
source, line, func);
|
||||
/* log to stderr also */
|
||||
fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
|
||||
source, line, func);
|
||||
fflush(curl_dbg_logfile); /* because it might crash now */
|
||||
}
|
||||
/* log to file */
|
||||
curl_dbg_log("LIMIT %s:%d %s reached memlimit\n",
|
||||
source, line, func);
|
||||
/* log to stderr also */
|
||||
fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
|
||||
source, line, func);
|
||||
fflush(curl_dbg_logfile); /* because it might crash now */
|
||||
errno = ENOMEM;
|
||||
return TRUE; /* RETURN ERROR! */
|
||||
}
|
||||
|
||||
@@ -152,14 +152,14 @@ curl_off_t VmsRealFileSize(const char *name,
|
||||
FILE * file;
|
||||
|
||||
file = fopen(name, FOPEN_READTEXT); /* VMS */
|
||||
if(file == NULL)
|
||||
if(!file)
|
||||
return 0;
|
||||
|
||||
count = 0;
|
||||
ret_stat = 1;
|
||||
while(ret_stat > 0) {
|
||||
ret_stat = fread(buffer, 1, sizeof(buffer), file);
|
||||
if(ret_stat != 0)
|
||||
if(ret_stat)
|
||||
count += ret_stat;
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1999 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1999 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -815,7 +815,7 @@ static int dprintf_formatf(
|
||||
size_t len;
|
||||
|
||||
str = (char *) p->data.str;
|
||||
if(str == NULL) {
|
||||
if(!str) {
|
||||
/* Write null[] if there's space. */
|
||||
if(prec == -1 || prec >= (long) sizeof(null) - 1) {
|
||||
str = null;
|
||||
|
||||
@@ -86,6 +86,7 @@ const struct Curl_handler Curl_handler_mqtt = {
|
||||
ZERO_NULL, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_MQTT, /* defport */
|
||||
CURLPROTO_MQTT, /* protocol */
|
||||
CURLPROTO_MQTT, /* family */
|
||||
|
||||
+296
-184
File diff suppressed because it is too large
Load Diff
@@ -40,27 +40,26 @@ struct Curl_message {
|
||||
well!
|
||||
*/
|
||||
typedef enum {
|
||||
CURLM_STATE_INIT, /* 0 - start in this state */
|
||||
CURLM_STATE_CONNECT_PEND, /* 1 - no connections, waiting for one */
|
||||
CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */
|
||||
CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */
|
||||
CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect to finalize */
|
||||
CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting HTTPS proxy SSL initialization
|
||||
to complete and/or proxy CONNECT to
|
||||
finalize */
|
||||
CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */
|
||||
CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect
|
||||
phase */
|
||||
CURLM_STATE_DO, /* 8 - start send off the request (part 1) */
|
||||
CURLM_STATE_DOING, /* 9 - sending off the request (part 1) */
|
||||
CURLM_STATE_DO_MORE, /* 10 - send off the request (part 2) */
|
||||
CURLM_STATE_DO_DONE, /* 11 - done sending off request */
|
||||
CURLM_STATE_PERFORM, /* 12 - transfer data */
|
||||
CURLM_STATE_TOOFAST, /* 13 - wait because limit-rate exceeded */
|
||||
CURLM_STATE_DONE, /* 14 - post data transfer operation */
|
||||
CURLM_STATE_COMPLETED, /* 15 - operation complete */
|
||||
CURLM_STATE_MSGSENT, /* 16 - the operation complete message is sent */
|
||||
CURLM_STATE_LAST /* 17 - not a true state, never use this */
|
||||
MSTATE_INIT, /* 0 - start in this state */
|
||||
MSTATE_PENDING, /* 1 - no connections, waiting for one */
|
||||
MSTATE_CONNECT, /* 2 - resolve/connect has been sent off */
|
||||
MSTATE_RESOLVING, /* 3 - awaiting the resolve to finalize */
|
||||
MSTATE_CONNECTING, /* 4 - awaiting the TCP connect to finalize */
|
||||
MSTATE_TUNNELING, /* 5 - awaiting HTTPS proxy SSL initialization to
|
||||
complete and/or proxy CONNECT to finalize */
|
||||
MSTATE_PROTOCONNECT, /* 6 - initiate protocol connect procedure */
|
||||
MSTATE_PROTOCONNECTING, /* 7 - completing the protocol-specific connect
|
||||
phase */
|
||||
MSTATE_DO, /* 8 - start send off the request (part 1) */
|
||||
MSTATE_DOING, /* 9 - sending off the request (part 1) */
|
||||
MSTATE_DOING_MORE, /* 10 - send off the request (part 2) */
|
||||
MSTATE_DID, /* 11 - done sending off request */
|
||||
MSTATE_PERFORMING, /* 12 - transfer data */
|
||||
MSTATE_RATELIMITING, /* 13 - wait because limit-rate exceeded */
|
||||
MSTATE_DONE, /* 14 - post data transfer operation */
|
||||
MSTATE_COMPLETED, /* 15 - operation complete */
|
||||
MSTATE_MSGSENT, /* 16 - the operation complete message is sent */
|
||||
MSTATE_LAST /* 17 - not a true state, never use this */
|
||||
} CURLMstate;
|
||||
|
||||
/* we support N sockets per easy handle. Set the corresponding bit to what
|
||||
@@ -71,8 +70,7 @@ typedef enum {
|
||||
|
||||
#define CURLPIPE_ANY (CURLPIPE_MULTIPLEX)
|
||||
|
||||
#if defined(USE_SOCKETPAIR) && !defined(USE_BLOCKING_SOCKETS) && \
|
||||
!defined(CURL_DISABLE_SOCKETPAIR)
|
||||
#if !defined(CURL_DISABLE_SOCKETPAIR)
|
||||
#define ENABLE_WAKEUP
|
||||
#endif
|
||||
|
||||
@@ -96,7 +94,7 @@ struct Curl_multi {
|
||||
struct Curl_llist msglist; /* a list of messages from completed transfers */
|
||||
|
||||
struct Curl_llist pending; /* Curl_easys that are in the
|
||||
CURLM_STATE_CONNECT_PEND state */
|
||||
MSTATE_PENDING state */
|
||||
|
||||
/* callback function and user data pointer for the *socket() API */
|
||||
curl_socket_callback socket_cb;
|
||||
@@ -142,9 +140,13 @@ struct Curl_multi {
|
||||
previous callback */
|
||||
unsigned int max_concurrent_streams;
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
WSAEVENT wsa_event; /* winsock event used for waits */
|
||||
#else
|
||||
#ifdef ENABLE_WAKEUP
|
||||
curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup
|
||||
0 is used for read, 1 is used for write */
|
||||
#endif
|
||||
#endif
|
||||
/* multiplexing wanted */
|
||||
bool multiplexing;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -127,7 +127,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
|
||||
&output_ptr, &out_bytes);
|
||||
if(!data)
|
||||
iconv_close(tmpcd);
|
||||
if((rc == ICONV_ERROR) || (in_bytes != 0)) {
|
||||
if((rc == ICONV_ERROR) || (in_bytes)) {
|
||||
failf(data,
|
||||
"The Curl_convert_to_network iconv call failed with errno %i: %s",
|
||||
errno, strerror(errno));
|
||||
@@ -193,7 +193,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
|
||||
&output_ptr, &out_bytes);
|
||||
if(!data)
|
||||
iconv_close(tmpcd);
|
||||
if((rc == ICONV_ERROR) || (in_bytes != 0)) {
|
||||
if((rc == ICONV_ERROR) || (in_bytes)) {
|
||||
failf(data,
|
||||
"Curl_convert_from_network iconv call failed with errno %i: %s",
|
||||
errno, strerror(errno));
|
||||
@@ -260,7 +260,7 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
|
||||
&output_ptr, &out_bytes);
|
||||
if(!data)
|
||||
iconv_close(tmpcd);
|
||||
if((rc == ICONV_ERROR) || (in_bytes != 0)) {
|
||||
if((rc == ICONV_ERROR) || (in_bytes)) {
|
||||
failf(data,
|
||||
"The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
|
||||
errno, strerror(errno));
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -47,13 +47,7 @@
|
||||
int curlx_nonblock(curl_socket_t sockfd, /* operate on this */
|
||||
int nonblock /* TRUE or FALSE */)
|
||||
{
|
||||
#if defined(USE_BLOCKING_SOCKETS)
|
||||
(void)sockfd;
|
||||
(void)nonblock;
|
||||
return 0; /* returns success */
|
||||
|
||||
#elif defined(HAVE_FCNTL_O_NONBLOCK)
|
||||
|
||||
#if defined(HAVE_FCNTL_O_NONBLOCK)
|
||||
/* most recent unix versions */
|
||||
int flags;
|
||||
flags = sfcntl(sockfd, F_GETFL, 0);
|
||||
|
||||
@@ -76,16 +76,16 @@ extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url,
|
||||
LDAP **ld);
|
||||
#endif
|
||||
|
||||
static CURLcode ldap_setup_connection(struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
static CURLcode ldap_do(struct Curl_easy *data, bool *done);
|
||||
static CURLcode ldap_done(struct Curl_easy *data, CURLcode, bool);
|
||||
static CURLcode ldap_connect(struct Curl_easy *data, bool *done);
|
||||
static CURLcode ldap_connecting(struct Curl_easy *data, bool *done);
|
||||
static CURLcode ldap_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn, bool dead);
|
||||
static CURLcode oldap_setup_connection(struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
static CURLcode oldap_do(struct Curl_easy *data, bool *done);
|
||||
static CURLcode oldap_done(struct Curl_easy *data, CURLcode, bool);
|
||||
static CURLcode oldap_connect(struct Curl_easy *data, bool *done);
|
||||
static CURLcode oldap_connecting(struct Curl_easy *data, bool *done);
|
||||
static CURLcode oldap_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn, bool dead);
|
||||
|
||||
static Curl_recv ldap_recv;
|
||||
static Curl_recv oldap_recv;
|
||||
|
||||
/*
|
||||
* LDAP protocol handler.
|
||||
@@ -93,20 +93,21 @@ static Curl_recv ldap_recv;
|
||||
|
||||
const struct Curl_handler Curl_handler_ldap = {
|
||||
"LDAP", /* scheme */
|
||||
ldap_setup_connection, /* setup_connection */
|
||||
ldap_do, /* do_it */
|
||||
ldap_done, /* done */
|
||||
oldap_setup_connection, /* setup_connection */
|
||||
oldap_do, /* do_it */
|
||||
oldap_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
ldap_connect, /* connect_it */
|
||||
ldap_connecting, /* connecting */
|
||||
oldap_connect, /* connect_it */
|
||||
oldap_connecting, /* connecting */
|
||||
ZERO_NULL, /* doing */
|
||||
ZERO_NULL, /* proto_getsock */
|
||||
ZERO_NULL, /* doing_getsock */
|
||||
ZERO_NULL, /* domore_getsock */
|
||||
ZERO_NULL, /* perform_getsock */
|
||||
ldap_disconnect, /* disconnect */
|
||||
oldap_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_LDAP, /* defport */
|
||||
CURLPROTO_LDAP, /* protocol */
|
||||
CURLPROTO_LDAP, /* family */
|
||||
@@ -120,20 +121,21 @@ const struct Curl_handler Curl_handler_ldap = {
|
||||
|
||||
const struct Curl_handler Curl_handler_ldaps = {
|
||||
"LDAPS", /* scheme */
|
||||
ldap_setup_connection, /* setup_connection */
|
||||
ldap_do, /* do_it */
|
||||
ldap_done, /* done */
|
||||
oldap_setup_connection, /* setup_connection */
|
||||
oldap_do, /* do_it */
|
||||
oldap_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
ldap_connect, /* connect_it */
|
||||
ldap_connecting, /* connecting */
|
||||
oldap_connect, /* connect_it */
|
||||
oldap_connecting, /* connecting */
|
||||
ZERO_NULL, /* doing */
|
||||
ZERO_NULL, /* proto_getsock */
|
||||
ZERO_NULL, /* doing_getsock */
|
||||
ZERO_NULL, /* domore_getsock */
|
||||
ZERO_NULL, /* perform_getsock */
|
||||
ldap_disconnect, /* disconnect */
|
||||
oldap_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_LDAPS, /* defport */
|
||||
CURLPROTO_LDAPS, /* protocol */
|
||||
CURLPROTO_LDAP, /* family */
|
||||
@@ -171,15 +173,15 @@ struct ldapreqinfo {
|
||||
int nument;
|
||||
};
|
||||
|
||||
static CURLcode ldap_setup_connection(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
static CURLcode oldap_setup_connection(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
struct ldapconninfo *li;
|
||||
LDAPURLDesc *lud;
|
||||
int rc, proto;
|
||||
CURLcode status;
|
||||
|
||||
rc = ldap_url_parse(data->change.url, &lud);
|
||||
rc = ldap_url_parse(data->state.url, &lud);
|
||||
if(rc != LDAP_URL_SUCCESS) {
|
||||
const char *msg = "url parsing problem";
|
||||
status = CURLE_URL_MALFORMAT;
|
||||
@@ -207,7 +209,7 @@ static CURLcode ldap_setup_connection(struct Curl_easy *data,
|
||||
static Sockbuf_IO ldapsb_tls;
|
||||
#endif
|
||||
|
||||
static CURLcode ldap_connect(struct Curl_easy *data, bool *done)
|
||||
static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
@@ -255,7 +257,7 @@ static CURLcode ldap_connect(struct Curl_easy *data, bool *done)
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode ldap_connecting(struct Curl_easy *data, bool *done)
|
||||
static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
@@ -278,7 +280,7 @@ static CURLcode ldap_connecting(struct Curl_easy *data, bool *done)
|
||||
if(!li->sslinst) {
|
||||
Sockbuf *sb;
|
||||
ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
|
||||
ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn);
|
||||
ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data);
|
||||
li->sslinst = TRUE;
|
||||
li->recv = conn->recv[FIRSTSOCKET];
|
||||
li->send = conn->send[FIRSTSOCKET];
|
||||
@@ -354,21 +356,28 @@ static CURLcode ldap_connecting(struct Curl_easy *data, bool *done)
|
||||
|
||||
if(info)
|
||||
ldap_memfree(info);
|
||||
conn->recv[FIRSTSOCKET] = ldap_recv;
|
||||
conn->recv[FIRSTSOCKET] = oldap_recv;
|
||||
*done = TRUE;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode ldap_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn, bool dead_connection)
|
||||
static CURLcode oldap_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool dead_connection)
|
||||
{
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
(void) dead_connection;
|
||||
(void) data;
|
||||
|
||||
if(li) {
|
||||
if(li->ld) {
|
||||
#ifdef USE_SSL
|
||||
if(conn->ssl[FIRSTSOCKET].use) {
|
||||
Sockbuf *sb;
|
||||
ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
|
||||
ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data);
|
||||
}
|
||||
#endif
|
||||
ldap_unbind_ext(li->ld, NULL, NULL);
|
||||
li->ld = NULL;
|
||||
}
|
||||
@@ -378,7 +387,7 @@ static CURLcode ldap_disconnect(struct Curl_easy *data,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
||||
static CURLcode oldap_do(struct Curl_easy *data, bool *done)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
@@ -390,9 +399,9 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
||||
|
||||
connkeep(conn, "OpenLDAP do");
|
||||
|
||||
infof(data, "LDAP local: %s\n", data->change.url);
|
||||
infof(data, "LDAP local: %s\n", data->state.url);
|
||||
|
||||
rc = ldap_url_parse(data->change.url, &ludp);
|
||||
rc = ldap_url_parse(data->state.url, &ludp);
|
||||
if(rc != LDAP_URL_SUCCESS) {
|
||||
const char *msg = "url parsing problem";
|
||||
status = CURLE_URL_MALFORMAT;
|
||||
@@ -423,8 +432,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode ldap_done(struct Curl_easy *data, CURLcode res,
|
||||
bool premature)
|
||||
static CURLcode oldap_done(struct Curl_easy *data, CURLcode res,
|
||||
bool premature)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ldapreqinfo *lr = data->req.p.ldap;
|
||||
@@ -446,8 +455,8 @@ static CURLcode ldap_done(struct Curl_easy *data, CURLcode res,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf,
|
||||
size_t len, CURLcode *err)
|
||||
static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
|
||||
size_t len, CURLcode *err)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
@@ -543,7 +552,7 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf,
|
||||
rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) {
|
||||
int i;
|
||||
|
||||
if(bv.bv_val == NULL)
|
||||
if(!bv.bv_val)
|
||||
break;
|
||||
|
||||
if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7))
|
||||
@@ -551,7 +560,7 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf,
|
||||
else
|
||||
binary = 0;
|
||||
|
||||
if(bvals == NULL) {
|
||||
if(!bvals) {
|
||||
writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
|
||||
if(writeerr) {
|
||||
*err = writeerr;
|
||||
@@ -660,7 +669,7 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf,
|
||||
|
||||
data->req.bytecount += bvals[i].bv_len + 1;
|
||||
}
|
||||
writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
|
||||
writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
|
||||
if(writeerr) {
|
||||
*err = writeerr;
|
||||
return -1;
|
||||
@@ -669,14 +678,14 @@ static ssize_t ldap_recv(struct Curl_easy *data, int sockindex, char *buf,
|
||||
data->req.bytecount++;
|
||||
}
|
||||
ber_memfree(bvals);
|
||||
writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
|
||||
writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
|
||||
if(writeerr) {
|
||||
*err = writeerr;
|
||||
return -1;
|
||||
}
|
||||
data->req.bytecount++;
|
||||
}
|
||||
writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
|
||||
writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
|
||||
if(writeerr) {
|
||||
*err = writeerr;
|
||||
return -1;
|
||||
@@ -716,8 +725,8 @@ ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
if(opt == LBER_SB_OPT_DATA_READY) {
|
||||
struct connectdata *conn = sbiod->sbiod_pvt;
|
||||
return Curl_ssl_data_pending(conn, FIRSTSOCKET);
|
||||
struct Curl_easy *data = sbiod->sbiod_pvt;
|
||||
return Curl_ssl_data_pending(data->conn, FIRSTSOCKET);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -725,14 +734,19 @@ ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
|
||||
static ber_slen_t
|
||||
ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
|
||||
{
|
||||
struct connectdata *conn = sbiod->sbiod_pvt;
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
ber_slen_t ret;
|
||||
CURLcode err = CURLE_RECV_ERROR;
|
||||
struct Curl_easy *data = sbiod->sbiod_pvt;
|
||||
ber_slen_t ret = 0;
|
||||
if(data) {
|
||||
struct connectdata *conn = data->conn;
|
||||
if(conn) {
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
CURLcode err = CURLE_RECV_ERROR;
|
||||
|
||||
ret = (li->recv)(conn->data, FIRSTSOCKET, buf, len, &err);
|
||||
if(ret < 0 && err == CURLE_AGAIN) {
|
||||
SET_SOCKERRNO(EWOULDBLOCK);
|
||||
ret = (li->recv)(data, FIRSTSOCKET, buf, len, &err);
|
||||
if(ret < 0 && err == CURLE_AGAIN) {
|
||||
SET_SOCKERRNO(EWOULDBLOCK);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -740,14 +754,18 @@ ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
|
||||
static ber_slen_t
|
||||
ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
|
||||
{
|
||||
struct connectdata *conn = sbiod->sbiod_pvt;
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
ber_slen_t ret;
|
||||
CURLcode err = CURLE_SEND_ERROR;
|
||||
|
||||
ret = (li->send)(conn->data, FIRSTSOCKET, buf, len, &err);
|
||||
if(ret < 0 && err == CURLE_AGAIN) {
|
||||
SET_SOCKERRNO(EWOULDBLOCK);
|
||||
struct Curl_easy *data = sbiod->sbiod_pvt;
|
||||
ber_slen_t ret = 0;
|
||||
if(data) {
|
||||
struct connectdata *conn = data->conn;
|
||||
if(conn) {
|
||||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
CURLcode err = CURLE_SEND_ERROR;
|
||||
ret = (li->send)(data, FIRSTSOCKET, buf, len, &err);
|
||||
if(ret < 0 && err == CURLE_AGAIN) {
|
||||
SET_SOCKERRNO(EWOULDBLOCK);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -33,10 +33,9 @@
|
||||
struct connectdata;
|
||||
|
||||
typedef enum {
|
||||
FTPTRANSFER_BODY, /* yes do transfer a body */
|
||||
FTPTRANSFER_INFO, /* do still go through to get info/headers */
|
||||
FTPTRANSFER_NONE, /* don't get anything and don't get info */
|
||||
FTPTRANSFER_LAST /* end of list marker, never used */
|
||||
PPTRANSFER_BODY, /* yes do transfer a body */
|
||||
PPTRANSFER_INFO, /* do still go through to get info/headers */
|
||||
PPTRANSFER_NONE /* don't get anything and don't get info */
|
||||
} curl_pp_transfer;
|
||||
|
||||
/*
|
||||
|
||||
@@ -131,6 +131,7 @@ const struct Curl_handler Curl_handler_pop3 = {
|
||||
pop3_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_POP3, /* defport */
|
||||
CURLPROTO_POP3, /* protocol */
|
||||
CURLPROTO_POP3, /* family */
|
||||
@@ -159,6 +160,7 @@ const struct Curl_handler Curl_handler_pop3s = {
|
||||
pop3_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_POP3S, /* defport */
|
||||
CURLPROTO_POP3S, /* protocol */
|
||||
CURLPROTO_POP3, /* family */
|
||||
@@ -571,12 +573,12 @@ static CURLcode pop3_perform_command(struct Curl_easy *data)
|
||||
const char *command = NULL;
|
||||
|
||||
/* Calculate the default command */
|
||||
if(pop3->id[0] == '\0' || data->set.ftp_list_only) {
|
||||
if(pop3->id[0] == '\0' || data->set.list_only) {
|
||||
command = "LIST";
|
||||
|
||||
if(pop3->id[0] != '\0')
|
||||
/* Message specific LIST so skip the BODY transfer */
|
||||
pop3->transfer = FTPTRANSFER_INFO;
|
||||
pop3->transfer = PPTRANSFER_INFO;
|
||||
}
|
||||
else
|
||||
command = "RETR";
|
||||
@@ -709,7 +711,7 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
|
||||
for(;;) {
|
||||
size_t llen;
|
||||
size_t wordlen;
|
||||
unsigned int mechbit;
|
||||
unsigned short mechbit;
|
||||
|
||||
while(len &&
|
||||
(*line == ' ' || *line == '\t' ||
|
||||
@@ -916,7 +918,7 @@ static CURLcode pop3_state_command_resp(struct Curl_easy *data,
|
||||
the strip counter here so that these bytes won't be delivered. */
|
||||
pop3c->strip = 2;
|
||||
|
||||
if(pop3->transfer == FTPTRANSFER_BODY) {
|
||||
if(pop3->transfer == PPTRANSFER_BODY) {
|
||||
/* POP3 download */
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
|
||||
|
||||
@@ -1150,7 +1152,7 @@ static CURLcode pop3_done(struct Curl_easy *data, CURLcode status,
|
||||
Curl_safefree(pop3->custom);
|
||||
|
||||
/* Clear the transfer mode for the next request */
|
||||
pop3->transfer = FTPTRANSFER_BODY;
|
||||
pop3->transfer = PPTRANSFER_BODY;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1174,7 +1176,7 @@ static CURLcode pop3_perform(struct Curl_easy *data, bool *connected,
|
||||
|
||||
if(data->set.opt_no_body) {
|
||||
/* Requested no body means no transfer */
|
||||
pop3->transfer = FTPTRANSFER_INFO;
|
||||
pop3->transfer = PPTRANSFER_INFO;
|
||||
}
|
||||
|
||||
*dophase_done = FALSE; /* not done yet */
|
||||
@@ -1515,8 +1517,17 @@ CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread)
|
||||
if(prev) {
|
||||
/* If the partial match was the CRLF and dot then only write the CRLF
|
||||
as the server would have inserted the dot */
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB,
|
||||
strip_dot ? prev - 1 : prev);
|
||||
if(strip_dot && prev - 1 > 0) {
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB,
|
||||
prev - 1);
|
||||
}
|
||||
else if(!strip_dot) {
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB,
|
||||
prev);
|
||||
}
|
||||
else {
|
||||
result = CURLE_OK;
|
||||
}
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
@@ -85,7 +85,7 @@ static char *max5data(curl_off_t bytes, char *max5)
|
||||
CURL_FORMAT_CURL_OFF_T "M", bytes/ONE_MEGABYTE,
|
||||
(bytes%ONE_MEGABYTE) / (ONE_MEGABYTE/CURL_OFF_T_C(10)) );
|
||||
|
||||
#if (CURL_SIZEOF_CURL_OFF_T > 4)
|
||||
#if (SIZEOF_CURL_OFF_T > 4)
|
||||
|
||||
else if(bytes < CURL_OFF_T_C(10000) * ONE_MEGABYTE)
|
||||
/* 'XXXXM' is good until we're at 10000MB or above */
|
||||
@@ -241,6 +241,8 @@ void Curl_pgrsStartNow(struct Curl_easy *data)
|
||||
data->progress.is_t_startransfer_set = false;
|
||||
data->progress.ul_limit_start = data->progress.start;
|
||||
data->progress.dl_limit_start = data->progress.start;
|
||||
data->progress.ul_limit_size = 0;
|
||||
data->progress.dl_limit_size = 0;
|
||||
data->progress.downloaded = 0;
|
||||
data->progress.uploaded = 0;
|
||||
/* clear all bits except HIDE and HEADERS_OUT */
|
||||
@@ -321,14 +323,14 @@ void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
|
||||
void Curl_ratelimit(struct Curl_easy *data, struct curltime now)
|
||||
{
|
||||
/* don't set a new stamp unless the time since last update is long enough */
|
||||
if(data->set.max_recv_speed > 0) {
|
||||
if(data->set.max_recv_speed) {
|
||||
if(Curl_timediff(now, data->progress.dl_limit_start) >=
|
||||
MIN_RATE_LIMIT_PERIOD) {
|
||||
data->progress.dl_limit_start = now;
|
||||
data->progress.dl_limit_size = data->progress.downloaded;
|
||||
}
|
||||
}
|
||||
if(data->set.max_send_speed > 0) {
|
||||
if(data->set.max_send_speed) {
|
||||
if(Curl_timediff(now, data->progress.ul_limit_start) >=
|
||||
MIN_RATE_LIMIT_PERIOD) {
|
||||
data->progress.ul_limit_start = now;
|
||||
@@ -369,94 +371,82 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size)
|
||||
}
|
||||
}
|
||||
|
||||
/* returns the average speed in bytes / second */
|
||||
static curl_off_t trspeed(curl_off_t size, /* number of bytes */
|
||||
curl_off_t us) /* microseconds */
|
||||
{
|
||||
if(us < 1)
|
||||
return size * 1000000;
|
||||
return (curl_off_t)((long double)size/us * 1000000);
|
||||
}
|
||||
|
||||
/* returns TRUE if it's time to show the progress meter */
|
||||
static bool progress_calc(struct Curl_easy *data, struct curltime now)
|
||||
{
|
||||
curl_off_t timespent;
|
||||
curl_off_t timespent_ms; /* milliseconds */
|
||||
curl_off_t dl = data->progress.downloaded;
|
||||
curl_off_t ul = data->progress.uploaded;
|
||||
bool timetoshow = FALSE;
|
||||
struct Progress * const p = &data->progress;
|
||||
|
||||
/* The time spent so far (from the start) */
|
||||
data->progress.timespent = Curl_timediff_us(now, data->progress.start);
|
||||
timespent = (curl_off_t)data->progress.timespent/1000000; /* seconds */
|
||||
timespent_ms = (curl_off_t)data->progress.timespent/1000; /* ms */
|
||||
|
||||
/* The average download speed this far */
|
||||
if(dl < CURL_OFF_T_MAX/1000)
|
||||
data->progress.dlspeed = (dl * 1000 / (timespent_ms>0?timespent_ms:1));
|
||||
else
|
||||
data->progress.dlspeed = (dl / (timespent>0?timespent:1));
|
||||
|
||||
/* The average upload speed this far */
|
||||
if(ul < CURL_OFF_T_MAX/1000)
|
||||
data->progress.ulspeed = (ul * 1000 / (timespent_ms>0?timespent_ms:1));
|
||||
else
|
||||
data->progress.ulspeed = (ul / (timespent>0?timespent:1));
|
||||
/* The time spent so far (from the start) in microseconds */
|
||||
p->timespent = Curl_timediff_us(now, p->start);
|
||||
p->dlspeed = trspeed(p->downloaded, p->timespent);
|
||||
p->ulspeed = trspeed(p->uploaded, p->timespent);
|
||||
|
||||
/* Calculations done at most once a second, unless end is reached */
|
||||
if(data->progress.lastshow != now.tv_sec) {
|
||||
if(p->lastshow != now.tv_sec) {
|
||||
int countindex; /* amount of seconds stored in the speeder array */
|
||||
int nowindex = data->progress.speeder_c% CURR_TIME;
|
||||
data->progress.lastshow = now.tv_sec;
|
||||
int nowindex = p->speeder_c% CURR_TIME;
|
||||
p->lastshow = now.tv_sec;
|
||||
timetoshow = TRUE;
|
||||
|
||||
/* Let's do the "current speed" thing, with the dl + ul speeds
|
||||
combined. Store the speed at entry 'nowindex'. */
|
||||
data->progress.speeder[ nowindex ] =
|
||||
data->progress.downloaded + data->progress.uploaded;
|
||||
p->speeder[ nowindex ] = p->downloaded + p->uploaded;
|
||||
|
||||
/* remember the exact time for this moment */
|
||||
data->progress.speeder_time [ nowindex ] = now;
|
||||
p->speeder_time [ nowindex ] = now;
|
||||
|
||||
/* advance our speeder_c counter, which is increased every time we get
|
||||
here and we expect it to never wrap as 2^32 is a lot of seconds! */
|
||||
data->progress.speeder_c++;
|
||||
p->speeder_c++;
|
||||
|
||||
/* figure out how many index entries of data we have stored in our speeder
|
||||
array. With N_ENTRIES filled in, we have about N_ENTRIES-1 seconds of
|
||||
transfer. Imagine, after one second we have filled in two entries,
|
||||
after two seconds we've filled in three entries etc. */
|
||||
countindex = ((data->progress.speeder_c >= CURR_TIME)?
|
||||
CURR_TIME:data->progress.speeder_c) - 1;
|
||||
countindex = ((p->speeder_c >= CURR_TIME)? CURR_TIME:p->speeder_c) - 1;
|
||||
|
||||
/* first of all, we don't do this if there's no counted seconds yet */
|
||||
if(countindex) {
|
||||
int checkindex;
|
||||
timediff_t span_ms;
|
||||
curl_off_t amount;
|
||||
|
||||
/* Get the index position to compare with the 'nowindex' position.
|
||||
Get the oldest entry possible. While we have less than CURR_TIME
|
||||
entries, the first entry will remain the oldest. */
|
||||
checkindex = (data->progress.speeder_c >= CURR_TIME)?
|
||||
data->progress.speeder_c%CURR_TIME:0;
|
||||
checkindex = (p->speeder_c >= CURR_TIME)? p->speeder_c%CURR_TIME:0;
|
||||
|
||||
/* Figure out the exact time for the time span */
|
||||
span_ms = Curl_timediff(now, data->progress.speeder_time[checkindex]);
|
||||
span_ms = Curl_timediff(now, p->speeder_time[checkindex]);
|
||||
if(0 == span_ms)
|
||||
span_ms = 1; /* at least one millisecond MUST have passed */
|
||||
|
||||
/* Calculate the average speed the last 'span_ms' milliseconds */
|
||||
{
|
||||
curl_off_t amount = data->progress.speeder[nowindex]-
|
||||
data->progress.speeder[checkindex];
|
||||
amount = p->speeder[nowindex]- p->speeder[checkindex];
|
||||
|
||||
if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */)
|
||||
/* the 'amount' value is bigger than would fit in 32 bits if
|
||||
multiplied with 1000, so we use the double math for this */
|
||||
data->progress.current_speed = (curl_off_t)
|
||||
((double)amount/((double)span_ms/1000.0));
|
||||
else
|
||||
/* the 'amount' value is small enough to fit within 32 bits even
|
||||
when multiplied with 1000 */
|
||||
data->progress.current_speed = amount*CURL_OFF_T_C(1000)/span_ms;
|
||||
}
|
||||
if(amount > CURL_OFF_T_C(4294967) /* 0xffffffff/1000 */)
|
||||
/* the 'amount' value is bigger than would fit in 32 bits if
|
||||
multiplied with 1000, so we use the double math for this */
|
||||
p->current_speed = (curl_off_t)
|
||||
((double)amount/((double)span_ms/1000.0));
|
||||
else
|
||||
/* the 'amount' value is small enough to fit within 32 bits even
|
||||
when multiplied with 1000 */
|
||||
p->current_speed = amount*CURL_OFF_T_C(1000)/span_ms;
|
||||
}
|
||||
else
|
||||
/* the first second we use the average */
|
||||
data->progress.current_speed =
|
||||
data->progress.ulspeed + data->progress.dlspeed;
|
||||
p->current_speed = p->ulspeed + p->dlspeed;
|
||||
|
||||
} /* Calculations end */
|
||||
return timetoshow;
|
||||
|
||||
@@ -109,6 +109,7 @@ const struct Curl_handler Curl_handler_rtsp = {
|
||||
rtsp_disconnect, /* disconnect */
|
||||
rtsp_rtp_readwrite, /* readwrite */
|
||||
rtsp_conncheck, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_RTSP, /* defport */
|
||||
CURLPROTO_RTSP, /* protocol */
|
||||
CURLPROTO_RTSP, /* family */
|
||||
@@ -404,8 +405,8 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
|
||||
|
||||
/* Referrer */
|
||||
Curl_safefree(data->state.aptr.ref);
|
||||
if(data->change.referer && !Curl_checkheaders(data, "Referer"))
|
||||
data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
|
||||
if(data->state.referer && !Curl_checkheaders(data, "Referer"))
|
||||
data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
|
||||
else
|
||||
data->state.aptr.ref = NULL;
|
||||
|
||||
@@ -680,7 +681,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
|
||||
if(rtp_dataleft != 0 && rtp[0] == '$') {
|
||||
if(rtp_dataleft && rtp[0] == '$') {
|
||||
DEBUGF(infof(data, "RTP Rewinding %zd %s\n", rtp_dataleft,
|
||||
*readmore ? "(READMORE)" : ""));
|
||||
|
||||
@@ -824,7 +825,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
|
||||
|
||||
/* Copy the id substring into a new buffer */
|
||||
data->set.str[STRING_RTSP_SESSION_ID] = malloc(idlen + 1);
|
||||
if(data->set.str[STRING_RTSP_SESSION_ID] == NULL)
|
||||
if(!data->set.str[STRING_RTSP_SESSION_ID])
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, idlen);
|
||||
(data->set.str[STRING_RTSP_SESSION_ID])[idlen] = '\0';
|
||||
|
||||
@@ -442,7 +442,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
|
||||
if(ufds[i].events & POLLPRI)
|
||||
ufds[i].revents |= POLLPRI;
|
||||
}
|
||||
if(ufds[i].revents != 0)
|
||||
if(ufds[i].revents)
|
||||
r++;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ static size_t convert_lineends(struct Curl_easy *data,
|
||||
char *inPtr, *outPtr;
|
||||
|
||||
/* sanity check */
|
||||
if((startPtr == NULL) || (size < 1)) {
|
||||
if(!startPtr || (size < 1)) {
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -309,6 +309,18 @@ CURLcode Curl_write(struct Curl_easy *data,
|
||||
conn = data->conn;
|
||||
num = (sockfd == conn->sock[SECONDARYSOCKET]);
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
{
|
||||
/* Allow debug builds to override this logic to force short sends
|
||||
*/
|
||||
char *p = getenv("CURL_SMALLSENDS");
|
||||
if(p) {
|
||||
size_t altsize = (size_t)strtoul(p, NULL, 10);
|
||||
if(altsize)
|
||||
len = CURLMIN(len, altsize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
bytes_written = conn->send[num](data, num, mem, len, &result);
|
||||
|
||||
*written = bytes_written;
|
||||
@@ -498,9 +510,7 @@ static CURLcode pausewrite(struct Curl_easy *data,
|
||||
/* store this information in the state struct for later use */
|
||||
Curl_dyn_init(&s->tempwrite[i].b, DYN_PAUSE_BUFFER);
|
||||
s->tempwrite[i].type = type;
|
||||
|
||||
if(newtype)
|
||||
s->tempcount++;
|
||||
s->tempcount++;
|
||||
}
|
||||
|
||||
if(Curl_dyn_addn(&s->tempwrite[i].b, (unsigned char *)ptr, len))
|
||||
@@ -606,7 +616,7 @@ static CURLcode chop_write(struct Curl_easy *data,
|
||||
/* Curl_client_write() sends data to the write callback(s)
|
||||
|
||||
The bit pattern defines to what "streams" to write to. Body and/or header.
|
||||
The defines are in sendf.h of course.
|
||||
The defines are in sendf.h of course. "len" is not allowed to be 0.
|
||||
|
||||
If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the
|
||||
local character encoding. This is a problem and should be changed in
|
||||
@@ -618,9 +628,8 @@ CURLcode Curl_client_write(struct Curl_easy *data,
|
||||
size_t len)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
if(0 == len)
|
||||
len = strlen(ptr);
|
||||
|
||||
DEBUGASSERT(len);
|
||||
DEBUGASSERT(type <= 3);
|
||||
|
||||
/* FTP data may need conversion. */
|
||||
|
||||
+123
-47
@@ -177,7 +177,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
break;
|
||||
case CURLOPT_SSL_CIPHER_LIST:
|
||||
/* set a list of cipher we want to use in the SSL connection */
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@@ -190,7 +190,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
case CURLOPT_TLS13_CIPHERS:
|
||||
if(Curl_ssl_tls13_ciphersuites()) {
|
||||
/* set preferred list of TLS 1.3 cipher suites */
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST],
|
||||
va_arg(param, char *));
|
||||
}
|
||||
else
|
||||
@@ -426,6 +426,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
version_max = C_SSLVERSION_MAX_VALUE(arg);
|
||||
|
||||
if(version < CURL_SSLVERSION_DEFAULT ||
|
||||
version == CURL_SSLVERSION_SSLv2 ||
|
||||
version == CURL_SSLVERSION_SSLv3 ||
|
||||
version >= CURL_SSLVERSION_LAST ||
|
||||
version_max < CURL_SSLVERSION_MAX_NONE ||
|
||||
version_max >= CURL_SSLVERSION_MAX_LAST)
|
||||
@@ -653,8 +655,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
data->set.httpauth = CURLAUTH_AWS_SIGV4;
|
||||
break;
|
||||
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
case CURLOPT_MIMEPOST:
|
||||
/*
|
||||
* Set to make us do MIME/form POST
|
||||
@@ -671,13 +671,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
/*
|
||||
* String to set in the HTTP Referer: field.
|
||||
*/
|
||||
if(data->change.referer_alloc) {
|
||||
Curl_safefree(data->change.referer);
|
||||
data->change.referer_alloc = FALSE;
|
||||
if(data->state.referer_alloc) {
|
||||
Curl_safefree(data->state.referer);
|
||||
data->state.referer_alloc = FALSE;
|
||||
}
|
||||
result = Curl_setstropt(&data->set.str[STRING_SET_REFERER],
|
||||
va_arg(param, char *));
|
||||
data->change.referer = data->set.str[STRING_SET_REFERER];
|
||||
data->state.referer = data->set.str[STRING_SET_REFERER];
|
||||
break;
|
||||
|
||||
case CURLOPT_USERAGENT:
|
||||
@@ -695,7 +695,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
data->set.headers = va_arg(param, struct curl_slist *);
|
||||
break;
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
case CURLOPT_PROXYHEADER:
|
||||
/*
|
||||
@@ -747,13 +746,27 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
/* append the cookie file name to the list of file names, and deal with
|
||||
them later */
|
||||
cl = curl_slist_append(data->change.cookielist, argptr);
|
||||
cl = curl_slist_append(data->state.cookielist, argptr);
|
||||
if(!cl) {
|
||||
curl_slist_free_all(data->change.cookielist);
|
||||
data->change.cookielist = NULL;
|
||||
curl_slist_free_all(data->state.cookielist);
|
||||
data->state.cookielist = NULL;
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
data->change.cookielist = cl; /* store the list for later use */
|
||||
data->state.cookielist = cl; /* store the list for later use */
|
||||
}
|
||||
else {
|
||||
/* clear the list of cookie files */
|
||||
curl_slist_free_all(data->state.cookielist);
|
||||
data->state.cookielist = NULL;
|
||||
|
||||
if(!data->share || !data->share->cookies) {
|
||||
/* throw away all existing cookies if this isn't a shared cookie
|
||||
container */
|
||||
Curl_cookie_clearall(data->cookies);
|
||||
Curl_cookie_cleanup(data->cookies);
|
||||
}
|
||||
/* disable the cookie engine */
|
||||
data->cookies = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -800,7 +813,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
case CURLOPT_COOKIELIST:
|
||||
argptr = va_arg(param, char *);
|
||||
|
||||
if(argptr == NULL)
|
||||
if(!argptr)
|
||||
break;
|
||||
|
||||
if(strcasecompare(argptr, "ALL")) {
|
||||
@@ -891,7 +904,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
if(arg == CURL_HTTP_VERSION_NONE)
|
||||
arg = CURL_HTTP_VERSION_2TLS;
|
||||
#endif
|
||||
data->set.httpversion = arg;
|
||||
data->set.httpwant = (unsigned char)arg;
|
||||
break;
|
||||
|
||||
case CURLOPT_EXPECT_100_TIMEOUT_MS:
|
||||
@@ -909,7 +922,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
arg = va_arg(param, unsigned long);
|
||||
if(arg > 1L)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
#ifdef USE_HYPER
|
||||
/* Hyper does not support HTTP/0.9 */
|
||||
if(arg)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
#else
|
||||
data->set.http09_allowed = arg ? TRUE : FALSE;
|
||||
#endif
|
||||
break;
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
@@ -1160,7 +1179,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
* An option that changes the command to one that asks for a list only, no
|
||||
* file info details. Used for FTP, POP3 and SFTP.
|
||||
*/
|
||||
data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
|
||||
data->set.list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
|
||||
break;
|
||||
|
||||
case CURLOPT_APPEND:
|
||||
@@ -1168,7 +1187,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
* We want to upload and append to an existing file. Used for FTP and
|
||||
* SFTP.
|
||||
*/
|
||||
data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
|
||||
data->set.remote_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
|
||||
break;
|
||||
|
||||
#ifndef CURL_DISABLE_FTP
|
||||
@@ -1335,14 +1354,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
/*
|
||||
* The URL to fetch.
|
||||
*/
|
||||
if(data->change.url_alloc) {
|
||||
if(data->state.url_alloc) {
|
||||
/* the already set URL is allocated, free it first! */
|
||||
Curl_safefree(data->change.url);
|
||||
data->change.url_alloc = FALSE;
|
||||
Curl_safefree(data->state.url);
|
||||
data->state.url_alloc = FALSE;
|
||||
}
|
||||
result = Curl_setstropt(&data->set.str[STRING_SET_URL],
|
||||
va_arg(param, char *));
|
||||
data->change.url = data->set.str[STRING_SET_URL];
|
||||
data->state.url = data->set.str[STRING_SET_URL];
|
||||
break;
|
||||
case CURLOPT_PORT:
|
||||
/*
|
||||
@@ -1416,7 +1435,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
result = Curl_setstropt(&data->set.str[STRING_USERNAME],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
|
||||
case CURLOPT_PASSWORD:
|
||||
/*
|
||||
* authentication password to use in the operation
|
||||
@@ -1474,7 +1492,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
* that aren't actually in use right now will be pruned immediately.
|
||||
*/
|
||||
data->set.resolve = va_arg(param, struct curl_slist *);
|
||||
data->change.resolve = data->set.resolve;
|
||||
data->state.resolve = data->set.resolve;
|
||||
break;
|
||||
case CURLOPT_PROGRESSFUNCTION:
|
||||
/*
|
||||
@@ -1666,14 +1684,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
/*
|
||||
* String that holds file name of the SSL certificate to use
|
||||
*/
|
||||
result = Curl_setstropt(&data->set.str[STRING_CERT_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_CERT],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
case CURLOPT_SSLCERT_BLOB:
|
||||
/*
|
||||
* Blob that holds file name of the SSL certificate to use
|
||||
*/
|
||||
result = Curl_setblobopt(&data->set.blobs[BLOB_CERT_ORIG],
|
||||
result = Curl_setblobopt(&data->set.blobs[BLOB_CERT],
|
||||
va_arg(param, struct curl_blob *));
|
||||
break;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@@ -1696,7 +1714,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
/*
|
||||
* String that holds file type of the SSL certificate to use
|
||||
*/
|
||||
result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@@ -1712,14 +1730,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
/*
|
||||
* String that holds file name of the SSL key to use
|
||||
*/
|
||||
result = Curl_setstropt(&data->set.str[STRING_KEY_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_KEY],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
case CURLOPT_SSLKEY_BLOB:
|
||||
/*
|
||||
* Blob that holds file name of the SSL key to use
|
||||
*/
|
||||
result = Curl_setblobopt(&data->set.blobs[BLOB_KEY_ORIG],
|
||||
result = Curl_setblobopt(&data->set.blobs[BLOB_KEY],
|
||||
va_arg(param, struct curl_blob *));
|
||||
break;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@@ -1742,7 +1760,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
/*
|
||||
* String that holds file type of the SSL key to use
|
||||
*/
|
||||
result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@@ -1758,7 +1776,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
/*
|
||||
* String that holds the SSL or SSH private key password.
|
||||
*/
|
||||
result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@@ -1852,6 +1870,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
data->set.ssl.primary.verifypeer;
|
||||
}
|
||||
break;
|
||||
case CURLOPT_DOH_SSL_VERIFYPEER:
|
||||
/*
|
||||
* Enable peer SSL verifying for DOH.
|
||||
*/
|
||||
data->set.doh_verifypeer = (0 != va_arg(param, long)) ?
|
||||
TRUE : FALSE;
|
||||
break;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
case CURLOPT_PROXY_SSL_VERIFYPEER:
|
||||
/*
|
||||
@@ -1884,6 +1909,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
data->set.ssl.primary.verifyhost;
|
||||
}
|
||||
break;
|
||||
case CURLOPT_DOH_SSL_VERIFYHOST:
|
||||
/*
|
||||
* Enable verification of the host name in the peer certificate for DOH
|
||||
*/
|
||||
arg = va_arg(param, long);
|
||||
|
||||
/* Treat both 1 and 2 as TRUE */
|
||||
data->set.doh_verifyhost = (bool)((arg & 3) ? TRUE : FALSE);
|
||||
break;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
case CURLOPT_PROXY_SSL_VERIFYHOST:
|
||||
/*
|
||||
@@ -1919,6 +1953,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
data->set.ssl.primary.verifystatus;
|
||||
}
|
||||
break;
|
||||
case CURLOPT_DOH_SSL_VERIFYSTATUS:
|
||||
/*
|
||||
* Enable certificate status verifying for DOH.
|
||||
*/
|
||||
if(!Curl_ssl_cert_status_request()) {
|
||||
result = CURLE_NOT_BUILT_IN;
|
||||
break;
|
||||
}
|
||||
|
||||
data->set.doh_verifystatus = (0 != va_arg(param, long)) ?
|
||||
TRUE : FALSE;
|
||||
break;
|
||||
case CURLOPT_SSL_CTX_FUNCTION:
|
||||
/*
|
||||
* Set a SSL_CTX callback
|
||||
@@ -1967,7 +2013,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
|
||||
va_arg(param, char *));
|
||||
else
|
||||
#endif
|
||||
@@ -1992,9 +2038,23 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
/*
|
||||
* Set CA info for SSL connection. Specify file name of the CA certificate
|
||||
*/
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
case CURLOPT_CAINFO_BLOB:
|
||||
/*
|
||||
* Blob that holds CA info for SSL connection.
|
||||
* Specify entire PEM of the CA certificate
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB)
|
||||
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO],
|
||||
va_arg(param, struct curl_blob *));
|
||||
else
|
||||
#endif
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
|
||||
break;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
case CURLOPT_PROXY_CAINFO:
|
||||
/*
|
||||
@@ -2004,6 +2064,19 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
case CURLOPT_PROXY_CAINFO_BLOB:
|
||||
/*
|
||||
* Blob that holds CA info for SSL connection proxy.
|
||||
* Specify entire PEM of the CA certificate
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB)
|
||||
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY],
|
||||
va_arg(param, struct curl_blob *));
|
||||
else
|
||||
#endif
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
break;
|
||||
#endif
|
||||
case CURLOPT_CAPATH:
|
||||
/*
|
||||
@@ -2013,7 +2086,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl->supports & SSLSUPP_CA_PATH)
|
||||
/* This does not work on windows. */
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH],
|
||||
va_arg(param, char *));
|
||||
else
|
||||
#endif
|
||||
@@ -2040,7 +2113,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
* Set CRL file info for SSL connection. Specify file name of the CRL
|
||||
* to check certificates revocation
|
||||
*/
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@@ -2058,14 +2131,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
* Set Issuer certificate file
|
||||
* to check certificates issuer
|
||||
*/
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
case CURLOPT_ISSUERCERT_BLOB:
|
||||
/*
|
||||
* Blob that holds Issuer certificate to check certificates issuer
|
||||
*/
|
||||
result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG],
|
||||
result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT],
|
||||
va_arg(param, struct curl_blob *));
|
||||
break;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@@ -2125,7 +2198,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
else if(arg < UPLOADBUFFER_MIN)
|
||||
arg = UPLOADBUFFER_MIN;
|
||||
|
||||
data->set.upload_buffer_size = arg;
|
||||
data->set.upload_buffer_size = (unsigned int)arg;
|
||||
Curl_safefree(data->state.ulbuf); /* force a realloc next opportunity */
|
||||
break;
|
||||
|
||||
@@ -2238,24 +2311,27 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
|
||||
case CURLOPT_SSL_OPTIONS:
|
||||
arg = va_arg(param, long);
|
||||
data->set.ssl.enable_beast =
|
||||
(bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE);
|
||||
data->set.ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
|
||||
data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
|
||||
data->set.ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
|
||||
data->set.ssl.revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
|
||||
data->set.ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
|
||||
data->set.ssl.auto_client_cert = !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
|
||||
/* If a setting is added here it should also be added in dohprobe()
|
||||
which sets its own CURLOPT_SSL_OPTIONS based on these settings. */
|
||||
break;
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
case CURLOPT_PROXY_SSL_OPTIONS:
|
||||
arg = va_arg(param, long);
|
||||
data->set.proxy_ssl.enable_beast =
|
||||
(bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE);
|
||||
data->set.proxy_ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
|
||||
data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
|
||||
data->set.proxy_ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
|
||||
data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
|
||||
data->set.proxy_ssl.revoke_best_effort =
|
||||
!!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
|
||||
data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
|
||||
data->set.proxy_ssl.auto_client_cert =
|
||||
!!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -2662,9 +2738,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
#endif
|
||||
#ifdef USE_TLS_SRP
|
||||
case CURLOPT_TLSAUTH_USERNAME:
|
||||
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
|
||||
va_arg(param, char *));
|
||||
if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
|
||||
if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
|
||||
data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
|
||||
break;
|
||||
case CURLOPT_PROXY_TLSAUTH_USERNAME:
|
||||
@@ -2677,9 +2753,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
#endif
|
||||
break;
|
||||
case CURLOPT_TLSAUTH_PASSWORD:
|
||||
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
|
||||
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
|
||||
va_arg(param, char *));
|
||||
if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
|
||||
if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
|
||||
data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
|
||||
break;
|
||||
case CURLOPT_PROXY_TLSAUTH_PASSWORD:
|
||||
@@ -2863,7 +2939,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
data->set.trailer_data = va_arg(param, void *);
|
||||
#endif
|
||||
break;
|
||||
#ifdef USE_HSTS
|
||||
#ifndef CURL_DISABLE_HSTS
|
||||
case CURLOPT_HSTSREADFUNCTION:
|
||||
data->set.hsts_read = va_arg(param, curl_hstsread_callback);
|
||||
break;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -87,7 +87,7 @@ static char *vms_translate_path(const char *path)
|
||||
/* See if the result is in VMS format, if not, we are done */
|
||||
/* Assume that this is a PATH, not just some data */
|
||||
test_str = strpbrk(path, ":[<^");
|
||||
if(test_str == NULL) {
|
||||
if(!test_str) {
|
||||
return (char *)path;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ static char *vms_getenv(const char *envvar)
|
||||
|
||||
/* first use the DECC getenv() function */
|
||||
result = decc$getenv(envvar);
|
||||
if(result == NULL) {
|
||||
if(!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ static struct passwd *vms_getpwuid(uid_t uid)
|
||||
#endif
|
||||
|
||||
my_passwd = decc_getpwuid(uid);
|
||||
if(my_passwd == NULL) {
|
||||
if(!my_passwd) {
|
||||
return my_passwd;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2017, Florin Petriuc, <petriuc.florin@gmail.com>
|
||||
* Copyright (C) 2018 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2018 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -50,11 +50,10 @@
|
||||
/* Please keep the SSL backend-specific #if branches in this order:
|
||||
*
|
||||
* 1. USE_OPENSSL
|
||||
* 2. USE_GNUTLS_NETTLE
|
||||
* 3. USE_GNUTLS
|
||||
* 4. USE_MBEDTLS
|
||||
* 5. USE_COMMON_CRYPTO
|
||||
* 6. USE_WIN32_CRYPTO
|
||||
* 2. USE_GNUTLS
|
||||
* 3. USE_MBEDTLS
|
||||
* 4. USE_COMMON_CRYPTO
|
||||
* 5. USE_WIN32_CRYPTO
|
||||
*
|
||||
* This ensures that the same SSL branch gets activated throughout this source
|
||||
* file even if multiple backends are enabled at the same time.
|
||||
@@ -65,7 +64,7 @@
|
||||
/* When OpenSSL is available we use the SHA256-function from OpenSSL */
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#elif defined(USE_GNUTLS_NETTLE)
|
||||
#elif defined(USE_GNUTLS)
|
||||
|
||||
#include <nettle/sha.h>
|
||||
|
||||
@@ -93,35 +92,6 @@ static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx)
|
||||
sha256_digest(ctx, SHA256_DIGEST_SIZE, digest);
|
||||
}
|
||||
|
||||
#elif defined(USE_GNUTLS)
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "curl_memory.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
typedef gcry_md_hd_t SHA256_CTX;
|
||||
|
||||
static void SHA256_Init(SHA256_CTX *ctx)
|
||||
{
|
||||
gcry_md_open(ctx, GCRY_MD_SHA256, 0);
|
||||
}
|
||||
|
||||
static void SHA256_Update(SHA256_CTX *ctx,
|
||||
const unsigned char *data,
|
||||
unsigned int length)
|
||||
{
|
||||
gcry_md_write(*ctx, data, length);
|
||||
}
|
||||
|
||||
static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx)
|
||||
{
|
||||
memcpy(digest, gcry_md_read(*ctx, 0), SHA256_DIGEST_LENGTH);
|
||||
gcry_md_close(*ctx);
|
||||
}
|
||||
|
||||
#elif defined(USE_MBEDTLS)
|
||||
|
||||
#include <mbedtls/sha256.h>
|
||||
|
||||
@@ -235,7 +235,7 @@ Curl_share_lock(struct Curl_easy *data, curl_lock_data type,
|
||||
{
|
||||
struct Curl_share *share = data->share;
|
||||
|
||||
if(share == NULL)
|
||||
if(!share)
|
||||
return CURLSHE_INVALID;
|
||||
|
||||
if(share->specifier & (1<<type)) {
|
||||
@@ -252,7 +252,7 @@ Curl_share_unlock(struct Curl_easy *data, curl_lock_data type)
|
||||
{
|
||||
struct Curl_share *share = data->share;
|
||||
|
||||
if(share == NULL)
|
||||
if(!share)
|
||||
return CURLSHE_INVALID;
|
||||
|
||||
if(share->specifier & (1<<type)) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && \
|
||||
(defined(USE_OPENSSL) || defined(USE_MBEDTLS))
|
||||
(defined(USE_OPENSSL) || defined(USE_MBEDTLS) || defined(USE_WOLFSSL))
|
||||
#include <signal.h>
|
||||
|
||||
struct sigpipe_ignore {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
|
||||
(CURL_SIZEOF_CURL_OFF_T > 4)
|
||||
(SIZEOF_CURL_OFF_T > 4)
|
||||
|
||||
#define BUILDING_CURL_SMB_C
|
||||
|
||||
@@ -88,6 +88,7 @@ const struct Curl_handler Curl_handler_smb = {
|
||||
smb_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_SMB, /* defport */
|
||||
CURLPROTO_SMB, /* protocol */
|
||||
CURLPROTO_SMB, /* family */
|
||||
@@ -114,6 +115,7 @@ const struct Curl_handler Curl_handler_smbs = {
|
||||
smb_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_SMBS, /* defport */
|
||||
CURLPROTO_SMBS, /* protocol */
|
||||
CURLPROTO_SMB, /* family */
|
||||
@@ -627,9 +629,8 @@ static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg)
|
||||
|
||||
/* Check if there is data in the transfer buffer */
|
||||
if(!smbc->send_size && smbc->upload_size) {
|
||||
size_t nread = smbc->upload_size > data->set.upload_buffer_size ?
|
||||
data->set.upload_buffer_size :
|
||||
smbc->upload_size;
|
||||
size_t nread = smbc->upload_size > (size_t)data->set.upload_buffer_size ?
|
||||
(size_t)data->set.upload_buffer_size : smbc->upload_size;
|
||||
data->req.upload_fromhere = data->state.ulbuf;
|
||||
result = Curl_fillreadbuffer(data, nread, &nread);
|
||||
if(result && result != CURLE_AGAIN)
|
||||
@@ -1022,4 +1023,4 @@ static CURLcode smb_parse_url_path(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
#endif /* CURL_DISABLE_SMB && USE_CURL_NTLM_CORE &&
|
||||
CURL_SIZEOF_CURL_OFF_T > 4 */
|
||||
SIZEOF_CURL_OFF_T > 4 */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
|
||||
* Copyright (C) 2018 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2018 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -244,12 +244,12 @@ struct smb_tree_disconnect {
|
||||
#endif /* BUILDING_CURL_SMB_C */
|
||||
|
||||
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
|
||||
(CURL_SIZEOF_CURL_OFF_T > 4)
|
||||
(SIZEOF_CURL_OFF_T > 4)
|
||||
|
||||
extern const struct Curl_handler Curl_handler_smb;
|
||||
extern const struct Curl_handler Curl_handler_smbs;
|
||||
|
||||
#endif /* CURL_DISABLE_SMB && USE_CURL_NTLM_CORE &&
|
||||
CURL_SIZEOF_CURL_OFF_T > 4 */
|
||||
SIZEOF_CURL_OFF_T > 4 */
|
||||
|
||||
#endif /* HEADER_CURL_SMB_H */
|
||||
|
||||
@@ -136,6 +136,7 @@ const struct Curl_handler Curl_handler_smtp = {
|
||||
smtp_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_SMTP, /* defport */
|
||||
CURLPROTO_SMTP, /* protocol */
|
||||
CURLPROTO_SMTP, /* family */
|
||||
@@ -164,6 +165,7 @@ const struct Curl_handler Curl_handler_smtps = {
|
||||
smtp_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
ZERO_NULL, /* connection_check */
|
||||
ZERO_NULL, /* attach connection */
|
||||
PORT_SMTPS, /* defport */
|
||||
CURLPROTO_SMTPS, /* protocol */
|
||||
CURLPROTO_SMTP, /* family */
|
||||
@@ -894,7 +896,7 @@ static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
|
||||
for(;;) {
|
||||
size_t llen;
|
||||
size_t wordlen;
|
||||
unsigned int mechbit;
|
||||
unsigned short mechbit;
|
||||
|
||||
while(len &&
|
||||
(*line == ' ' || *line == '\t' ||
|
||||
@@ -1433,7 +1435,7 @@ static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
|
||||
}
|
||||
|
||||
/* Clear the transfer mode for the next request */
|
||||
smtp->transfer = FTPTRANSFER_BODY;
|
||||
smtp->transfer = PPTRANSFER_BODY;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1457,7 +1459,7 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
|
||||
|
||||
if(data->set.opt_no_body) {
|
||||
/* Requested no body means no transfer */
|
||||
smtp->transfer = FTPTRANSFER_INFO;
|
||||
smtp->transfer = PPTRANSFER_INFO;
|
||||
}
|
||||
|
||||
*dophase_done = FALSE; /* not done yet */
|
||||
@@ -1564,7 +1566,7 @@ static CURLcode smtp_dophase_done(struct Curl_easy *data, bool connected)
|
||||
|
||||
(void)connected;
|
||||
|
||||
if(smtp->transfer != FTPTRANSFER_BODY)
|
||||
if(smtp->transfer != PPTRANSFER_BODY)
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
|
||||
@@ -1821,7 +1823,7 @@ CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
DEBUGASSERT(data->set.upload_buffer_size >= (size_t)nread);
|
||||
DEBUGASSERT((size_t)data->set.upload_buffer_size >= (size_t)nread);
|
||||
|
||||
/* Have we already sent part of the EOB? */
|
||||
eob_sent = smtp->eob;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2019 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -30,7 +30,4 @@ int Curl_socketpair(int domain, int type, int protocol,
|
||||
#define Curl_socketpair(a,b,c,d) socketpair(a,b,c,d)
|
||||
#endif
|
||||
|
||||
/* Defined here to allow specific build configs to disable it completely */
|
||||
#define USE_SOCKETPAIR 1
|
||||
|
||||
#endif /* HEADER_CURL_SOCKETPAIR_H */
|
||||
|
||||
@@ -426,7 +426,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
|
||||
*/
|
||||
|
||||
/* wrong version ? */
|
||||
if(socksreq[0] != 0) {
|
||||
if(socksreq[0]) {
|
||||
failf(data,
|
||||
"SOCKS4 reply has wrong version, version should be 0.");
|
||||
return CURLPX_BAD_VERSION;
|
||||
@@ -742,7 +742,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
||||
return CURLPX_OK;
|
||||
}
|
||||
/* ignore the first (VER) byte */
|
||||
else if(socksreq[1] != 0) { /* status */
|
||||
else if(socksreq[1]) { /* status */
|
||||
failf(data, "User was rejected by the SOCKS5 server (%d %d).",
|
||||
socksreq[0], socksreq[1]);
|
||||
return CURLPX_USER_REJECTED;
|
||||
@@ -927,7 +927,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
||||
"SOCKS5 reply has wrong version, version should be 5.");
|
||||
return CURLPX_BAD_VERSION;
|
||||
}
|
||||
else if(socksreq[1] != 0) { /* Anything besides 0 is an error */
|
||||
else if(socksreq[1]) { /* Anything besides 0 is an error */
|
||||
CURLproxycode rc = CURLPX_REPLY_UNASSIGNED;
|
||||
int code = socksreq[1];
|
||||
failf(data, "Can't complete SOCKS5 connection to %s. (%d)",
|
||||
|
||||
@@ -195,7 +195,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(gss_send_token.length != 0) {
|
||||
if(gss_send_token.length) {
|
||||
socksreq[0] = 1; /* GSS-API subnegotiation version */
|
||||
socksreq[1] = 1; /* authentication message type */
|
||||
us_length = htons((short)gss_send_token.length);
|
||||
|
||||
@@ -198,7 +198,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(sspi_send_token.cbBuffer != 0) {
|
||||
if(sspi_send_token.cbBuffer) {
|
||||
socksreq[0] = 1; /* GSS-API subnegotiation version */
|
||||
socksreq[1] = 1; /* authentication message type */
|
||||
us_length = htons((short)sspi_send_token.cbBuffer);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1997 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1997 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -42,7 +42,7 @@ struct Curl_tree *Curl_splay(struct curltime i,
|
||||
{
|
||||
struct Curl_tree N, *l, *r, *y;
|
||||
|
||||
if(t == NULL)
|
||||
if(!t)
|
||||
return t;
|
||||
N.smaller = N.larger = NULL;
|
||||
l = r = &N;
|
||||
@@ -50,14 +50,14 @@ struct Curl_tree *Curl_splay(struct curltime i,
|
||||
for(;;) {
|
||||
long comp = compare(i, t->key);
|
||||
if(comp < 0) {
|
||||
if(t->smaller == NULL)
|
||||
if(!t->smaller)
|
||||
break;
|
||||
if(compare(i, t->smaller->key) < 0) {
|
||||
y = t->smaller; /* rotate smaller */
|
||||
t->smaller = y->larger;
|
||||
y->larger = t;
|
||||
t = y;
|
||||
if(t->smaller == NULL)
|
||||
if(!t->smaller)
|
||||
break;
|
||||
}
|
||||
r->smaller = t; /* link smaller */
|
||||
@@ -65,14 +65,14 @@ struct Curl_tree *Curl_splay(struct curltime i,
|
||||
t = t->smaller;
|
||||
}
|
||||
else if(comp > 0) {
|
||||
if(t->larger == NULL)
|
||||
if(!t->larger)
|
||||
break;
|
||||
if(compare(i, t->larger->key) > 0) {
|
||||
y = t->larger; /* rotate larger */
|
||||
t->larger = y->smaller;
|
||||
y->smaller = t;
|
||||
t = y;
|
||||
if(t->larger == NULL)
|
||||
if(!t->larger)
|
||||
break;
|
||||
}
|
||||
l->larger = t; /* link larger */
|
||||
@@ -104,7 +104,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i,
|
||||
(time_t)-1, (unsigned int)-1
|
||||
}; /* will *NEVER* appear */
|
||||
|
||||
if(node == NULL)
|
||||
if(!node)
|
||||
return t;
|
||||
|
||||
if(t != NULL) {
|
||||
@@ -125,7 +125,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i,
|
||||
}
|
||||
}
|
||||
|
||||
if(t == NULL) {
|
||||
if(!t) {
|
||||
node->smaller = node->larger = NULL;
|
||||
}
|
||||
else if(compare(i, t->key) < 0) {
|
||||
@@ -262,7 +262,7 @@ int Curl_splayremove(struct Curl_tree *t,
|
||||
}
|
||||
else {
|
||||
/* Remove the root node */
|
||||
if(t->smaller == NULL)
|
||||
if(!t->smaller)
|
||||
x = t->larger;
|
||||
else {
|
||||
x = Curl_splay(removenode->key, t->smaller);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user