Merge branch 'upstream-curl' into update-curl

* upstream-curl:
  curl 2021-05-26 (6b951a69)
This commit is contained in:
Brad King
2021-05-27 15:23:20 -04:00
145 changed files with 6384 additions and 4479 deletions
+1 -19
View File
@@ -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)
+87 -43
View File
@@ -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}
+37 -8
View File
@@ -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()
+5 -5
View File
@@ -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;
+12 -5
View File
@@ -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}
+5
View File
@@ -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 \
+28 -1
View File
@@ -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__ */
+15 -45
View File
@@ -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);
}
+16 -60
View File
@@ -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));
+127
View File
@@ -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;
}
+46
View File
@@ -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
+31 -16
View File
@@ -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;
-2
View File
@@ -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);
+71 -56
View File
@@ -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;
+3 -3
View File
@@ -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);
+5 -4
View File
@@ -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
View File
@@ -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);
}
+7 -6
View File
@@ -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
+7 -1
View File
@@ -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 */
+19 -46
View File
@@ -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
+3 -3
View File
@@ -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 */
+2 -2
View File
@@ -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);
+2 -2
View File
@@ -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"
+1 -1
View File
@@ -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;
}
-1
View File
@@ -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 *);
};
+53 -35
View File
@@ -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 */
+21 -22
View File
@@ -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 */
+69 -76
View File
@@ -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);
+10 -8
View File
@@ -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);
+5 -5
View File
@@ -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);
+7 -1
View File
@@ -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
View File
@@ -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);
+11 -6
View File
@@ -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,
+46 -25
View File
@@ -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
+2 -17
View File
@@ -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.
*/
+6 -5
View File
@@ -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
View File
@@ -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],
+2 -2
View File
@@ -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
View File
@@ -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;
+6 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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 */
+1 -2
View File
@@ -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;
+7 -3
View File
@@ -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;
+2
View File
@@ -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 */
+2 -2
View File
@@ -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 */
}
+4 -4
View File
@@ -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;
+65 -19
View File
@@ -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 */
+1 -9
View File
@@ -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 */
+3 -16
View File
@@ -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;
+13 -8
View File
@@ -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 */
+4 -4
View File
@@ -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
View File
@@ -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 {
+11 -5
View File
@@ -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
View File
@@ -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 */
+3 -3
View File
@@ -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
+2 -2
View File
@@ -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};
+5 -6
View File
@@ -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;
}
-1
View File
@@ -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);
+1 -1
View File
@@ -179,7 +179,7 @@ CURLcode Curl_output_negotiate(struct Curl_easy *data,
free(base64);
if(userp == NULL) {
if(!userp) {
return CURLE_OUT_OF_MEMORY;
}
+59 -43
View File
@@ -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)
+84 -30
View File
@@ -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;
}
+24
View File
@@ -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 */
+6 -4
View File
@@ -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);
+2 -2
View File
@@ -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?
+5 -17
View File
@@ -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
View File
@@ -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);
}
+3 -3
View File
@@ -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;
+3 -30
View File
@@ -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);
+2 -29
View File
@@ -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>
+25 -10
View File
@@ -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! */
}
+2 -2
View File
@@ -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);
+2 -2
View 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;
+1
View File
@@ -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 */
File diff suppressed because it is too large Load Diff
+26 -24
View File
@@ -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;
+4 -4
View File
@@ -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));
+2 -8
View File
@@ -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);
+78 -60
View File
@@ -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;
}
+3 -4
View File
@@ -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;
/*
+19 -8
View File
@@ -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;
+40 -50
View File
@@ -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;
+5 -4
View File
@@ -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';
+1 -1
View File
@@ -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++;
}
+16 -7
View File
@@ -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
View File
@@ -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;
+4 -4
View File
@@ -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 -36
View File
@@ -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>
+2 -2
View File
@@ -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)) {
+2 -2
View File
@@ -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 {
+6 -5
View File
@@ -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 */
+3 -3
View File
@@ -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 */
+7 -5
View File
@@ -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;
+1 -4
View File
@@ -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 */
+3 -3
View File
@@ -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)",
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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);
+9 -9
View File
@@ -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