mirror of
https://github.com/reactos/CMake.git
synced 2024-12-14 07:09:22 +00:00
curl 2017-06-14 (54b636f1)
Code extracted from: https://github.com/curl/curl.git at commit 54b636f14546d3fde9f9c67c3b32701d78563161 (curl-7_54_1).
This commit is contained in:
parent
fd7d521c9d
commit
06d6d6c4ae
@ -380,7 +380,7 @@ if(CMAKE_USE_MBEDTLS)
|
||||
set(SSL_ENABLED ON)
|
||||
set(USE_MBEDTLS ON)
|
||||
list(APPEND CURL_LIBS ${MBEDTLS_LIBRARIES})
|
||||
include_directories(${MBEDTLS_INCLUDE_DIR})
|
||||
include_directories(${MBEDTLS_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
option(USE_NGHTTP2 "Use Nghttp2 library" OFF)
|
||||
@ -623,6 +623,78 @@ else()
|
||||
endif()
|
||||
|
||||
|
||||
#
|
||||
# CA handling
|
||||
#
|
||||
set(CURL_CA_BUNDLE "auto" CACHE STRING
|
||||
"Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
|
||||
set(CURL_CA_FALLBACK OFF CACHE BOOL
|
||||
"Set ON to use built-in CA store of TLS backend. Defaults to OFF")
|
||||
set(CURL_CA_PATH "auto" CACHE STRING
|
||||
"Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
|
||||
|
||||
if("${CURL_CA_BUNDLE}" STREQUAL "")
|
||||
message(FATAL_ERROR "Invalid value of CURL_CA_BUNDLE. Use 'none', 'auto' or file path.")
|
||||
elseif("${CURL_CA_BUNDLE}" STREQUAL "none")
|
||||
unset(CURL_CA_BUNDLE CACHE)
|
||||
elseif("${CURL_CA_BUNDLE}" STREQUAL "auto")
|
||||
unset(CURL_CA_BUNDLE CACHE)
|
||||
set(CURL_CA_BUNDLE_AUTODETECT TRUE)
|
||||
else()
|
||||
set(CURL_CA_BUNDLE_SET TRUE)
|
||||
endif()
|
||||
|
||||
if("${CURL_CA_PATH}" STREQUAL "")
|
||||
message(FATAL_ERROR "Invalid value of CURL_CA_PATH. Use 'none', 'auto' or directory path.")
|
||||
elseif("${CURL_CA_PATH}" STREQUAL "none")
|
||||
unset(CURL_CA_PATH CACHE)
|
||||
elseif("${CURL_CA_PATH}" STREQUAL "auto")
|
||||
unset(CURL_CA_PATH CACHE)
|
||||
set(CURL_CA_PATH_AUTODETECT TRUE)
|
||||
else()
|
||||
set(CURL_CA_PATH_SET TRUE)
|
||||
endif()
|
||||
|
||||
if(CURL_CA_BUNDLE_SET AND CURL_CA_PATH_AUTODETECT)
|
||||
# Skip autodetection of unset CA path because CA bundle is set explicitly
|
||||
elseif(CURL_CA_PATH_SET AND CURL_CA_BUNDLE_AUTODETECT)
|
||||
# Skip autodetection of unset CA bundle because CA path is set explicitly
|
||||
elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT)
|
||||
# first try autodetecting a CA bundle, then a CA path
|
||||
|
||||
if(CURL_CA_BUNDLE_AUTODETECT)
|
||||
set(SEARCH_CA_BUNDLE_PATHS
|
||||
/etc/ssl/certs/ca-certificates.crt
|
||||
/etc/pki/tls/certs/ca-bundle.crt
|
||||
/usr/share/ssl/certs/ca-bundle.crt
|
||||
/usr/local/share/certs/ca-root-nss.crt
|
||||
/etc/ssl/cert.pem)
|
||||
|
||||
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_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
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_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CURL_CA_PATH_SET AND NOT USE_OPENSSL AND NOT USE_MBEDTLS)
|
||||
message(FATAL_ERROR
|
||||
"CA path only supported by OpenSSL, GnuTLS or mbed TLS. "
|
||||
"Set CURL_CA_PATH=none or enable one of those TLS backends.")
|
||||
endif()
|
||||
|
||||
|
||||
# Check for header files
|
||||
if(NOT UNIX)
|
||||
check_include_file_concat("windows.h" HAVE_WINDOWS_H)
|
||||
@ -1127,8 +1199,7 @@ _add_if("Kerberos" NOT CURL_DISABLE_CRYPTO_AUTH AND
|
||||
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
|
||||
# NTLM support requires crypto function adaptions from various SSL libs
|
||||
# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
|
||||
if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR
|
||||
USE_WINDOWS_SSPI OR GNUTLS_ENABLED OR NSS_ENABLED OR USE_DARWINSSL OR USE_MBEDTLS))
|
||||
if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_DARWINSSL OR USE_MBEDTLS))
|
||||
_add_if("NTLM" 1)
|
||||
# TODO missing option (autoconf: --enable-ntlm-wb)
|
||||
_add_if("NTLM_WB" NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
|
||||
@ -1177,8 +1248,6 @@ set(CC "${CMAKE_C_COMPILER}")
|
||||
set(CONFIGURE_OPTIONS "")
|
||||
# TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB?
|
||||
set(CPPFLAG_CURL_STATICLIB "")
|
||||
# TODO need to set this (see CURL_CHECK_CA_BUNDLE in acinclude.m4)
|
||||
set(CURL_CA_BUNDLE "")
|
||||
set(CURLVERSION "${CURL_VERSION}")
|
||||
set(ENABLE_SHARED "yes")
|
||||
if(CURL_STATICLIB)
|
||||
|
@ -2251,6 +2251,7 @@ struct curl_tlssessioninfo {
|
||||
#define CURLINFO_LONG 0x200000
|
||||
#define CURLINFO_DOUBLE 0x300000
|
||||
#define CURLINFO_SLIST 0x400000
|
||||
#define CURLINFO_PTR 0x400000 /* same as SLIST */
|
||||
#define CURLINFO_SOCKET 0x500000
|
||||
#define CURLINFO_MASK 0x0fffff
|
||||
#define CURLINFO_TYPEMASK 0xf00000
|
||||
@ -2290,7 +2291,7 @@ typedef enum {
|
||||
CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31,
|
||||
CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32,
|
||||
CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33,
|
||||
CURLINFO_CERTINFO = CURLINFO_SLIST + 34,
|
||||
CURLINFO_CERTINFO = CURLINFO_PTR + 34,
|
||||
CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35,
|
||||
CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36,
|
||||
CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37,
|
||||
@ -2299,9 +2300,9 @@ typedef enum {
|
||||
CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
|
||||
CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
|
||||
CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
|
||||
CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43,
|
||||
CURLINFO_TLS_SESSION = CURLINFO_PTR + 43,
|
||||
CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44,
|
||||
CURLINFO_TLS_SSL_PTR = CURLINFO_SLIST + 45,
|
||||
CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45,
|
||||
CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46,
|
||||
CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
|
||||
CURLINFO_PROTOCOL = CURLINFO_LONG + 48,
|
||||
|
@ -30,13 +30,13 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.54.0-DEV"
|
||||
#define LIBCURL_VERSION "7.54.1-DEV"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 54
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
#define LIBCURL_VERSION_PATCH 1
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
|
||||
@ -57,18 +57,18 @@
|
||||
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 0x073600
|
||||
#define LIBCURL_VERSION_NUM 0x073601
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
* timestamp is not stored in git, as the timestamp is properly set in the
|
||||
* tarballs by the maketgz script.
|
||||
*
|
||||
* The format of the date should follow this template:
|
||||
* The format of the date follows this template:
|
||||
*
|
||||
* "Mon Feb 12 11:35:33 UTC 2007"
|
||||
* "2007-11-23"
|
||||
*/
|
||||
#define LIBCURL_TIMESTAMP "DEV"
|
||||
#define LIBCURL_TIMESTAMP "[unreleased]"
|
||||
|
||||
#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
|
||||
#define CURL_AT_LEAST_VERSION(x,y,z) \
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@ -124,6 +124,15 @@ __extension__ ({ \
|
||||
if(_curl_is_slist_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), struct curl_slist *)) \
|
||||
_curl_easy_getinfo_err_curl_slist(); \
|
||||
if(_curl_is_tlssessioninfo_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), struct curl_tlssessioninfo *)) \
|
||||
_curl_easy_getinfo_err_curl_tlssesssioninfo(); \
|
||||
if(_curl_is_certinfo_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), struct curl_certinfo *)) \
|
||||
_curl_easy_getinfo_err_curl_certinfo(); \
|
||||
if(_curl_is_socket_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), curl_socket_t)) \
|
||||
_curl_easy_getinfo_err_curl_socket(); \
|
||||
} \
|
||||
curl_easy_getinfo(handle, _curl_info, arg); \
|
||||
})
|
||||
@ -201,6 +210,14 @@ _CURL_WARNING(_curl_easy_getinfo_err_double,
|
||||
"curl_easy_getinfo expects a pointer to double for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
|
||||
"curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
|
||||
"curl_easy_getinfo expects a pointer to "
|
||||
"'struct curl_tlssessioninfo *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_certinfo,
|
||||
"curl_easy_getinfo expects a pointer to "
|
||||
"'struct curl_certinfo *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_socket,
|
||||
"curl_easy_getinfo expects a pointer to curl_socket_t for this info")
|
||||
|
||||
/* groups of curl_easy_setops options that take the same type of argument */
|
||||
|
||||
@ -249,11 +266,25 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
|
||||
(option) == CURLOPT_NOPROXY || \
|
||||
(option) == CURLOPT_PASSWORD || \
|
||||
(option) == CURLOPT_PINNEDPUBLICKEY || \
|
||||
(option) == CURLOPT_PRE_PROXY || \
|
||||
(option) == CURLOPT_PROXY || \
|
||||
(option) == CURLOPT_PROXYPASSWORD || \
|
||||
(option) == CURLOPT_PROXYUSERNAME || \
|
||||
(option) == CURLOPT_PROXYUSERPWD || \
|
||||
(option) == CURLOPT_PROXY_CAINFO || \
|
||||
(option) == CURLOPT_PROXY_CAPATH || \
|
||||
(option) == CURLOPT_PROXY_CRLFILE || \
|
||||
(option) == CURLOPT_PROXY_KEYPASSWD || \
|
||||
(option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
|
||||
(option) == CURLOPT_PROXY_SERVICE_NAME || \
|
||||
(option) == CURLOPT_PROXY_SSLCERT || \
|
||||
(option) == CURLOPT_PROXY_SSLCERTTYPE || \
|
||||
(option) == CURLOPT_PROXY_SSLKEY || \
|
||||
(option) == CURLOPT_PROXY_SSLKEYTYPE || \
|
||||
(option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
|
||||
(option) == CURLOPT_RANDOM_FILE || \
|
||||
(option) == CURLOPT_RANGE || \
|
||||
(option) == CURLOPT_REFERER || \
|
||||
@ -348,8 +379,19 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
|
||||
(CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
|
||||
|
||||
/* true if info expects a pointer to struct curl_slist * argument */
|
||||
#define _curl_is_slist_info(info) \
|
||||
(CURLINFO_SLIST < (info))
|
||||
#define _curl_is_slist_info(info) \
|
||||
(((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
|
||||
|
||||
/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
|
||||
#define _curl_is_tlssessioninfo_info(info) \
|
||||
(((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
|
||||
|
||||
/* true if info expects a pointer to struct curl_certinfo * argument */
|
||||
#define _curl_is_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
|
||||
|
||||
/* true if info expects a pointer to struct curl_socket_t argument */
|
||||
#define _curl_is_socket_info(info) \
|
||||
(CURLINFO_SOCKET < (info))
|
||||
|
||||
|
||||
/* typecheck helpers -- check whether given expression has requested type*/
|
||||
@ -428,8 +470,9 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
|
||||
#endif
|
||||
|
||||
/* evaluates to true if expr is of type FILE* */
|
||||
#define _curl_is_FILE(expr) \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), FILE *))
|
||||
#define _curl_is_FILE(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), FILE *)))
|
||||
|
||||
/* evaluates to true if expr can be passed as POST data (void* or char*) */
|
||||
#define _curl_is_postfields(expr) \
|
||||
@ -444,102 +487,102 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
|
||||
* function pointers, hide it */
|
||||
#define _curl_callback_compatible(func, type) \
|
||||
(__builtin_types_compatible_p(__typeof__(func), type) || \
|
||||
__builtin_types_compatible_p(__typeof__(func), type*))
|
||||
__builtin_types_compatible_p(__typeof__(func) *, type))
|
||||
|
||||
/* evaluates to true if expr is of type curl_read_callback or "similar" */
|
||||
#define _curl_is_read_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), curl_read_callback) || \
|
||||
_curl_callback_compatible((expr), __typeof__(fread) *) || \
|
||||
_curl_callback_compatible((expr), curl_read_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback6))
|
||||
typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void *);
|
||||
typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void *);
|
||||
typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE *);
|
||||
typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void *);
|
||||
typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void *);
|
||||
typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE *);
|
||||
typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *);
|
||||
typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
|
||||
typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *);
|
||||
typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_write_callback or "similar" */
|
||||
#define _curl_is_write_cb(expr) \
|
||||
(_curl_is_read_cb(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), curl_write_callback) || \
|
||||
_curl_callback_compatible((expr), __typeof__(fwrite) *) || \
|
||||
_curl_callback_compatible((expr), curl_write_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback6))
|
||||
typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void *);
|
||||
typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
|
||||
typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
|
||||
const void *);
|
||||
typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE *);
|
||||
typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void *);
|
||||
typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
|
||||
typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *);
|
||||
typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t,
|
||||
const void *);
|
||||
typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE *);
|
||||
typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
|
||||
#define _curl_is_ioctl_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) || \
|
||||
_curl_callback_compatible((expr), curl_ioctl_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback4))
|
||||
typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void *);
|
||||
typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void *);
|
||||
typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void *);
|
||||
typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
|
||||
#define _curl_is_sockopt_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) || \
|
||||
_curl_callback_compatible((expr), curl_sockopt_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_sockopt_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_sockopt_callback2))
|
||||
typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
|
||||
typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t,
|
||||
typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
|
||||
typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
|
||||
curlsocktype);
|
||||
|
||||
/* evaluates to true if expr is of type curl_opensocket_callback or
|
||||
"similar" */
|
||||
#define _curl_is_opensocket_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\
|
||||
_curl_callback_compatible((expr), curl_opensocket_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback4))
|
||||
typedef curl_socket_t (_curl_opensocket_callback1)
|
||||
typedef curl_socket_t (*_curl_opensocket_callback1)
|
||||
(void *, curlsocktype, struct curl_sockaddr *);
|
||||
typedef curl_socket_t (_curl_opensocket_callback2)
|
||||
typedef curl_socket_t (*_curl_opensocket_callback2)
|
||||
(void *, curlsocktype, const struct curl_sockaddr *);
|
||||
typedef curl_socket_t (_curl_opensocket_callback3)
|
||||
typedef curl_socket_t (*_curl_opensocket_callback3)
|
||||
(const void *, curlsocktype, struct curl_sockaddr *);
|
||||
typedef curl_socket_t (_curl_opensocket_callback4)
|
||||
typedef curl_socket_t (*_curl_opensocket_callback4)
|
||||
(const void *, curlsocktype, const struct curl_sockaddr *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_progress_callback or "similar" */
|
||||
#define _curl_is_progress_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) || \
|
||||
_curl_callback_compatible((expr), curl_progress_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_progress_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_progress_callback2))
|
||||
typedef int (_curl_progress_callback1)(void *,
|
||||
typedef int (*_curl_progress_callback1)(void *,
|
||||
double, double, double, double);
|
||||
typedef int (_curl_progress_callback2)(const void *,
|
||||
typedef int (*_curl_progress_callback2)(const void *,
|
||||
double, double, double, double);
|
||||
|
||||
/* evaluates to true if expr is of type curl_debug_callback or "similar" */
|
||||
#define _curl_is_debug_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) || \
|
||||
_curl_callback_compatible((expr), curl_debug_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback3) || \
|
||||
@ -548,28 +591,28 @@ typedef int (_curl_progress_callback2)(const void *,
|
||||
_curl_callback_compatible((expr), _curl_debug_callback6) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback7) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback8))
|
||||
typedef int (_curl_debug_callback1) (CURL *,
|
||||
typedef int (*_curl_debug_callback1) (CURL *,
|
||||
curl_infotype, char *, size_t, void *);
|
||||
typedef int (_curl_debug_callback2) (CURL *,
|
||||
typedef int (*_curl_debug_callback2) (CURL *,
|
||||
curl_infotype, char *, size_t, const void *);
|
||||
typedef int (_curl_debug_callback3) (CURL *,
|
||||
typedef int (*_curl_debug_callback3) (CURL *,
|
||||
curl_infotype, const char *, size_t, void *);
|
||||
typedef int (_curl_debug_callback4) (CURL *,
|
||||
typedef int (*_curl_debug_callback4) (CURL *,
|
||||
curl_infotype, const char *, size_t, const void *);
|
||||
typedef int (_curl_debug_callback5) (CURL *,
|
||||
typedef int (*_curl_debug_callback5) (CURL *,
|
||||
curl_infotype, unsigned char *, size_t, void *);
|
||||
typedef int (_curl_debug_callback6) (CURL *,
|
||||
typedef int (*_curl_debug_callback6) (CURL *,
|
||||
curl_infotype, unsigned char *, size_t, const void *);
|
||||
typedef int (_curl_debug_callback7) (CURL *,
|
||||
typedef int (*_curl_debug_callback7) (CURL *,
|
||||
curl_infotype, const unsigned char *, size_t, void *);
|
||||
typedef int (_curl_debug_callback8) (CURL *,
|
||||
typedef int (*_curl_debug_callback8) (CURL *,
|
||||
curl_infotype, const unsigned char *, size_t, const void *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
|
||||
/* this is getting even messier... */
|
||||
#define _curl_is_ssl_ctx_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) || \
|
||||
_curl_callback_compatible((expr), curl_ssl_ctx_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \
|
||||
@ -578,18 +621,19 @@ typedef int (_curl_debug_callback8) (CURL *,
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
|
||||
typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *);
|
||||
typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
|
||||
typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
|
||||
typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
|
||||
const void *);
|
||||
#ifdef HEADER_SSL_H
|
||||
/* 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,
|
||||
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;
|
||||
@ -601,7 +645,7 @@ typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
|
||||
/* evaluates to true if expr is of type curl_conv_callback or "similar" */
|
||||
#define _curl_is_conv_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) || \
|
||||
_curl_callback_compatible((expr), curl_conv_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback3) || \
|
||||
@ -614,7 +658,7 @@ typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
|
||||
/* evaluates to true if expr is of type curl_seek_callback or "similar" */
|
||||
#define _curl_is_seek_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) || \
|
||||
_curl_callback_compatible((expr), curl_seek_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_seek_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_seek_callback2))
|
||||
typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
|
||||
|
@ -232,7 +232,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
|
||||
milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
|
||||
if(milli == 0)
|
||||
milli += 10;
|
||||
Curl_expire_latest(conn->data, milli);
|
||||
Curl_expire(conn->data, milli, EXPIRE_ASYNC_NAME);
|
||||
|
||||
return max;
|
||||
}
|
||||
@ -373,7 +373,6 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
|
||||
/* Wait for the name resolve query to complete. */
|
||||
while(!result) {
|
||||
struct timeval *tvp, tv, store;
|
||||
long timediff;
|
||||
int itimeout;
|
||||
int timeout_ms;
|
||||
|
||||
@ -402,8 +401,13 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
else {
|
||||
struct timeval now2 = Curl_tvnow();
|
||||
timediff = Curl_tvdiff(now2, now); /* spent time */
|
||||
timeout -= timediff?timediff:1; /* always deduct at least 1 */
|
||||
time_t timediff = Curl_tvdiff(now2, now); /* spent time */
|
||||
if(timediff <= 0)
|
||||
timeout -= 1; /* always deduct at least 1 */
|
||||
else if(timediff > timeout)
|
||||
timeout = -1;
|
||||
else
|
||||
timeout -= (long)timediff;
|
||||
now = now2; /* for next loop */
|
||||
}
|
||||
if(timeout < 0)
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@ -22,6 +22,11 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
/***********************************************************************
|
||||
* Only for threaded name resolves builds
|
||||
**********************************************************************/
|
||||
#ifdef CURLRES_THREADED
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
@ -74,11 +79,6 @@
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
/***********************************************************************
|
||||
* Only for threaded name resolves builds
|
||||
**********************************************************************/
|
||||
#ifdef CURLRES_THREADED
|
||||
|
||||
/*
|
||||
* Curl_resolver_global_init()
|
||||
* Called from curl_global_init() to initialize global resolver environment.
|
||||
@ -540,7 +540,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
|
||||
td->poll_interval = 250;
|
||||
|
||||
td->interval_end = elapsed + td->poll_interval;
|
||||
Curl_expire(conn->data, td->poll_interval);
|
||||
Curl_expire(conn->data, td->poll_interval, EXPIRE_ASYNC_NAME);
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
|
@ -72,13 +72,11 @@ static void bundle_destroy(struct connectbundle *cb_ptr)
|
||||
|
||||
/* Add a connection to a bundle */
|
||||
static CURLcode bundle_add_conn(struct connectbundle *cb_ptr,
|
||||
struct connectdata *conn)
|
||||
struct connectdata *conn)
|
||||
{
|
||||
if(!Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn,
|
||||
&conn->bundle_node);
|
||||
conn->bundle = cb_ptr;
|
||||
|
||||
cb_ptr->num_connections++;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2017, 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
|
||||
@ -1070,7 +1070,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
|
||||
|
||||
conn->connecttime = Curl_tvnow();
|
||||
if(conn->num_addr > 1)
|
||||
Curl_expire_latest(data, conn->timeoutms_per_addr);
|
||||
Curl_expire(data, conn->timeoutms_per_addr, EXPIRE_DNS_PER_NAME);
|
||||
|
||||
/* Connect TCP sockets, bind UDP */
|
||||
if(!isconnected && (conn->socktype == SOCK_STREAM)) {
|
||||
@ -1169,7 +1169,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
conn->tempaddr[1] = NULL;
|
||||
conn->tempsock[0] = CURL_SOCKET_BAD;
|
||||
conn->tempsock[1] = CURL_SOCKET_BAD;
|
||||
Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
|
||||
Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS);
|
||||
|
||||
/* Max time for the next connection attempt */
|
||||
conn->timeoutms_per_addr =
|
||||
|
@ -4,10 +4,13 @@
|
||||
#cmakedefine BUILDING_LIBCURL 1
|
||||
|
||||
/* Location of default ca bundle */
|
||||
#cmakedefine CURL_CA_BUNDLE ${CURL_CA_BUNDLE}
|
||||
#cmakedefine CURL_CA_BUNDLE "${CURL_CA_BUNDLE}"
|
||||
|
||||
/* define "1" to use built-in ca store of TLS backend */
|
||||
#cmakedefine CURL_CA_FALLBACK 1
|
||||
|
||||
/* Location of default ca path */
|
||||
#cmakedefine CURL_CA_PATH ${CURL_CA_PATH}
|
||||
#cmakedefine CURL_CA_PATH "${CURL_CA_PATH}"
|
||||
|
||||
/* to disable cookies support */
|
||||
#cmakedefine CURL_DISABLE_COOKIES 1
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2017, 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
|
||||
@ -62,44 +62,6 @@ unsigned int Curl_read32_le(const unsigned char *buf)
|
||||
((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
|
||||
}
|
||||
|
||||
#if (CURL_SIZEOF_CURL_OFF_T > 4)
|
||||
/*
|
||||
* Curl_read64_le()
|
||||
*
|
||||
* This function converts a 64-bit integer from the little endian format, as
|
||||
* used in the incoming package to whatever endian format we're using
|
||||
* natively.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* buf [in] - A pointer to a 8 byte buffer.
|
||||
*
|
||||
* Returns the integer.
|
||||
*/
|
||||
#if defined(HAVE_LONGLONG)
|
||||
unsigned long long Curl_read64_le(const unsigned char *buf)
|
||||
{
|
||||
return ((unsigned long long)buf[0]) |
|
||||
((unsigned long long)buf[1] << 8) |
|
||||
((unsigned long long)buf[2] << 16) |
|
||||
((unsigned long long)buf[3] << 24) |
|
||||
((unsigned long long)buf[4] << 32) |
|
||||
((unsigned long long)buf[5] << 40) |
|
||||
((unsigned long long)buf[6] << 48) |
|
||||
((unsigned long long)buf[7] << 56);
|
||||
}
|
||||
#else
|
||||
unsigned __int64 Curl_read64_le(const unsigned char *buf)
|
||||
{
|
||||
return ((unsigned __int64)buf[0]) | ((unsigned __int64)buf[1] << 8) |
|
||||
((unsigned __int64)buf[2] << 16) | ((unsigned __int64)buf[3] << 24) |
|
||||
((unsigned __int64)buf[4] << 32) | ((unsigned __int64)buf[5] << 40) |
|
||||
((unsigned __int64)buf[6] << 48) | ((unsigned __int64)buf[7] << 56);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */
|
||||
|
||||
/*
|
||||
* Curl_read16_be()
|
||||
*
|
||||
@ -119,80 +81,6 @@ unsigned short Curl_read16_be(const unsigned char *buf)
|
||||
((unsigned short)buf[1]));
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_read32_be()
|
||||
*
|
||||
* This function converts a 32-bit integer from the big endian format, as
|
||||
* used in the incoming package to whatever endian format we're using
|
||||
* natively.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* buf [in] - A pointer to a 4 byte buffer.
|
||||
*
|
||||
* Returns the integer.
|
||||
*/
|
||||
unsigned int Curl_read32_be(const unsigned char *buf)
|
||||
{
|
||||
return ((unsigned int)buf[0] << 24) | ((unsigned int)buf[1] << 16) |
|
||||
((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]);
|
||||
}
|
||||
|
||||
#if (CURL_SIZEOF_CURL_OFF_T > 4)
|
||||
/*
|
||||
* Curl_read64_be()
|
||||
*
|
||||
* This function converts a 64-bit integer from the big endian format, as
|
||||
* used in the incoming package to whatever endian format we're using
|
||||
* natively.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* buf [in] - A pointer to a 8 byte buffer.
|
||||
*
|
||||
* Returns the integer.
|
||||
*/
|
||||
#if defined(HAVE_LONGLONG)
|
||||
unsigned long long Curl_read64_be(const unsigned char *buf)
|
||||
{
|
||||
return ((unsigned long long)buf[0] << 56) |
|
||||
((unsigned long long)buf[1] << 48) |
|
||||
((unsigned long long)buf[2] << 40) |
|
||||
((unsigned long long)buf[3] << 32) |
|
||||
((unsigned long long)buf[4] << 24) |
|
||||
((unsigned long long)buf[5] << 16) |
|
||||
((unsigned long long)buf[6] << 8) |
|
||||
((unsigned long long)buf[7]);
|
||||
}
|
||||
#else
|
||||
unsigned __int64 Curl_read64_be(const unsigned char *buf)
|
||||
{
|
||||
return ((unsigned __int64)buf[0] << 56) | ((unsigned __int64)buf[1] << 48) |
|
||||
((unsigned __int64)buf[2] << 40) | ((unsigned __int64)buf[3] << 32) |
|
||||
((unsigned __int64)buf[4] << 24) | ((unsigned __int64)buf[5] << 16) |
|
||||
((unsigned __int64)buf[6] << 8) | ((unsigned __int64)buf[7]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */
|
||||
|
||||
/*
|
||||
* Curl_write16_le()
|
||||
*
|
||||
* This function converts a 16-bit integer from the native endian format,
|
||||
* to little endian format ready for sending down the wire.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* value [in] - The 16-bit integer value.
|
||||
* buffer [in] - A pointer to the output buffer.
|
||||
*/
|
||||
void Curl_write16_le(const short value, unsigned char *buffer)
|
||||
{
|
||||
buffer[0] = (char)(value & 0x00FF);
|
||||
buffer[1] = (char)((value & 0xFF00) >> 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_write32_le()
|
||||
*
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@ -28,33 +28,9 @@ unsigned short Curl_read16_le(const unsigned char *buf);
|
||||
/* Converts a 32-bit integer from little endian */
|
||||
unsigned int Curl_read32_le(const unsigned char *buf);
|
||||
|
||||
#if (CURL_SIZEOF_CURL_OFF_T > 4)
|
||||
/* Converts a 64-bit integer from little endian */
|
||||
#if defined(HAVE_LONGLONG)
|
||||
unsigned long long Curl_read64_le(const unsigned char *buf);
|
||||
#else
|
||||
unsigned __int64 Curl_read64_le(const unsigned char *buf);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Converts a 16-bit integer from big endian */
|
||||
unsigned short Curl_read16_be(const unsigned char *buf);
|
||||
|
||||
/* Converts a 32-bit integer from big endian */
|
||||
unsigned int Curl_read32_be(const unsigned char *buf);
|
||||
|
||||
#if (CURL_SIZEOF_CURL_OFF_T > 4)
|
||||
/* Converts a 64-bit integer from big endian */
|
||||
#if defined(HAVE_LONGLONG)
|
||||
unsigned long long Curl_read64_be(const unsigned char *buf);
|
||||
#else
|
||||
unsigned __int64 Curl_read64_be(const unsigned char *buf);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Converts a 16-bit integer to little endian */
|
||||
void Curl_write16_le(const short value, unsigned char *buffer);
|
||||
|
||||
/* Converts a 32-bit integer to little endian */
|
||||
void Curl_write32_le(const int value, unsigned char *buffer);
|
||||
|
||||
|
@ -24,12 +24,12 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
/* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so
|
||||
* that we have a local implementation of it */
|
||||
#if defined(USE_NSS) || defined(USE_OS400CRYPTO)
|
||||
#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
|
||||
(defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
|
||||
|
||||
void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len);
|
||||
|
||||
#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */
|
||||
#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
|
||||
(defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
|
||||
|
||||
#endif /* HEADER_CURL_MD4_H */
|
||||
|
@ -80,6 +80,9 @@
|
||||
|
||||
# include <mbedtls/des.h>
|
||||
# include <mbedtls/md4.h>
|
||||
# if !defined(MBEDTLS_MD4_C)
|
||||
# include "curl_md4.h"
|
||||
# endif
|
||||
|
||||
#elif defined(USE_NSS)
|
||||
|
||||
@ -519,7 +522,7 @@ static void ascii_uppercase_to_unicode_le(unsigned char *dest,
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < srclen; i++) {
|
||||
dest[2 * i] = (unsigned char)(toupper(src[i]));
|
||||
dest[2 * i] = (unsigned char)(Curl_raw_toupper(src[i]));
|
||||
dest[2 * i + 1] = '\0';
|
||||
}
|
||||
}
|
||||
@ -568,10 +571,11 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
|
||||
gcry_md_write(MD4pw, pw, 2 * len);
|
||||
memcpy(ntbuffer, gcry_md_read(MD4pw, 0), MD4_DIGEST_LENGTH);
|
||||
gcry_md_close(MD4pw);
|
||||
#elif defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
|
||||
(defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
|
||||
Curl_md4it(ntbuffer, pw, 2 * len);
|
||||
#elif defined(USE_MBEDTLS)
|
||||
mbedtls_md4(pw, 2 * len, ntbuffer);
|
||||
#elif defined(USE_NSS) || defined(USE_OS400CRYPTO)
|
||||
Curl_md4it(ntbuffer, pw, 2 * len);
|
||||
#elif defined(USE_DARWINSSL)
|
||||
(void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
|
||||
#elif defined(USE_WIN32_CRYPTO)
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#ifdef USE_LIBRTMP
|
||||
|
||||
#include "curl_rtmp.h"
|
||||
#include "urldata.h"
|
||||
#include "nonblock.h" /* for curlx_nonblock */
|
||||
#include "progress.h" /* for Curl_pgrsSetUploadSize */
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2012 - 2017, 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
|
||||
@ -415,7 +415,6 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
|
||||
conn->host.name;
|
||||
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
char *serverdata;
|
||||
char *chlg = NULL;
|
||||
size_t chlglen = 0;
|
||||
#endif
|
||||
@ -423,6 +422,10 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
|
||||
const char *service = data->set.str[STRING_SERVICE_NAME] ?
|
||||
data->set.str[STRING_SERVICE_NAME] :
|
||||
sasl->params->service;
|
||||
#endif
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
|
||||
defined(USE_NTLM)
|
||||
char *serverdata;
|
||||
#endif
|
||||
size_t len = 0;
|
||||
|
||||
|
@ -588,11 +588,15 @@ int netware_init(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H)
|
||||
#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN)
|
||||
/* The lib and header are present */
|
||||
#define USE_LIBIDN2
|
||||
#endif
|
||||
|
||||
#if defined(USE_LIBIDN2) && defined(USE_WIN32_IDN)
|
||||
#error "Both libidn2 and WinIDN are enabled, choose one."
|
||||
#endif
|
||||
|
||||
#ifndef SIZEOF_TIME_T
|
||||
/* assume default size of time_t to be 32 bit */
|
||||
#define SIZEOF_TIME_T 4
|
||||
@ -623,14 +627,14 @@ int netware_init(void);
|
||||
#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
|
||||
defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \
|
||||
defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
|
||||
defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
|
||||
defined(USE_MBEDTLS)
|
||||
|
||||
#define USE_NTLM
|
||||
|
||||
#elif defined(USE_MBEDTLS)
|
||||
# if defined(USE_MBEDTLS)
|
||||
/* Get definition of MBEDTLS_MD4_C */
|
||||
# include <mbedtls/md4.h>
|
||||
# if defined(MBEDTLS_MD4_C)
|
||||
#define USE_NTLM
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
@ -196,7 +196,7 @@ struct timeval {
|
||||
/* */
|
||||
#else
|
||||
#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \
|
||||
(SEND_TYPE_ARG2)(y), \
|
||||
(SEND_QUAL_ARG2 SEND_TYPE_ARG2)(y), \
|
||||
(SEND_TYPE_ARG3)(z), \
|
||||
(SEND_TYPE_ARG4)(SEND_4TH_ARG))
|
||||
#endif
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@ -147,6 +147,7 @@ char *Curl_dedotdotify(const char *input)
|
||||
|
||||
else if(!strcmp(".", clone) || !strcmp("..", clone)) {
|
||||
*clone=0;
|
||||
*out=0;
|
||||
}
|
||||
|
||||
else {
|
||||
|
18
lib/easy.c
18
lib/easy.c
@ -561,7 +561,7 @@ static void events_setup(struct Curl_multi *multi, struct events *ev)
|
||||
static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
|
||||
{
|
||||
bool done = FALSE;
|
||||
CURLMcode mcode;
|
||||
CURLMcode mcode = CURLM_OK;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
while(!done) {
|
||||
@ -615,12 +615,18 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
|
||||
}
|
||||
}
|
||||
|
||||
if(!ev->msbump)
|
||||
if(!ev->msbump) {
|
||||
/* If nothing updated the timeout, we decrease it by the spent time.
|
||||
* If it was updated, it has the new timeout time stored already.
|
||||
*/
|
||||
ev->ms += (long)curlx_tvdiff(after, before);
|
||||
|
||||
time_t timediff = curlx_tvdiff(after, before);
|
||||
if(timediff > 0) {
|
||||
if(timediff > ev->ms)
|
||||
ev->ms = 0;
|
||||
else
|
||||
ev->ms -= (long)timediff;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
return CURLE_RECV_ERROR;
|
||||
@ -870,7 +876,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
|
||||
* the likeliness of us forgetting to init a buffer here in the future.
|
||||
*/
|
||||
outcurl->set.buffer_size = data->set.buffer_size;
|
||||
outcurl->state.buffer = malloc(CURL_BUFSIZE(outcurl->set.buffer_size) + 1);
|
||||
outcurl->state.buffer = malloc(outcurl->set.buffer_size + 1);
|
||||
if(!outcurl->state.buffer)
|
||||
goto fail;
|
||||
|
||||
@ -1044,7 +1050,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
||||
if(!result &&
|
||||
((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
|
||||
(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
|
||||
Curl_expire(data, 0); /* get this handle going again */
|
||||
Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
24
lib/file.c
24
lib/file.c
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2017, 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
|
||||
@ -311,7 +311,6 @@ static CURLcode file_upload(struct connectdata *conn)
|
||||
size_t nread;
|
||||
size_t nwrite;
|
||||
curl_off_t bytecount = 0;
|
||||
struct timeval now = Curl_tvnow();
|
||||
struct_stat file_stat;
|
||||
const char *buf2;
|
||||
|
||||
@ -360,7 +359,7 @@ static CURLcode file_upload(struct connectdata *conn)
|
||||
|
||||
while(!result) {
|
||||
int readcount;
|
||||
result = Curl_fillreadbuffer(conn, BUFSIZE, &readcount);
|
||||
result = Curl_fillreadbuffer(conn, (int)data->set.buffer_size, &readcount);
|
||||
if(result)
|
||||
break;
|
||||
|
||||
@ -399,7 +398,7 @@ static CURLcode file_upload(struct connectdata *conn)
|
||||
if(Curl_pgrsUpdate(conn))
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
else
|
||||
result = Curl_speedcheck(data, now);
|
||||
result = Curl_speedcheck(data, Curl_tvnow());
|
||||
}
|
||||
if(!result && Curl_pgrsUpdate(conn))
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
@ -436,7 +435,6 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
|
||||
char *buf = data->state.buffer;
|
||||
curl_off_t bytecount = 0;
|
||||
int fd;
|
||||
struct timeval now = Curl_tvnow();
|
||||
struct FILEPROTO *file;
|
||||
|
||||
*done = TRUE; /* unconditionally */
|
||||
@ -475,9 +473,10 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
|
||||
time_t filetime;
|
||||
struct tm buffer;
|
||||
const struct tm *tm = &buffer;
|
||||
snprintf(buf, CURL_BUFSIZE(data->set.buffer_size),
|
||||
char header[80];
|
||||
snprintf(header, sizeof(header),
|
||||
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size);
|
||||
result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
|
||||
result = Curl_client_write(conn, CLIENTWRITE_BOTH, header, 0);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
@ -492,7 +491,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
|
||||
return result;
|
||||
|
||||
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
|
||||
snprintf(buf, BUFSIZE-1,
|
||||
snprintf(header, sizeof(header),
|
||||
"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,
|
||||
@ -557,12 +556,11 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
|
||||
size_t bytestoread;
|
||||
|
||||
if(size_known) {
|
||||
bytestoread =
|
||||
(expected_size < CURL_OFF_T_C(BUFSIZE) - CURL_OFF_T_C(1)) ?
|
||||
curlx_sotouz(expected_size) : BUFSIZE - 1;
|
||||
bytestoread = (expected_size < data->set.buffer_size) ?
|
||||
curlx_sotouz(expected_size) : (size_t)data->set.buffer_size;
|
||||
}
|
||||
else
|
||||
bytestoread = BUFSIZE-1;
|
||||
bytestoread = data->set.buffer_size-1;
|
||||
|
||||
nread = read(fd, buf, bytestoread);
|
||||
|
||||
@ -585,7 +583,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
|
||||
if(Curl_pgrsUpdate(conn))
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
else
|
||||
result = Curl_speedcheck(data, now);
|
||||
result = Curl_speedcheck(data, Curl_tvnow());
|
||||
}
|
||||
if(Curl_pgrsUpdate(conn))
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2010 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@ -28,23 +28,19 @@
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
struct curl_fileinfo *Curl_fileinfo_alloc(void)
|
||||
struct fileinfo *Curl_fileinfo_alloc(void)
|
||||
{
|
||||
struct curl_fileinfo *tmp = malloc(sizeof(struct curl_fileinfo));
|
||||
if(!tmp)
|
||||
return NULL;
|
||||
memset(tmp, 0, sizeof(struct curl_fileinfo));
|
||||
return tmp;
|
||||
return calloc(1, sizeof(struct fileinfo));
|
||||
}
|
||||
|
||||
void Curl_fileinfo_dtor(void *user, void *element)
|
||||
{
|
||||
struct curl_fileinfo *finfo = element;
|
||||
struct fileinfo *finfo = element;
|
||||
(void) user;
|
||||
if(!finfo)
|
||||
return;
|
||||
|
||||
Curl_safefree(finfo->b_data);
|
||||
Curl_safefree(finfo->info.b_data);
|
||||
|
||||
free(finfo);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2010, 2017, 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,11 +23,15 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "llist.h"
|
||||
|
||||
struct curl_fileinfo *Curl_fileinfo_alloc(void);
|
||||
struct fileinfo {
|
||||
struct curl_fileinfo info;
|
||||
struct curl_llist_element list;
|
||||
};
|
||||
|
||||
struct fileinfo *Curl_fileinfo_alloc(void);
|
||||
|
||||
void Curl_fileinfo_dtor(void *, void *);
|
||||
|
||||
struct curl_fileinfo *Curl_fileinfo_dup(const struct curl_fileinfo *src);
|
||||
|
||||
#endif /* HEADER_CURL_FILEINFO_H */
|
||||
|
@ -48,15 +48,12 @@ static char *Curl_basename(char *path);
|
||||
#endif
|
||||
|
||||
static size_t readfromfile(struct Form *form, char *buffer, size_t size);
|
||||
static char *formboundary(struct Curl_easy *data);
|
||||
static CURLcode formboundary(struct Curl_easy *data, char *buffer, size_t len);
|
||||
|
||||
/* What kind of Content-Type to use on un-specified files with unrecognized
|
||||
extensions. */
|
||||
#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
|
||||
|
||||
#define FORM_FILE_SEPARATOR ','
|
||||
#define FORM_TYPE_SEPARATOR ';'
|
||||
|
||||
#define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
|
||||
#define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
|
||||
#define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
|
||||
@ -99,7 +96,7 @@ AddHttpPost(char *name, size_t namelength,
|
||||
post->contenttype = contenttype;
|
||||
post->contentheader = contentHeader;
|
||||
post->showfilename = showfilename;
|
||||
post->userp = userp,
|
||||
post->userp = userp;
|
||||
post->flags = flags | CURL_HTTPPOST_LARGE;
|
||||
}
|
||||
else
|
||||
@ -1162,20 +1159,19 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
|
||||
struct FormData *firstform;
|
||||
struct curl_httppost *file;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
curl_off_t size = 0; /* support potentially ENORMOUS formposts */
|
||||
char *boundary;
|
||||
char *fileboundary = NULL;
|
||||
char fileboundary[42];
|
||||
struct curl_slist *curList;
|
||||
char boundary[42];
|
||||
|
||||
*finalform = NULL; /* default form is empty */
|
||||
|
||||
if(!post)
|
||||
return result; /* no input => no output! */
|
||||
|
||||
boundary = formboundary(data);
|
||||
if(!boundary)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
result = formboundary(data, boundary, sizeof(boundary));
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Make the first line of the output */
|
||||
result = AddFormDataf(&form, NULL,
|
||||
@ -1185,7 +1181,6 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
|
||||
boundary);
|
||||
|
||||
if(result) {
|
||||
free(boundary);
|
||||
return result;
|
||||
}
|
||||
/* we DO NOT include that line in the total size of the POST, since it'll be
|
||||
@ -1228,10 +1223,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
|
||||
/* If used, this is a link to more file names, we must then do
|
||||
the magic to include several files with the same field name */
|
||||
|
||||
free(fileboundary);
|
||||
fileboundary = formboundary(data);
|
||||
if(!fileboundary) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
result = formboundary(data, fileboundary, sizeof(fileboundary));
|
||||
if(result) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1382,16 +1375,10 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
|
||||
|
||||
if(result) {
|
||||
Curl_formclean(&firstform);
|
||||
free(fileboundary);
|
||||
free(boundary);
|
||||
return result;
|
||||
}
|
||||
|
||||
*sizep = size;
|
||||
|
||||
free(fileboundary);
|
||||
free(boundary);
|
||||
|
||||
*finalform = firstform;
|
||||
|
||||
return result;
|
||||
@ -1565,16 +1552,18 @@ char *Curl_formpostheader(void *formp, size_t *len)
|
||||
* formboundary() creates a suitable boundary string and returns an allocated
|
||||
* one.
|
||||
*/
|
||||
static char *formboundary(struct Curl_easy *data)
|
||||
static CURLcode formboundary(struct Curl_easy *data,
|
||||
char *buffer, size_t buflen)
|
||||
{
|
||||
/* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
|
||||
combinations */
|
||||
unsigned int rnd[2];
|
||||
CURLcode result = Curl_rand(data, &rnd[0], 2);
|
||||
if(result)
|
||||
return NULL;
|
||||
if(buflen < 41)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
return aprintf("------------------------%08x%08x", rnd[0], rnd[1]);
|
||||
memset(buffer, '-', 24);
|
||||
Curl_rand_hex(data, (unsigned char *)&buffer[24], 17);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#else /* CURL_DISABLE_HTTP */
|
||||
|
37
lib/ftp.c
37
lib/ftp.c
@ -580,10 +580,8 @@ static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
|
||||
else {
|
||||
/* Add timeout to multi handle and break out of the loop */
|
||||
if(!result && *connected == FALSE) {
|
||||
if(data->set.accepttimeout > 0)
|
||||
Curl_expire(data, data->set.accepttimeout);
|
||||
else
|
||||
Curl_expire(data, DEFAULT_ACCEPT_TIMEOUT);
|
||||
Curl_expire(data, data->set.accepttimeout > 0 ?
|
||||
data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1681,8 +1679,9 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
|
||||
/* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
|
||||
do {
|
||||
size_t readthisamountnow =
|
||||
(data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
|
||||
BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
|
||||
(data->state.resume_from - passed > data->set.buffer_size) ?
|
||||
(size_t)data->set.buffer_size :
|
||||
curlx_sotouz(data->state.resume_from - passed);
|
||||
|
||||
size_t actuallyread =
|
||||
data->state.fread_func(data->state.buffer, 1, readthisamountnow,
|
||||
@ -2101,17 +2100,17 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
|
||||
/* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
|
||||
last .sss part is optional and means fractions of a second */
|
||||
int year, month, day, hour, minute, second;
|
||||
char *buf = data->state.buffer;
|
||||
if(6 == sscanf(buf+4, "%04d%02d%02d%02d%02d%02d",
|
||||
if(6 == sscanf(&data->state.buffer[4], "%04d%02d%02d%02d%02d%02d",
|
||||
&year, &month, &day, &hour, &minute, &second)) {
|
||||
/* we have a time, reformat it */
|
||||
char timebuf[24];
|
||||
time_t secs=time(NULL);
|
||||
/* using the good old yacc/bison yuck */
|
||||
snprintf(buf, CURL_BUFSIZE(conn->data->set.buffer_size),
|
||||
|
||||
snprintf(timebuf, sizeof(timebuf),
|
||||
"%04d%02d%02d %02d:%02d:%02d GMT",
|
||||
year, month, day, hour, minute, second);
|
||||
/* now, convert this into a time() value: */
|
||||
data->info.filetime = (long)curl_getdate(buf, &secs);
|
||||
data->info.filetime = (long)curl_getdate(timebuf, &secs);
|
||||
}
|
||||
|
||||
#ifdef CURL_FTP_HTTPSTYLE_HEAD
|
||||
@ -2122,6 +2121,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
|
||||
ftpc->file &&
|
||||
data->set.get_filetime &&
|
||||
(data->info.filetime>=0) ) {
|
||||
char headerbuf[128];
|
||||
time_t filetime = (time_t)data->info.filetime;
|
||||
struct tm buffer;
|
||||
const struct tm *tm = &buffer;
|
||||
@ -2131,7 +2131,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
|
||||
return result;
|
||||
|
||||
/* format: "Tue, 15 Nov 1994 12:45:26" */
|
||||
snprintf(buf, BUFSIZE-1,
|
||||
snprintf(headerbuf, sizeof(headerbuf),
|
||||
"Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
|
||||
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
|
||||
tm->tm_mday,
|
||||
@ -2140,7 +2140,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
|
||||
tm->tm_hour,
|
||||
tm->tm_min,
|
||||
tm->tm_sec);
|
||||
result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
|
||||
result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0);
|
||||
if(result)
|
||||
return result;
|
||||
} /* end of a ridiculous amount of conditionals */
|
||||
@ -2318,9 +2318,10 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
|
||||
if(instate == FTP_SIZE) {
|
||||
#ifdef CURL_FTP_HTTPSTYLE_HEAD
|
||||
if(-1 != filesize) {
|
||||
snprintf(buf, CURL_BUFSIZE(data->set.buffer_size),
|
||||
char clbuf[128];
|
||||
snprintf(clbuf, sizeof(clbuf),
|
||||
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
|
||||
result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
|
||||
result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@ -2420,7 +2421,6 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
|
||||
CURLcode result = CURLE_OK;
|
||||
struct Curl_easy *data = conn->data;
|
||||
struct FTP *ftp = data->req.protop;
|
||||
char *buf = data->state.buffer;
|
||||
|
||||
if((ftpcode == 150) || (ftpcode == 125)) {
|
||||
|
||||
@ -2464,6 +2464,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
|
||||
*
|
||||
* Example D above makes this parsing a little tricky */
|
||||
char *bytes;
|
||||
char *buf = data->state.buffer;
|
||||
bytes=strstr(buf, " bytes");
|
||||
if(bytes--) {
|
||||
long in=(long)(bytes-buf);
|
||||
@ -2822,7 +2823,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
||||
case FTP_PWD:
|
||||
if(ftpcode == 257) {
|
||||
char *ptr=&data->state.buffer[4]; /* start on the first letter */
|
||||
const size_t buf_size = CURL_BUFSIZE(data->set.buffer_size);
|
||||
const size_t buf_size = data->set.buffer_size;
|
||||
char *dir;
|
||||
char *store;
|
||||
|
||||
@ -3587,7 +3588,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
|
||||
if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) {
|
||||
/* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
|
||||
aren't used so we blank their arguments. TODO: make this nicer */
|
||||
result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0, FALSE);
|
||||
result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ struct ftp_parselist_data {
|
||||
} state;
|
||||
|
||||
CURLcode error;
|
||||
struct curl_fileinfo *file_data;
|
||||
struct fileinfo *file_data;
|
||||
unsigned int item_length;
|
||||
size_t item_offset;
|
||||
struct {
|
||||
@ -275,7 +275,7 @@ static void PL_ERROR(struct connectdata *conn, CURLcode err)
|
||||
}
|
||||
|
||||
static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
|
||||
struct curl_fileinfo *finfo)
|
||||
struct fileinfo *infop)
|
||||
{
|
||||
curl_fnmatch_callback compare;
|
||||
struct WildcardData *wc = &conn->data->wildcard;
|
||||
@ -283,6 +283,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
|
||||
struct curl_llist *llist = &wc->filelist;
|
||||
struct ftp_parselist_data *parser = tmpdata->parser;
|
||||
bool add = TRUE;
|
||||
struct curl_fileinfo *finfo = &infop->info;
|
||||
|
||||
/* move finfo pointers to b_data */
|
||||
char *str = finfo->b_data;
|
||||
@ -316,11 +317,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
|
||||
}
|
||||
|
||||
if(add) {
|
||||
if(!Curl_llist_insert_next(llist, llist->tail, finfo)) {
|
||||
Curl_fileinfo_dtor(NULL, finfo);
|
||||
tmpdata->parser->file_data = NULL;
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
|
||||
}
|
||||
else {
|
||||
Curl_fileinfo_dtor(NULL, finfo);
|
||||
@ -337,6 +334,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
struct connectdata *conn = (struct connectdata *)connptr;
|
||||
struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
|
||||
struct ftp_parselist_data *parser = tmpdata->parser;
|
||||
struct fileinfo *infop;
|
||||
struct curl_fileinfo *finfo;
|
||||
unsigned long i = 0;
|
||||
CURLcode result;
|
||||
@ -366,17 +364,18 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
parser->error = CURLE_OUT_OF_MEMORY;
|
||||
return bufflen;
|
||||
}
|
||||
parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE);
|
||||
if(!parser->file_data->b_data) {
|
||||
parser->file_data->info.b_data = malloc(FTP_BUFFER_ALLOCSIZE);
|
||||
if(!parser->file_data->info.b_data) {
|
||||
PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
|
||||
return bufflen;
|
||||
}
|
||||
parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE;
|
||||
parser->file_data->info.b_size = FTP_BUFFER_ALLOCSIZE;
|
||||
parser->item_offset = 0;
|
||||
parser->item_length = 0;
|
||||
}
|
||||
|
||||
finfo = parser->file_data;
|
||||
infop = parser->file_data;
|
||||
finfo = &infop->info;
|
||||
finfo->b_data[finfo->b_used++] = c;
|
||||
|
||||
if(finfo->b_used >= finfo->b_size - 1) {
|
||||
@ -498,8 +497,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
|
||||
return bufflen;
|
||||
}
|
||||
parser->file_data->flags |= CURLFINFOFLAG_KNOWN_PERM;
|
||||
parser->file_data->perm = perm;
|
||||
parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM;
|
||||
parser->file_data->info.perm = perm;
|
||||
parser->offsets.perm = parser->item_offset;
|
||||
|
||||
parser->item_length = 0;
|
||||
@ -530,8 +529,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
|
||||
hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10);
|
||||
if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) {
|
||||
parser->file_data->flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
|
||||
parser->file_data->hardlinks = hlinks;
|
||||
parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
|
||||
parser->file_data->info.hardlinks = hlinks;
|
||||
}
|
||||
parser->item_length = 0;
|
||||
parser->item_offset = 0;
|
||||
@ -613,8 +612,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10);
|
||||
if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
|
||||
fsize != CURL_OFF_T_MIN) {
|
||||
parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
|
||||
parser->file_data->size = fsize;
|
||||
parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
|
||||
parser->file_data->info.size = fsize;
|
||||
}
|
||||
parser->item_length = 0;
|
||||
parser->item_offset = 0;
|
||||
@ -731,7 +730,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
|
||||
parser->offsets.filename = parser->item_offset;
|
||||
parser->state.UNIX.main = PL_UNIX_FILETYPE;
|
||||
result = ftp_pl_insert_finfo(conn, finfo);
|
||||
result = ftp_pl_insert_finfo(conn, infop);
|
||||
if(result) {
|
||||
PL_ERROR(conn, result);
|
||||
return bufflen;
|
||||
@ -743,7 +742,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
|
||||
parser->offsets.filename = parser->item_offset;
|
||||
parser->state.UNIX.main = PL_UNIX_FILETYPE;
|
||||
result = ftp_pl_insert_finfo(conn, finfo);
|
||||
result = ftp_pl_insert_finfo(conn, infop);
|
||||
if(result) {
|
||||
PL_ERROR(conn, result);
|
||||
return bufflen;
|
||||
@ -838,7 +837,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
else if(c == '\n') {
|
||||
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
|
||||
parser->offsets.symlink_target = parser->item_offset;
|
||||
result = ftp_pl_insert_finfo(conn, finfo);
|
||||
result = ftp_pl_insert_finfo(conn, infop);
|
||||
if(result) {
|
||||
PL_ERROR(conn, result);
|
||||
return bufflen;
|
||||
@ -850,7 +849,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
if(c == '\n') {
|
||||
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
|
||||
parser->offsets.symlink_target = parser->item_offset;
|
||||
result = ftp_pl_insert_finfo(conn, finfo);
|
||||
result = ftp_pl_insert_finfo(conn, infop);
|
||||
if(result) {
|
||||
PL_ERROR(conn, result);
|
||||
return bufflen;
|
||||
@ -953,10 +952,10 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
return bufflen;
|
||||
}
|
||||
/* correct file type */
|
||||
parser->file_data->filetype = CURLFILETYPE_FILE;
|
||||
parser->file_data->info.filetype = CURLFILETYPE_FILE;
|
||||
}
|
||||
|
||||
parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
|
||||
parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
|
||||
parser->item_length = 0;
|
||||
parser->state.NT.main = PL_WINNT_FILENAME;
|
||||
parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
|
||||
@ -983,7 +982,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
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(conn, finfo);
|
||||
result = ftp_pl_insert_finfo(conn, infop);
|
||||
if(result) {
|
||||
PL_ERROR(conn, result);
|
||||
return bufflen;
|
||||
@ -995,7 +994,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
case PL_WINNT_FILENAME_WINEOL:
|
||||
if(c == '\n') {
|
||||
parser->offsets.filename = parser->item_offset;
|
||||
result = ftp_pl_insert_finfo(conn, finfo);
|
||||
result = ftp_pl_insert_finfo(conn, infop);
|
||||
if(result) {
|
||||
PL_ERROR(conn, result);
|
||||
return bufflen;
|
||||
|
14
lib/hash.c
14
lib/hash.c
@ -124,17 +124,9 @@ Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
|
||||
|
||||
he = mk_hash_element(key, key_len, p);
|
||||
if(he) {
|
||||
if(Curl_llist_insert_next(l, l->tail, he)) {
|
||||
++h->size;
|
||||
return p; /* return the new entry */
|
||||
}
|
||||
/*
|
||||
* Couldn't insert it, destroy the 'he' element and the key again. We
|
||||
* don't call hash_element_dtor() since that would also call the
|
||||
* "destructor" for the actual data 'p'. When we fail, we shall not touch
|
||||
* that data.
|
||||
*/
|
||||
free(he);
|
||||
Curl_llist_insert_next(l, l->tail, he, &he->list);
|
||||
++h->size;
|
||||
return p; /* return the new entry */
|
||||
}
|
||||
|
||||
return NULL; /* failure */
|
||||
|
@ -57,6 +57,7 @@ struct curl_hash {
|
||||
};
|
||||
|
||||
struct curl_hash_element {
|
||||
struct curl_llist_element list;
|
||||
void *ptr;
|
||||
size_t key_len;
|
||||
char key[1]; /* allocated memory following the struct */
|
||||
|
@ -538,7 +538,6 @@ RETSIGTYPE alarmfunc(int sig)
|
||||
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
|
||||
(void)sig;
|
||||
siglongjmp(curl_jmpenv, 1);
|
||||
return;
|
||||
}
|
||||
#endif /* USE_ALARM_TIMEOUT */
|
||||
|
||||
@ -597,7 +596,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
|
||||
/* Ignore the timeout when signals are disabled */
|
||||
timeout = 0;
|
||||
else
|
||||
timeout = timeoutms;
|
||||
timeout = (timeoutms > LONG_MAX) ? LONG_MAX : (long)timeoutms;
|
||||
|
||||
if(!timeout)
|
||||
/* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
|
||||
@ -689,10 +688,11 @@ clean_up:
|
||||
the time we spent until now! */
|
||||
if(prev_alarm) {
|
||||
/* there was an alarm() set before us, now put it back */
|
||||
unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created);
|
||||
unsigned long elapsed_secs = (unsigned long) (Curl_tvdiff(Curl_tvnow(),
|
||||
conn->created) / 1000);
|
||||
|
||||
/* the alarm period is counted in even number of seconds */
|
||||
unsigned long alarm_set = prev_alarm - elapsed_ms/1000;
|
||||
unsigned long alarm_set = prev_alarm - elapsed_secs;
|
||||
|
||||
if(!alarm_set ||
|
||||
((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) {
|
||||
|
89
lib/http.c
89
lib/http.c
@ -285,6 +285,7 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
|
||||
const char *user;
|
||||
const char *pwd;
|
||||
CURLcode result;
|
||||
char *out;
|
||||
|
||||
if(proxy) {
|
||||
userp = &conn->allocptr.proxyuserpwd;
|
||||
@ -297,27 +298,32 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
|
||||
pwd = conn->passwd;
|
||||
}
|
||||
|
||||
snprintf(data->state.buffer, CURL_BUFSIZE(data->set.buffer_size),
|
||||
"%s:%s", user, pwd);
|
||||
out = aprintf("%s:%s", user, pwd);
|
||||
if(!out)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
result = Curl_base64_encode(data,
|
||||
data->state.buffer, strlen(data->state.buffer),
|
||||
&authorization, &size);
|
||||
result = Curl_base64_encode(data, out, strlen(out), &authorization, &size);
|
||||
if(result)
|
||||
return result;
|
||||
goto fail;
|
||||
|
||||
if(!authorization)
|
||||
return CURLE_REMOTE_ACCESS_DENIED;
|
||||
if(!authorization) {
|
||||
result = CURLE_REMOTE_ACCESS_DENIED;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
free(*userp);
|
||||
*userp = aprintf("%sAuthorization: Basic %s\r\n",
|
||||
proxy ? "Proxy-" : "",
|
||||
authorization);
|
||||
free(authorization);
|
||||
if(!*userp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(!*userp) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
fail:
|
||||
free(out);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* pickoneauth() selects the most favourable authentication method from the
|
||||
@ -413,8 +419,6 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
|
||||
case HTTPREQ_POST:
|
||||
if(data->state.infilesize != -1)
|
||||
expectsend = data->state.infilesize;
|
||||
else if(data->set.postfields)
|
||||
expectsend = (curl_off_t)strlen(data->set.postfields);
|
||||
break;
|
||||
case HTTPREQ_PUT:
|
||||
if(data->state.infilesize != -1)
|
||||
@ -1111,7 +1115,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
|
||||
buffer is using this size.
|
||||
*/
|
||||
|
||||
sendsize = (size > CURL_MAX_WRITE_SIZE) ? CURL_MAX_WRITE_SIZE : size;
|
||||
sendsize = CURLMIN(size, CURL_MAX_WRITE_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
|
||||
@ -1689,9 +1693,10 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
|
||||
Curl_send_buffer *req_buffer)
|
||||
{
|
||||
const struct tm *tm;
|
||||
char *buf = data->state.buffer;
|
||||
struct tm keeptime;
|
||||
CURLcode result;
|
||||
char datestr[80];
|
||||
const char *condp;
|
||||
|
||||
if(data->set.timecondition == CURL_TIMECOND_NONE)
|
||||
/* no condition was asked for */
|
||||
@ -1704,6 +1709,21 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
|
||||
}
|
||||
tm = &keeptime;
|
||||
|
||||
switch(data->set.timecondition) {
|
||||
default:
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
case CURL_TIMECOND_IFMODSINCE:
|
||||
condp = "If-Modified-Since";
|
||||
break;
|
||||
case CURL_TIMECOND_IFUNMODSINCE:
|
||||
condp = "If-Unmodified-Since";
|
||||
break;
|
||||
case CURL_TIMECOND_LASTMOD:
|
||||
condp = "Last-Modified";
|
||||
break;
|
||||
}
|
||||
|
||||
/* The If-Modified-Since header family should have their times set in
|
||||
* GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
|
||||
* represented in Greenwich Mean Time (GMT), without exception. For the
|
||||
@ -1712,8 +1732,9 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
|
||||
*/
|
||||
|
||||
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
|
||||
snprintf(buf, BUFSIZE-1,
|
||||
"%s, %02d %s %4d %02d:%02d:%02d GMT",
|
||||
snprintf(datestr, sizeof(datestr),
|
||||
"%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
|
||||
condp,
|
||||
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
|
||||
tm->tm_mday,
|
||||
Curl_month[tm->tm_mon],
|
||||
@ -1722,22 +1743,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
|
||||
tm->tm_min,
|
||||
tm->tm_sec);
|
||||
|
||||
switch(data->set.timecondition) {
|
||||
default:
|
||||
break;
|
||||
case CURL_TIMECOND_IFMODSINCE:
|
||||
result = Curl_add_bufferf(req_buffer,
|
||||
"If-Modified-Since: %s\r\n", buf);
|
||||
break;
|
||||
case CURL_TIMECOND_IFUNMODSINCE:
|
||||
result = Curl_add_bufferf(req_buffer,
|
||||
"If-Unmodified-Since: %s\r\n", buf);
|
||||
break;
|
||||
case CURL_TIMECOND_LASTMOD:
|
||||
result = Curl_add_bufferf(req_buffer,
|
||||
"Last-Modified: %s\r\n", buf);
|
||||
break;
|
||||
}
|
||||
result = Curl_add_buffer(req_buffer, datestr, strlen(datestr));
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -2164,8 +2170,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
/* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
|
||||
do {
|
||||
size_t readthisamountnow =
|
||||
(data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
|
||||
BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
|
||||
(data->state.resume_from - passed > data->set.buffer_size) ?
|
||||
(size_t)data->set.buffer_size :
|
||||
curlx_sotouz(data->state.resume_from - passed);
|
||||
|
||||
size_t actuallyread =
|
||||
data->state.fread_func(data->state.buffer, 1, readthisamountnow,
|
||||
@ -2550,12 +2557,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
|
||||
if(conn->bits.authneg)
|
||||
postsize = 0;
|
||||
else {
|
||||
/* figure out the size of the postfields */
|
||||
postsize = (data->state.infilesize != -1)?
|
||||
data->state.infilesize:
|
||||
(data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
|
||||
}
|
||||
else
|
||||
/* the size of the post body */
|
||||
postsize = data->state.infilesize;
|
||||
|
||||
/* We only set Content-Length and allow a custom Content-Length if
|
||||
we don't upload data chunked, as RFC2616 forbids us to set both
|
||||
@ -2737,6 +2741,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
data->req.upload_done = TRUE;
|
||||
data->req.keepon &= ~KEEP_SEND; /* we're done writing */
|
||||
data->req.exp100 = EXP100_SEND_DATA; /* already sent */
|
||||
Curl_expire_done(data, EXPIRE_100_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3033,6 +3038,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
if(k->exp100 > EXP100_SEND_DATA) {
|
||||
k->exp100 = EXP100_SEND_DATA;
|
||||
k->keepon |= KEEP_SEND;
|
||||
Curl_expire_done(data, EXPIRE_100_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
case 101:
|
||||
@ -3159,6 +3165,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
* request body has been sent we stop sending and mark the
|
||||
* connection for closure after we've read the entire response.
|
||||
*/
|
||||
Curl_expire_done(data, EXPIRE_100_TIMEOUT);
|
||||
if(!k->upload_done) {
|
||||
if(data->set.http_keep_sending_on_error) {
|
||||
infof(data, "HTTP error before end of send, keep sending\n");
|
||||
|
62
lib/http2.c
62
lib/http2.c
@ -165,7 +165,7 @@ void Curl_http2_setup_req(struct Curl_easy *data)
|
||||
http->closed = FALSE;
|
||||
http->close_handled = FALSE;
|
||||
http->mem = data->state.buffer;
|
||||
http->len = BUFSIZE;
|
||||
http->len = data->set.buffer_size;
|
||||
http->memlen = 0;
|
||||
}
|
||||
|
||||
@ -181,7 +181,7 @@ void Curl_http2_setup_conn(struct connectdata *conn)
|
||||
* but will be used at run-time when the protocol is dynamically switched from
|
||||
* HTTP to HTTP2.
|
||||
*/
|
||||
const struct Curl_handler Curl_handler_http2 = {
|
||||
static const struct Curl_handler Curl_handler_http2 = {
|
||||
"HTTP", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
@ -201,7 +201,7 @@ const struct Curl_handler Curl_handler_http2 = {
|
||||
PROTOPT_STREAM /* flags */
|
||||
};
|
||||
|
||||
const struct Curl_handler Curl_handler_http2_ssl = {
|
||||
static const struct Curl_handler Curl_handler_http2_ssl = {
|
||||
"HTTPS", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
Curl_http, /* do_it */
|
||||
@ -569,7 +569,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(conn_s->data != data_s)
|
||||
Curl_expire(data_s, 0);
|
||||
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
|
||||
}
|
||||
break;
|
||||
case NGHTTP2_PUSH_PROMISE:
|
||||
@ -646,7 +646,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
|
||||
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(conn->data != data_s)
|
||||
Curl_expire(data_s, 0);
|
||||
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
|
||||
|
||||
DEBUGF(infof(data_s, "%zu data received for stream %u "
|
||||
"(%zu left in buffer %p, total %zu)\n",
|
||||
@ -784,7 +784,7 @@ static int on_begin_headers(nghttp2_session *session,
|
||||
/* This is trailer HEADERS started. Allocate buffer for them. */
|
||||
DEBUGF(infof(data_s, "trailer field started\n"));
|
||||
|
||||
assert(stream->trailer_recvbuf == NULL);
|
||||
DEBUGASSERT(stream->trailer_recvbuf == NULL);
|
||||
|
||||
stream->trailer_recvbuf = Curl_add_buffer_init();
|
||||
if(!stream->trailer_recvbuf) {
|
||||
@ -909,7 +909,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
Curl_add_buffer(stream->header_recvbuf, " \r\n", 3);
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(conn->data != data_s)
|
||||
Curl_expire(data_s, 0);
|
||||
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
|
||||
|
||||
DEBUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
|
||||
stream->status_code, data_s));
|
||||
@ -925,7 +925,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(conn->data != data_s)
|
||||
Curl_expire(data_s, 0);
|
||||
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
|
||||
|
||||
DEBUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
|
||||
value));
|
||||
@ -1453,7 +1453,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
infof(data, "%zu data bytes written\n", nread);
|
||||
if(stream->pauselen == 0) {
|
||||
DEBUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
|
||||
assert(httpc->pause_stream_id == stream->stream_id);
|
||||
DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
|
||||
httpc->pause_stream_id = 0;
|
||||
|
||||
stream->pausedata = NULL;
|
||||
@ -2137,35 +2137,37 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
|
||||
void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child,
|
||||
bool exclusive)
|
||||
{
|
||||
struct Curl_http2_dep **tail;
|
||||
struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep));
|
||||
dep->data = child;
|
||||
if(parent) {
|
||||
struct Curl_http2_dep **tail;
|
||||
struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep));
|
||||
dep->data = child;
|
||||
|
||||
if(parent->set.stream_dependents && exclusive) {
|
||||
struct Curl_http2_dep *node = parent->set.stream_dependents;
|
||||
while(node) {
|
||||
node->data->set.stream_depends_on = child;
|
||||
node = node->next;
|
||||
if(parent->set.stream_dependents && exclusive) {
|
||||
struct Curl_http2_dep *node = parent->set.stream_dependents;
|
||||
while(node) {
|
||||
node->data->set.stream_depends_on = child;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
tail = &child->set.stream_dependents;
|
||||
while(*tail)
|
||||
tail = &(*tail)->next;
|
||||
|
||||
DEBUGASSERT(!*tail);
|
||||
*tail = parent->set.stream_dependents;
|
||||
parent->set.stream_dependents = 0;
|
||||
}
|
||||
|
||||
tail = &child->set.stream_dependents;
|
||||
while(*tail)
|
||||
tail = &parent->set.stream_dependents;
|
||||
while(*tail) {
|
||||
(*tail)->data->set.stream_depends_e = FALSE;
|
||||
tail = &(*tail)->next;
|
||||
}
|
||||
|
||||
DEBUGASSERT(!*tail);
|
||||
*tail = parent->set.stream_dependents;
|
||||
parent->set.stream_dependents = 0;
|
||||
*tail = dep;
|
||||
}
|
||||
|
||||
tail = &parent->set.stream_dependents;
|
||||
while(*tail) {
|
||||
(*tail)->data->set.stream_depends_e = FALSE;
|
||||
tail = &(*tail)->next;
|
||||
}
|
||||
|
||||
DEBUGASSERT(!*tail);
|
||||
*tail = dep;
|
||||
|
||||
child->set.stream_depends_on = parent;
|
||||
child->set.stream_depends_e = exclusive;
|
||||
}
|
||||
|
@ -122,8 +122,7 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
|
||||
remote_port = conn->conn_to_port;
|
||||
else
|
||||
remote_port = conn->remote_port;
|
||||
result = Curl_proxyCONNECT(conn, sockindex, hostname,
|
||||
remote_port, FALSE);
|
||||
result = Curl_proxyCONNECT(conn, sockindex, hostname, remote_port);
|
||||
conn->data->req.protop = prot_save;
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
@ -136,20 +135,12 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
|
||||
* function will issue the necessary commands to get a seamless tunnel through
|
||||
* this proxy. After that, the socket can be used just as a normal socket.
|
||||
*
|
||||
* 'blocking' set to TRUE means that this function will do the entire CONNECT
|
||||
* + response in a blocking fashion. Should be avoided!
|
||||
*/
|
||||
#define CONNECT_BUFFER_SIZE 16384
|
||||
|
||||
CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
int sockindex,
|
||||
const char *hostname,
|
||||
int remote_port,
|
||||
bool blocking)
|
||||
static CURLcode CONNECT(struct connectdata *conn,
|
||||
int sockindex,
|
||||
const char *hostname,
|
||||
int remote_port)
|
||||
{
|
||||
int subversion=0;
|
||||
struct Curl_easy *data=conn->data;
|
||||
@ -289,13 +280,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
|
||||
if(!blocking) {
|
||||
if(!Curl_conn_data_pending(conn, sockindex))
|
||||
/* return so we'll be called again polling-style */
|
||||
return CURLE_OK;
|
||||
DEBUGF(infof(data,
|
||||
"Read response immediately from proxy CONNECT\n"));
|
||||
}
|
||||
if(!Curl_conn_data_pending(conn, sockindex))
|
||||
/* return so we'll be called again polling-style */
|
||||
return CURLE_OK;
|
||||
DEBUGF(infof(data, "Read response immediately from proxy CONNECT\n"));
|
||||
|
||||
/* at this point, the tunnel_connecting phase is over. */
|
||||
|
||||
@ -307,17 +295,17 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
char *ptr;
|
||||
char *line_start;
|
||||
|
||||
ptr = data->state.buffer;
|
||||
ptr = conn->connect_buffer;
|
||||
line_start = ptr;
|
||||
|
||||
nread = 0;
|
||||
perline = 0;
|
||||
|
||||
while(nread < BUFSIZE && keepon && !error) {
|
||||
while(nread < (size_t)CONNECT_BUFFER_SIZE && keepon && !error) {
|
||||
if(Curl_pgrsUpdate(conn))
|
||||
return CURLE_ABORTED_BY_CALLBACK;
|
||||
|
||||
if(ptr >= &data->state.buffer[BUFSIZE]) {
|
||||
if(ptr >= &conn->connect_buffer[CONNECT_BUFFER_SIZE]) {
|
||||
failf(data, "CONNECT response too large!");
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
@ -366,7 +354,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
/* This means we are currently ignoring a response-body */
|
||||
|
||||
nread = 0; /* make next read start over in the read buffer */
|
||||
ptr = data->state.buffer;
|
||||
ptr = conn->connect_buffer;
|
||||
if(cl) {
|
||||
/* A Content-Length based body: simply count down the counter
|
||||
and make sure to break out of the loop when we're done! */
|
||||
@ -438,7 +426,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
/* end of response-headers from the proxy */
|
||||
nread = 0; /* make next read start over in the read
|
||||
buffer */
|
||||
ptr = data->state.buffer;
|
||||
ptr = conn->connect_buffer;
|
||||
if((407 == k->httpcode) && !data->state.authproblem) {
|
||||
/* If we get a 407 response code with content length
|
||||
when we have no auth problem, we must ignore the
|
||||
@ -551,7 +539,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
}
|
||||
|
||||
perline = 0; /* line starts over here */
|
||||
ptr = data->state.buffer;
|
||||
ptr = conn->connect_buffer;
|
||||
line_start = ptr;
|
||||
} /* while there's buffer left and loop is requested */
|
||||
|
||||
@ -636,4 +624,33 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
document request */
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
|
||||
* function will issue the necessary commands to get a seamless tunnel through
|
||||
* this proxy. After that, the socket can be used just as a normal socket.
|
||||
*/
|
||||
|
||||
CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
int sockindex,
|
||||
const char *hostname,
|
||||
int remote_port)
|
||||
{
|
||||
CURLcode result;
|
||||
if(TUNNEL_INIT == conn->tunnel_state[sockindex]) {
|
||||
if(!conn->connect_buffer) {
|
||||
conn->connect_buffer = malloc(CONNECT_BUFFER_SIZE);
|
||||
if(!conn->connect_buffer)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
result = CONNECT(conn, sockindex, hostname, remote_port);
|
||||
|
||||
if(result || (TUNNEL_COMPLETE == conn->tunnel_state[sockindex]))
|
||||
Curl_safefree(conn->connect_buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#endif /* CURL_DISABLE_PROXY */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@ -26,8 +26,7 @@
|
||||
/* ftp can use this as well */
|
||||
CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
int tunnelsocket,
|
||||
const char *hostname, int remote_port,
|
||||
bool blocking);
|
||||
const char *hostname, int remote_port);
|
||||
|
||||
/* Default proxy timeout in milliseconds */
|
||||
#define PROXY_TIMEOUT (3600*1000)
|
||||
@ -35,7 +34,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex);
|
||||
|
||||
#else
|
||||
#define Curl_proxyCONNECT(x,y,z,w,v) CURLE_NOT_BUILT_IN
|
||||
#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN
|
||||
#define Curl_proxy_connect(x,y) CURLE_OK
|
||||
#endif
|
||||
|
||||
|
@ -239,7 +239,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
|
||||
return IF2IP_NOT_FOUND;
|
||||
}
|
||||
|
||||
s = (struct sockaddr_in *)&req.ifr_addr;
|
||||
s = (struct sockaddr_in *)(void *)&req.ifr_addr;
|
||||
memcpy(&in, &s->sin_addr, sizeof(in));
|
||||
Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
|
||||
|
||||
|
14
lib/krb5.c
14
lib/krb5.c
@ -164,6 +164,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
|
||||
size_t base64_sz = 0;
|
||||
struct sockaddr_in **remote_addr =
|
||||
(struct sockaddr_in **)&conn->ip_addr->ai_addr;
|
||||
char *stringp;
|
||||
|
||||
if(getsockname(conn->sock[FIRSTSOCKET],
|
||||
(struct sockaddr *)&conn->local_addr, &l) < 0)
|
||||
@ -193,16 +194,19 @@ krb5_auth(void *app_data, struct connectdata *conn)
|
||||
return -1;
|
||||
}
|
||||
|
||||
input_buffer.value = data->state.buffer;
|
||||
input_buffer.length = snprintf(input_buffer.value, BUFSIZE, "%s@%s",
|
||||
service, host);
|
||||
stringp = aprintf("%s@%s", service, host);
|
||||
if(!stringp)
|
||||
return -2;
|
||||
|
||||
input_buffer.value = stringp;
|
||||
input_buffer.length = strlen(stringp);
|
||||
maj = gss_import_name(&min, &input_buffer, GSS_C_NT_HOSTBASED_SERVICE,
|
||||
&gssname);
|
||||
free(stringp);
|
||||
if(maj != GSS_S_COMPLETE) {
|
||||
gss_release_name(&min, &gssname);
|
||||
if(service == srv_host) {
|
||||
Curl_failf(data, "Error importing service name %s",
|
||||
input_buffer.value);
|
||||
Curl_failf(data, "Error importing service name %s@%s", service, host);
|
||||
return AUTH_ERROR;
|
||||
}
|
||||
service = srv_host;
|
||||
|
101
lib/ldap.c
101
lib/ldap.c
@ -181,6 +181,81 @@ const struct Curl_handler Curl_handler_ldaps = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(USE_WIN32_LDAP)
|
||||
|
||||
#if defined(USE_WINDOWS_SSPI)
|
||||
static int ldap_win_bind_auth(LDAP *server, const char *user,
|
||||
const char *passwd, unsigned long authflags)
|
||||
{
|
||||
ULONG method = 0;
|
||||
SEC_WINNT_AUTH_IDENTITY cred = { 0, };
|
||||
int rc = LDAP_AUTH_METHOD_NOT_SUPPORTED;
|
||||
|
||||
#if defined(USE_SPNEGO)
|
||||
if(authflags & CURLAUTH_NEGOTIATE) {
|
||||
method = LDAP_AUTH_NEGOTIATE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(USE_NTLM)
|
||||
if(authflags & CURLAUTH_NTLM) {
|
||||
method = LDAP_AUTH_NTLM;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
if(authflags & CURLAUTH_DIGEST) {
|
||||
method = LDAP_AUTH_DIGEST;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* required anyway if one of upper preprocessor definitions enabled */
|
||||
}
|
||||
|
||||
if(method && user && passwd) {
|
||||
rc = Curl_create_sspi_identity(user, passwd, &cred);
|
||||
if(!rc) {
|
||||
rc = ldap_bind_s(server, NULL, (TCHAR *)&cred, method);
|
||||
Curl_sspi_free_identity(&cred);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* proceed with current user credentials */
|
||||
method = LDAP_AUTH_NEGOTIATE;
|
||||
rc = ldap_bind_s(server, NULL, NULL, method);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif /* #if defined(USE_WINDOWS_SSPI) */
|
||||
|
||||
static int ldap_win_bind(struct connectdata *conn, LDAP *server,
|
||||
const char *user, const char *passwd)
|
||||
{
|
||||
int rc = LDAP_INVALID_CREDENTIALS;
|
||||
ULONG method = LDAP_AUTH_SIMPLE;
|
||||
|
||||
PTCHAR inuser = NULL;
|
||||
PTCHAR inpass = NULL;
|
||||
|
||||
if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) {
|
||||
inuser = Curl_convert_UTF8_to_tchar((char *) user);
|
||||
inpass = Curl_convert_UTF8_to_tchar((char *) passwd);
|
||||
|
||||
rc = ldap_bind_s(server, inuser, inpass, method);
|
||||
|
||||
Curl_unicodefree(inuser);
|
||||
Curl_unicodefree(inpass);
|
||||
}
|
||||
#if defined(USE_WINDOWS_SSPI)
|
||||
else {
|
||||
rc = ldap_win_bind_auth(server, user, passwd, conn->data->set.httpauth);
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif /* #if defined(USE_WIN32_LDAP) */
|
||||
|
||||
static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
{
|
||||
@ -202,13 +277,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
#endif
|
||||
#if defined(USE_WIN32_LDAP)
|
||||
TCHAR *host = NULL;
|
||||
TCHAR *user = NULL;
|
||||
TCHAR *passwd = NULL;
|
||||
#else
|
||||
char *host = NULL;
|
||||
#endif
|
||||
char *user = NULL;
|
||||
char *passwd = NULL;
|
||||
#endif
|
||||
|
||||
*done = TRUE; /* unconditionally */
|
||||
infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n",
|
||||
@ -239,24 +312,14 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if(conn->bits.user_passwd) {
|
||||
user = Curl_convert_UTF8_to_tchar(conn->user);
|
||||
passwd = Curl_convert_UTF8_to_tchar(conn->passwd);
|
||||
if(!user || !passwd) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
#else
|
||||
host = conn->host.name;
|
||||
#endif
|
||||
|
||||
if(conn->bits.user_passwd) {
|
||||
user = conn->user;
|
||||
passwd = conn->passwd;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LDAP_OPT_NETWORK_TIMEOUT
|
||||
ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout);
|
||||
@ -402,11 +465,19 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
|
||||
#endif
|
||||
|
||||
#ifdef USE_WIN32_LDAP
|
||||
rc = ldap_win_bind(conn, server, user, passwd);
|
||||
#else
|
||||
rc = ldap_simple_bind_s(server, user, passwd);
|
||||
#endif
|
||||
if(!ldap_ssl && rc != 0) {
|
||||
ldap_proto = LDAP_VERSION2;
|
||||
ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
|
||||
#ifdef USE_WIN32_LDAP
|
||||
rc = ldap_win_bind(conn, server, user, passwd);
|
||||
#else
|
||||
rc = ldap_simple_bind_s(server, user, passwd);
|
||||
#endif
|
||||
}
|
||||
if(rc != 0) {
|
||||
failf(data, "LDAP local: ldap_simple_bind_s %s", ldap_err2string(rc));
|
||||
@ -669,8 +740,6 @@ quit:
|
||||
#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
|
||||
|
||||
#if defined(USE_WIN32_LDAP)
|
||||
Curl_unicodefree(passwd);
|
||||
Curl_unicodefree(user);
|
||||
Curl_unicodefree(host);
|
||||
#endif
|
||||
|
||||
|
35
lib/llist.c
35
lib/llist.c
@ -49,18 +49,15 @@ Curl_llist_init(struct curl_llist *l, curl_llist_dtor dtor)
|
||||
* entry is NULL and the list already has elements, the new one will be
|
||||
* inserted first in the list.
|
||||
*
|
||||
* Returns: 1 on success and 0 on failure.
|
||||
* The 'ne' argument should be a pointer into the object to store.
|
||||
*
|
||||
* @unittest: 1300
|
||||
*/
|
||||
int
|
||||
void
|
||||
Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e,
|
||||
const void *p)
|
||||
const void *p,
|
||||
struct curl_llist_element *ne)
|
||||
{
|
||||
struct curl_llist_element *ne = malloc(sizeof(struct curl_llist_element));
|
||||
if(!ne)
|
||||
return 0;
|
||||
|
||||
ne->ptr = (void *) p;
|
||||
if(list->size == 0) {
|
||||
list->head = ne;
|
||||
@ -87,19 +84,18 @@ Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e,
|
||||
}
|
||||
|
||||
++list->size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unittest: 1300
|
||||
*/
|
||||
int
|
||||
void
|
||||
Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
|
||||
void *user)
|
||||
{
|
||||
void *ptr;
|
||||
if(e == NULL || list->size == 0)
|
||||
return 1;
|
||||
return;
|
||||
|
||||
if(e == list->head) {
|
||||
list->head = e->next;
|
||||
@ -117,16 +113,17 @@ Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
|
||||
e->next->prev = e->prev;
|
||||
}
|
||||
|
||||
list->dtor(user, e->ptr);
|
||||
ptr = e->ptr;
|
||||
|
||||
e->ptr = NULL;
|
||||
e->prev = NULL;
|
||||
e->next = NULL;
|
||||
|
||||
free(e);
|
||||
--list->size;
|
||||
|
||||
return 1;
|
||||
/* call the dtor() last for when it actually frees the 'e' memory itself */
|
||||
if(list->dtor)
|
||||
list->dtor(user, ptr);
|
||||
}
|
||||
|
||||
void
|
||||
@ -147,13 +144,13 @@ Curl_llist_count(struct curl_llist *list)
|
||||
/*
|
||||
* @unittest: 1300
|
||||
*/
|
||||
int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e,
|
||||
struct curl_llist *to_list,
|
||||
struct curl_llist_element *to_e)
|
||||
void Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e,
|
||||
struct curl_llist *to_list,
|
||||
struct curl_llist_element *to_e)
|
||||
{
|
||||
/* Remove element from list */
|
||||
if(e == NULL || list->size == 0)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if(e == list->head) {
|
||||
list->head = e->next;
|
||||
@ -193,6 +190,4 @@ int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e,
|
||||
}
|
||||
|
||||
++to_list->size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
15
lib/llist.h
15
lib/llist.h
@ -29,7 +29,6 @@ typedef void (*curl_llist_dtor)(void *, void *);
|
||||
|
||||
struct curl_llist_element {
|
||||
void *ptr;
|
||||
|
||||
struct curl_llist_element *prev;
|
||||
struct curl_llist_element *next;
|
||||
};
|
||||
@ -37,21 +36,19 @@ struct curl_llist_element {
|
||||
struct curl_llist {
|
||||
struct curl_llist_element *head;
|
||||
struct curl_llist_element *tail;
|
||||
|
||||
curl_llist_dtor dtor;
|
||||
|
||||
size_t size;
|
||||
};
|
||||
|
||||
void Curl_llist_init(struct curl_llist *, curl_llist_dtor);
|
||||
int Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *,
|
||||
const void *);
|
||||
int Curl_llist_remove(struct curl_llist *, struct curl_llist_element *,
|
||||
void *);
|
||||
void Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *,
|
||||
const void *, struct curl_llist_element *node);
|
||||
void Curl_llist_remove(struct curl_llist *, struct curl_llist_element *,
|
||||
void *);
|
||||
size_t Curl_llist_count(struct curl_llist *);
|
||||
void Curl_llist_destroy(struct curl_llist *, void *);
|
||||
int Curl_llist_move(struct curl_llist *, struct curl_llist_element *,
|
||||
struct curl_llist *, struct curl_llist_element *);
|
||||
void Curl_llist_move(struct curl_llist *, struct curl_llist_element *,
|
||||
struct curl_llist *, struct curl_llist_element *);
|
||||
|
||||
#endif /* HEADER_CURL_LLIST_H */
|
||||
|
||||
|
12
lib/md4.c
12
lib/md4.c
@ -37,9 +37,10 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
/* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so
|
||||
* that we have a local implementation of it */
|
||||
#if defined(USE_NSS) || defined(USE_OS400CRYPTO)
|
||||
/* The NSS, OS/400 and sometimes mbed TLS crypto libraries do not provide the
|
||||
* MD4 hash algorithm, so we have a local implementation of it */
|
||||
#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
|
||||
(defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
|
||||
|
||||
#include "curl_md4.h"
|
||||
#include "warnless.h"
|
||||
@ -89,7 +90,7 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx);
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
|
||||
#define SET(n) \
|
||||
(*(MD4_u32plus *)&ptr[(n) * 4])
|
||||
(*(MD4_u32plus *)(void *)&ptr[(n) * 4])
|
||||
#define GET(n) \
|
||||
SET(n)
|
||||
#else
|
||||
@ -302,4 +303,5 @@ void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
|
||||
MD4_Update(&ctx, input, curlx_uztoui(len));
|
||||
MD4_Final(output, &ctx);
|
||||
}
|
||||
#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */
|
||||
#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
|
||||
(defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
|
||||
|
@ -260,7 +260,7 @@ static void MD5_Final(unsigned char *result, MD5_CTX *ctx);
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
|
||||
#define SET(n) \
|
||||
(*(MD5_u32plus *)&ptr[(n) * 4])
|
||||
(*(MD5_u32plus *)(void *)&ptr[(n) * 4])
|
||||
#define GET(n) \
|
||||
SET(n)
|
||||
#else
|
||||
|
@ -35,10 +35,6 @@
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifndef HAVE_ASSERT_H
|
||||
# define assert(x) Curl_nop_stmt
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Until 2011-08-17 libcurl's Memory Tracking feature also performed
|
||||
* automatic malloc and free filling operations using 0xA5 and 0x13
|
||||
@ -167,7 +163,7 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source)
|
||||
struct memdebug *mem;
|
||||
size_t size;
|
||||
|
||||
assert(wantedsize != 0);
|
||||
DEBUGASSERT(wantedsize != 0);
|
||||
|
||||
if(countcheck("malloc", line, source))
|
||||
return NULL;
|
||||
@ -196,8 +192,8 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
|
||||
struct memdebug *mem;
|
||||
size_t size, user_size;
|
||||
|
||||
assert(wanted_elements != 0);
|
||||
assert(wanted_size != 0);
|
||||
DEBUGASSERT(wanted_elements != 0);
|
||||
DEBUGASSERT(wanted_size != 0);
|
||||
|
||||
if(countcheck("calloc", line, source))
|
||||
return NULL;
|
||||
@ -223,7 +219,7 @@ char *curl_dostrdup(const char *str, int line, const char *source)
|
||||
char *mem;
|
||||
size_t len;
|
||||
|
||||
assert(str != NULL);
|
||||
DEBUGASSERT(str != NULL);
|
||||
|
||||
if(countcheck("strdup", line, source))
|
||||
return NULL;
|
||||
@ -236,7 +232,7 @@ char *curl_dostrdup(const char *str, int line, const char *source)
|
||||
|
||||
if(source)
|
||||
curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n",
|
||||
source, line, (void *)str, len, (void *)mem);
|
||||
source, line, (const void *)str, len, (const void *)mem);
|
||||
|
||||
return mem;
|
||||
}
|
||||
@ -247,7 +243,7 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
|
||||
wchar_t *mem;
|
||||
size_t wsiz, bsiz;
|
||||
|
||||
assert(str != NULL);
|
||||
DEBUGASSERT(str != NULL);
|
||||
|
||||
if(countcheck("wcsdup", line, source))
|
||||
return NULL;
|
||||
@ -276,7 +272,7 @@ void *curl_dorealloc(void *ptr, size_t wantedsize,
|
||||
|
||||
size_t size = sizeof(struct memdebug)+wantedsize;
|
||||
|
||||
assert(wantedsize != 0);
|
||||
DEBUGASSERT(wantedsize != 0);
|
||||
|
||||
if(countcheck("realloc", line, source))
|
||||
return NULL;
|
||||
@ -445,7 +441,7 @@ int curl_fclose(FILE *file, int line, const char *source)
|
||||
{
|
||||
int res;
|
||||
|
||||
assert(file != NULL);
|
||||
DEBUGASSERT(file != NULL);
|
||||
|
||||
res=fclose(file);
|
||||
|
||||
@ -480,7 +476,7 @@ void curl_memlog(const char *format, ...)
|
||||
nchars = LOGLINE_BUFSIZE - 1;
|
||||
|
||||
if(nchars > 0)
|
||||
fwrite(buf, 1, nchars, logfile);
|
||||
fwrite(buf, 1, (size_t)nchars, logfile);
|
||||
|
||||
(Curl_cfree)(buf);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1999 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1999 - 2017, 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,10 +42,6 @@
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifndef SIZEOF_LONG_DOUBLE
|
||||
#define SIZEOF_LONG_DOUBLE 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If SIZEOF_SIZE_T has not been defined, default to the size of long.
|
||||
*/
|
||||
@ -614,7 +610,7 @@ static int dprintf_formatf(
|
||||
int is_neg;
|
||||
|
||||
/* Base of a number to be written. */
|
||||
long base;
|
||||
unsigned long base;
|
||||
|
||||
/* Integral values to be written. */
|
||||
mp_uintmax_t num;
|
||||
@ -955,9 +951,7 @@ static int dprintf_formatf(
|
||||
/* NOTE NOTE NOTE!! Not all sprintf implementations return number of
|
||||
output characters */
|
||||
(sprintf)(work, formatbuf, p->data.dnum);
|
||||
#ifdef CURLDEBUG
|
||||
assert(strlen(work) <= sizeof(work));
|
||||
#endif
|
||||
DEBUGASSERT(strlen(work) <= sizeof(work));
|
||||
for(fptr=work; *fptr; fptr++)
|
||||
OUTCHAR(*fptr);
|
||||
}
|
||||
|
164
lib/multi.c
164
lib/multi.c
@ -99,8 +99,6 @@ static const char * const statename[]={
|
||||
};
|
||||
#endif
|
||||
|
||||
static void multi_freetimeout(void *a, void *b);
|
||||
|
||||
/* function pointer called once when switching TO a state */
|
||||
typedef void (*init_multistate_func)(struct Curl_easy *data);
|
||||
|
||||
@ -280,9 +278,8 @@ static int sh_init(struct curl_hash *hash, int hashsize)
|
||||
static CURLMcode multi_addmsg(struct Curl_multi *multi,
|
||||
struct Curl_message *msg)
|
||||
{
|
||||
if(!Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg))
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
|
||||
Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg,
|
||||
&msg->list);
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
@ -370,7 +367,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
|
||||
return CURLM_ADDED_ALREADY;
|
||||
|
||||
/* Initialize timeout list for this handle */
|
||||
Curl_llist_init(&data->state.timeoutlist, multi_freetimeout);
|
||||
Curl_llist_init(&data->state.timeoutlist, NULL);
|
||||
|
||||
/*
|
||||
* No failure allowed in this function beyond this point. And no
|
||||
@ -431,7 +428,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
|
||||
sockets that time-out or have actions will be dealt with. Since this
|
||||
handle has no action yet, we make sure it times out to get things to
|
||||
happen. */
|
||||
Curl_expire(data, 0);
|
||||
Curl_expire(data, 0, EXPIRE_RUN_NOW);
|
||||
|
||||
/* increase the node-counter */
|
||||
multi->num_easy++;
|
||||
@ -1015,7 +1012,7 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
|
||||
curlfds = nfds; /* number of internal file descriptors */
|
||||
nfds += extra_nfds; /* add the externally provided ones */
|
||||
|
||||
if(nfds || extra_nfds) {
|
||||
if(nfds) {
|
||||
if(nfds > NUM_POLLS_ON_STACK) {
|
||||
ufds = malloc(nfds * sizeof(struct pollfd));
|
||||
if(!ufds)
|
||||
@ -1432,10 +1429,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
multistate(data, CURLM_STATE_CONNECT_PEND);
|
||||
|
||||
/* add this handle to the list of connect-pending handles */
|
||||
if(!Curl_llist_insert_next(&multi->pending, multi->pending.tail, data))
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
else
|
||||
result = CURLE_OK;
|
||||
Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
|
||||
&data->connect_queue);
|
||||
result = CURLE_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1719,20 +1715,18 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
else {
|
||||
/* Follow failed */
|
||||
result = drc;
|
||||
free(newurl);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* done didn't return OK or SEND_ERROR */
|
||||
result = drc;
|
||||
free(newurl);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Have error handler disconnect conn if we can't retry */
|
||||
stream_error = TRUE;
|
||||
free(newurl);
|
||||
}
|
||||
free(newurl);
|
||||
}
|
||||
else {
|
||||
/* failure detected */
|
||||
@ -1846,9 +1840,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
if(send_timeout_ms <= 0 && recv_timeout_ms <= 0)
|
||||
multistate(data, CURLM_STATE_PERFORM);
|
||||
else if(send_timeout_ms >= recv_timeout_ms)
|
||||
Curl_expire_latest(data, send_timeout_ms);
|
||||
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
|
||||
else
|
||||
Curl_expire_latest(data, recv_timeout_ms);
|
||||
Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1879,9 +1873,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
if(send_timeout_ms > 0 || recv_timeout_ms > 0) {
|
||||
multistate(data, CURLM_STATE_TOOFAST);
|
||||
if(send_timeout_ms >= recv_timeout_ms)
|
||||
Curl_expire_latest(data, send_timeout_ms);
|
||||
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
|
||||
else
|
||||
Curl_expire_latest(data, recv_timeout_ms);
|
||||
Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1942,7 +1936,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
|
||||
/* expire the new receiving pipeline head */
|
||||
if(data->easy_conn->recv_pipe.head)
|
||||
Curl_expire_latest(data->easy_conn->recv_pipe.head->ptr, 0);
|
||||
Curl_expire(data->easy_conn->recv_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
|
||||
|
||||
/* Check if we can move pending requests to send pipe */
|
||||
Curl_multi_process_pending_handles(multi);
|
||||
@ -1966,9 +1960,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
if(!result) {
|
||||
multistate(data, CURLM_STATE_CONNECT);
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
newurl = NULL; /* handed over the memory ownership to
|
||||
Curl_follow(), make sure we don't free() it
|
||||
here */
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1982,9 +1973,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
newurl = data->req.location;
|
||||
data->req.location = NULL;
|
||||
result = Curl_follow(data, newurl, FOLLOW_FAKE);
|
||||
if(!result)
|
||||
newurl = NULL; /* allocation was handed over Curl_follow() */
|
||||
else
|
||||
if(result)
|
||||
stream_error = TRUE;
|
||||
}
|
||||
|
||||
@ -2483,8 +2472,6 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* add_next_timeout()
|
||||
*
|
||||
@ -2504,13 +2491,16 @@ static CURLMcode add_next_timeout(struct timeval now,
|
||||
struct timeval *tv = &d->state.expiretime;
|
||||
struct curl_llist *list = &d->state.timeoutlist;
|
||||
struct curl_llist_element *e;
|
||||
struct time_node *node = NULL;
|
||||
|
||||
/* move over the timeout list for this specific handle and remove all
|
||||
timeouts that are now passed tense and store the next pending
|
||||
timeout in *tv */
|
||||
for(e = list->head; e;) {
|
||||
struct curl_llist_element *n = e->next;
|
||||
time_t diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
|
||||
time_t diff;
|
||||
node = (struct time_node *)e->ptr;
|
||||
diff = curlx_tvdiff(node->time, now);
|
||||
if(diff <= 0)
|
||||
/* remove outdated entry */
|
||||
Curl_llist_remove(list, e, NULL);
|
||||
@ -2528,7 +2518,7 @@ static CURLMcode add_next_timeout(struct timeval now,
|
||||
}
|
||||
else {
|
||||
/* copy the first entry to 'tv' */
|
||||
memcpy(tv, e->ptr, sizeof(*tv));
|
||||
memcpy(tv, &node->time, sizeof(*tv));
|
||||
|
||||
/* remove first entry from list */
|
||||
Curl_llist_remove(list, e, NULL);
|
||||
@ -2854,17 +2844,23 @@ static int update_timer(struct Curl_multi *multi)
|
||||
}
|
||||
|
||||
/*
|
||||
* multi_freetimeout()
|
||||
* multi_deltimeout()
|
||||
*
|
||||
* Callback used by the llist system when a single timeout list entry is
|
||||
* destroyed.
|
||||
* Remove a given timestamp from the list of timeouts.
|
||||
*/
|
||||
static void multi_freetimeout(void *user, void *entryptr)
|
||||
static void
|
||||
multi_deltimeout(struct Curl_easy *data, expire_id eid)
|
||||
{
|
||||
(void)user;
|
||||
|
||||
/* the entry was plain malloc()'ed */
|
||||
free(entryptr);
|
||||
struct curl_llist_element *e;
|
||||
struct curl_llist *timeoutlist = &data->state.timeoutlist;
|
||||
/* find and remove the specific node from the list */
|
||||
for(e = timeoutlist->head; e; e = e->next) {
|
||||
struct time_node *n = (struct time_node *)e->ptr;
|
||||
if(n->eid == eid) {
|
||||
Curl_llist_remove(timeoutlist, e, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2875,25 +2871,28 @@ static void multi_freetimeout(void *user, void *entryptr)
|
||||
*
|
||||
*/
|
||||
static CURLMcode
|
||||
multi_addtimeout(struct curl_llist *timeoutlist,
|
||||
struct timeval *stamp)
|
||||
multi_addtimeout(struct Curl_easy *data,
|
||||
struct timeval *stamp,
|
||||
expire_id eid)
|
||||
{
|
||||
struct curl_llist_element *e;
|
||||
struct timeval *timedup;
|
||||
struct time_node *node;
|
||||
struct curl_llist_element *prev = NULL;
|
||||
size_t n;
|
||||
struct curl_llist *timeoutlist = &data->state.timeoutlist;
|
||||
|
||||
timedup = malloc(sizeof(*timedup));
|
||||
if(!timedup)
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
node = &data->state.expires[eid];
|
||||
|
||||
/* copy the timestamp */
|
||||
memcpy(timedup, stamp, sizeof(*timedup));
|
||||
/* copy the timestamp and id */
|
||||
memcpy(&node->time, stamp, sizeof(*stamp));
|
||||
node->eid = eid; /* also marks it as in use */
|
||||
|
||||
if(Curl_llist_count(timeoutlist)) {
|
||||
n = Curl_llist_count(timeoutlist);
|
||||
if(n) {
|
||||
/* find the correct spot in the list */
|
||||
for(e = timeoutlist->head; e; e = e->next) {
|
||||
struct timeval *checktime = e->ptr;
|
||||
time_t diff = curlx_tvdiff(*checktime, *timedup);
|
||||
struct time_node *check = (struct time_node *)e->ptr;
|
||||
time_t diff = curlx_tvdiff(check->time, node->time);
|
||||
if(diff > 0)
|
||||
break;
|
||||
prev = e;
|
||||
@ -2903,11 +2902,7 @@ multi_addtimeout(struct curl_llist *timeoutlist,
|
||||
/* else
|
||||
this is the first timeout on the list */
|
||||
|
||||
if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
|
||||
free(timedup);
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
@ -2919,8 +2914,10 @@ multi_addtimeout(struct curl_llist *timeoutlist,
|
||||
*
|
||||
* The timeout will be added to a queue of timeouts if it defines a moment in
|
||||
* time that is later than the current head of queue.
|
||||
*
|
||||
* Expire replaces a former timeout using the same id if already set.
|
||||
*/
|
||||
void Curl_expire(struct Curl_easy *data, time_t milli)
|
||||
void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id)
|
||||
{
|
||||
struct Curl_multi *multi = data->multi;
|
||||
struct timeval *nowp = &data->state.expiretime;
|
||||
@ -2932,6 +2929,8 @@ void Curl_expire(struct Curl_easy *data, time_t milli)
|
||||
if(!multi)
|
||||
return;
|
||||
|
||||
DEBUGASSERT(id < EXPIRE_LAST);
|
||||
|
||||
set = Curl_tvnow();
|
||||
set.tv_sec += (long)(milli/1000);
|
||||
set.tv_usec += (long)(milli%1000)*1000;
|
||||
@ -2946,16 +2945,20 @@ void Curl_expire(struct Curl_easy *data, time_t milli)
|
||||
Compare if the new time is earlier, and only remove-old/add-new if it
|
||||
is. */
|
||||
time_t diff = curlx_tvdiff(set, *nowp);
|
||||
|
||||
/* remove the previous timer first, if there */
|
||||
multi_deltimeout(data, id);
|
||||
|
||||
if(diff > 0) {
|
||||
/* the new expire time was later so just add it to the queue
|
||||
and get out */
|
||||
multi_addtimeout(&data->state.timeoutlist, &set);
|
||||
multi_addtimeout(data, &set, id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* the new time is newer than the presently set one, so add the current
|
||||
to the queue and update the head */
|
||||
multi_addtimeout(&data->state.timeoutlist, nowp);
|
||||
multi_addtimeout(data, nowp, id);
|
||||
|
||||
/* Since this is an updated time, we must remove the previous entry from
|
||||
the splay tree first and then re-add the new value */
|
||||
@ -2973,49 +2976,17 @@ void Curl_expire(struct Curl_easy *data, time_t milli)
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_expire_latest()
|
||||
* Curl_expire_done()
|
||||
*
|
||||
* This is like Curl_expire() but will only add a timeout node to the list of
|
||||
* timers if there is no timeout that will expire before the given time.
|
||||
*
|
||||
* Use this function if the code logic risks calling this function many times
|
||||
* or if there's no particular conditional wait in the code for this specific
|
||||
* time-out period to expire.
|
||||
* Removes the expire timer. Marks it as done.
|
||||
*
|
||||
*/
|
||||
void Curl_expire_latest(struct Curl_easy *data, time_t milli)
|
||||
void Curl_expire_done(struct Curl_easy *data, expire_id id)
|
||||
{
|
||||
struct timeval *expire = &data->state.expiretime;
|
||||
|
||||
struct timeval set;
|
||||
|
||||
set = Curl_tvnow();
|
||||
set.tv_sec += (long)(milli / 1000);
|
||||
set.tv_usec += (long)(milli % 1000) * 1000;
|
||||
|
||||
if(set.tv_usec >= 1000000) {
|
||||
set.tv_sec++;
|
||||
set.tv_usec -= 1000000;
|
||||
}
|
||||
|
||||
if(expire->tv_sec || expire->tv_usec) {
|
||||
/* This means that the struct is added as a node in the splay tree.
|
||||
Compare if the new time is earlier, and only remove-old/add-new if it
|
||||
is. */
|
||||
time_t diff = curlx_tvdiff(set, *expire);
|
||||
if((diff > 0) && (diff < milli)) {
|
||||
/* if the new expire time is later than the top time, skip it, but not
|
||||
if the diff is larger than the new offset since then the previous
|
||||
time is already expired! */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Just add the timeout like normal */
|
||||
Curl_expire(data, milli);
|
||||
/* remove the timer, if there */
|
||||
multi_deltimeout(data, id);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Curl_expire_clear()
|
||||
*
|
||||
@ -3044,8 +3015,9 @@ void Curl_expire_clear(struct Curl_easy *data)
|
||||
infof(data, "Internal error clearing splay node = %d\n", rc);
|
||||
|
||||
/* flush the timeout list too */
|
||||
while(list->size > 0)
|
||||
while(list->size > 0) {
|
||||
Curl_llist_remove(list, list->tail, NULL);
|
||||
}
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
infof(data, "Expire cleared\n");
|
||||
@ -3118,7 +3090,7 @@ void Curl_multi_process_pending_handles(struct Curl_multi *multi)
|
||||
Curl_llist_remove(&multi->pending, e, NULL);
|
||||
|
||||
/* Make sure that the handle will be processed soonish. */
|
||||
Curl_expire_latest(data, 0);
|
||||
Curl_expire(data, 0, EXPIRE_RUN_NOW);
|
||||
}
|
||||
|
||||
e = next; /* operate on next handle */
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "conncache.h"
|
||||
|
||||
struct Curl_message {
|
||||
struct curl_llist_element list;
|
||||
/* the 'CURLMsg' is the part that is visible to the external user */
|
||||
struct CURLMsg extmsg;
|
||||
};
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@ -25,9 +25,10 @@
|
||||
/*
|
||||
* Prototypes for library-wide functions provided by multi.c
|
||||
*/
|
||||
void Curl_expire(struct Curl_easy *data, time_t milli);
|
||||
|
||||
void Curl_expire(struct Curl_easy *data, time_t milli, expire_id);
|
||||
void Curl_expire_clear(struct Curl_easy *data);
|
||||
void Curl_expire_latest(struct Curl_easy *data, time_t milli);
|
||||
void Curl_expire_done(struct Curl_easy *data, expire_id id);
|
||||
bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
|
||||
void Curl_multi_handlePipeBreak(struct Curl_easy *data);
|
||||
|
||||
|
@ -286,7 +286,8 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
|
||||
/* number of bytes in the current line, so far */
|
||||
perline = (ssize_t)(ptr-pp->linestart_resp);
|
||||
|
||||
while((pp->nread_resp<BUFSIZE) && (keepon && !result)) {
|
||||
while((pp->nread_resp < (size_t)data->set.buffer_size) &&
|
||||
(keepon && !result)) {
|
||||
|
||||
if(pp->cache) {
|
||||
/* we had data in the "cache", copy that instead of doing an actual
|
||||
@ -296,7 +297,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
|
||||
* it would have been populated with something of size int to begin
|
||||
* with, even though its datatype may be larger than an int.
|
||||
*/
|
||||
DEBUGASSERT((ptr+pp->cache_size) <= (buf+BUFSIZE+1));
|
||||
DEBUGASSERT((ptr+pp->cache_size) <= (buf+data->set.buffer_size+1));
|
||||
memcpy(ptr, pp->cache, pp->cache_size);
|
||||
gotbytes = (ssize_t)pp->cache_size;
|
||||
free(pp->cache); /* free the cache */
|
||||
@ -308,8 +309,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
|
||||
enum protection_level prot = conn->data_prot;
|
||||
conn->data_prot = PROT_CLEAR;
|
||||
#endif
|
||||
DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1));
|
||||
result = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp,
|
||||
DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <=
|
||||
(buf + data->set.buffer_size + 1));
|
||||
result = Curl_read(conn, sockfd, ptr,
|
||||
data->set.buffer_size - pp->nread_resp,
|
||||
&gotbytes);
|
||||
#ifdef HAVE_GSSAPI
|
||||
DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST);
|
||||
@ -402,7 +405,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
|
||||
}
|
||||
else if(keepon) {
|
||||
|
||||
if((perline == gotbytes) && (gotbytes > BUFSIZE/2)) {
|
||||
if((perline == gotbytes) && (gotbytes > data->set.buffer_size/2)) {
|
||||
/* We got an excessive line without newlines and we need to deal
|
||||
with it. We keep the first bytes of the line then we throw
|
||||
away the rest. */
|
||||
@ -414,7 +417,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
|
||||
interested in the first piece */
|
||||
clipamount = 40;
|
||||
}
|
||||
else if(pp->nread_resp > BUFSIZE/2) {
|
||||
else if(pp->nread_resp > (size_t)data->set.buffer_size/2) {
|
||||
/* We got a large chunk of data and there's potentially still
|
||||
trailing data to take care of, so we put any such part in the
|
||||
"cache", clear the buffer to make space and restart. */
|
||||
|
@ -38,16 +38,15 @@
|
||||
#include "memdebug.h"
|
||||
|
||||
struct site_blacklist_entry {
|
||||
char *hostname;
|
||||
struct curl_llist_element list;
|
||||
unsigned short port;
|
||||
char hostname[1];
|
||||
};
|
||||
|
||||
static void site_blacklist_llist_dtor(void *user, void *element)
|
||||
{
|
||||
struct site_blacklist_entry *entry = element;
|
||||
(void)user;
|
||||
|
||||
Curl_safefree(entry->hostname);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
@ -94,8 +93,8 @@ bool Curl_pipeline_penalized(struct Curl_easy *data,
|
||||
static CURLcode addHandleToPipeline(struct Curl_easy *data,
|
||||
struct curl_llist *pipeline)
|
||||
{
|
||||
if(!Curl_llist_insert_next(pipeline, pipeline->tail, data))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
Curl_llist_insert_next(pipeline, pipeline->tail, data,
|
||||
&data->pipeline_queue);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@ -114,7 +113,7 @@ CURLcode Curl_add_handle_to_pipeline(struct Curl_easy *handle,
|
||||
if(pipeline == &conn->send_pipe && sendhead != conn->send_pipe.head) {
|
||||
/* this is a new one as head, expire it */
|
||||
Curl_pipeline_leave_write(conn); /* not in use yet */
|
||||
Curl_expire(conn->send_pipe.head->ptr, 0);
|
||||
Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
|
||||
}
|
||||
|
||||
#if 0 /* enable for pipeline debugging */
|
||||
@ -149,7 +148,7 @@ void Curl_move_handle_from_send_to_recv_pipe(struct Curl_easy *handle,
|
||||
infof(conn->data, "%p is at send pipe head B!\n",
|
||||
(void *)conn->send_pipe.head->ptr);
|
||||
#endif
|
||||
Curl_expire(conn->send_pipe.head->ptr, 0);
|
||||
Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
|
||||
}
|
||||
|
||||
/* The receiver's list is not really interesting here since either this
|
||||
@ -202,24 +201,17 @@ CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
|
||||
|
||||
/* Parse the URLs and populate the list */
|
||||
while(*sites) {
|
||||
char *hostname;
|
||||
char *port;
|
||||
struct site_blacklist_entry *entry;
|
||||
|
||||
hostname = strdup(*sites);
|
||||
if(!hostname) {
|
||||
Curl_llist_destroy(list, NULL);
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
entry = malloc(sizeof(struct site_blacklist_entry));
|
||||
entry = malloc(sizeof(struct site_blacklist_entry) + strlen(*sites));
|
||||
if(!entry) {
|
||||
free(hostname);
|
||||
Curl_llist_destroy(list, NULL);
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
strcpy(entry->hostname, *sites);
|
||||
|
||||
port = strchr(hostname, ':');
|
||||
port = strchr(entry->hostname, ':');
|
||||
if(port) {
|
||||
*port = '\0';
|
||||
port++;
|
||||
@ -230,14 +222,7 @@ CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
|
||||
entry->port = 80;
|
||||
}
|
||||
|
||||
entry->hostname = hostname;
|
||||
|
||||
if(!Curl_llist_insert_next(list, list->tail, entry)) {
|
||||
site_blacklist_llist_dtor(NULL, entry);
|
||||
Curl_llist_destroy(list, NULL);
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
Curl_llist_insert_next(list, list->tail, entry, &entry->list);
|
||||
sites++;
|
||||
}
|
||||
}
|
||||
@ -274,6 +259,11 @@ bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
struct blacklist_node {
|
||||
struct curl_llist_element list;
|
||||
char server_name[1];
|
||||
};
|
||||
|
||||
CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
|
||||
struct curl_llist *list)
|
||||
{
|
||||
@ -286,20 +276,18 @@ CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
|
||||
|
||||
/* Parse the URLs and populate the list */
|
||||
while(*servers) {
|
||||
char *server_name;
|
||||
struct blacklist_node *n;
|
||||
size_t len = strlen(*servers);
|
||||
|
||||
server_name = strdup(*servers);
|
||||
if(!server_name) {
|
||||
n = malloc(sizeof(struct blacklist_node) + len);
|
||||
if(!n) {
|
||||
Curl_llist_destroy(list, NULL);
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
strcpy(n->server_name, *servers);
|
||||
|
||||
if(!Curl_llist_insert_next(list, list->tail, server_name)) {
|
||||
Curl_llist_destroy(list, NULL);
|
||||
Curl_safefree(server_name);
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
Curl_llist_insert_next(list, list->tail, n->server_name,
|
||||
&n->list);
|
||||
servers++;
|
||||
}
|
||||
}
|
||||
|
63
lib/rand.c
63
lib/rand.c
@ -47,10 +47,12 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
|
||||
char *force_entropy = getenv("CURL_ENTROPY");
|
||||
if(force_entropy) {
|
||||
if(!seeded) {
|
||||
unsigned int seed = 0;
|
||||
size_t elen = strlen(force_entropy);
|
||||
size_t clen = sizeof(randseed);
|
||||
size_t clen = sizeof(seed);
|
||||
size_t min = elen < clen ? elen : clen;
|
||||
memcpy((char *)&randseed, force_entropy, min);
|
||||
memcpy((char *)&seed, force_entropy, min);
|
||||
randseed = ntohl(seed);
|
||||
seeded = TRUE;
|
||||
}
|
||||
else
|
||||
@ -115,18 +117,63 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
|
||||
*
|
||||
*/
|
||||
|
||||
CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rndptr,
|
||||
unsigned int num)
|
||||
CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num)
|
||||
{
|
||||
CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
unsigned int i;
|
||||
|
||||
assert(num > 0);
|
||||
DEBUGASSERT(num > 0);
|
||||
|
||||
for(i = 0; i < num; i++) {
|
||||
result = randit(data, rndptr++);
|
||||
while(num) {
|
||||
unsigned int r;
|
||||
size_t left = num < sizeof(unsigned int) ? num : sizeof(unsigned int);
|
||||
|
||||
result = randit(data, &r);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
while(left) {
|
||||
*rnd++ = (unsigned char)(r & 0xFF);
|
||||
r >>= 8;
|
||||
--num;
|
||||
--left;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random
|
||||
* hexadecimal digits PLUS a zero terminating byte. It must be an odd number
|
||||
* size.
|
||||
*/
|
||||
|
||||
CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
|
||||
size_t num)
|
||||
{
|
||||
CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
const char *hex = "0123456789abcdef";
|
||||
unsigned char buffer[128];
|
||||
unsigned char *bufp = buffer;
|
||||
DEBUGASSERT(num > 1);
|
||||
|
||||
if((num/2 >= sizeof(buffer)) || !(num&1))
|
||||
/* make sure it fits in the local buffer and that it is an odd number! */
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
num--; /* save one for zero termination */
|
||||
|
||||
result = Curl_rand(data, buffer, num/2);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
while(num) {
|
||||
*rnd++ = hex[(*bufp & 0xF0)>>4];
|
||||
*rnd++ = hex[*bufp & 0x0F];
|
||||
bufp++;
|
||||
num -= 2;
|
||||
}
|
||||
*rnd = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
12
lib/rand.h
12
lib/rand.h
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2017, 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 @@
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Curl_rand() stores 'num' number of random unsigned integers in the buffer
|
||||
* Curl_rand() stores 'num' number of random unsigned characters in the buffer
|
||||
* 'rnd' points to.
|
||||
*
|
||||
* If libcurl is built without TLS support or with a TLS backend that lacks a
|
||||
@ -37,7 +37,11 @@
|
||||
* easy handle!
|
||||
*
|
||||
*/
|
||||
CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rnd,
|
||||
unsigned int num);
|
||||
CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
|
||||
|
||||
/* Same as above but outputs only random lowercase hex characters.
|
||||
Does NOT terminate.*/
|
||||
CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
|
||||
size_t num);
|
||||
|
||||
#endif /* HEADER_CURL_RAND_H */
|
||||
|
77
lib/sendf.c
77
lib/sendf.c
@ -149,7 +149,7 @@ static void pre_receive_plain(struct connectdata *conn, int num)
|
||||
/* Have some incoming data */
|
||||
if(!psnd->buffer) {
|
||||
/* Use buffer double default size for intermediate buffer */
|
||||
psnd->allocated_size = 2 * BUFSIZE;
|
||||
psnd->allocated_size = 2 * conn->data->set.buffer_size;
|
||||
psnd->buffer = malloc(psnd->allocated_size);
|
||||
psnd->recv_size = 0;
|
||||
psnd->recv_processed = 0;
|
||||
@ -243,21 +243,20 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
size_t len;
|
||||
char error[CURL_ERROR_SIZE + 2];
|
||||
va_start(ap, fmt);
|
||||
|
||||
vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
|
||||
vsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
|
||||
len = strlen(error);
|
||||
|
||||
if(data->set.errorbuffer && !data->state.errorbuf) {
|
||||
snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
|
||||
strcpy(data->set.errorbuffer, error);
|
||||
data->state.errorbuf = TRUE; /* wrote error string */
|
||||
}
|
||||
if(data->set.verbose) {
|
||||
len = strlen(data->state.buffer);
|
||||
if(len < BUFSIZE - 1) {
|
||||
data->state.buffer[len] = '\n';
|
||||
data->state.buffer[++len] = '\0';
|
||||
}
|
||||
Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
|
||||
error[len] = '\n';
|
||||
error[++len] = '\0';
|
||||
Curl_debug(data, CURLINFO_TEXT, error, len, NULL);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
@ -694,9 +693,10 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
|
||||
ssize_t nread = 0;
|
||||
size_t bytesfromsocket = 0;
|
||||
char *buffertofill = NULL;
|
||||
struct Curl_easy *data = conn->data;
|
||||
|
||||
/* if HTTP/1 pipelining is both wanted and possible */
|
||||
bool pipelining = Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1) &&
|
||||
bool pipelining = Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
|
||||
(conn->bundle->multiuse == BUNDLE_PIPELINING);
|
||||
|
||||
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
|
||||
@ -722,13 +722,11 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
|
||||
}
|
||||
/* If we come here, it means that there is no data to read from the buffer,
|
||||
* so we read from the socket */
|
||||
bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof(char));
|
||||
bytesfromsocket = CURLMIN(sizerequested, MASTERBUF_SIZE);
|
||||
buffertofill = conn->master_buffer;
|
||||
}
|
||||
else {
|
||||
bytesfromsocket = CURLMIN((long)sizerequested,
|
||||
conn->data->set.buffer_size ?
|
||||
conn->data->set.buffer_size : BUFSIZE);
|
||||
bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
|
||||
buffertofill = buf;
|
||||
}
|
||||
|
||||
@ -753,21 +751,19 @@ static int showit(struct Curl_easy *data, curl_infotype type,
|
||||
{
|
||||
static const char s_infotype[CURLINFO_END][3] = {
|
||||
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
|
||||
int rc = 0;
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
char buf[BUFSIZE+1];
|
||||
char *buf = NULL;
|
||||
size_t conv_size = 0;
|
||||
|
||||
switch(type) {
|
||||
case CURLINFO_HEADER_OUT:
|
||||
/* assume output headers are ASCII */
|
||||
/* copy the data into my buffer so the original is unchanged */
|
||||
if(size > BUFSIZE) {
|
||||
size = BUFSIZE; /* truncate if necessary */
|
||||
buf[BUFSIZE] = '\0';
|
||||
}
|
||||
buf = Curl_memdup(ptr, size);
|
||||
if(!buf)
|
||||
return 1;
|
||||
conv_size = size;
|
||||
memcpy(buf, ptr, size);
|
||||
|
||||
/* Special processing is needed for this block if it
|
||||
* contains both headers and data (separated by CRLFCRLF).
|
||||
* We want to convert just the headers, leaving the data as-is.
|
||||
@ -795,26 +791,29 @@ static int showit(struct Curl_easy *data, curl_infotype type,
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
if(data->set.fdebug)
|
||||
return (*data->set.fdebug)(data, type, ptr, size,
|
||||
data->set.debugdata);
|
||||
|
||||
switch(type) {
|
||||
case CURLINFO_TEXT:
|
||||
case CURLINFO_HEADER_OUT:
|
||||
case CURLINFO_HEADER_IN:
|
||||
fwrite(s_infotype[type], 2, 1, data->set.err);
|
||||
fwrite(ptr, size, 1, data->set.err);
|
||||
rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
|
||||
else {
|
||||
switch(type) {
|
||||
case CURLINFO_TEXT:
|
||||
case CURLINFO_HEADER_OUT:
|
||||
case CURLINFO_HEADER_IN:
|
||||
fwrite(s_infotype[type], 2, 1, data->set.err);
|
||||
fwrite(ptr, size, 1, data->set.err);
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
if(size != conv_size) {
|
||||
/* we had untranslated data so we need an explicit newline */
|
||||
fwrite("\n", 1, 1, data->set.err);
|
||||
}
|
||||
if(size != conv_size) {
|
||||
/* we had untranslated data so we need an explicit newline */
|
||||
fwrite("\n", 1, 1, data->set.err);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default: /* nada */
|
||||
break;
|
||||
break;
|
||||
default: /* nada */
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
free(buf);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
int Curl_debug(struct Curl_easy *data, curl_infotype type,
|
||||
|
@ -607,7 +607,7 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
|
||||
|
||||
/* Check if there is data in the transfer buffer */
|
||||
if(!smbc->send_size && smbc->upload_size) {
|
||||
int nread = smbc->upload_size > BUFSIZE ? BUFSIZE :
|
||||
int nread = smbc->upload_size > UPLOAD_BUFSIZE ? UPLOAD_BUFSIZE :
|
||||
(int) smbc->upload_size;
|
||||
conn->data->req.upload_fromhere = conn->data->state.uploadbuffer;
|
||||
result = Curl_fillreadbuffer(conn, nread, &nread);
|
||||
|
@ -1591,7 +1591,7 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
|
||||
if(!scratch || data->set.crlf) {
|
||||
oldscratch = scratch;
|
||||
|
||||
scratch = newscratch = malloc(2 * BUFSIZE);
|
||||
scratch = newscratch = malloc(2 * data->set.buffer_size);
|
||||
if(!newscratch) {
|
||||
failf(data, "Failed to alloc scratch buffer!");
|
||||
|
||||
|
@ -67,7 +67,7 @@ CURLcode Curl_speedcheck(struct Curl_easy *data,
|
||||
if(data->set.low_speed_limit)
|
||||
/* if low speed limit is enabled, set the expire timer to make this
|
||||
connection's speed get checked again in a second */
|
||||
Curl_expire_latest(data, 1000);
|
||||
Curl_expire(data, 1000, EXPIRE_SPEEDCHECK);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
38
lib/ssh.c
38
lib/ssh.c
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2017, 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
|
||||
@ -113,6 +113,7 @@
|
||||
libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
|
||||
(t), (m), LIBSSH2_SFTP_REALPATH)
|
||||
|
||||
|
||||
/* Local functions: */
|
||||
static const char *sftp_libssh2_strerror(int err);
|
||||
static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
|
||||
@ -1837,8 +1838,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
/* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
|
||||
do {
|
||||
size_t readthisamountnow =
|
||||
(data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
|
||||
BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
|
||||
(data->state.resume_from - passed > data->set.buffer_size) ?
|
||||
(size_t)data->set.buffer_size :
|
||||
curlx_sotouz(data->state.resume_from - passed);
|
||||
|
||||
size_t actuallyread =
|
||||
data->state.fread_func(data->state.buffer, 1,
|
||||
@ -1890,7 +1892,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
/* since we don't really wait for anything at this point, we want the
|
||||
state machine to move on as soon as possible so we set a very short
|
||||
timeout here */
|
||||
Curl_expire(data, 0);
|
||||
Curl_expire(data, 0, EXPIRE_RUN_NOW);
|
||||
|
||||
state(conn, SSH_STOP);
|
||||
}
|
||||
@ -2814,7 +2816,7 @@ static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
|
||||
}
|
||||
|
||||
static CURLcode ssh_block_statemach(struct connectdata *conn,
|
||||
bool duringconnect)
|
||||
bool disconnect)
|
||||
{
|
||||
struct ssh_conn *sshc = &conn->proto.sshc;
|
||||
CURLcode result = CURLE_OK;
|
||||
@ -2822,24 +2824,26 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
|
||||
|
||||
while((sshc->state != SSH_STOP) && !result) {
|
||||
bool block;
|
||||
time_t left;
|
||||
time_t left = 1000;
|
||||
struct timeval now = Curl_tvnow();
|
||||
|
||||
result = ssh_statemach_act(conn, &block);
|
||||
if(result)
|
||||
break;
|
||||
|
||||
if(Curl_pgrsUpdate(conn))
|
||||
return CURLE_ABORTED_BY_CALLBACK;
|
||||
if(!disconnect) {
|
||||
if(Curl_pgrsUpdate(conn))
|
||||
return CURLE_ABORTED_BY_CALLBACK;
|
||||
|
||||
result = Curl_speedcheck(data, now);
|
||||
if(result)
|
||||
break;
|
||||
result = Curl_speedcheck(data, now);
|
||||
if(result)
|
||||
break;
|
||||
|
||||
left = Curl_timeleft(data, NULL, duringconnect);
|
||||
if(left < 0) {
|
||||
failf(data, "Operation timed out");
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
left = Curl_timeleft(data, NULL, FALSE);
|
||||
if(left < 0) {
|
||||
failf(data, "Operation timed out");
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
|
||||
@ -3055,7 +3059,7 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
|
||||
state(conn, SSH_SESSION_DISCONNECT);
|
||||
|
||||
result = ssh_block_statemach(conn, FALSE);
|
||||
result = ssh_block_statemach(conn, TRUE);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -3209,7 +3213,7 @@ static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
if(conn->proto.sshc.ssh_session) {
|
||||
/* only if there's a session still around to use! */
|
||||
state(conn, SSH_SFTP_SHUTDOWN);
|
||||
result = ssh_block_statemach(conn, FALSE);
|
||||
result = ssh_block_statemach(conn, TRUE);
|
||||
}
|
||||
|
||||
DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
|
||||
|
98
lib/telnet.c
98
lib/telnet.c
@ -81,10 +81,12 @@
|
||||
} WHILE_FALSE
|
||||
|
||||
#define CURL_SB_GET(x) ((*x->subpointer++)&0xff)
|
||||
#define CURL_SB_PEEK(x) ((*x->subpointer)&0xff)
|
||||
#define CURL_SB_EOF(x) (x->subpointer >= x->subend)
|
||||
#define CURL_SB_LEN(x) (x->subend - x->subpointer)
|
||||
|
||||
/* For posterity:
|
||||
#define CURL_SB_PEEK(x) ((*x->subpointer)&0xff)
|
||||
#define CURL_SB_EOF(x) (x->subpointer >= x->subend) */
|
||||
|
||||
#ifdef CURL_DISABLE_VERBOSE_STRINGS
|
||||
#define printoption(a,b,c,d) Curl_nop_stmt
|
||||
#endif
|
||||
@ -1218,43 +1220,63 @@ CURLcode telrcv(struct connectdata *conn,
|
||||
}
|
||||
|
||||
/* Escape and send a telnet data block */
|
||||
/* TODO: write large chunks of data instead of one byte at a time */
|
||||
static CURLcode send_telnet_data(struct connectdata *conn,
|
||||
char *buffer, ssize_t nread)
|
||||
{
|
||||
unsigned char outbuf[2];
|
||||
ssize_t bytes_written, total_written;
|
||||
int out_count;
|
||||
ssize_t escapes, i, j, outlen;
|
||||
unsigned char *outbuf = NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
ssize_t bytes_written, total_written;
|
||||
|
||||
while(!result && nread--) {
|
||||
outbuf[0] = *buffer++;
|
||||
out_count = 1;
|
||||
if(outbuf[0] == CURL_IAC)
|
||||
outbuf[out_count++] = CURL_IAC;
|
||||
/* Determine size of new buffer after escaping */
|
||||
escapes = 0;
|
||||
for(i = 0; i < nread; i++)
|
||||
if((unsigned char)buffer[i] == CURL_IAC)
|
||||
escapes++;
|
||||
outlen = nread + escapes;
|
||||
|
||||
total_written = 0;
|
||||
do {
|
||||
/* Make sure socket is writable to avoid EWOULDBLOCK condition */
|
||||
struct pollfd pfd[1];
|
||||
pfd[0].fd = conn->sock[FIRSTSOCKET];
|
||||
pfd[0].events = POLLOUT;
|
||||
switch(Curl_poll(pfd, 1, -1)) {
|
||||
case -1: /* error, abort writing */
|
||||
case 0: /* timeout (will never happen) */
|
||||
result = CURLE_SEND_ERROR;
|
||||
break;
|
||||
default: /* write! */
|
||||
bytes_written = 0;
|
||||
result = Curl_write(conn, conn->sock[FIRSTSOCKET],
|
||||
outbuf+total_written, out_count-total_written,
|
||||
&bytes_written);
|
||||
total_written += bytes_written;
|
||||
break;
|
||||
}
|
||||
/* handle partial write */
|
||||
} while(!result && total_written < out_count);
|
||||
if(outlen == nread)
|
||||
outbuf = (unsigned char *)buffer;
|
||||
else {
|
||||
outbuf = malloc(nread + escapes + 1);
|
||||
if(!outbuf)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
j = 0;
|
||||
for(i = 0; i < nread; i++) {
|
||||
outbuf[j++] = buffer[i];
|
||||
if((unsigned char)buffer[i] == CURL_IAC)
|
||||
outbuf[j++] = CURL_IAC;
|
||||
}
|
||||
outbuf[j] = '\0';
|
||||
}
|
||||
|
||||
total_written = 0;
|
||||
while(!result && total_written < outlen) {
|
||||
/* Make sure socket is writable to avoid EWOULDBLOCK condition */
|
||||
struct pollfd pfd[1];
|
||||
pfd[0].fd = conn->sock[FIRSTSOCKET];
|
||||
pfd[0].events = POLLOUT;
|
||||
switch(Curl_poll(pfd, 1, -1)) {
|
||||
case -1: /* error, abort writing */
|
||||
case 0: /* timeout (will never happen) */
|
||||
result = CURLE_SEND_ERROR;
|
||||
break;
|
||||
default: /* write! */
|
||||
bytes_written = 0;
|
||||
result = Curl_write(conn, conn->sock[FIRSTSOCKET],
|
||||
outbuf + total_written,
|
||||
outlen - total_written,
|
||||
&bytes_written);
|
||||
total_written += bytes_written;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free malloc copy if escaped */
|
||||
if(outbuf != (unsigned char *)buffer)
|
||||
free(outbuf);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1414,7 +1436,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
|
||||
|
||||
/* Keep on listening and act on events */
|
||||
while(keepon) {
|
||||
const DWORD buf_size = (DWORD)CURL_BUFSIZE(data->set.buffer_size);
|
||||
const DWORD buf_size = (DWORD)data->set.buffer_size;
|
||||
waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout);
|
||||
switch(waitret) {
|
||||
case WAIT_TIMEOUT:
|
||||
@ -1423,7 +1445,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
|
||||
if(data->set.is_fread_set) {
|
||||
size_t n;
|
||||
/* read from user-supplied method */
|
||||
n = data->state.fread_func(buf, 1, BUFSIZE - 1, data->state.in);
|
||||
n = data->state.fread_func(buf, 1, buf_size, data->state.in);
|
||||
if(n == CURL_READFUNC_ABORT) {
|
||||
keepon = FALSE;
|
||||
result = CURLE_READ_ERROR;
|
||||
@ -1498,7 +1520,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
|
||||
}
|
||||
if(events.lNetworkEvents & FD_READ) {
|
||||
/* read data from network */
|
||||
result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
|
||||
result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread);
|
||||
/* read would've blocked. Loop again */
|
||||
if(result == CURLE_AGAIN)
|
||||
break;
|
||||
@ -1587,7 +1609,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
|
||||
default: /* read! */
|
||||
if(pfd[0].revents & POLLIN) {
|
||||
/* read data from network */
|
||||
result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
|
||||
result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread);
|
||||
/* read would've blocked. Loop again */
|
||||
if(result == CURLE_AGAIN)
|
||||
break;
|
||||
@ -1623,12 +1645,12 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
|
||||
nread = 0;
|
||||
if(poll_cnt == 2) {
|
||||
if(pfd[1].revents & POLLIN) { /* read from in file */
|
||||
nread = read(pfd[1].fd, buf, BUFSIZE - 1);
|
||||
nread = read(pfd[1].fd, buf, data->set.buffer_size);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* read from user-supplied method */
|
||||
nread = (int)data->state.fread_func(buf, 1, BUFSIZE - 1,
|
||||
nread = (int)data->state.fread_func(buf, 1, data->set.buffer_size,
|
||||
data->state.in);
|
||||
if(nread == CURL_READFUNC_ABORT) {
|
||||
keepon = FALSE;
|
||||
|
@ -1119,7 +1119,8 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
|
||||
}
|
||||
else {
|
||||
/* The event is given by the TFTP packet time */
|
||||
state->event = (tftp_event_t)getrpacketevent(&state->rpacket);
|
||||
unsigned short event = getrpacketevent(&state->rpacket);
|
||||
state->event = (tftp_event_t)event;
|
||||
|
||||
switch(state->event) {
|
||||
case TFTP_EVENT_DATA:
|
||||
@ -1138,9 +1139,12 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
|
||||
}
|
||||
break;
|
||||
case TFTP_EVENT_ERROR:
|
||||
state->error = (tftp_error_t)getrpacketblock(&state->rpacket);
|
||||
{
|
||||
unsigned short error = getrpacketblock(&state->rpacket);
|
||||
state->error = (tftp_error_t)error;
|
||||
infof(data, "%s\n", (const char *)state->rpacket.data+4);
|
||||
break;
|
||||
}
|
||||
case TFTP_EVENT_ACK:
|
||||
break;
|
||||
case TFTP_EVENT_OACK:
|
||||
|
@ -141,9 +141,3 @@ double curlx_tvdiff_secs(struct timeval newer, struct timeval older)
|
||||
(double)(newer.tv_usec-older.tv_usec)/1000000.0;
|
||||
return (double)(newer.tv_usec-older.tv_usec)/1000000.0;
|
||||
}
|
||||
|
||||
/* return the number of seconds in the given input timeval struct */
|
||||
time_t Curl_tvlong(struct timeval t1)
|
||||
{
|
||||
return t1.tv_sec;
|
||||
}
|
||||
|
@ -46,8 +46,6 @@ time_t curlx_tvdiff(struct timeval t1, struct timeval t2);
|
||||
*/
|
||||
double curlx_tvdiff_secs(struct timeval t1, struct timeval t2);
|
||||
|
||||
time_t Curl_tvlong(struct timeval t1);
|
||||
|
||||
/* These two defines below exist to provide the older API for library
|
||||
internals only. */
|
||||
#define Curl_tvnow() curlx_tvnow()
|
||||
|
127
lib/transfer.c
127
lib/transfer.c
@ -405,8 +405,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
||||
/* This is where we loop until we have read everything there is to
|
||||
read or we get a CURLE_AGAIN */
|
||||
do {
|
||||
size_t buffersize = data->set.buffer_size?
|
||||
data->set.buffer_size : BUFSIZE;
|
||||
size_t buffersize = data->set.buffer_size;
|
||||
size_t bytestoread = buffersize;
|
||||
|
||||
if(
|
||||
@ -681,8 +680,6 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
||||
excess = (size_t)(k->bytecount + nread - k->maxdownload);
|
||||
if(excess > 0 && !k->ignorebody) {
|
||||
if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) {
|
||||
/* The 'excess' amount below can't be more than BUFSIZE which
|
||||
always will fit in a size_t */
|
||||
infof(data,
|
||||
"Rewinding stream by : %zu"
|
||||
" bytes on url %s (size = %" CURL_FORMAT_CURL_OFF_T
|
||||
@ -853,7 +850,6 @@ static CURLcode done_sending(struct connectdata *conn,
|
||||
*/
|
||||
static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
struct SingleRequest *k,
|
||||
int *didwhat)
|
||||
{
|
||||
ssize_t i, si;
|
||||
@ -861,6 +857,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
CURLcode result;
|
||||
ssize_t nread; /* number of bytes read */
|
||||
bool sending_http_headers = FALSE;
|
||||
struct SingleRequest *k = &data->req;
|
||||
|
||||
if((k->bytecount == 0) && (k->writebytecount == 0))
|
||||
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
|
||||
@ -871,15 +868,15 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
|
||||
/* only read more data if there's no upload data already
|
||||
present in the upload buffer */
|
||||
if(0 == data->req.upload_present) {
|
||||
if(0 == k->upload_present) {
|
||||
/* init the "upload from here" pointer */
|
||||
data->req.upload_fromhere = k->uploadbuf;
|
||||
k->upload_fromhere = data->state.uploadbuffer;
|
||||
|
||||
if(!k->upload_done) {
|
||||
/* HTTP pollution, this should be written nicer to become more
|
||||
protocol agnostic. */
|
||||
int fillcount;
|
||||
struct HTTP *http = data->req.protop;
|
||||
struct HTTP *http = k->protop;
|
||||
|
||||
if((k->exp100 == EXP100_SENDING_REQUEST) &&
|
||||
(http->sending == HTTPSEND_BODY)) {
|
||||
@ -892,7 +889,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
*didwhat &= ~KEEP_SEND; /* we didn't write anything actually */
|
||||
|
||||
/* set a timeout for the multi interface */
|
||||
Curl_expire(data, data->set.expect_100_timeout);
|
||||
Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -905,7 +902,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
sending_http_headers = FALSE;
|
||||
}
|
||||
|
||||
result = Curl_fillreadbuffer(conn, BUFSIZE, &fillcount);
|
||||
result = Curl_fillreadbuffer(conn, UPLOAD_BUFSIZE, &fillcount);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
@ -926,7 +923,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
/* store number of bytes available for upload */
|
||||
data->req.upload_present = nread;
|
||||
k->upload_present = nread;
|
||||
|
||||
/* convert LF to CRLF if so asked */
|
||||
if((!sending_http_headers) && (
|
||||
@ -937,7 +934,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
(data->set.crlf))) {
|
||||
/* Do we need to allocate a scratch buffer? */
|
||||
if(!data->state.scratch) {
|
||||
data->state.scratch = malloc(2 * BUFSIZE);
|
||||
data->state.scratch = malloc(2 * data->set.buffer_size);
|
||||
if(!data->state.scratch) {
|
||||
failf(data, "Failed to alloc scratch buffer!");
|
||||
|
||||
@ -952,7 +949,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
* must be used instead of the escape sequences \r & \n.
|
||||
*/
|
||||
for(i = 0, si = 0; i < nread; i++, si++) {
|
||||
if(data->req.upload_fromhere[i] == 0x0a) {
|
||||
if(k->upload_fromhere[i] == 0x0a) {
|
||||
data->state.scratch[si++] = 0x0d;
|
||||
data->state.scratch[si] = 0x0a;
|
||||
if(!data->set.crlf) {
|
||||
@ -963,7 +960,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
else
|
||||
data->state.scratch[si] = data->req.upload_fromhere[i];
|
||||
data->state.scratch[si] = k->upload_fromhere[i];
|
||||
}
|
||||
|
||||
if(si != nread) {
|
||||
@ -972,10 +969,10 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
nread = si;
|
||||
|
||||
/* upload from the new (replaced) buffer instead */
|
||||
data->req.upload_fromhere = data->state.scratch;
|
||||
k->upload_fromhere = data->state.scratch;
|
||||
|
||||
/* set the new amount too */
|
||||
data->req.upload_present = nread;
|
||||
k->upload_present = nread;
|
||||
}
|
||||
}
|
||||
|
||||
@ -986,7 +983,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
return result;
|
||||
}
|
||||
#endif /* CURL_DISABLE_SMTP */
|
||||
} /* if 0 == data->req.upload_present */
|
||||
} /* if 0 == k->upload_present */
|
||||
else {
|
||||
/* We have a partial buffer left from a previous "round". Use
|
||||
that instead of reading more data */
|
||||
@ -994,17 +991,17 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
|
||||
/* write to socket (send away data) */
|
||||
result = Curl_write(conn,
|
||||
conn->writesockfd, /* socket to send to */
|
||||
data->req.upload_fromhere, /* buffer pointer */
|
||||
data->req.upload_present, /* buffer size */
|
||||
&bytes_written); /* actually sent */
|
||||
conn->writesockfd, /* socket to send to */
|
||||
k->upload_fromhere, /* buffer pointer */
|
||||
k->upload_present, /* buffer size */
|
||||
&bytes_written); /* actually sent */
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(data->set.verbose)
|
||||
/* show the data before we change the pointer upload_fromhere */
|
||||
Curl_debug(data, CURLINFO_DATA_OUT, data->req.upload_fromhere,
|
||||
Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere,
|
||||
(size_t)bytes_written, conn);
|
||||
|
||||
k->writebytecount += bytes_written;
|
||||
@ -1015,20 +1012,20 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
infof(data, "We are completely uploaded and fine\n");
|
||||
}
|
||||
|
||||
if(data->req.upload_present != bytes_written) {
|
||||
if(k->upload_present != bytes_written) {
|
||||
/* we only wrote a part of the buffer (if anything), deal with it! */
|
||||
|
||||
/* store the amount of bytes left in the buffer to write */
|
||||
data->req.upload_present -= bytes_written;
|
||||
k->upload_present -= bytes_written;
|
||||
|
||||
/* advance the pointer where to find the buffer when the next send
|
||||
is to happen */
|
||||
data->req.upload_fromhere += bytes_written;
|
||||
k->upload_fromhere += bytes_written;
|
||||
}
|
||||
else {
|
||||
/* we've uploaded that buffer now */
|
||||
data->req.upload_fromhere = k->uploadbuf;
|
||||
data->req.upload_present = 0; /* no more bytes left */
|
||||
k->upload_fromhere = data->state.uploadbuffer;
|
||||
k->upload_present = 0; /* no more bytes left */
|
||||
|
||||
if(k->upload_done) {
|
||||
result = done_sending(conn, k);
|
||||
@ -1108,7 +1105,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) {
|
||||
/* write */
|
||||
|
||||
result = readwrite_upload(data, conn, k, &didwhat);
|
||||
result = readwrite_upload(data, conn, &didwhat);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@ -1142,6 +1139,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
/* we've waited long enough, continue anyway */
|
||||
k->exp100 = EXP100_SEND_DATA;
|
||||
k->keepon |= KEEP_SEND;
|
||||
Curl_expire_done(data, EXPIRE_100_TIMEOUT);
|
||||
infof(data, "Done waiting for 100-continue\n");
|
||||
}
|
||||
}
|
||||
@ -1186,15 +1184,13 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
*/
|
||||
(k->bytecount != (k->size + data->state.crlf_conversions)) &&
|
||||
#endif /* CURL_DO_LINEEND_CONV */
|
||||
!data->req.newurl) {
|
||||
!k->newurl) {
|
||||
failf(data, "transfer closed with %" CURL_FORMAT_CURL_OFF_T
|
||||
" bytes remaining to read",
|
||||
k->size - k->bytecount);
|
||||
" bytes remaining to read", k->size - k->bytecount);
|
||||
return CURLE_PARTIAL_FILE;
|
||||
}
|
||||
if(!(data->set.opt_no_body) &&
|
||||
k->chunk &&
|
||||
(conn->chunk.state != CHUNK_STOP)) {
|
||||
if(!(data->set.opt_no_body) && k->chunk &&
|
||||
(conn->chunk.state != CHUNK_STOP)) {
|
||||
/*
|
||||
* In chunked mode, return an error if the connection is closed prior to
|
||||
* the empty (terminating) chunk is read.
|
||||
@ -1313,8 +1309,11 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
|
||||
|
||||
if(data->set.httpreq == HTTPREQ_PUT)
|
||||
data->state.infilesize = data->set.filesize;
|
||||
else
|
||||
else {
|
||||
data->state.infilesize = data->set.postfieldsize;
|
||||
if(data->set.postfields && (data->state.infilesize == -1))
|
||||
data->state.infilesize = (curl_off_t)strlen(data->set.postfields);
|
||||
}
|
||||
|
||||
/* If there is a list of cookie files to read, do it now! */
|
||||
if(data->change.cookielist)
|
||||
@ -1343,10 +1342,10 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
|
||||
Curl_pgrsStartNow(data);
|
||||
|
||||
if(data->set.timeout)
|
||||
Curl_expire(data, data->set.timeout);
|
||||
Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
|
||||
|
||||
if(data->set.connecttimeout)
|
||||
Curl_expire(data, data->set.connecttimeout);
|
||||
Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
|
||||
|
||||
/* In case the handle is re-used and an authentication method was picked
|
||||
in the session we need to make sure we only use the one(s) we now
|
||||
@ -1628,9 +1627,7 @@ static char *concat_url(const char *base, const char *relurl)
|
||||
* as given by the remote server and set up the new URL to request.
|
||||
*/
|
||||
CURLcode Curl_follow(struct Curl_easy *data,
|
||||
char *newurl, /* this 'newurl' is the Location: string,
|
||||
and it must be malloc()ed before passed
|
||||
here */
|
||||
char *newurl, /* the Location: string */
|
||||
followtype type) /* see transfer.h */
|
||||
{
|
||||
#ifdef CURL_DISABLE_HTTP
|
||||
@ -1643,33 +1640,36 @@ CURLcode Curl_follow(struct Curl_easy *data,
|
||||
|
||||
/* Location: redirect */
|
||||
bool disallowport = FALSE;
|
||||
bool reachedmax = FALSE;
|
||||
|
||||
if(type == FOLLOW_REDIR) {
|
||||
if((data->set.maxredirs != -1) &&
|
||||
(data->set.followlocation >= data->set.maxredirs)) {
|
||||
failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
|
||||
return CURLE_TOO_MANY_REDIRECTS;
|
||||
(data->set.followlocation >= data->set.maxredirs)) {
|
||||
reachedmax = TRUE;
|
||||
type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
|
||||
to URL */
|
||||
}
|
||||
else {
|
||||
/* mark the next request as a followed location: */
|
||||
data->state.this_is_a_follow = TRUE;
|
||||
|
||||
/* mark the next request as a followed location: */
|
||||
data->state.this_is_a_follow = TRUE;
|
||||
data->set.followlocation++; /* count location-followers */
|
||||
|
||||
data->set.followlocation++; /* count location-followers */
|
||||
if(data->set.http_auto_referer) {
|
||||
/* We are asked to automatically set the previous URL as the referer
|
||||
when we get the next URL. We pick the ->url field, which may or may
|
||||
not be 100% correct */
|
||||
|
||||
if(data->set.http_auto_referer) {
|
||||
/* We are asked to automatically set the previous URL as the referer
|
||||
when we get the next URL. We pick the ->url field, which may or may
|
||||
not be 100% correct */
|
||||
if(data->change.referer_alloc) {
|
||||
Curl_safefree(data->change.referer);
|
||||
data->change.referer_alloc = FALSE;
|
||||
}
|
||||
|
||||
if(data->change.referer_alloc) {
|
||||
Curl_safefree(data->change.referer);
|
||||
data->change.referer_alloc = FALSE;
|
||||
data->change.referer = strdup(data->change.url);
|
||||
if(!data->change.referer)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
data->change.referer_alloc = TRUE; /* yes, free this later */
|
||||
}
|
||||
|
||||
data->change.referer = strdup(data->change.url);
|
||||
if(!data->change.referer)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
data->change.referer_alloc = TRUE; /* yes, free this later */
|
||||
}
|
||||
}
|
||||
|
||||
@ -1681,7 +1681,6 @@ CURLcode Curl_follow(struct Curl_easy *data,
|
||||
char *absolute = concat_url(data->change.url, newurl);
|
||||
if(!absolute)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
free(newurl);
|
||||
newurl = absolute;
|
||||
}
|
||||
else {
|
||||
@ -1697,8 +1696,6 @@ CURLcode Curl_follow(struct Curl_easy *data,
|
||||
if(!newest)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
strcpy_url(newest, newurl); /* create a space-free URL */
|
||||
|
||||
free(newurl); /* that was no good */
|
||||
newurl = newest; /* use this instead now */
|
||||
|
||||
}
|
||||
@ -1707,6 +1704,11 @@ CURLcode Curl_follow(struct Curl_easy *data,
|
||||
/* we're only figuring out the new url if we would've followed locations
|
||||
but now we're done so we can get out! */
|
||||
data->info.wouldredirect = newurl;
|
||||
|
||||
if(reachedmax) {
|
||||
failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
|
||||
return CURLE_TOO_MANY_REDIRECTS;
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@ -1720,7 +1722,6 @@ CURLcode Curl_follow(struct Curl_easy *data,
|
||||
|
||||
data->change.url = newurl;
|
||||
data->change.url_alloc = TRUE;
|
||||
newurl = NULL; /* don't free! */
|
||||
|
||||
infof(data, "Issue another request to this URL: '%s'\n", data->change.url);
|
||||
|
||||
@ -1947,7 +1948,7 @@ Curl_setup_transfer(
|
||||
|
||||
/* Set a timeout for the multi interface. Add the inaccuracy margin so
|
||||
that we don't fire slightly too early and get denied to run. */
|
||||
Curl_expire(data, data->set.expect_100_timeout);
|
||||
Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
|
||||
}
|
||||
else {
|
||||
if(data->state.expect100header)
|
||||
|
154
lib/url.c
154
lib/url.c
@ -140,6 +140,19 @@ static CURLcode parse_login_details(const char *login, const size_t len,
|
||||
char **optionsptr);
|
||||
static unsigned int get_protocol_family(unsigned int protocol);
|
||||
|
||||
#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
|
||||
#define READBUFFER_MAX CURL_MAX_READ_SIZE
|
||||
#define READBUFFER_MIN 1024
|
||||
|
||||
/* Some parts of the code (e.g. chunked encoding) assume this buffer has at
|
||||
* more than just a few bytes to play with. Don't let it become too small or
|
||||
* bad things will happen.
|
||||
*/
|
||||
#if READBUFFER_SIZE < READBUFFER_MIN
|
||||
# error READBUFFER_SIZE is too small
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Protocol table.
|
||||
*/
|
||||
@ -607,6 +620,7 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
|
||||
|
||||
set->expect_100_timeout = 1000L; /* Wait for a second by default. */
|
||||
set->sep_headers = TRUE; /* separated header lists by default */
|
||||
set->buffer_size = READBUFFER_SIZE;
|
||||
|
||||
Curl_http2_init_userset(set);
|
||||
return result;
|
||||
@ -644,7 +658,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
|
||||
|
||||
/* We do some initial setup here, all those fields that can't be just 0 */
|
||||
|
||||
data->state.buffer = malloc(BUFSIZE + 1);
|
||||
data->state.buffer = malloc(READBUFFER_SIZE + 1);
|
||||
if(!data->state.buffer) {
|
||||
DEBUGF(fprintf(stderr, "Error: malloc of buffer failed\n"));
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
@ -1009,8 +1023,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
|
||||
* CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
|
||||
* other - POST is kept as POST after 301 and 302
|
||||
*/
|
||||
int postRedir = curlx_sltosi(va_arg(param, long));
|
||||
data->set.keep_post = postRedir & CURL_REDIR_POST_ALL;
|
||||
arg = va_arg(param, long);
|
||||
data->set.keep_post = arg & CURL_REDIR_POST_ALL;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2061,13 +2075,19 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
|
||||
/*
|
||||
* Set what local port to bind the socket to when performing an operation.
|
||||
*/
|
||||
data->set.localport = curlx_sltous(va_arg(param, long));
|
||||
arg = va_arg(param, long);
|
||||
if((arg < 0) || (arg > 65535))
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
data->set.localport = curlx_sltous(arg);
|
||||
break;
|
||||
case CURLOPT_LOCALPORTRANGE:
|
||||
/*
|
||||
* Set number of local ports to try, starting with CURLOPT_LOCALPORT.
|
||||
*/
|
||||
data->set.localportrange = curlx_sltosi(va_arg(param, long));
|
||||
arg = va_arg(param, long);
|
||||
if((arg < 0) || (arg > 65535))
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
data->set.localportrange = curlx_sltosi(arg);
|
||||
break;
|
||||
case CURLOPT_KRBLEVEL:
|
||||
/*
|
||||
@ -2284,22 +2304,26 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
|
||||
* The application kindly asks for a differently sized receive buffer.
|
||||
* If it seems reasonable, we'll use it.
|
||||
*/
|
||||
data->set.buffer_size = va_arg(param, long);
|
||||
arg = va_arg(param, long);
|
||||
|
||||
if(data->set.buffer_size > MAX_BUFSIZE)
|
||||
data->set.buffer_size = MAX_BUFSIZE; /* huge internal default */
|
||||
else if(data->set.buffer_size < 1)
|
||||
data->set.buffer_size = BUFSIZE;
|
||||
if(arg > READBUFFER_MAX)
|
||||
arg = READBUFFER_MAX;
|
||||
else if(arg < 1)
|
||||
arg = READBUFFER_SIZE;
|
||||
else if(arg < READBUFFER_MIN)
|
||||
arg = READBUFFER_MIN;
|
||||
|
||||
/* Resize only if larger than default buffer size. */
|
||||
if(data->set.buffer_size > BUFSIZE) {
|
||||
data->state.buffer = realloc(data->state.buffer,
|
||||
data->set.buffer_size + 1);
|
||||
if(!data->state.buffer) {
|
||||
/* Resize if new size */
|
||||
if(arg != data->set.buffer_size) {
|
||||
char *newbuff = realloc(data->state.buffer, arg + 1);
|
||||
if(!newbuff) {
|
||||
DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else
|
||||
data->state.buffer = newbuff;
|
||||
}
|
||||
data->set.buffer_size = arg;
|
||||
|
||||
break;
|
||||
|
||||
@ -2592,7 +2616,10 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
|
||||
* know that an unsigned int will always hold the value so we blindly
|
||||
* typecast to this type
|
||||
*/
|
||||
data->set.scope_id = curlx_sltoui(va_arg(param, long));
|
||||
arg = va_arg(param, long);
|
||||
if((arg < 0) || (arg > 0xf))
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
data->set.scope_id = curlx_sltoui(arg);
|
||||
break;
|
||||
|
||||
case CURLOPT_PROTOCOLS:
|
||||
@ -2794,13 +2821,17 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
|
||||
data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
|
||||
break;
|
||||
case CURLOPT_TLSAUTH_TYPE:
|
||||
if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
|
||||
argptr = va_arg(param, char *);
|
||||
if(!argptr ||
|
||||
strncasecompare(argptr, "SRP", strlen("SRP")))
|
||||
data->set.ssl.authtype = CURL_TLSAUTH_SRP;
|
||||
else
|
||||
data->set.ssl.authtype = CURL_TLSAUTH_NONE;
|
||||
break;
|
||||
case CURLOPT_PROXY_TLSAUTH_TYPE:
|
||||
if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
|
||||
argptr = va_arg(param, char *);
|
||||
if(!argptr ||
|
||||
strncasecompare(argptr, "SRP", strlen("SRP")))
|
||||
data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
|
||||
else
|
||||
data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
|
||||
@ -2935,8 +2966,7 @@ static void conn_reset_all_postponed_data(struct connectdata *conn)
|
||||
conn_reset_postponed_data(conn, 1);
|
||||
}
|
||||
#else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
|
||||
/* Use "do-nothing" macros instead of functions when workaround not used */
|
||||
#define conn_reset_postponed_data(c,n) do {} WHILE_FALSE
|
||||
/* Use "do-nothing" macro instead of function when workaround not used */
|
||||
#define conn_reset_all_postponed_data(c) do {} WHILE_FALSE
|
||||
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
|
||||
|
||||
@ -2993,6 +3023,7 @@ static void conn_free(struct connectdata *conn)
|
||||
Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
|
||||
Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
|
||||
Curl_safefree(conn->master_buffer);
|
||||
Curl_safefree(conn->connect_buffer);
|
||||
|
||||
conn_reset_all_postponed_data(conn);
|
||||
|
||||
@ -3100,12 +3131,16 @@ static bool SocketIsDead(curl_socket_t sock)
|
||||
}
|
||||
|
||||
/*
|
||||
* IsPipeliningPossible() returns TRUE if the options set would allow
|
||||
* pipelining/multiplexing and the connection is using a HTTP protocol.
|
||||
* IsPipeliningPossible()
|
||||
*
|
||||
* Return a bitmask with the available pipelining and multiplexing options for
|
||||
* the given requested connection.
|
||||
*/
|
||||
static bool IsPipeliningPossible(const struct Curl_easy *handle,
|
||||
const struct connectdata *conn)
|
||||
static int IsPipeliningPossible(const struct Curl_easy *handle,
|
||||
const struct connectdata *conn)
|
||||
{
|
||||
int avail = 0;
|
||||
|
||||
/* If a HTTP protocol and pipelining is enabled */
|
||||
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
|
||||
(!conn->bits.protoconnstart || !conn->bits.close)) {
|
||||
@ -3115,14 +3150,14 @@ static bool IsPipeliningPossible(const struct Curl_easy *handle,
|
||||
(handle->set.httpreq == HTTPREQ_GET ||
|
||||
handle->set.httpreq == HTTPREQ_HEAD))
|
||||
/* didn't ask for HTTP/1.0 and a GET or HEAD */
|
||||
return TRUE;
|
||||
avail |= CURLPIPE_HTTP1;
|
||||
|
||||
if(Curl_pipeline_wanted(handle->multi, CURLPIPE_MULTIPLEX) &&
|
||||
(handle->set.httpversion >= CURL_HTTP_VERSION_2))
|
||||
/* allows HTTP/2 */
|
||||
return TRUE;
|
||||
avail |= CURLPIPE_MULTIPLEX;
|
||||
}
|
||||
return FALSE;
|
||||
return avail;
|
||||
}
|
||||
|
||||
int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
|
||||
@ -3409,7 +3444,7 @@ ConnectionExists(struct Curl_easy *data,
|
||||
struct connectdata *check;
|
||||
struct connectdata *chosen = 0;
|
||||
bool foundPendingCandidate = FALSE;
|
||||
bool canPipeline = IsPipeliningPossible(data, needle);
|
||||
int canpipe = IsPipeliningPossible(data, needle);
|
||||
struct connectbundle *bundle;
|
||||
|
||||
#ifdef USE_NTLM
|
||||
@ -3425,10 +3460,10 @@ ConnectionExists(struct Curl_easy *data,
|
||||
*force_reuse = FALSE;
|
||||
*waitpipe = FALSE;
|
||||
|
||||
/* We can't pipe if the site is blacklisted */
|
||||
if(canPipeline && Curl_pipeline_site_blacklisted(data, needle)) {
|
||||
canPipeline = FALSE;
|
||||
}
|
||||
/* We can't pipeline if the site is blacklisted */
|
||||
if((canpipe & CURLPIPE_HTTP1) &&
|
||||
Curl_pipeline_site_blacklisted(data, needle))
|
||||
canpipe &= ~ CURLPIPE_HTTP1;
|
||||
|
||||
/* Look up the bundle with all the connections to this
|
||||
particular host */
|
||||
@ -3448,8 +3483,8 @@ ConnectionExists(struct Curl_easy *data,
|
||||
(bundle->multiuse == BUNDLE_MULTIPLEX ?
|
||||
"can multiplex" : "serially")));
|
||||
|
||||
/* We can't pipe if we don't know anything about the server */
|
||||
if(canPipeline) {
|
||||
/* We can't pipeline if we don't know anything about the server */
|
||||
if(canpipe) {
|
||||
if(bundle->multiuse <= BUNDLE_UNKNOWN) {
|
||||
if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) {
|
||||
infof(data, "Server doesn't support multi-use yet, wait\n");
|
||||
@ -3458,18 +3493,18 @@ ConnectionExists(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
infof(data, "Server doesn't support multi-use (yet)\n");
|
||||
canPipeline = FALSE;
|
||||
canpipe = 0;
|
||||
}
|
||||
if((bundle->multiuse == BUNDLE_PIPELINING) &&
|
||||
!Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1)) {
|
||||
/* not asked for, switch off */
|
||||
infof(data, "Could pipeline, but not asked to!\n");
|
||||
canPipeline = FALSE;
|
||||
canpipe = 0;
|
||||
}
|
||||
else if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
|
||||
!Curl_pipeline_wanted(data->multi, CURLPIPE_MULTIPLEX)) {
|
||||
infof(data, "Could multiplex, but not asked to!\n");
|
||||
canPipeline = FALSE;
|
||||
canpipe = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3490,20 +3525,21 @@ ConnectionExists(struct Curl_easy *data,
|
||||
|
||||
pipeLen = check->send_pipe.size + check->recv_pipe.size;
|
||||
|
||||
if(canPipeline) {
|
||||
if(canpipe) {
|
||||
if(check->bits.protoconnstart && check->bits.close)
|
||||
continue;
|
||||
|
||||
if(!check->bits.multiplex) {
|
||||
/* If not multiplexing, make sure the pipe has only GET requests */
|
||||
/* If not multiplexing, make sure the connection is fine for HTTP/1
|
||||
pipelining */
|
||||
struct Curl_easy* sh = gethandleathead(&check->send_pipe);
|
||||
struct Curl_easy* rh = gethandleathead(&check->recv_pipe);
|
||||
if(sh) {
|
||||
if(!IsPipeliningPossible(sh, check))
|
||||
if(!(IsPipeliningPossible(sh, check) & CURLPIPE_HTTP1))
|
||||
continue;
|
||||
}
|
||||
else if(rh) {
|
||||
if(!IsPipeliningPossible(rh, check))
|
||||
if(!(IsPipeliningPossible(rh, check) & CURLPIPE_HTTP1))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -3611,7 +3647,7 @@ ConnectionExists(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
|
||||
if(!canPipeline && check->inuse)
|
||||
if(!canpipe && check->inuse)
|
||||
/* this request can't be pipelined but the checked connection is
|
||||
already in use so we skip it */
|
||||
continue;
|
||||
@ -3742,7 +3778,7 @@ ConnectionExists(struct Curl_easy *data,
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if(canPipeline) {
|
||||
if(canpipe) {
|
||||
/* We can pipeline if we want to. Let's continue looking for
|
||||
the optimal connection to use, i.e the shortest pipe that is not
|
||||
blacklisted. */
|
||||
@ -4203,7 +4239,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
|
||||
if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
|
||||
!conn->master_buffer) {
|
||||
/* Allocate master_buffer to be used for HTTP/1 pipelining */
|
||||
conn->master_buffer = calloc(BUFSIZE, sizeof(char));
|
||||
conn->master_buffer = calloc(MASTERBUF_SIZE, sizeof(char));
|
||||
if(!conn->master_buffer)
|
||||
goto error;
|
||||
}
|
||||
@ -4430,6 +4466,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
|
||||
#endif
|
||||
|
||||
protop = "file"; /* protocol string */
|
||||
*prot_missing = !url_has_scheme;
|
||||
}
|
||||
else {
|
||||
/* clear path */
|
||||
@ -4593,14 +4630,30 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
|
||||
|
||||
size_t plen = strlen(path); /* new path, should be 1 byte longer than
|
||||
the original */
|
||||
size_t urllen = strlen(data->change.url); /* original URL length */
|
||||
|
||||
size_t prefixlen = strlen(conn->host.name);
|
||||
|
||||
if(!*prot_missing)
|
||||
prefixlen += strlen(protop) + strlen("://");
|
||||
if(!*prot_missing) {
|
||||
size_t protolen = strlen(protop);
|
||||
|
||||
reurl = malloc(urllen + 2); /* 2 for zerobyte + slash */
|
||||
if(curl_strnequal(protop, data->change.url, protolen))
|
||||
prefixlen += protolen;
|
||||
else {
|
||||
failf(data, "<url> malformed");
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
|
||||
if(curl_strnequal("://", &data->change.url[protolen], 3))
|
||||
prefixlen += 3;
|
||||
/* only file: is allowed to omit one or both slashes */
|
||||
else if(curl_strnequal("file:", data->change.url, 5))
|
||||
prefixlen += 1 + (data->change.url[5] == '/');
|
||||
else {
|
||||
failf(data, "<url> malformed");
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
reurl = malloc(prefixlen + plen + 1);
|
||||
if(!reurl)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
@ -6961,7 +7014,6 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
|
||||
k->bytecount = 0;
|
||||
|
||||
k->buf = data->state.buffer;
|
||||
k->uploadbuf = data->state.uploadbuffer;
|
||||
k->hbufp = data->state.headerbuff;
|
||||
k->ignorebody=FALSE;
|
||||
|
||||
@ -6985,7 +7037,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
|
||||
* Returns the family as a single bit protocol identifier.
|
||||
*/
|
||||
|
||||
unsigned int get_protocol_family(unsigned int protocol)
|
||||
static unsigned int get_protocol_family(unsigned int protocol)
|
||||
{
|
||||
unsigned int family;
|
||||
|
||||
|
@ -200,12 +200,12 @@
|
||||
#include <libssh2_sftp.h>
|
||||
#endif /* HAVE_LIBSSH2_H */
|
||||
|
||||
/* Download buffer size, keep it fairly big for speed reasons */
|
||||
#undef BUFSIZE
|
||||
#define BUFSIZE CURL_MAX_WRITE_SIZE
|
||||
#undef MAX_BUFSIZE
|
||||
#define MAX_BUFSIZE CURL_MAX_READ_SIZE
|
||||
#define CURL_BUFSIZE(x) ((x)?(x):(BUFSIZE))
|
||||
/* The upload buffer size, should not be smaller than CURL_MAX_WRITE_SIZE, as
|
||||
it needs to hold a full buffer as could be sent in a write callback */
|
||||
#define UPLOAD_BUFSIZE CURL_MAX_WRITE_SIZE
|
||||
|
||||
/* The "master buffer" is for HTTP pipelining */
|
||||
#define MASTERBUF_SIZE 16384
|
||||
|
||||
/* Initial size of the buffer to store headers in, it'll be enlarged in case
|
||||
of need. */
|
||||
@ -333,6 +333,11 @@ struct ssl_connect_data {
|
||||
size_t encdata_length, decdata_length;
|
||||
size_t encdata_offset, decdata_offset;
|
||||
unsigned char *encdata_buffer, *decdata_buffer;
|
||||
/* encdata_is_incomplete: if encdata contains only a partial record that
|
||||
can't be decrypted without another Curl_read_plain (that is, status is
|
||||
SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
|
||||
more bytes into encdata then set this back to false. */
|
||||
bool encdata_is_incomplete;
|
||||
unsigned long req_flags, ret_flags;
|
||||
CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
|
||||
bool recv_sspi_close_notify; /* true if connection closed by close_notify */
|
||||
@ -716,7 +721,6 @@ struct SingleRequest {
|
||||
long bodywrites;
|
||||
|
||||
char *buf;
|
||||
char *uploadbuf;
|
||||
curl_socket_t maxfd;
|
||||
|
||||
int keepon;
|
||||
@ -898,6 +902,8 @@ struct connectdata {
|
||||
connection is used! */
|
||||
struct Curl_easy *data;
|
||||
|
||||
struct curl_llist_element bundle_node; /* conncache */
|
||||
|
||||
/* chunk is for HTTP chunked encoding, but is in the general connectdata
|
||||
struct only because we can do just about any protocol through a HTTP proxy
|
||||
and a HTTP proxy may in fact respond using chunked encoding */
|
||||
@ -1138,6 +1144,7 @@ struct connectdata {
|
||||
struct connectbundle *bundle; /* The bundle we are member of */
|
||||
|
||||
int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
|
||||
char *connect_buffer; /* for CONNECT business */
|
||||
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
char *unix_domain_socket;
|
||||
@ -1307,6 +1314,30 @@ struct tempbuf {
|
||||
Curl_client_write() */
|
||||
};
|
||||
|
||||
/* Timers */
|
||||
typedef enum {
|
||||
EXPIRE_100_TIMEOUT,
|
||||
EXPIRE_ASYNC_NAME,
|
||||
EXPIRE_CONNECTTIMEOUT,
|
||||
EXPIRE_DNS_PER_NAME,
|
||||
EXPIRE_HAPPY_EYEBALLS,
|
||||
EXPIRE_MULTI_PENDING,
|
||||
EXPIRE_RUN_NOW,
|
||||
EXPIRE_SPEEDCHECK,
|
||||
EXPIRE_TIMEOUT,
|
||||
EXPIRE_TOOFAST,
|
||||
EXPIRE_LAST /* not an actual timer, used as a marker only */
|
||||
} expire_id;
|
||||
|
||||
/*
|
||||
* One instance for each timeout an easy handle can set.
|
||||
*/
|
||||
struct time_node {
|
||||
struct curl_llist_element list;
|
||||
struct timeval time;
|
||||
expire_id eid;
|
||||
};
|
||||
|
||||
struct UrlState {
|
||||
|
||||
/* Points to the connection cache */
|
||||
@ -1326,7 +1357,7 @@ struct UrlState {
|
||||
size_t headersize; /* size of the allocation */
|
||||
|
||||
char *buffer; /* download buffer */
|
||||
char uploadbuffer[BUFSIZE+1]; /* upload buffer */
|
||||
char uploadbuffer[UPLOAD_BUFSIZE+1]; /* upload buffer */
|
||||
curl_off_t current_speed; /* the ProgressShow() function sets this,
|
||||
bytes / second */
|
||||
bool this_is_a_follow; /* this is a followed Location: request */
|
||||
@ -1342,7 +1373,7 @@ struct UrlState {
|
||||
long sessionage; /* number of the most recent session */
|
||||
unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */
|
||||
struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */
|
||||
char *scratch; /* huge buffer[BUFSIZE*2] when doing upload CRLF replacing */
|
||||
char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */
|
||||
bool errorbuf; /* Set to TRUE if the error buffer is already filled in.
|
||||
This must be set to FALSE every time _easy_perform() is
|
||||
called. */
|
||||
@ -1375,6 +1406,7 @@ struct UrlState {
|
||||
struct timeval expiretime; /* set this with Curl_expire() only */
|
||||
struct Curl_tree timenode; /* for the splay stuff */
|
||||
struct curl_llist timeoutlist; /* list of pending timeouts */
|
||||
struct time_node expires[EXPIRE_LAST]; /* nodes for each expire type */
|
||||
|
||||
/* a place to store the most recently set FTP entrypath */
|
||||
char *most_recent_ftp_entrypath;
|
||||
@ -1804,6 +1836,8 @@ struct Curl_easy {
|
||||
struct Curl_easy *prev;
|
||||
|
||||
struct connectdata *easy_conn; /* the "unit's" connection */
|
||||
struct curl_llist_element connect_queue;
|
||||
struct curl_llist_element pipeline_queue;
|
||||
|
||||
CURLMstate mstate; /* the handle's state */
|
||||
CURLcode result; /* previous result */
|
||||
|
@ -205,7 +205,7 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value)
|
||||
{
|
||||
char *tmp;
|
||||
char *token;
|
||||
char *tok_buf;
|
||||
char *tok_buf = NULL;
|
||||
|
||||
/* Initialise the output */
|
||||
*value = 0;
|
||||
@ -360,7 +360,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
|
||||
char qop_options[64];
|
||||
int qop_values;
|
||||
char cnonce[33];
|
||||
unsigned int entropy[4];
|
||||
char nonceCount[] = "00000001";
|
||||
char method[] = "AUTHENTICATE";
|
||||
char qop[] = DIGEST_QOP_VALUE_STRING_AUTH;
|
||||
@ -387,15 +386,11 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
|
||||
if(!(qop_values & DIGEST_QOP_VALUE_AUTH))
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
|
||||
/* Generate 16 bytes of random data */
|
||||
result = Curl_rand(data, &entropy[0], 4);
|
||||
/* Generate 32 random hex chars, 32 bytes + 1 zero termination */
|
||||
result = Curl_rand_hex(data, (unsigned char *)cnonce, sizeof(cnonce));
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Convert the random data into a 32 byte hex string */
|
||||
snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x",
|
||||
entropy[0], entropy[1], entropy[2], entropy[3]);
|
||||
|
||||
/* So far so good, now calculate A1 and H(A1) according to RFC 2831 */
|
||||
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
|
||||
if(!ctxt)
|
||||
@ -563,7 +558,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else if(strcasecompare(value, "qop")) {
|
||||
char *tok_buf;
|
||||
char *tok_buf = NULL;
|
||||
/* Tokenize the list and choose auth if possible, use a temporary
|
||||
clone of the buffer since strtok_r() ruins it */
|
||||
tmp = strdup(content);
|
||||
@ -684,12 +679,10 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
|
||||
digest->nc = 1;
|
||||
|
||||
if(!digest->cnonce) {
|
||||
unsigned int rnd[4];
|
||||
result = Curl_rand(data, &rnd[0], 4);
|
||||
result = Curl_rand_hex(data, (unsigned char *)cnoncebuf,
|
||||
sizeof(cnoncebuf));
|
||||
if(result)
|
||||
return result;
|
||||
snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x",
|
||||
rnd[0], rnd[1], rnd[2], rnd[3]);
|
||||
|
||||
result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
|
||||
&cnonce, &cnonce_sz);
|
||||
|
@ -555,10 +555,10 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
|
||||
#if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2)
|
||||
if(ntlm->target_info_len) {
|
||||
unsigned char ntbuffer[0x18];
|
||||
unsigned int entropy[2];
|
||||
unsigned char entropy[8];
|
||||
unsigned char ntlmv2hash[0x18];
|
||||
|
||||
result = Curl_rand(data, &entropy[0], 2);
|
||||
result = Curl_rand(data, entropy, 8);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
@ -572,15 +572,13 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
|
||||
return result;
|
||||
|
||||
/* LMv2 response */
|
||||
result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash,
|
||||
(unsigned char *)&entropy[0],
|
||||
result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy,
|
||||
&ntlm->nonce[0], lmresp);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* NTLMv2 response */
|
||||
result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash,
|
||||
(unsigned char *)&entropy[0],
|
||||
result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy,
|
||||
ntlm, &ntlmv2resp, &ntresplen);
|
||||
if(result)
|
||||
return result;
|
||||
@ -596,10 +594,10 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
|
||||
unsigned char ntbuffer[0x18];
|
||||
unsigned char tmp[0x18];
|
||||
unsigned char md5sum[MD5_DIGEST_LENGTH];
|
||||
unsigned int entropy[2];
|
||||
unsigned char entropy[8];
|
||||
|
||||
/* Need to create 8 bytes random data */
|
||||
result = Curl_rand(data, &entropy[0], 2);
|
||||
result = Curl_rand(data, entropy, 8);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -44,6 +44,38 @@ and that's a problem since options.h hasn't been included yet. */
|
||||
#include <cyassl/options.h>
|
||||
#endif
|
||||
|
||||
/* To determine what functions are available we rely on one or both of:
|
||||
- the user's options.h generated by CyaSSL/wolfSSL
|
||||
- the symbols detected by curl's configure
|
||||
Since they are markedly different from one another, and one or the other may
|
||||
not be available, we do some checking below to bring things in sync. */
|
||||
|
||||
/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */
|
||||
#ifndef HAVE_ALPN
|
||||
#ifdef HAVE_WOLFSSL_USEALPN
|
||||
#define HAVE_ALPN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in
|
||||
options.h, but is only seen in >= 3.6.6 since that's when they started
|
||||
disabling SSLv3 by default. */
|
||||
#ifndef WOLFSSL_ALLOW_SSLV3
|
||||
#if (LIBCYASSL_VERSION_HEX < 0x03006006) || \
|
||||
defined(HAVE_WOLFSSLV3_CLIENT_METHOD)
|
||||
#define WOLFSSL_ALLOW_SSLV3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC
|
||||
supported curve extension in options.h. Note ECC is enabled separately. */
|
||||
#ifndef HAVE_SUPPORTED_CURVES
|
||||
#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \
|
||||
defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE)
|
||||
#define HAVE_SUPPORTED_CURVES
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
@ -78,38 +110,6 @@ and that's a problem since options.h hasn't been included yet. */
|
||||
#define CYASSL_MAX_ERROR_SZ 80
|
||||
#endif
|
||||
|
||||
/* To determine what functions are available we rely on one or both of:
|
||||
- the user's options.h generated by CyaSSL/wolfSSL
|
||||
- the symbols detected by curl's configure
|
||||
Since they are markedly different from one another, and one or the other may
|
||||
not be available, we do some checking below to bring things in sync. */
|
||||
|
||||
/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */
|
||||
#ifndef HAVE_ALPN
|
||||
#ifdef HAVE_WOLFSSL_USEALPN
|
||||
#define HAVE_ALPN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in
|
||||
options.h, but is only seen in >= 3.6.6 since that's when they started
|
||||
disabling SSLv3 by default. */
|
||||
#ifndef WOLFSSL_ALLOW_SSLV3
|
||||
#if (LIBCYASSL_VERSION_HEX < 0x03006006) || \
|
||||
defined(HAVE_WOLFSSLV3_CLIENT_METHOD)
|
||||
#define WOLFSSL_ALLOW_SSLV3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC
|
||||
supported curve extension in options.h. Note ECC is enabled separately. */
|
||||
#ifndef HAVE_SUPPORTED_CURVES
|
||||
#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \
|
||||
defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE)
|
||||
#define HAVE_SUPPORTED_CURVES
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static Curl_recv cyassl_recv;
|
||||
static Curl_send cyassl_send;
|
||||
|
||||
|
@ -113,6 +113,36 @@
|
||||
#define ioErr -36
|
||||
#define paramErr -50
|
||||
|
||||
#ifdef DARWIN_SSL_PINNEDPUBKEY
|
||||
/* both new and old APIs return rsa keys missing the spki header (not DER) */
|
||||
static const unsigned char rsa4096SpkiHeader[] = {
|
||||
0x30, 0x82, 0x02, 0x22, 0x30, 0x0d,
|
||||
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
|
||||
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
|
||||
0x00, 0x03, 0x82, 0x02, 0x0f, 0x00};
|
||||
|
||||
static const unsigned char rsa2048SpkiHeader[] = {
|
||||
0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
|
||||
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
|
||||
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
|
||||
0x00, 0x03, 0x82, 0x01, 0x0f, 0x00};
|
||||
#ifdef DARWIN_SSL_PINNEDPUBKEY_V1
|
||||
/* the *new* version doesn't return DER encoded ecdsa certs like the old... */
|
||||
static const unsigned char ecDsaSecp256r1SpkiHeader[] = {
|
||||
0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
|
||||
0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
|
||||
0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
|
||||
0x42, 0x00};
|
||||
|
||||
static const unsigned char ecDsaSecp384r1SpkiHeader[] = {
|
||||
0x30, 0x76, 0x30, 0x10, 0x06, 0x07,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
|
||||
0x01, 0x06, 0x05, 0x2b, 0x81, 0x04,
|
||||
0x00, 0x22, 0x03, 0x62, 0x00};
|
||||
#endif /* DARWIN_SSL_PINNEDPUBKEY_V1 */
|
||||
#endif /* DARWIN_SSL_PINNEDPUBKEY */
|
||||
|
||||
/* The following two functions were ripped from Apple sample code,
|
||||
* with some modifications: */
|
||||
static OSStatus SocketRead(SSLConnectionRef connection,
|
||||
@ -1374,7 +1404,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
else
|
||||
err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
|
||||
|
||||
if(err == noErr) {
|
||||
if(err == noErr && cert_and_key) {
|
||||
SecCertificateRef cert = NULL;
|
||||
CFTypeRef certs_c[1];
|
||||
CFArrayRef certs;
|
||||
@ -1996,6 +2026,112 @@ static int verify_cert(const char *cafile, struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DARWIN_SSL_PINNEDPUBKEY
|
||||
static CURLcode pkp_pin_peer_pubkey(struct SessionHandle *data,
|
||||
SSLContextRef ctx,
|
||||
const char *pinnedpubkey)
|
||||
{ /* Scratch */
|
||||
size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24;
|
||||
unsigned char *pubkey = NULL, *realpubkey = NULL, *spkiHeader = NULL;
|
||||
CFDataRef publicKeyBits = NULL;
|
||||
|
||||
/* Result is returned to caller */
|
||||
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
|
||||
|
||||
/* if a path wasn't specified, don't pin */
|
||||
if(!pinnedpubkey)
|
||||
return CURLE_OK;
|
||||
|
||||
|
||||
if(!ctx)
|
||||
return result;
|
||||
|
||||
do {
|
||||
SecTrustRef trust;
|
||||
OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
|
||||
if(ret != noErr || trust == NULL)
|
||||
break;
|
||||
|
||||
SecKeyRef keyRef = SecTrustCopyPublicKey(trust);
|
||||
CFRelease(trust);
|
||||
if(keyRef == NULL)
|
||||
break;
|
||||
|
||||
#ifdef DARWIN_SSL_PINNEDPUBKEY_V1
|
||||
|
||||
publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL);
|
||||
CFRelease(keyRef);
|
||||
if(publicKeyBits == NULL)
|
||||
break;
|
||||
|
||||
#elif DARWIN_SSL_PINNEDPUBKEY_V2
|
||||
|
||||
OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
|
||||
&publicKeyBits);
|
||||
CFRelease(keyRef);
|
||||
if(success != errSecSuccess || publicKeyBits == NULL)
|
||||
break;
|
||||
|
||||
#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */
|
||||
|
||||
pubkeylen = CFDataGetLength(publicKeyBits);
|
||||
pubkey = CFDataGetBytePtr(publicKeyBits);
|
||||
|
||||
switch(pubkeylen) {
|
||||
case 526:
|
||||
/* 4096 bit RSA pubkeylen == 526 */
|
||||
spkiHeader = rsa4096SpkiHeader;
|
||||
break;
|
||||
case 270:
|
||||
/* 2048 bit RSA pubkeylen == 270 */
|
||||
spkiHeader = rsa2048SpkiHeader;
|
||||
break;
|
||||
#ifdef DARWIN_SSL_PINNEDPUBKEY_V1
|
||||
case 65:
|
||||
/* ecDSA secp256r1 pubkeylen == 65 */
|
||||
spkiHeader = ecDsaSecp256r1SpkiHeader;
|
||||
spkiHeaderLength = 26;
|
||||
break;
|
||||
case 97:
|
||||
/* ecDSA secp384r1 pubkeylen == 97 */
|
||||
spkiHeader = ecDsaSecp384r1SpkiHeader;
|
||||
spkiHeaderLength = 23;
|
||||
break;
|
||||
default:
|
||||
infof(data, "SSL: unhandled public key length: %d\n", pubkeylen);
|
||||
#elif DARWIN_SSL_PINNEDPUBKEY_V2
|
||||
default:
|
||||
/* ecDSA secp256r1 pubkeylen == 91 header already included?
|
||||
* ecDSA secp384r1 header already included too
|
||||
* we assume rest of algorithms do same, so do nothing
|
||||
*/
|
||||
result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey,
|
||||
pubkeylen);
|
||||
#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */
|
||||
continue; /* break from loop */
|
||||
}
|
||||
|
||||
realpubkeylen = pubkeylen + spkiHeaderLength;
|
||||
realpubkey = malloc(realpubkeylen);
|
||||
if(!realpubkey)
|
||||
break;
|
||||
|
||||
memcpy(realpubkey, spkiHeader, spkiHeaderLength);
|
||||
memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen);
|
||||
|
||||
result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey,
|
||||
realpubkeylen);
|
||||
|
||||
} while(0);
|
||||
|
||||
Curl_safefree(realpubkey);
|
||||
if(publicKeyBits != NULL)
|
||||
CFRelease(publicKeyBits);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif /* DARWIN_SSL_PINNEDPUBKEY */
|
||||
|
||||
static CURLcode
|
||||
darwinssl_connect_step2(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
@ -2102,6 +2238,17 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
|
||||
/* we have been connected fine, we're not waiting for anything else. */
|
||||
connssl->connecting_state = ssl_connect_3;
|
||||
|
||||
#ifdef DARWIN_SSL_PINNEDPUBKEY
|
||||
if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) {
|
||||
CURLcode result = pkp_pin_peer_pubkey(data, connssl->ssl_ctx,
|
||||
data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]);
|
||||
if(result) {
|
||||
failf(data, "SSL: public key does not match pinned public key!");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif /* DARWIN_SSL_PINNEDPUBKEY */
|
||||
|
||||
/* Informational message */
|
||||
(void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
|
||||
(void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol);
|
||||
@ -2573,6 +2720,15 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
|
||||
(void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
|
||||
}
|
||||
|
||||
void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */
|
||||
size_t tmplen,
|
||||
unsigned char *sha256sum, /* output */
|
||||
size_t sha256len)
|
||||
{
|
||||
assert(sha256len >= SHA256_DIGEST_LENGTH);
|
||||
(void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
|
||||
}
|
||||
|
||||
bool Curl_darwinssl_false_start(void)
|
||||
{
|
||||
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
|
||||
|
@ -48,11 +48,34 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
|
||||
size_t tmplen,
|
||||
unsigned char *md5sum, /* output */
|
||||
size_t md5len);
|
||||
void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */
|
||||
size_t tmplen,
|
||||
unsigned char *sha256sum, /* output */
|
||||
size_t sha256len);
|
||||
bool Curl_darwinssl_false_start(void);
|
||||
|
||||
/* Set the API backend definition to SecureTransport */
|
||||
#define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL
|
||||
|
||||
/* pinned public key support tests */
|
||||
|
||||
/* version 1 supports macOS 10.12+ and iOS 10+ */
|
||||
#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
|
||||
(!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200))
|
||||
#define DARWIN_SSL_PINNEDPUBKEY_V1 1
|
||||
#endif
|
||||
|
||||
/* version 2 supports MacOSX 10.7+ */
|
||||
#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
|
||||
#define DARWIN_SSL_PINNEDPUBKEY_V2 1
|
||||
#endif
|
||||
|
||||
#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2)
|
||||
/* this backend supports CURLOPT_PINNEDPUBLICKEY */
|
||||
#define DARWIN_SSL_PINNEDPUBKEY 1
|
||||
#define have_curlssl_pinnedpubkey 1
|
||||
#endif /* DARWIN_SSL_PINNEDPUBKEY */
|
||||
|
||||
/* API setup for SecureTransport */
|
||||
#define curlssl_init() (1)
|
||||
#define curlssl_cleanup() Curl_nop_stmt
|
||||
@ -70,6 +93,7 @@ bool Curl_darwinssl_false_start(void);
|
||||
#define curlssl_data_pending(x,y) Curl_darwinssl_data_pending(x, y)
|
||||
#define curlssl_random(x,y,z) ((void)x, Curl_darwinssl_random(y,z))
|
||||
#define curlssl_md5sum(a,b,c,d) Curl_darwinssl_md5sum(a,b,c,d)
|
||||
#define curlssl_sha256sum(a,b,c,d) Curl_darwinssl_sha256sum(a,b,c,d)
|
||||
#define curlssl_false_start() Curl_darwinssl_false_start()
|
||||
|
||||
#endif /* USE_DARWINSSL */
|
||||
|
@ -211,18 +211,20 @@ int Curl_gtls_cleanup(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
static void showtime(struct Curl_easy *data,
|
||||
const char *text,
|
||||
time_t stamp)
|
||||
{
|
||||
struct tm buffer;
|
||||
const struct tm *tm = &buffer;
|
||||
char str[96];
|
||||
CURLcode result = Curl_gmtime(stamp, &buffer);
|
||||
if(result)
|
||||
return;
|
||||
|
||||
snprintf(data->state.buffer,
|
||||
BUFSIZE,
|
||||
snprintf(str,
|
||||
sizeof(str),
|
||||
"\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
|
||||
text,
|
||||
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
|
||||
@ -232,8 +234,9 @@ static void showtime(struct Curl_easy *data,
|
||||
tm->tm_hour,
|
||||
tm->tm_min,
|
||||
tm->tm_sec);
|
||||
infof(data, "%s\n", data->state.buffer);
|
||||
infof(data, "%s\n", str);
|
||||
}
|
||||
#endif
|
||||
|
||||
static gnutls_datum_t load_file(const char *file)
|
||||
{
|
||||
@ -962,8 +965,6 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
gnutls_datum_t issuerp;
|
||||
char certbuf[256] = ""; /* big enough? */
|
||||
size_t size;
|
||||
unsigned int algo;
|
||||
unsigned int bits;
|
||||
time_t certclock;
|
||||
const char *ptr;
|
||||
struct Curl_easy *data = conn->data;
|
||||
@ -974,6 +975,8 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
#endif
|
||||
CURLcode result = CURLE_OK;
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
unsigned int algo;
|
||||
unsigned int bits;
|
||||
gnutls_protocol_t version = gnutls_protocol_get_version(session);
|
||||
#endif
|
||||
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
|
||||
@ -1344,6 +1347,7 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
|
||||
*/
|
||||
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
/* public key algorithm's parameters */
|
||||
algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
|
||||
infof(data, "\t certificate public key: %s\n",
|
||||
@ -1368,12 +1372,13 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
|
||||
infof(data, "\t issuer: %s\n", certbuf);
|
||||
|
||||
gnutls_x509_crt_deinit(x509_cert);
|
||||
|
||||
/* compression algorithm (if any) */
|
||||
ptr = gnutls_compression_get_name(gnutls_compression_get(session));
|
||||
/* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
|
||||
infof(data, "\t compression: %s\n", ptr);
|
||||
#endif
|
||||
|
||||
gnutls_x509_crt_deinit(x509_cert);
|
||||
|
||||
#ifdef HAS_ALPN
|
||||
if(conn->bits.tls_enable_alpn) {
|
||||
|
@ -67,7 +67,7 @@
|
||||
#endif
|
||||
|
||||
#if defined(THREADING_SUPPORT)
|
||||
static mbedtls_entropy_context entropy;
|
||||
static mbedtls_entropy_context ts_entropy;
|
||||
|
||||
static int entropy_init_initialized = 0;
|
||||
|
||||
@ -131,7 +131,7 @@ static void mbed_debug(void *context, int level, const char *f_name,
|
||||
/*
|
||||
* profile
|
||||
*/
|
||||
const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
|
||||
static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
|
||||
{
|
||||
/* Hashes from SHA-1 and above */
|
||||
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) |
|
||||
@ -247,11 +247,11 @@ mbed_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
|
||||
#ifdef THREADING_SUPPORT
|
||||
entropy_init_mutex(&entropy);
|
||||
entropy_init_mutex(&ts_entropy);
|
||||
mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
|
||||
|
||||
ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex,
|
||||
&entropy, NULL, 0);
|
||||
&ts_entropy, NULL, 0);
|
||||
if(ret) {
|
||||
#ifdef MBEDTLS_ERROR_C
|
||||
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
|
||||
@ -424,6 +424,11 @@ mbed_connect_step1(struct connectdata *conn,
|
||||
mbedtls_ssl_conf_ciphersuites(&connssl->config,
|
||||
mbedtls_ssl_list_ciphersuites());
|
||||
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
mbedtls_ssl_conf_renegotiation(&connssl->config,
|
||||
MBEDTLS_SSL_RENEGOTIATION_ENABLED);
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||
mbedtls_ssl_conf_session_tickets(&connssl->config,
|
||||
MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
|
||||
|
168
lib/vtls/nss.c
168
lib/vtls/nss.c
@ -81,10 +81,17 @@
|
||||
static PRLock *nss_initlock = NULL;
|
||||
static PRLock *nss_crllock = NULL;
|
||||
static PRLock *nss_findslot_lock = NULL;
|
||||
static PRLock *nss_trustload_lock = NULL;
|
||||
static struct curl_llist nss_crl_list;
|
||||
static NSSInitContext *nss_context = NULL;
|
||||
static volatile int initialized = 0;
|
||||
|
||||
/* type used to wrap pointers as list nodes */
|
||||
struct ptr_list_wrap {
|
||||
void *ptr;
|
||||
struct curl_llist_element node;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int num;
|
||||
@ -201,7 +208,10 @@ static const cipher_s cipherlist[] = {
|
||||
};
|
||||
|
||||
static const char *pem_library = "libnsspem.so";
|
||||
static SECMODModule *mod = NULL;
|
||||
static SECMODModule *pem_module = NULL;
|
||||
|
||||
static const char *trust_library = "libnssckbi.so";
|
||||
static SECMODModule *trust_module = NULL;
|
||||
|
||||
/* NSPR I/O layer we use to detect blocking direction during SSL handshake */
|
||||
static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
|
||||
@ -371,6 +381,18 @@ static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
|
||||
return slot;
|
||||
}
|
||||
|
||||
/* wrap 'ptr' as list node and tail-insert into 'list' */
|
||||
static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr)
|
||||
{
|
||||
struct ptr_list_wrap *wrap = malloc(sizeof *wrap);
|
||||
if(!wrap)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
wrap->ptr = ptr;
|
||||
Curl_llist_insert_next(list, list->tail, wrap, &wrap->node);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* Call PK11_CreateGenericObject() with the given obj_class and filename. If
|
||||
* the call succeeds, append the object handle to the list of objects so that
|
||||
* the object can be destroyed in Curl_nss_close(). */
|
||||
@ -413,7 +435,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
|
||||
if(!obj)
|
||||
return result;
|
||||
|
||||
if(!Curl_llist_insert_next(&ssl->obj_list, ssl->obj_list.tail, obj)) {
|
||||
if(insert_wrapped_ptr(&ssl->obj_list, obj) != CURLE_OK) {
|
||||
PK11_DestroyGenericObject(obj);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -430,17 +452,21 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
|
||||
* NSS objects in Curl_nss_close() */
|
||||
static void nss_destroy_object(void *user, void *ptr)
|
||||
{
|
||||
PK11GenericObject *obj = (PK11GenericObject *)ptr;
|
||||
struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
|
||||
PK11GenericObject *obj = (PK11GenericObject *) wrap->ptr;
|
||||
(void) user;
|
||||
PK11_DestroyGenericObject(obj);
|
||||
free(wrap);
|
||||
}
|
||||
|
||||
/* same as nss_destroy_object() but for CRL items */
|
||||
static void nss_destroy_crl_item(void *user, void *ptr)
|
||||
{
|
||||
SECItem *crl_der = (SECItem *)ptr;
|
||||
struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
|
||||
SECItem *crl_der = (SECItem *) wrap->ptr;
|
||||
(void) user;
|
||||
SECITEM_FreeItem(crl_der, PR_TRUE);
|
||||
free(wrap);
|
||||
}
|
||||
|
||||
static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
|
||||
@ -496,7 +522,7 @@ static CURLcode nss_cache_crl(SECItem *crl_der)
|
||||
PR_Lock(nss_crllock);
|
||||
|
||||
/* store the CRL item so that we can free it in Curl_nss_cleanup() */
|
||||
if(!Curl_llist_insert_next(&nss_crl_list, nss_crl_list.tail, crl_der)) {
|
||||
if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) {
|
||||
SECITEM_FreeItem(crl_der, PR_TRUE);
|
||||
PR_Unlock(nss_crllock);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
@ -581,7 +607,7 @@ fail:
|
||||
static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
|
||||
char *key_file)
|
||||
{
|
||||
PK11SlotInfo *slot;
|
||||
PK11SlotInfo *slot, *tmp;
|
||||
SECStatus status;
|
||||
CURLcode result;
|
||||
struct ssl_connect_data *ssl = conn->ssl;
|
||||
@ -600,7 +626,9 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
|
||||
/* This will force the token to be seen as re-inserted */
|
||||
SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
|
||||
tmp = SECMOD_WaitForAnyTokenEvent(pem_module, 0, 0);
|
||||
if(tmp)
|
||||
PK11_FreeSlot(tmp);
|
||||
PK11_IsPresent(slot);
|
||||
|
||||
status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd));
|
||||
@ -1178,6 +1206,50 @@ static PRStatus nspr_io_close(PRFileDesc *fd)
|
||||
return close_fn(fd);
|
||||
}
|
||||
|
||||
/* load a PKCS #11 module */
|
||||
static CURLcode nss_load_module(SECMODModule **pmod, const char *library,
|
||||
const char *name)
|
||||
{
|
||||
char *config_string;
|
||||
SECMODModule *module = *pmod;
|
||||
if(module)
|
||||
/* already loaded */
|
||||
return CURLE_OK;
|
||||
|
||||
config_string = aprintf("library=%s name=%s", library, name);
|
||||
if(!config_string)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
module = SECMOD_LoadUserModule(config_string, NULL, PR_FALSE);
|
||||
free(config_string);
|
||||
|
||||
if(module && module->loaded) {
|
||||
/* loaded successfully */
|
||||
*pmod = module;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
if(module)
|
||||
SECMOD_DestroyModule(module);
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
/* unload a PKCS #11 module */
|
||||
static void nss_unload_module(SECMODModule **pmod)
|
||||
{
|
||||
SECMODModule *module = *pmod;
|
||||
if(!module)
|
||||
/* not loaded */
|
||||
return;
|
||||
|
||||
if(SECMOD_UnloadUserModule(module) != SECSuccess)
|
||||
/* unload failed */
|
||||
return;
|
||||
|
||||
SECMOD_DestroyModule(module);
|
||||
*pmod = NULL;
|
||||
}
|
||||
|
||||
/* data might be NULL */
|
||||
static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
|
||||
{
|
||||
@ -1287,6 +1359,7 @@ int Curl_nss_init(void)
|
||||
nss_initlock = PR_NewLock();
|
||||
nss_crllock = PR_NewLock();
|
||||
nss_findslot_lock = PR_NewLock();
|
||||
nss_trustload_lock = PR_NewLock();
|
||||
}
|
||||
|
||||
/* We will actually initialize NSS later */
|
||||
@ -1325,10 +1398,8 @@ void Curl_nss_cleanup(void)
|
||||
* the certificates. */
|
||||
SSL_ClearSessionCache();
|
||||
|
||||
if(mod && SECSuccess == SECMOD_UnloadUserModule(mod)) {
|
||||
SECMOD_DestroyModule(mod);
|
||||
mod = NULL;
|
||||
}
|
||||
nss_unload_module(&pem_module);
|
||||
nss_unload_module(&trust_module);
|
||||
NSS_ShutdownContext(nss_context);
|
||||
nss_context = NULL;
|
||||
}
|
||||
@ -1341,6 +1412,7 @@ void Curl_nss_cleanup(void)
|
||||
PR_DestroyLock(nss_initlock);
|
||||
PR_DestroyLock(nss_crllock);
|
||||
PR_DestroyLock(nss_findslot_lock);
|
||||
PR_DestroyLock(nss_trustload_lock);
|
||||
nss_initlock = NULL;
|
||||
|
||||
initialized = 0;
|
||||
@ -1462,12 +1534,44 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
|
||||
struct Curl_easy *data = conn->data;
|
||||
const char *cafile = SSL_CONN_CONFIG(CAfile);
|
||||
const char *capath = SSL_CONN_CONFIG(CApath);
|
||||
bool use_trust_module;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(cafile) {
|
||||
CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
|
||||
if(result)
|
||||
return result;
|
||||
/* treat empty string as unset */
|
||||
if(cafile && !cafile[0])
|
||||
cafile = NULL;
|
||||
if(capath && !capath[0])
|
||||
capath = NULL;
|
||||
|
||||
infof(data, " CAfile: %s\n CApath: %s\n",
|
||||
cafile ? cafile : "none",
|
||||
capath ? capath : "none");
|
||||
|
||||
/* load libnssckbi.so if no other trust roots were specified */
|
||||
use_trust_module = !cafile && !capath;
|
||||
|
||||
PR_Lock(nss_trustload_lock);
|
||||
if(use_trust_module && !trust_module) {
|
||||
/* libnssckbi.so needed but not yet loaded --> load it! */
|
||||
result = nss_load_module(&trust_module, trust_library, "trust");
|
||||
infof(data, "%s %s\n", (result) ? "failed to load" : "loaded",
|
||||
trust_library);
|
||||
if(result == CURLE_FAILED_INIT)
|
||||
/* make the error non-fatal if we are not going to verify peer */
|
||||
result = CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
else if(!use_trust_module && trust_module) {
|
||||
/* libnssckbi.so not needed but already loaded --> unload it! */
|
||||
infof(data, "unloading %s\n", trust_library);
|
||||
nss_unload_module(&trust_module);
|
||||
}
|
||||
PR_Unlock(nss_trustload_lock);
|
||||
|
||||
if(cafile)
|
||||
result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(capath) {
|
||||
struct_stat st;
|
||||
@ -1501,10 +1605,6 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
|
||||
infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath);
|
||||
}
|
||||
|
||||
infof(data, " CAfile: %s\n CApath: %s\n",
|
||||
cafile ? cafile : "none",
|
||||
capath ? capath : "none");
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@ -1683,29 +1783,17 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
|
||||
if(!mod) {
|
||||
char *configstring = aprintf("library=%s name=PEM", pem_library);
|
||||
if(!configstring) {
|
||||
PR_Unlock(nss_initlock);
|
||||
goto error;
|
||||
}
|
||||
mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
|
||||
free(configstring);
|
||||
|
||||
if(!mod || !mod->loaded) {
|
||||
if(mod) {
|
||||
SECMOD_DestroyModule(mod);
|
||||
mod = NULL;
|
||||
}
|
||||
infof(data, "WARNING: failed to load NSS PEM library %s. Using "
|
||||
"OpenSSL PEM certificates will not work.\n", pem_library);
|
||||
}
|
||||
}
|
||||
|
||||
PK11_SetPasswordFunc(nss_get_password);
|
||||
|
||||
result = nss_load_module(&pem_module, pem_library, "PEM");
|
||||
PR_Unlock(nss_initlock);
|
||||
if(result == CURLE_FAILED_INIT)
|
||||
infof(data, "WARNING: failed to load NSS PEM library %s. Using "
|
||||
"OpenSSL PEM certificates will not work.\n", pem_library);
|
||||
else if(result)
|
||||
goto error;
|
||||
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
|
||||
model = PR_NewTCPSocket();
|
||||
if(!model)
|
||||
|
@ -236,8 +236,8 @@ static CURLcode Curl_ossl_seed(struct Curl_easy *data)
|
||||
/* we have the "SSL is seeded" boolean static to prevent multiple
|
||||
time-consuming seedings in vain */
|
||||
static bool ssl_seeded = FALSE;
|
||||
char *buf = data->state.buffer; /* point to the big buffer */
|
||||
int nread=0;
|
||||
char fname[256];
|
||||
|
||||
if(ssl_seeded)
|
||||
return CURLE_OK;
|
||||
@ -297,11 +297,11 @@ static CURLcode Curl_ossl_seed(struct Curl_easy *data)
|
||||
} while(!rand_enough());
|
||||
|
||||
/* generates a default path for the random seed file */
|
||||
buf[0]=0; /* blank it first */
|
||||
RAND_file_name(buf, BUFSIZE);
|
||||
if(buf[0]) {
|
||||
fname[0]=0; /* blank it first */
|
||||
RAND_file_name(fname, sizeof(fname));
|
||||
if(fname[0]) {
|
||||
/* we got a file name to try */
|
||||
nread += RAND_load_file(buf, RAND_LOAD_LENGTH);
|
||||
nread += RAND_load_file(fname, RAND_LOAD_LENGTH);
|
||||
if(rand_enough())
|
||||
return nread;
|
||||
}
|
||||
@ -1371,7 +1371,8 @@ static CURLcode verifystatus(struct connectdata *conn,
|
||||
st = SSL_CTX_get_cert_store(connssl->ctx);
|
||||
|
||||
#if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \
|
||||
defined(LIBRESSL_VERSION_NUMBER))
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && \
|
||||
LIBRESSL_VERSION_NUMBER <= 0x2040200fL))
|
||||
/* The authorized responder cert in the OCSP response MUST be signed by the
|
||||
peer cert's issuer (see RFC6960 section 4.2.2.2). If that's a root cert,
|
||||
no problem, but if it's an intermediate cert OpenSSL has a bug where it
|
||||
@ -2807,7 +2808,7 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
struct Curl_easy *data = conn->data;
|
||||
X509 *issuer;
|
||||
FILE *fp;
|
||||
char *buffer = data->state.buffer;
|
||||
char buffer[2048];
|
||||
const char *ptr;
|
||||
long * const certverifyresult = SSL_IS_PROXY() ?
|
||||
&data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
|
||||
@ -2819,6 +2820,7 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
|
||||
connssl->server_cert = SSL_get_peer_certificate(connssl->handle);
|
||||
if(!connssl->server_cert) {
|
||||
BIO_free(mem);
|
||||
if(!strict)
|
||||
return CURLE_OK;
|
||||
|
||||
@ -2829,7 +2831,7 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server");
|
||||
|
||||
rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
|
||||
buffer, BUFSIZE);
|
||||
buffer, sizeof(buffer));
|
||||
infof(data, " subject: %s\n", rc?"[NONE]":buffer);
|
||||
|
||||
ASN1_TIME_print(mem, X509_get0_notBefore(connssl->server_cert));
|
||||
@ -2854,7 +2856,7 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
}
|
||||
|
||||
rc = x509_name_oneline(X509_get_issuer_name(connssl->server_cert),
|
||||
buffer, BUFSIZE);
|
||||
buffer, sizeof(buffer));
|
||||
if(rc) {
|
||||
if(strict)
|
||||
failf(data, "SSL: couldn't get X509-issuer name!");
|
||||
|
@ -432,6 +432,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
|
||||
connssl->recv_unrecoverable_err = CURLE_OK;
|
||||
connssl->recv_sspi_close_notify = false;
|
||||
connssl->recv_connection_closed = false;
|
||||
connssl->encdata_is_incomplete = false;
|
||||
|
||||
/* continue to second handshake step */
|
||||
connssl->connecting_state = ssl_connect_2;
|
||||
@ -480,6 +481,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
|
||||
|
||||
/* buffer to store previously received and encrypted data */
|
||||
if(connssl->encdata_buffer == NULL) {
|
||||
connssl->encdata_is_incomplete = false;
|
||||
connssl->encdata_offset = 0;
|
||||
connssl->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
|
||||
connssl->encdata_buffer = malloc(connssl->encdata_length);
|
||||
@ -532,6 +534,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
|
||||
|
||||
/* increase encrypted data buffer offset */
|
||||
connssl->encdata_offset += nread;
|
||||
connssl->encdata_is_incomplete = false;
|
||||
infof(data, "schannel: encrypted data got %zd\n", nread);
|
||||
}
|
||||
|
||||
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
|
||||
@ -576,6 +580,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
|
||||
|
||||
/* check if the handshake was incomplete */
|
||||
if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
|
||||
connssl->encdata_is_incomplete = true;
|
||||
connssl->connecting_state = ssl_connect_2_reading;
|
||||
infof(data, "schannel: received incomplete message, need more data\n");
|
||||
return CURLE_OK;
|
||||
@ -625,7 +630,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
|
||||
else
|
||||
failf(data, "schannel: next InitializeSecurityContext failed: %s",
|
||||
Curl_sspi_strerror(conn, sspi_status));
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
return sspi_status == SEC_E_UNTRUSTED_ROOT ?
|
||||
CURLE_SSL_CACERT_BADFILE : CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
/* check if there was additional remaining encrypted data */
|
||||
@ -1177,6 +1183,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
|
||||
}
|
||||
else if(nread > 0) {
|
||||
connssl->encdata_offset += (size_t)nread;
|
||||
connssl->encdata_is_incomplete = false;
|
||||
infof(data, "schannel: encrypted data got %zd\n", nread);
|
||||
}
|
||||
}
|
||||
@ -1313,6 +1320,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
|
||||
}
|
||||
}
|
||||
else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
|
||||
connssl->encdata_is_incomplete = true;
|
||||
if(!*err)
|
||||
*err = CURLE_AGAIN;
|
||||
infof(data, "schannel: failed to decrypt data, need more data\n");
|
||||
@ -1414,8 +1422,8 @@ bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex)
|
||||
const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
|
||||
if(connssl->use) /* SSL/TLS is in use */
|
||||
return (connssl->encdata_offset > 0 ||
|
||||
connssl->decdata_offset > 0) ? TRUE : FALSE;
|
||||
return (connssl->decdata_offset > 0 ||
|
||||
(connssl->encdata_offset > 0 && !connssl->encdata_is_incomplete));
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
@ -1518,6 +1526,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
|
||||
Curl_safefree(connssl->encdata_buffer);
|
||||
connssl->encdata_length = 0;
|
||||
connssl->encdata_offset = 0;
|
||||
connssl->encdata_is_incomplete = false;
|
||||
}
|
||||
|
||||
/* free internal buffer for received decrypted data */
|
||||
|
@ -466,6 +466,7 @@ static const char *GTime2str(const char *beg, const char *end)
|
||||
break;
|
||||
case 2:
|
||||
sec1 = fracp[-2];
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
sec2 = fracp[-1];
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user