init repo.

This commit is contained in:
tqcq
2024-12-19 13:14:37 +08:00
commit 7d7845acb5
1412 changed files with 596214 additions and 0 deletions

1
third_party/curl/lib/.checksrc vendored Normal file
View File

@ -0,0 +1 @@
enable STRERROR

251
third_party/curl/lib/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,251 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
set(LIB_NAME libcurl)
set(LIBCURL_OUTPUT_NAME libcurl CACHE STRING "Basename of the curl library")
add_definitions(-DBUILDING_LIBCURL)
configure_file(curl_config.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h)
transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake)
# DllMain is added later for DLL builds only.
list(REMOVE_ITEM CSOURCES dllmain.c)
list(APPEND HHEADERS ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h)
# The rest of the build
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/..)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
if(USE_ARES)
include_directories(${CARES_INCLUDE_DIR})
endif()
if(BUILD_TESTING)
add_library(
curlu # special libcurlu library just for unittests
STATIC
EXCLUDE_FROM_ALL
${HHEADERS} ${CSOURCES}
)
target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
target_link_libraries(curlu PRIVATE ${CURL_LIBS})
endif()
if(ENABLE_CURLDEBUG)
# We must compile these sources separately to avoid memdebug.h redefinitions
# applying to them.
set_source_files_properties(memdebug.c curl_multibyte.c PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
endif()
transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake)
if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
CMAKE_SYSTEM_NAME STREQUAL "SunOS" OR
CMAKE_SYSTEM_NAME STREQUAL "GNU/kFreeBSD" OR
# FreeBSD comes with the a.out and elf flavours
# but a.out was supported up to version 3.x and
# elf from 3.x. I cannot imagine someone running
# CMake on those ancient systems
CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
CMAKE_SYSTEM_NAME STREQUAL "Haiku")
math(EXPR CMAKESONAME "${VERSIONCHANGE} - ${VERSIONDEL}")
set(CMAKEVERSION "${CMAKESONAME}.${VERSIONDEL}.${VERSIONADD}")
else()
unset(CMAKESONAME)
endif()
## Library definition
# Add "_imp" as a suffix before the extension to avoid conflicting with
# the statically linked "libcurl.lib" (typically with MSVC)
if(WIN32 AND
NOT IMPORT_LIB_SUFFIX AND
CMAKE_STATIC_LIBRARY_SUFFIX STREQUAL CMAKE_IMPORT_LIBRARY_SUFFIX)
set(IMPORT_LIB_SUFFIX "_imp")
endif()
# Whether to do a single compilation pass for libcurl sources and reuse these
# objects to generate both static and shared target.
if(NOT DEFINED SHARE_LIB_OBJECT)
# Enable it by default on platforms where PIC is the default for both shared
# and static and there is a way to tell the linker which libcurl symbols it
# should export (vs. marking these symbols exportable at compile-time).
if(WIN32)
set(SHARE_LIB_OBJECT ON)
else()
# On other platforms, make it an option disabled by default
set(SHARE_LIB_OBJECT OFF)
endif()
endif()
if(SHARE_LIB_OBJECT)
set(LIB_OBJECT "libcurl_object")
add_library(${LIB_OBJECT} OBJECT ${HHEADERS} ${CSOURCES})
if(WIN32)
# Define CURL_STATICLIB always, to disable __declspec(dllexport) for
# exported libcurl symbols. We handle exports via libcurl.def instead.
# Except with symbol hiding disabled or debug mode enabled, when we export
# _all_ symbols from libcurl DLL, without using libcurl.def.
set_property(TARGET ${LIB_OBJECT} APPEND
PROPERTY COMPILE_DEFINITIONS "CURL_STATICLIB")
endif()
target_link_libraries(${LIB_OBJECT} PRIVATE ${CURL_LIBS})
set_target_properties(${LIB_OBJECT} PROPERTIES
POSITION_INDEPENDENT_CODE ON)
if(HIDES_CURL_PRIVATE_SYMBOLS)
set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
set_target_properties(${LIB_OBJECT} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
endif()
target_include_directories(${LIB_OBJECT} INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
set(LIB_SOURCE $<TARGET_OBJECTS:${LIB_OBJECT}>)
else()
set(LIB_SOURCE ${HHEADERS} ${CSOURCES})
endif()
# we want it to be called libcurl on all platforms
if(BUILD_STATIC_LIBS)
list(APPEND libcurl_export ${LIB_STATIC})
add_library(${LIB_STATIC} STATIC ${LIB_SOURCE})
add_library(${PROJECT_NAME}::${LIB_STATIC} ALIAS ${LIB_STATIC})
if(WIN32)
set_property(TARGET ${LIB_OBJECT} APPEND
PROPERTY COMPILE_DEFINITIONS "CURL_STATICLIB")
endif()
target_link_libraries(${LIB_STATIC} PRIVATE ${CURL_LIBS})
# Remove the "lib" prefix since the library is already named "libcurl".
set_target_properties(${LIB_STATIC} PROPERTIES
PREFIX "" OUTPUT_NAME "${LIBCURL_OUTPUT_NAME}"
SUFFIX "${STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}"
INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB")
if(HIDES_CURL_PRIVATE_SYMBOLS)
set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
set_target_properties(${LIB_STATIC} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
endif()
if(CMAKEVERSION AND CMAKESONAME)
set_target_properties(${LIB_STATIC} PROPERTIES
VERSION ${CMAKEVERSION} SOVERSION ${CMAKESONAME})
endif()
target_include_directories(${LIB_STATIC} INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
endif()
if(BUILD_SHARED_LIBS)
list(APPEND libcurl_export ${LIB_SHARED})
add_library(${LIB_SHARED} SHARED ${LIB_SOURCE})
add_library(${PROJECT_NAME}::${LIB_SHARED} ALIAS ${LIB_SHARED})
if(WIN32 OR CYGWIN)
if(CYGWIN)
# For cygwin always compile dllmain.c as a separate unit since it
# includes windows.h, which shouldn't be included in other units.
set_source_files_properties(dllmain.c PROPERTIES
SKIP_UNITY_BUILD_INCLUSION ON)
endif()
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES dllmain.c)
endif()
if(WIN32)
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES libcurl.rc)
if(HIDES_CURL_PRIVATE_SYMBOLS)
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES "${CURL_SOURCE_DIR}/libcurl.def")
endif()
endif()
target_link_libraries(${LIB_SHARED} PRIVATE ${CURL_LIBS})
# Remove the "lib" prefix since the library is already named "libcurl".
set_target_properties(${LIB_SHARED} PROPERTIES
PREFIX "" OUTPUT_NAME "${LIBCURL_OUTPUT_NAME}"
IMPORT_PREFIX "" IMPORT_SUFFIX "${IMPORT_LIB_SUFFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}"
POSITION_INDEPENDENT_CODE ON)
if(HIDES_CURL_PRIVATE_SYMBOLS)
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
set_target_properties(${LIB_SHARED} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
endif()
if(CMAKEVERSION AND CMAKESONAME)
set_target_properties(${LIB_SHARED} PROPERTIES
VERSION ${CMAKEVERSION} SOVERSION ${CMAKESONAME})
endif()
target_include_directories(${LIB_SHARED} INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
endif()
add_library(${LIB_NAME} ALIAS ${LIB_SELECTED})
add_library(${PROJECT_NAME}::${LIB_NAME} ALIAS ${LIB_SELECTED})
if(CURL_ENABLE_EXPORT_TARGET)
if(BUILD_STATIC_LIBS)
install(TARGETS ${LIB_STATIC}
EXPORT ${TARGETS_EXPORT_NAME}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
endif()
if(BUILD_SHARED_LIBS)
install(TARGETS ${LIB_SHARED}
EXPORT ${TARGETS_EXPORT_NAME}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
endif()
export(TARGETS ${libcurl_export}
FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
NAMESPACE ${PROJECT_NAME}::
)
endif()

148
third_party/curl/lib/Makefile.am vendored Normal file
View File

@ -0,0 +1,148 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
AUTOMAKE_OPTIONS = foreign nostdinc
CMAKE_DIST = CMakeLists.txt curl_config.h.cmake
EXTRA_DIST = Makefile.mk config-win32.h config-win32ce.h config-plan9.h \
config-riscos.h config-mac.h curl_config.h.in config-dos.h libcurl.rc \
config-amigaos.h config-win32ce.h config-os400.h setup-os400.h \
$(CMAKE_DIST) setup-win32.h .checksrc Makefile.soname
lib_LTLIBRARIES = libcurl.la
if BUILD_UNITTESTS
noinst_LTLIBRARIES = libcurlu.la
else
noinst_LTLIBRARIES =
endif
# This might hold -Werror
CFLAGS += @CURL_CFLAG_EXTRAS@
# Specify our include paths here, and do it relative to $(top_srcdir) and
# $(top_builddir), to ensure that these paths which belong to the library
# being currently built and tested are searched before the library which
# might possibly already be installed in the system.
#
# $(top_srcdir)/include is for libcurl's external include files
# $(top_builddir)/lib is for libcurl's generated lib/curl_config.h file
# $(top_srcdir)/lib for libcurl's lib/curl_setup.h and other "private" files
AM_CPPFLAGS = -I$(top_srcdir)/include \
-I$(top_builddir)/lib \
-I$(top_srcdir)/lib
# Prevent LIBS from being used for all link targets
LIBS = $(BLANK_AT_MAKETIME)
include Makefile.soname
AM_CPPFLAGS += -DBUILDING_LIBCURL
AM_LDFLAGS =
AM_CFLAGS =
# Makefile.inc provides the CSOURCES and HHEADERS defines
include Makefile.inc
libcurl_la_SOURCES = $(CSOURCES) $(HHEADERS)
libcurlu_la_SOURCES = $(CSOURCES) $(HHEADERS)
libcurl_la_CPPFLAGS_EXTRA =
libcurl_la_LDFLAGS_EXTRA =
libcurl_la_CFLAGS_EXTRA =
if CURL_LT_SHLIB_USE_VERSION_INFO
libcurl_la_LDFLAGS_EXTRA += $(VERSIONINFO)
endif
if CURL_LT_SHLIB_USE_NO_UNDEFINED
libcurl_la_LDFLAGS_EXTRA += -no-undefined
endif
if CURL_LT_SHLIB_USE_MIMPURE_TEXT
libcurl_la_LDFLAGS_EXTRA += -mimpure-text
endif
if CURL_LT_SHLIB_USE_VERSIONED_SYMBOLS
libcurl_la_LDFLAGS_EXTRA += -Wl,--version-script=libcurl.vers
else
# if symbol-hiding is enabled, hide them!
if DOING_CURL_SYMBOL_HIDING
libcurl_la_LDFLAGS_EXTRA += -export-symbols-regex '^curl_.*'
endif
endif
if USE_CPPFLAG_CURL_STATICLIB
libcurl_la_CPPFLAGS_EXTRA += -DCURL_STATICLIB
else
if HAVE_WINDRES
libcurl_la_SOURCES += $(LIB_RCFILES)
$(LIB_RCFILES): $(top_srcdir)/include/curl/curlver.h
endif
endif
if DOING_CURL_SYMBOL_HIDING
libcurl_la_CPPFLAGS_EXTRA += -DCURL_HIDDEN_SYMBOLS
libcurl_la_CFLAGS_EXTRA += $(CFLAG_CURL_SYMBOL_HIDING)
endif
libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA)
libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(CURL_LDFLAGS_LIB) $(LIBCURL_LIBS)
libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA)
libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS
libcurlu_la_LDFLAGS = $(AM_LDFLAGS) -static $(LIBCURL_LIBS)
libcurlu_la_CFLAGS = $(AM_CFLAGS)
CHECKSRC = $(CS_$(V))
CS_0 = @echo " RUN " $@;
CS_1 =
CS_ = $(CS_0)
checksrc:
$(CHECKSRC)(@PERL@ $(top_srcdir)/scripts/checksrc.pl -D$(srcdir) \
-W$(srcdir)/curl_config.h $(srcdir)/*.[ch] $(srcdir)/vauth/*.[ch] \
$(srcdir)/vtls/*.[ch] $(srcdir)/vquic/*.[ch] $(srcdir)/vssh/*.[ch])
if CURLDEBUG
# for debug builds, we scan the sources on all regular make invokes
all-local: checksrc
endif
# disable the tests that are mostly causing false positives
TIDYFLAGS=-checks=-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-clang-analyzer-valist.Uninitialized,-clang-analyzer-core.NonNullParamChecker,-clang-analyzer-core.NullDereference -quiet
TIDY:=clang-tidy
tidy:
$(TIDY) $(CSOURCES) $(TIDYFLAGS) -- $(AM_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H
optiontable:
perl optiontable.pl < $(top_srcdir)/include/curl/curl.h > easyoptions.c
if HAVE_WINDRES
.rc.lo:
$(LIBTOOL) --tag=RC --mode=compile $(RC) -I$(top_srcdir)/include $(RCFLAGS) -i $< -o $@
endif

5523
third_party/curl/lib/Makefile.in vendored Normal file

File diff suppressed because it is too large Load Diff

381
third_party/curl/lib/Makefile.inc vendored Normal file
View File

@ -0,0 +1,381 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
LIB_VAUTH_CFILES = \
vauth/cleartext.c \
vauth/cram.c \
vauth/digest.c \
vauth/digest_sspi.c \
vauth/gsasl.c \
vauth/krb5_gssapi.c \
vauth/krb5_sspi.c \
vauth/ntlm.c \
vauth/ntlm_sspi.c \
vauth/oauth2.c \
vauth/spnego_gssapi.c \
vauth/spnego_sspi.c \
vauth/vauth.c
LIB_VAUTH_HFILES = \
vauth/digest.h \
vauth/ntlm.h \
vauth/vauth.h
LIB_VTLS_CFILES = \
vtls/bearssl.c \
vtls/cipher_suite.c \
vtls/gtls.c \
vtls/hostcheck.c \
vtls/keylog.c \
vtls/mbedtls.c \
vtls/mbedtls_threadlock.c \
vtls/openssl.c \
vtls/rustls.c \
vtls/schannel.c \
vtls/schannel_verify.c \
vtls/sectransp.c \
vtls/vtls.c \
vtls/wolfssl.c \
vtls/x509asn1.c
LIB_VTLS_HFILES = \
vtls/bearssl.h \
vtls/cipher_suite.h \
vtls/gtls.h \
vtls/hostcheck.h \
vtls/keylog.h \
vtls/mbedtls.h \
vtls/mbedtls_threadlock.h \
vtls/openssl.h \
vtls/rustls.h \
vtls/schannel.h \
vtls/schannel_int.h \
vtls/sectransp.h \
vtls/vtls.h \
vtls/vtls_int.h \
vtls/wolfssl.h \
vtls/x509asn1.h
LIB_VQUIC_CFILES = \
vquic/curl_msh3.c \
vquic/curl_ngtcp2.c \
vquic/curl_osslq.c \
vquic/curl_quiche.c \
vquic/vquic.c \
vquic/vquic-tls.c
LIB_VQUIC_HFILES = \
vquic/curl_msh3.h \
vquic/curl_ngtcp2.h \
vquic/curl_osslq.h \
vquic/curl_quiche.h \
vquic/vquic.h \
vquic/vquic_int.h \
vquic/vquic-tls.h
LIB_VSSH_CFILES = \
vssh/libssh.c \
vssh/libssh2.c \
vssh/wolfssh.c
LIB_VSSH_HFILES = \
vssh/ssh.h
LIB_CFILES = \
altsvc.c \
amigaos.c \
asyn-ares.c \
asyn-thread.c \
base64.c \
bufq.c \
bufref.c \
c-hyper.c \
cf-h1-proxy.c \
cf-h2-proxy.c \
cf-haproxy.c \
cf-https-connect.c \
cf-socket.c \
cfilters.c \
conncache.c \
connect.c \
content_encoding.c \
cookie.c \
curl_addrinfo.c \
curl_des.c \
curl_endian.c \
curl_fnmatch.c \
curl_get_line.c \
curl_gethostname.c \
curl_gssapi.c \
curl_memrchr.c \
curl_multibyte.c \
curl_ntlm_core.c \
curl_path.c \
curl_range.c \
curl_rtmp.c \
curl_sasl.c \
curl_sha512_256.c \
curl_sspi.c \
curl_threads.c \
curl_trc.c \
cw-out.c \
dict.c \
dllmain.c \
doh.c \
dynbuf.c \
dynhds.c \
easy.c \
easygetopt.c \
easyoptions.c \
escape.c \
file.c \
fileinfo.c \
fopen.c \
formdata.c \
ftp.c \
ftplistparser.c \
getenv.c \
getinfo.c \
gopher.c \
hash.c \
headers.c \
hmac.c \
hostasyn.c \
hostip.c \
hostip4.c \
hostip6.c \
hostsyn.c \
hsts.c \
http.c \
http1.c \
http2.c \
http_aws_sigv4.c \
http_chunks.c \
http_digest.c \
http_negotiate.c \
http_ntlm.c \
http_proxy.c \
idn.c \
if2ip.c \
imap.c \
inet_ntop.c \
inet_pton.c \
krb5.c \
ldap.c \
llist.c \
macos.c \
md4.c \
md5.c \
memdebug.c \
mime.c \
mprintf.c \
mqtt.c \
multi.c \
netrc.c \
nonblock.c \
noproxy.c \
openldap.c \
parsedate.c \
pingpong.c \
pop3.c \
progress.c \
psl.c \
rand.c \
rename.c \
request.c \
rtsp.c \
select.c \
sendf.c \
setopt.c \
sha256.c \
share.c \
slist.c \
smb.c \
smtp.c \
socketpair.c \
socks.c \
socks_gssapi.c \
socks_sspi.c \
speedcheck.c \
splay.c \
strcase.c \
strdup.c \
strerror.c \
strtok.c \
strtoofft.c \
system_win32.c \
telnet.c \
tftp.c \
timediff.c \
timeval.c \
transfer.c \
url.c \
urlapi.c \
version.c \
version_win32.c \
warnless.c \
ws.c
LIB_HFILES = \
altsvc.h \
amigaos.h \
arpa_telnet.h \
asyn.h \
bufq.h \
bufref.h \
c-hyper.h \
cf-h1-proxy.h \
cf-h2-proxy.h \
cf-haproxy.h \
cf-https-connect.h \
cf-socket.h \
cfilters.h \
conncache.h \
connect.h \
content_encoding.h \
cookie.h \
curl_addrinfo.h \
curl_base64.h \
curl_ctype.h \
curl_des.h \
curl_endian.h \
curl_fnmatch.h \
curl_get_line.h \
curl_gethostname.h \
curl_gssapi.h \
curl_hmac.h \
curl_krb5.h \
curl_ldap.h \
curl_md4.h \
curl_md5.h \
curl_memory.h \
curl_memrchr.h \
curl_multibyte.h \
curl_ntlm_core.h \
curl_path.h \
curl_printf.h \
curl_range.h \
curl_rtmp.h \
curl_sasl.h \
curl_setup.h \
curl_setup_once.h \
curl_sha256.h \
curl_sha512_256.h \
curl_sspi.h \
curl_threads.h \
curl_trc.h \
curlx.h \
cw-out.h \
dict.h \
doh.h \
dynbuf.h \
dynhds.h \
easy_lock.h \
easyif.h \
easyoptions.h \
escape.h \
file.h \
fileinfo.h \
fopen.h \
formdata.h \
ftp.h \
ftplistparser.h \
functypes.h \
getinfo.h \
gopher.h \
hash.h \
headers.h \
hostip.h \
hsts.h \
http.h \
http1.h \
http2.h \
http_aws_sigv4.h \
http_chunks.h \
http_digest.h \
http_negotiate.h \
http_ntlm.h \
http_proxy.h \
idn.h \
if2ip.h \
imap.h \
inet_ntop.h \
inet_pton.h \
llist.h \
macos.h \
memdebug.h \
mime.h \
mqtt.h \
multihandle.h \
multiif.h \
netrc.h \
nonblock.h \
noproxy.h \
parsedate.h \
pingpong.h \
pop3.h \
progress.h \
psl.h \
rand.h \
rename.h \
request.h \
rtsp.h \
select.h \
sendf.h \
setopt.h \
setup-vms.h \
share.h \
sigpipe.h \
slist.h \
smb.h \
smtp.h \
sockaddr.h \
socketpair.h \
socks.h \
speedcheck.h \
splay.h \
strcase.h \
strdup.h \
strerror.h \
strtok.h \
strtoofft.h \
system_win32.h \
telnet.h \
tftp.h \
timediff.h \
timeval.h \
transfer.h \
url.h \
urlapi-int.h \
urldata.h \
version_win32.h \
warnless.h \
ws.h
LIB_RCFILES = libcurl.rc
CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) \
$(LIB_VQUIC_CFILES) $(LIB_VSSH_CFILES)
HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) \
$(LIB_VQUIC_HFILES) $(LIB_VSSH_HFILES)

334
third_party/curl/lib/Makefile.mk vendored Normal file
View File

@ -0,0 +1,334 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
#***************************************************************************
# Makefile to build curl parts with GCC-like toolchains and optional features.
#
# Usage: make -f Makefile.mk CFG=-feat1[-feat2][-feat3][...]
# Example: make -f Makefile.mk CFG=-zlib-ssl-libssh2-ipv6
#
# Look for ' ?=' to find all accepted customization variables.
# This script is reused by 'src' and 'docs/examples' Makefile.mk scripts.
ifndef PROOT
PROOT := ..
LOCAL := 1
endif
### Common
CFLAGS ?=
CPPFLAGS ?=
LDFLAGS ?=
LIBS ?=
CROSSPREFIX ?=
ifeq ($(CC),cc)
CC := gcc
endif
CC := $(CROSSPREFIX)$(CC)
AR := $(CROSSPREFIX)$(AR)
TRIPLET ?= $(shell $(CC) -dumpmachine)
BIN_EXT :=
ifneq ($(findstring msdos,$(TRIPLET)),)
# Cross-tools: https://github.com/andrewwutw/build-djgpp
MSDOS := 1
BIN_EXT := .exe
else ifneq ($(findstring amigaos,$(TRIPLET)),)
# Cross-tools: https://github.com/bebbo/amiga-gcc
AMIGA := 1
endif
CPPFLAGS += -I. -I$(PROOT)/include
### Deprecated settings. For compatibility.
ifdef WATT_ROOT
WATT_PATH := $(realpath $(WATT_ROOT))
endif
### Optional features
ifneq ($(findstring -debug,$(CFG)),)
CFLAGS += -g
CPPFLAGS += -DDEBUGBUILD
else
CPPFLAGS += -DNDEBUG
endif
ifneq ($(findstring -trackmem,$(CFG)),)
CPPFLAGS += -DCURLDEBUG
endif
ifneq ($(findstring -map,$(CFG)),)
MAP := 1
endif
# CPPFLAGS below are only necessary when building libcurl via 'lib' (see
# comments below about exceptions). Always include them anyway to match
# behavior of other build systems.
ifneq ($(findstring -sync,$(CFG)),)
CPPFLAGS += -DUSE_SYNC_DNS
else ifneq ($(findstring -ares,$(CFG)),)
LIBCARES_PATH ?= $(PROOT)/../c-ares
CPPFLAGS += -DUSE_ARES
CPPFLAGS += -I"$(LIBCARES_PATH)/include"
LDFLAGS += -L"$(LIBCARES_PATH)/lib"
LIBS += -lcares
endif
ifneq ($(findstring -rtmp,$(CFG)),)
LIBRTMP_PATH ?= $(PROOT)/../librtmp
CPPFLAGS += -DUSE_LIBRTMP
CPPFLAGS += -I"$(LIBRTMP_PATH)"
LDFLAGS += -L"$(LIBRTMP_PATH)/librtmp"
LIBS += -lrtmp
ZLIB := 1
endif
ifneq ($(findstring -ssh2,$(CFG)),)
LIBSSH2_PATH ?= $(PROOT)/../libssh2
CPPFLAGS += -DUSE_LIBSSH2
CPPFLAGS += -I"$(LIBSSH2_PATH)/include"
LDFLAGS += -L"$(LIBSSH2_PATH)/lib"
LIBS += -lssh2
else ifneq ($(findstring -libssh,$(CFG)),)
LIBSSH_PATH ?= $(PROOT)/../libssh
CPPFLAGS += -DUSE_LIBSSH
CPPFLAGS += -I"$(LIBSSH_PATH)/include"
LDFLAGS += -L"$(LIBSSH_PATH)/lib"
LIBS += -lssh
else ifneq ($(findstring -wolfssh,$(CFG)),)
WOLFSSH_PATH ?= $(PROOT)/../wolfssh
CPPFLAGS += -DUSE_WOLFSSH
CPPFLAGS += -I"$(WOLFSSH_PATH)/include"
LDFLAGS += -L"$(WOLFSSH_PATH)/lib"
LIBS += -lwolfssh
endif
ifneq ($(findstring -ssl,$(CFG)),)
OPENSSL_PATH ?= $(PROOT)/../openssl
CPPFLAGS += -DUSE_OPENSSL
CPPFLAGS += -DCURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG
OPENSSL_INCLUDE ?= $(OPENSSL_PATH)/include
OPENSSL_LIBPATH ?= $(OPENSSL_PATH)/lib
CPPFLAGS += -I"$(OPENSSL_INCLUDE)"
LDFLAGS += -L"$(OPENSSL_LIBPATH)"
OPENSSL_LIBS ?= -lssl -lcrypto
LIBS += $(OPENSSL_LIBS)
ifneq ($(findstring -srp,$(CFG)),)
ifneq ($(wildcard $(OPENSSL_INCLUDE)/openssl/srp.h),)
# OpenSSL 1.0.1 and later.
CPPFLAGS += -DHAVE_OPENSSL_SRP -DUSE_TLS_SRP
endif
endif
SSLLIBS += 1
endif
ifneq ($(findstring -wolfssl,$(CFG)),)
WOLFSSL_PATH ?= $(PROOT)/../wolfssl
CPPFLAGS += -DUSE_WOLFSSL
CPPFLAGS += -DSIZEOF_LONG_LONG=8
CPPFLAGS += -I"$(WOLFSSL_PATH)/include"
LDFLAGS += -L"$(WOLFSSL_PATH)/lib"
LIBS += -lwolfssl
SSLLIBS += 1
endif
ifneq ($(findstring -mbedtls,$(CFG)),)
MBEDTLS_PATH ?= $(PROOT)/../mbedtls
CPPFLAGS += -DUSE_MBEDTLS
CPPFLAGS += -I"$(MBEDTLS_PATH)/include"
LDFLAGS += -L"$(MBEDTLS_PATH)/lib"
LIBS += -lmbedtls -lmbedx509 -lmbedcrypto
SSLLIBS += 1
endif
ifneq ($(findstring -nghttp2,$(CFG)),)
NGHTTP2_PATH ?= $(PROOT)/../nghttp2
CPPFLAGS += -DUSE_NGHTTP2
CPPFLAGS += -I"$(NGHTTP2_PATH)/include"
LDFLAGS += -L"$(NGHTTP2_PATH)/lib"
LIBS += -lnghttp2
endif
ifeq ($(findstring -nghttp3,$(CFG))$(findstring -ngtcp2,$(CFG)),-nghttp3-ngtcp2)
NGHTTP3_PATH ?= $(PROOT)/../nghttp3
CPPFLAGS += -DUSE_NGHTTP3
CPPFLAGS += -I"$(NGHTTP3_PATH)/include"
LDFLAGS += -L"$(NGHTTP3_PATH)/lib"
LIBS += -lnghttp3
NGTCP2_PATH ?= $(PROOT)/../ngtcp2
CPPFLAGS += -DUSE_NGTCP2
CPPFLAGS += -I"$(NGTCP2_PATH)/include"
LDFLAGS += -L"$(NGTCP2_PATH)/lib"
NGTCP2_LIBS ?=
ifeq ($(NGTCP2_LIBS),)
ifneq ($(findstring -ssl,$(CFG)),)
ifneq ($(wildcard $(OPENSSL_INCLUDE)/openssl/aead.h),)
NGTCP2_LIBS := -lngtcp2_crypto_boringssl
else # including libressl
NGTCP2_LIBS := -lngtcp2_crypto_quictls
endif
else ifneq ($(findstring -wolfssl,$(CFG)),)
NGTCP2_LIBS := -lngtcp2_crypto_wolfssl
endif
endif
LIBS += -lngtcp2 $(NGTCP2_LIBS)
endif
ifneq ($(findstring -zlib,$(CFG))$(ZLIB),)
ZLIB_PATH ?= $(PROOT)/../zlib
# These CPPFLAGS are also required when compiling the curl tool via 'src'.
CPPFLAGS += -DHAVE_LIBZ
CPPFLAGS += -I"$(ZLIB_PATH)/include"
LDFLAGS += -L"$(ZLIB_PATH)/lib"
ZLIB_LIBS ?= -lz
LIBS += $(ZLIB_LIBS)
ZLIB := 1
endif
ifneq ($(findstring -zstd,$(CFG)),)
ZSTD_PATH ?= $(PROOT)/../zstd
CPPFLAGS += -DHAVE_ZSTD
CPPFLAGS += -I"$(ZSTD_PATH)/include"
LDFLAGS += -L"$(ZSTD_PATH)/lib"
ZSTD_LIBS ?= -lzstd
LIBS += $(ZSTD_LIBS)
endif
ifneq ($(findstring -brotli,$(CFG)),)
BROTLI_PATH ?= $(PROOT)/../brotli
CPPFLAGS += -DHAVE_BROTLI
CPPFLAGS += -I"$(BROTLI_PATH)/include"
LDFLAGS += -L"$(BROTLI_PATH)/lib"
BROTLI_LIBS ?= -lbrotlidec -lbrotlicommon
LIBS += $(BROTLI_LIBS)
endif
ifneq ($(findstring -gsasl,$(CFG)),)
LIBGSASL_PATH ?= $(PROOT)/../gsasl
CPPFLAGS += -DUSE_GSASL
CPPFLAGS += -I"$(LIBGSASL_PATH)/include"
LDFLAGS += -L"$(LIBGSASL_PATH)/lib"
LIBS += -lgsasl
endif
ifneq ($(findstring -idn2,$(CFG)),)
LIBIDN2_PATH ?= $(PROOT)/../libidn2
CPPFLAGS += -DUSE_LIBIDN2
CPPFLAGS += -I"$(LIBIDN2_PATH)/include"
LDFLAGS += -L"$(LIBIDN2_PATH)/lib"
LIBS += -lidn2
ifneq ($(findstring -psl,$(CFG)),)
LIBPSL_PATH ?= $(PROOT)/../libpsl
CPPFLAGS += -DUSE_LIBPSL
CPPFLAGS += -I"$(LIBPSL_PATH)/include"
LDFLAGS += -L"$(LIBPSL_PATH)/lib"
LIBS += -lpsl
endif
endif
ifneq ($(findstring -ipv6,$(CFG)),)
CPPFLAGS += -DUSE_IPV6
endif
ifneq ($(findstring -watt,$(CFG))$(MSDOS),)
WATT_PATH ?= $(PROOT)/../watt
CPPFLAGS += -I"$(WATT_PATH)/inc"
LDFLAGS += -L"$(WATT_PATH)/lib"
LIBS += -lwatt
endif
ifneq ($(findstring 11,$(subst $(subst ,, ),,$(SSLLIBS))),)
CPPFLAGS += -DCURL_WITH_MULTI_SSL
endif
### Common rules
OBJ_DIR := $(TRIPLET)
ifneq ($(findstring /sh,$(SHELL)),)
DEL = rm -f $1
COPY = -cp -afv $1 $2
MKDIR = mkdir -p $1
RMDIR = rm -fr $1
WHICH = $(SHELL) -c "command -v $1"
else
DEL = -del 2>NUL /q /f $(subst /,\,$1)
COPY = -copy 2>NUL /y $(subst /,\,$1) $(subst /,\,$2)
MKDIR = -md 2>NUL $(subst /,\,$1)
RMDIR = -rd 2>NUL /q /s $(subst /,\,$1)
WHICH = where $1
endif
all: $(TARGETS)
$(OBJ_DIR):
-$(call MKDIR, $(OBJ_DIR))
$(OBJ_DIR)/%.o: %.c
$(CC) -W -Wall $(CFLAGS) $(CPPFLAGS) -c $< -o $@
clean:
@$(call DEL, $(TOCLEAN))
@$(RMDIR) $(OBJ_DIR)
distclean vclean: clean
@$(call DEL, $(TARGETS) $(TOVCLEAN))
### Local
ifdef LOCAL
CPPFLAGS += -DBUILDING_LIBCURL
### Sources and targets
# Provides CSOURCES, HHEADERS
include Makefile.inc
vpath %.c vauth vquic vssh vtls
libcurl_a_LIBRARY := libcurl.a
TARGETS := $(libcurl_a_LIBRARY)
libcurl_a_OBJECTS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(notdir $(strip $(CSOURCES))))
libcurl_a_DEPENDENCIES := $(strip $(CSOURCES) $(HHEADERS))
TOCLEAN :=
TOVCLEAN :=
### Rules
$(libcurl_a_LIBRARY): $(libcurl_a_OBJECTS) $(libcurl_a_DEPENDENCIES)
@$(call DEL, $@)
$(AR) rcs $@ $(libcurl_a_OBJECTS)
all: $(OBJ_DIR) $(TARGETS)
endif

42
third_party/curl/lib/Makefile.soname vendored Normal file
View File

@ -0,0 +1,42 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
VERSIONCHANGE=12
VERSIONADD=0
VERSIONDEL=8
# libtool version:
VERSIONINFO=-version-info $(VERSIONCHANGE):$(VERSIONADD):$(VERSIONDEL)
# This flag accepts an argument of the form current[:revision[:age]]. So,
# passing -version-info 3:12:1 sets current to 3, revision to 12, and age to
# 1.
#
# Here's the simplified rule guide on how to change -version-info:
# (current version is C:R:A)
#
# 1. if there are only source changes, use C:R+1:A
# 2. if interfaces were added use C+1:0:A+1
# 3. if interfaces were removed, then use C+1:0:0
#
# For the full guide on libcurl ABI rules, see docs/libcurl/ABI

708
third_party/curl/lib/altsvc.c vendored Normal file
View File

@ -0,0 +1,708 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/*
* The Alt-Svc: header is defined in RFC 7838:
* https://datatracker.ietf.org/doc/html/rfc7838
*/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_ALTSVC)
#include <curl/curl.h>
#include "urldata.h"
#include "altsvc.h"
#include "curl_get_line.h"
#include "strcase.h"
#include "parsedate.h"
#include "sendf.h"
#include "warnless.h"
#include "fopen.h"
#include "rename.h"
#include "strdup.h"
#include "inet_pton.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
#define MAX_ALTSVC_LINE 4095
#define MAX_ALTSVC_DATELENSTR "64"
#define MAX_ALTSVC_DATELEN 64
#define MAX_ALTSVC_HOSTLENSTR "512"
#define MAX_ALTSVC_HOSTLEN 512
#define MAX_ALTSVC_ALPNLENSTR "10"
#define MAX_ALTSVC_ALPNLEN 10
#define H3VERSION "h3"
static enum alpnid alpn2alpnid(char *name)
{
if(strcasecompare(name, "h1"))
return ALPN_h1;
if(strcasecompare(name, "h2"))
return ALPN_h2;
if(strcasecompare(name, H3VERSION))
return ALPN_h3;
return ALPN_none; /* unknown, probably rubbish input */
}
/* Given the ALPN ID, return the name */
const char *Curl_alpnid2str(enum alpnid id)
{
switch(id) {
case ALPN_h1:
return "h1";
case ALPN_h2:
return "h2";
case ALPN_h3:
return H3VERSION;
default:
return ""; /* bad */
}
}
static void altsvc_free(struct altsvc *as)
{
free(as->src.host);
free(as->dst.host);
free(as);
}
static struct altsvc *altsvc_createid(const char *srchost,
const char *dsthost,
enum alpnid srcalpnid,
enum alpnid dstalpnid,
unsigned int srcport,
unsigned int dstport)
{
struct altsvc *as = calloc(1, sizeof(struct altsvc));
size_t hlen;
size_t dlen;
if(!as)
return NULL;
hlen = strlen(srchost);
dlen = strlen(dsthost);
DEBUGASSERT(hlen);
DEBUGASSERT(dlen);
if(!hlen || !dlen) {
/* bad input */
free(as);
return NULL;
}
if((hlen > 2) && srchost[0] == '[') {
/* IPv6 address, strip off brackets */
srchost++;
hlen -= 2;
}
else if(srchost[hlen - 1] == '.')
/* strip off trailing dot */
hlen--;
if((dlen > 2) && dsthost[0] == '[') {
/* IPv6 address, strip off brackets */
dsthost++;
dlen -= 2;
}
as->src.host = Curl_memdup0(srchost, hlen);
if(!as->src.host)
goto error;
as->dst.host = Curl_memdup0(dsthost, dlen);
if(!as->dst.host)
goto error;
as->src.alpnid = srcalpnid;
as->dst.alpnid = dstalpnid;
as->src.port = curlx_ultous(srcport);
as->dst.port = curlx_ultous(dstport);
return as;
error:
altsvc_free(as);
return NULL;
}
static struct altsvc *altsvc_create(char *srchost,
char *dsthost,
char *srcalpn,
char *dstalpn,
unsigned int srcport,
unsigned int dstport)
{
enum alpnid dstalpnid = alpn2alpnid(dstalpn);
enum alpnid srcalpnid = alpn2alpnid(srcalpn);
if(!srcalpnid || !dstalpnid)
return NULL;
return altsvc_createid(srchost, dsthost, srcalpnid, dstalpnid,
srcport, dstport);
}
/* only returns SERIOUS errors */
static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
{
/* Example line:
h2 example.com 443 h3 shiny.example.com 8443 "20191231 10:00:00" 1
*/
char srchost[MAX_ALTSVC_HOSTLEN + 1];
char dsthost[MAX_ALTSVC_HOSTLEN + 1];
char srcalpn[MAX_ALTSVC_ALPNLEN + 1];
char dstalpn[MAX_ALTSVC_ALPNLEN + 1];
char date[MAX_ALTSVC_DATELEN + 1];
unsigned int srcport;
unsigned int dstport;
unsigned int prio;
unsigned int persist;
int rc;
rc = sscanf(line,
"%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
"%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
"\"%" MAX_ALTSVC_DATELENSTR "[^\"]\" %u %u",
srcalpn, srchost, &srcport,
dstalpn, dsthost, &dstport,
date, &persist, &prio);
if(9 == rc) {
struct altsvc *as;
time_t expires = Curl_getdate_capped(date);
as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport);
if(as) {
as->expires = expires;
as->prio = prio;
as->persist = persist ? 1 : 0;
Curl_llist_append(&asi->list, as, &as->node);
}
}
return CURLE_OK;
}
/*
* Load alt-svc entries from the given file. The text based line-oriented file
* format is documented here: https://curl.se/docs/alt-svc.html
*
* This function only returns error on major problems that prevent alt-svc
* handling to work completely. It will ignore individual syntactical errors
* etc.
*/
static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
{
CURLcode result = CURLE_OK;
FILE *fp;
/* we need a private copy of the file name so that the altsvc cache file
name survives an easy handle reset */
free(asi->filename);
asi->filename = strdup(file);
if(!asi->filename)
return CURLE_OUT_OF_MEMORY;
fp = fopen(file, FOPEN_READTEXT);
if(fp) {
struct dynbuf buf;
Curl_dyn_init(&buf, MAX_ALTSVC_LINE);
while(Curl_get_line(&buf, fp)) {
char *lineptr = Curl_dyn_ptr(&buf);
while(*lineptr && ISBLANK(*lineptr))
lineptr++;
if(*lineptr == '#')
/* skip commented lines */
continue;
altsvc_add(asi, lineptr);
}
Curl_dyn_free(&buf); /* free the line buffer */
fclose(fp);
}
return result;
}
/*
* Write this single altsvc entry to a single output line
*/
static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
{
struct tm stamp;
const char *dst6_pre = "";
const char *dst6_post = "";
const char *src6_pre = "";
const char *src6_post = "";
CURLcode result = Curl_gmtime(as->expires, &stamp);
if(result)
return result;
#ifdef USE_IPV6
else {
char ipv6_unused[16];
if(1 == Curl_inet_pton(AF_INET6, as->dst.host, ipv6_unused)) {
dst6_pre = "[";
dst6_post = "]";
}
if(1 == Curl_inet_pton(AF_INET6, as->src.host, ipv6_unused)) {
src6_pre = "[";
src6_post = "]";
}
}
#endif
fprintf(fp,
"%s %s%s%s %u "
"%s %s%s%s %u "
"\"%d%02d%02d "
"%02d:%02d:%02d\" "
"%u %d\n",
Curl_alpnid2str(as->src.alpnid),
src6_pre, as->src.host, src6_post,
as->src.port,
Curl_alpnid2str(as->dst.alpnid),
dst6_pre, as->dst.host, dst6_post,
as->dst.port,
stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
stamp.tm_hour, stamp.tm_min, stamp.tm_sec,
as->persist, as->prio);
return CURLE_OK;
}
/* ---- library-wide functions below ---- */
/*
* Curl_altsvc_init() creates a new altsvc cache.
* It returns the new instance or NULL if something goes wrong.
*/
struct altsvcinfo *Curl_altsvc_init(void)
{
struct altsvcinfo *asi = calloc(1, sizeof(struct altsvcinfo));
if(!asi)
return NULL;
Curl_llist_init(&asi->list, NULL);
/* set default behavior */
asi->flags = CURLALTSVC_H1
#ifdef USE_HTTP2
| CURLALTSVC_H2
#endif
#ifdef USE_HTTP3
| CURLALTSVC_H3
#endif
;
return asi;
}
/*
* Curl_altsvc_load() loads alt-svc from file.
*/
CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file)
{
CURLcode result;
DEBUGASSERT(asi);
result = altsvc_load(asi, file);
return result;
}
/*
* Curl_altsvc_ctrl() passes on the external bitmask.
*/
CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl)
{
DEBUGASSERT(asi);
asi->flags = ctrl;
return CURLE_OK;
}
/*
* Curl_altsvc_cleanup() frees an altsvc cache instance and all associated
* resources.
*/
void Curl_altsvc_cleanup(struct altsvcinfo **altsvcp)
{
struct Curl_llist_element *e;
struct Curl_llist_element *n;
if(*altsvcp) {
struct altsvcinfo *altsvc = *altsvcp;
for(e = altsvc->list.head; e; e = n) {
struct altsvc *as = e->ptr;
n = e->next;
altsvc_free(as);
}
free(altsvc->filename);
free(altsvc);
*altsvcp = NULL; /* clear the pointer */
}
}
/*
* Curl_altsvc_save() writes the altsvc cache to a file.
*/
CURLcode Curl_altsvc_save(struct Curl_easy *data,
struct altsvcinfo *altsvc, const char *file)
{
struct Curl_llist_element *e;
struct Curl_llist_element *n;
CURLcode result = CURLE_OK;
FILE *out;
char *tempstore = NULL;
if(!altsvc)
/* no cache activated */
return CURLE_OK;
/* if not new name is given, use the one we stored from the load */
if(!file && altsvc->filename)
file = altsvc->filename;
if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file || !file[0])
/* marked as read-only, no file or zero length file name */
return CURLE_OK;
result = Curl_fopen(data, file, &out, &tempstore);
if(!result) {
fputs("# Your alt-svc cache. https://curl.se/docs/alt-svc.html\n"
"# This file was generated by libcurl! Edit at your own risk.\n",
out);
for(e = altsvc->list.head; e; e = n) {
struct altsvc *as = e->ptr;
n = e->next;
result = altsvc_out(as, out);
if(result)
break;
}
fclose(out);
if(!result && tempstore && Curl_rename(tempstore, file))
result = CURLE_WRITE_ERROR;
if(result && tempstore)
unlink(tempstore);
}
free(tempstore);
return result;
}
static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen)
{
size_t len;
const char *protop;
const char *p = *ptr;
while(*p && ISBLANK(*p))
p++;
protop = p;
while(*p && !ISBLANK(*p) && (*p != ';') && (*p != '='))
p++;
len = p - protop;
*ptr = p;
if(!len || (len >= buflen))
return CURLE_BAD_FUNCTION_ARGUMENT;
memcpy(alpnbuf, protop, len);
alpnbuf[len] = 0;
return CURLE_OK;
}
/* hostcompare() returns true if 'host' matches 'check'. The first host
* argument may have a trailing dot present that will be ignored.
*/
static bool hostcompare(const char *host, const char *check)
{
size_t hlen = strlen(host);
size_t clen = strlen(check);
if(hlen && (host[hlen - 1] == '.'))
hlen--;
if(hlen != clen)
/* they can't match if they have different lengths */
return FALSE;
return strncasecompare(host, check, hlen);
}
/* altsvc_flush() removes all alternatives for this source origin from the
list */
static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
const char *srchost, unsigned short srcport)
{
struct Curl_llist_element *e;
struct Curl_llist_element *n;
for(e = asi->list.head; e; e = n) {
struct altsvc *as = e->ptr;
n = e->next;
if((srcalpnid == as->src.alpnid) &&
(srcport == as->src.port) &&
hostcompare(srchost, as->src.host)) {
Curl_llist_remove(&asi->list, e, NULL);
altsvc_free(as);
}
}
}
#ifdef DEBUGBUILD
/* to play well with debug builds, we can *set* a fixed time this will
return */
static time_t altsvc_debugtime(void *unused)
{
char *timestr = getenv("CURL_TIME");
(void)unused;
if(timestr) {
unsigned long val = strtol(timestr, NULL, 10);
return (time_t)val;
}
return time(NULL);
}
#undef time
#define time(x) altsvc_debugtime(x)
#endif
#define ISNEWLINE(x) (((x) == '\n') || (x) == '\r')
/*
* Curl_altsvc_parse() takes an incoming alt-svc response header and stores
* the data correctly in the cache.
*
* 'value' points to the header *value*. That's contents to the right of the
* header name.
*
* Currently this function rejects invalid data without returning an error.
* Invalid host name, port number will result in the specific alternative
* being rejected. Unknown protocols are skipped.
*/
CURLcode Curl_altsvc_parse(struct Curl_easy *data,
struct altsvcinfo *asi, const char *value,
enum alpnid srcalpnid, const char *srchost,
unsigned short srcport)
{
const char *p = value;
size_t len;
char namebuf[MAX_ALTSVC_HOSTLEN] = "";
char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
struct altsvc *as;
unsigned short dstport = srcport; /* the same by default */
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
size_t entries = 0;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
#endif
if(result) {
infof(data, "Excessive alt-svc header, ignoring.");
return CURLE_OK;
}
DEBUGASSERT(asi);
/* "clear" is a magic keyword */
if(strcasecompare(alpnbuf, "clear")) {
/* Flush cached alternatives for this source origin */
altsvc_flush(asi, srcalpnid, srchost, srcport);
return CURLE_OK;
}
do {
if(*p == '=') {
/* [protocol]="[host][:port]" */
enum alpnid dstalpnid = alpn2alpnid(alpnbuf); /* the same by default */
p++;
if(*p == '\"') {
const char *dsthost = "";
const char *value_ptr;
char option[32];
unsigned long num;
char *end_ptr;
bool quoted = FALSE;
time_t maxage = 24 * 3600; /* default is 24 hours */
bool persist = FALSE;
bool valid = TRUE;
p++;
if(*p != ':') {
/* host name starts here */
const char *hostp = p;
if(*p == '[') {
/* pass all valid IPv6 letters - does not handle zone id */
len = strspn(++p, "0123456789abcdefABCDEF:.");
if(p[len] != ']')
/* invalid host syntax, bail out */
break;
/* we store the IPv6 numerical address *with* brackets */
len += 2;
p = &p[len-1];
}
else {
while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
p++;
len = p - hostp;
}
if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
infof(data, "Excessive alt-svc host name, ignoring.");
valid = FALSE;
}
else {
memcpy(namebuf, hostp, len);
namebuf[len] = 0;
dsthost = namebuf;
}
}
else {
/* no destination name, use source host */
dsthost = srchost;
}
if(*p == ':') {
unsigned long port = 0;
p++;
if(ISDIGIT(*p))
/* a port number */
port = strtoul(p, &end_ptr, 10);
else
end_ptr = (char *)p; /* not left uninitialized */
if(!port || port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
infof(data, "Unknown alt-svc port number, ignoring.");
valid = FALSE;
}
else {
dstport = curlx_ultous(port);
p = end_ptr;
}
}
if(*p++ != '\"')
break;
/* Handle the optional 'ma' and 'persist' flags. Unknown flags
are skipped. */
for(;;) {
while(ISBLANK(*p))
p++;
if(*p != ';')
break;
p++; /* pass the semicolon */
if(!*p || ISNEWLINE(*p))
break;
result = getalnum(&p, option, sizeof(option));
if(result) {
/* skip option if name is too long */
option[0] = '\0';
}
while(*p && ISBLANK(*p))
p++;
if(*p != '=')
return CURLE_OK;
p++;
while(*p && ISBLANK(*p))
p++;
if(!*p)
return CURLE_OK;
if(*p == '\"') {
/* quoted value */
p++;
quoted = TRUE;
}
value_ptr = p;
if(quoted) {
while(*p && *p != '\"')
p++;
if(!*p++)
return CURLE_OK;
}
else {
while(*p && !ISBLANK(*p) && *p!= ';' && *p != ',')
p++;
}
num = strtoul(value_ptr, &end_ptr, 10);
if((end_ptr != value_ptr) && (num < ULONG_MAX)) {
if(strcasecompare("ma", option))
maxage = num;
else if(strcasecompare("persist", option) && (num == 1))
persist = TRUE;
}
}
if(dstalpnid && valid) {
if(!entries++)
/* Flush cached alternatives for this source origin, if any - when
this is the first entry of the line. */
altsvc_flush(asi, srcalpnid, srchost, srcport);
as = altsvc_createid(srchost, dsthost,
srcalpnid, dstalpnid,
srcport, dstport);
if(as) {
/* The expires time also needs to take the Age: value (if any) into
account. [See RFC 7838 section 3.1] */
as->expires = maxage + time(NULL);
as->persist = persist;
Curl_llist_append(&asi->list, as, &as->node);
infof(data, "Added alt-svc: %s:%d over %s", dsthost, dstport,
Curl_alpnid2str(dstalpnid));
}
}
}
else
break;
/* after the double quote there can be a comma if there's another
string or a semicolon if no more */
if(*p == ',') {
/* comma means another alternative is presented */
p++;
result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
if(result)
break;
}
}
else
break;
} while(*p && (*p != ';') && (*p != '\n') && (*p != '\r'));
return CURLE_OK;
}
/*
* Return TRUE on a match
*/
bool Curl_altsvc_lookup(struct altsvcinfo *asi,
enum alpnid srcalpnid, const char *srchost,
int srcport,
struct altsvc **dstentry,
const int versions) /* one or more bits */
{
struct Curl_llist_element *e;
struct Curl_llist_element *n;
time_t now = time(NULL);
DEBUGASSERT(asi);
DEBUGASSERT(srchost);
DEBUGASSERT(dstentry);
for(e = asi->list.head; e; e = n) {
struct altsvc *as = e->ptr;
n = e->next;
if(as->expires < now) {
/* an expired entry, remove */
Curl_llist_remove(&asi->list, e, NULL);
altsvc_free(as);
continue;
}
if((as->src.alpnid == srcalpnid) &&
hostcompare(srchost, as->src.host) &&
(as->src.port == srcport) &&
(versions & as->dst.alpnid)) {
/* match */
*dstentry = as;
return TRUE;
}
}
return FALSE;
}
#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_ALTSVC */

81
third_party/curl/lib/altsvc.h vendored Normal file
View File

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

247
third_party/curl/lib/amigaos.c vendored Normal file
View File

@ -0,0 +1,247 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#ifdef __AMIGA__
#include <curl/curl.h>
#include "hostip.h"
#include "amigaos.h"
#ifdef HAVE_PROTO_BSDSOCKET_H
# if defined(__amigaos4__)
# include <bsdsocket/socketbasetags.h>
# elif !defined(USE_AMISSL)
# include <amitcp/socketbasetags.h>
# endif
# ifdef __libnix__
# include <stabs.h>
# endif
#endif
/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"
#ifdef HAVE_PROTO_BSDSOCKET_H
#ifdef __amigaos4__
/*
* AmigaOS 4.x specific code
*/
/*
* hostip4.c - Curl_ipv4_resolve_r() replacement code
*
* Logic that needs to be considered are the following build cases:
* - newlib networking
* - clib2 networking
* - direct bsdsocket.library networking (usually AmiSSL builds)
* Each with the threaded resolver enabled or not.
*
* With the threaded resolver enabled, try to use gethostbyname_r() where
* available, otherwise (re)open bsdsocket.library and fallback to
* gethostbyname().
*/
#include <proto/bsdsocket.h>
static struct SocketIFace *__CurlISocket = NULL;
static uint32 SocketFeatures = 0;
#define HAVE_BSDSOCKET_GETHOSTBYNAME_R 0x01
#define HAVE_BSDSOCKET_GETADDRINFO 0x02
CURLcode Curl_amiga_init(void)
{
struct SocketIFace *ISocket;
struct Library *base = OpenLibrary("bsdsocket.library", 4);
if(base) {
ISocket = (struct SocketIFace *)GetInterface(base, "main", 1, NULL);
if(ISocket) {
ULONG enabled = 0;
SocketBaseTags(SBTM_SETVAL(SBTC_CAN_SHARE_LIBRARY_BASES), TRUE,
SBTM_GETREF(SBTC_HAVE_GETHOSTADDR_R_API), (ULONG)&enabled,
TAG_DONE);
if(enabled) {
SocketFeatures |= HAVE_BSDSOCKET_GETHOSTBYNAME_R;
}
__CurlISocket = ISocket;
atexit(Curl_amiga_cleanup);
return CURLE_OK;
}
CloseLibrary(base);
}
return CURLE_FAILED_INIT;
}
void Curl_amiga_cleanup(void)
{
if(__CurlISocket) {
struct Library *base = __CurlISocket->Data.LibBase;
DropInterface((struct Interface *)__CurlISocket);
CloseLibrary(base);
__CurlISocket = NULL;
}
}
#ifdef CURLRES_AMIGA
/*
* Because we need to handle the different cases in hostip4.c at run-time,
* not at compile-time, based on what was detected in Curl_amiga_init(),
* we replace it completely with our own as to not complicate the baseline
* code. Assumes malloc/calloc/free are thread safe because Curl_he2ai()
* allocates memory also.
*/
struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
int port)
{
struct Curl_addrinfo *ai = NULL;
struct hostent *h;
struct SocketIFace *ISocket = __CurlISocket;
if(SocketFeatures & HAVE_BSDSOCKET_GETHOSTBYNAME_R) {
LONG h_errnop = 0;
struct hostent *buf;
buf = calloc(1, CURL_HOSTENT_SIZE);
if(buf) {
h = gethostbyname_r((STRPTR)hostname, buf,
(char *)buf + sizeof(struct hostent),
CURL_HOSTENT_SIZE - sizeof(struct hostent),
&h_errnop);
if(h) {
ai = Curl_he2ai(h, port);
}
free(buf);
}
}
else {
#ifdef CURLRES_THREADED
/* gethostbyname() is not thread safe, so we need to reopen bsdsocket
* on the thread's context
*/
struct Library *base = OpenLibrary("bsdsocket.library", 4);
if(base) {
ISocket = (struct SocketIFace *)GetInterface(base, "main", 1, NULL);
if(ISocket) {
h = gethostbyname((STRPTR)hostname);
if(h) {
ai = Curl_he2ai(h, port);
}
DropInterface((struct Interface *)ISocket);
}
CloseLibrary(base);
}
#else
/* not using threaded resolver - safe to use this as-is */
h = gethostbyname(hostname);
if(h) {
ai = Curl_he2ai(h, port);
}
#endif
}
return ai;
}
#endif /* CURLRES_AMIGA */
#ifdef USE_AMISSL
#include <signal.h>
int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *errorfds, struct timeval *timeout)
{
int r = WaitSelect(nfds, readfds, writefds, errorfds, timeout, 0);
/* Ensure Ctrl-C signal is actioned */
if((r == -1) && (SOCKERRNO == EINTR))
raise(SIGINT);
return r;
}
#endif /* USE_AMISSL */
#elif !defined(USE_AMISSL) /* __amigaos4__ */
/*
* Amiga OS3 specific code
*/
struct Library *SocketBase = NULL;
extern int errno, h_errno;
#ifdef __libnix__
void __request(const char *msg);
#else
# define __request(msg) Printf(msg "\n\a")
#endif
void Curl_amiga_cleanup(void)
{
if(SocketBase) {
CloseLibrary(SocketBase);
SocketBase = NULL;
}
}
CURLcode Curl_amiga_init(void)
{
if(!SocketBase)
SocketBase = OpenLibrary("bsdsocket.library", 4);
if(!SocketBase) {
__request("No TCP/IP Stack running!");
return CURLE_FAILED_INIT;
}
if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno,
SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "curl",
TAG_DONE)) {
__request("SocketBaseTags ERROR");
return CURLE_FAILED_INIT;
}
#ifndef __libnix__
atexit(Curl_amiga_cleanup);
#endif
return CURLE_OK;
}
#ifdef __libnix__
ADD2EXIT(Curl_amiga_cleanup, -50);
#endif
#endif /* !USE_AMISSL */
#endif /* HAVE_PROTO_BSDSOCKET_H */
#endif /* __AMIGA__ */

41
third_party/curl/lib/amigaos.h vendored Normal file
View File

@ -0,0 +1,41 @@
#ifndef HEADER_CURL_AMIGAOS_H
#define HEADER_CURL_AMIGAOS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if defined(__AMIGA__) && defined(HAVE_PROTO_BSDSOCKET_H) && \
(!defined(USE_AMISSL) || defined(__amigaos4__))
CURLcode Curl_amiga_init(void);
void Curl_amiga_cleanup(void);
#else
#define Curl_amiga_init() CURLE_OK
#define Curl_amiga_cleanup() Curl_nop_stmt
#endif
#endif /* HEADER_CURL_AMIGAOS_H */

117
third_party/curl/lib/arpa_telnet.h vendored Normal file
View File

@ -0,0 +1,117 @@
#ifndef HEADER_CURL_ARPA_TELNET_H
#define HEADER_CURL_ARPA_TELNET_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#ifndef CURL_DISABLE_TELNET
/*
* Telnet option defines. Add more here if in need.
*/
#define CURL_TELOPT_BINARY 0 /* binary 8bit data */
#define CURL_TELOPT_ECHO 1 /* just echo! */
#define CURL_TELOPT_SGA 3 /* Suppress Go Ahead */
#define CURL_TELOPT_EXOPL 255 /* EXtended OPtions List */
#define CURL_TELOPT_TTYPE 24 /* Terminal TYPE */
#define CURL_TELOPT_NAWS 31 /* Negotiate About Window Size */
#define CURL_TELOPT_XDISPLOC 35 /* X DISPlay LOCation */
#define CURL_TELOPT_NEW_ENVIRON 39 /* NEW ENVIRONment variables */
#define CURL_NEW_ENV_VAR 0
#define CURL_NEW_ENV_VALUE 1
#ifndef CURL_DISABLE_VERBOSE_STRINGS
/*
* The telnet options represented as strings
*/
static const char * const telnetoptions[]=
{
"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD",
"NAME", "STATUS", "TIMING MARK", "RCTE",
"NAOL", "NAOP", "NAOCRD", "NAOHTS",
"NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD",
"NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
"DE TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION",
"TERM TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING",
"TTYLOC", "3270 REGIME", "X3 PAD", "NAWS",
"TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC",
"OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON"
};
#define CURL_TELOPT(x) telnetoptions[x]
#else
#define CURL_TELOPT(x) ""
#endif
#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON
#define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM)
#define CURL_NTELOPTS 40
/*
* First some defines
*/
#define CURL_xEOF 236 /* End Of File */
#define CURL_SE 240 /* Sub negotiation End */
#define CURL_NOP 241 /* No OPeration */
#define CURL_DM 242 /* Data Mark */
#define CURL_GA 249 /* Go Ahead, reverse the line */
#define CURL_SB 250 /* SuBnegotiation */
#define CURL_WILL 251 /* Our side WILL use this option */
#define CURL_WONT 252 /* Our side WON'T use this option */
#define CURL_DO 253 /* DO use this option! */
#define CURL_DONT 254 /* DON'T use this option! */
#define CURL_IAC 255 /* Interpret As Command */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
/*
* Then those numbers represented as strings:
*/
static const char * const telnetcmds[]=
{
"EOF", "SUSP", "ABORT", "EOR", "SE",
"NOP", "DMARK", "BRK", "IP", "AO",
"AYT", "EC", "EL", "GA", "SB",
"WILL", "WONT", "DO", "DONT", "IAC"
};
#endif
#define CURL_TELCMD_MINIMUM CURL_xEOF /* the first one */
#define CURL_TELCMD_MAXIMUM CURL_IAC /* surprise, 255 is the last one! ;-) */
#define CURL_TELQUAL_IS 0
#define CURL_TELQUAL_SEND 1
#define CURL_TELQUAL_INFO 2
#define CURL_TELQUAL_NAME 3
#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \
((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) )
#ifndef CURL_DISABLE_VERBOSE_STRINGS
#define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM]
#else
#define CURL_TELCMD(x) ""
#endif
#endif /* CURL_DISABLE_TELNET */
#endif /* HEADER_CURL_ARPA_TELNET_H */

958
third_party/curl/lib/asyn-ares.c vendored Normal file
View File

@ -0,0 +1,958 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
/***********************************************************************
* Only for ares-enabled builds
* And only for functions that fulfill the asynch resolver backend API
* as defined in asyn.h, nothing else belongs in this file!
**********************************************************************/
#ifdef CURLRES_ARES
#include <limits.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
#include "share.h"
#include "url.h"
#include "multiif.h"
#include "inet_pton.h"
#include "connect.h"
#include "select.h"
#include "progress.h"
#include "timediff.h"
#if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
defined(_WIN32)
# define CARES_STATICLIB
#endif
#include <ares.h>
#include <ares_version.h> /* really old c-ares didn't include this by
itself */
#if ARES_VERSION >= 0x010500
/* c-ares 1.5.0 or later, the callback proto is modified */
#define HAVE_CARES_CALLBACK_TIMEOUTS 1
#endif
#if ARES_VERSION >= 0x010601
/* IPv6 supported since 1.6.1 */
#define HAVE_CARES_IPV6 1
#endif
#if ARES_VERSION >= 0x010704
#define HAVE_CARES_SERVERS_CSV 1
#define HAVE_CARES_LOCAL_DEV 1
#define HAVE_CARES_SET_LOCAL 1
#endif
#if ARES_VERSION >= 0x010b00
#define HAVE_CARES_PORTS_CSV 1
#endif
#if ARES_VERSION >= 0x011000
/* 1.16.0 or later has ares_getaddrinfo */
#define HAVE_CARES_GETADDRINFO 1
#endif
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
struct thread_data {
int num_pending; /* number of outstanding c-ares requests */
struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares
parts */
int last_status;
#ifndef HAVE_CARES_GETADDRINFO
struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
#endif
char hostname[1];
};
/* How long we are willing to wait for additional parallel responses after
obtaining a "definitive" one. For old c-ares without getaddrinfo.
This is intended to equal the c-ares default timeout. cURL always uses that
default value. Unfortunately, c-ares doesn't expose its default timeout in
its API, but it is officially documented as 5 seconds.
See query_completed_cb() for an explanation of how this is used.
*/
#define HAPPY_EYEBALLS_DNS_TIMEOUT 5000
#define CARES_TIMEOUT_PER_ATTEMPT 2000
static int ares_ver = 0;
/*
* Curl_resolver_global_init() - the generic low-level asynchronous name
* resolve API. Called from curl_global_init() to initialize global resolver
* environment. Initializes ares library.
*/
int Curl_resolver_global_init(void)
{
#ifdef CARES_HAVE_ARES_LIBRARY_INIT
if(ares_library_init(ARES_LIB_INIT_ALL)) {
return CURLE_FAILED_INIT;
}
#endif
ares_version(&ares_ver);
return CURLE_OK;
}
/*
* Curl_resolver_global_cleanup()
*
* Called from curl_global_cleanup() to destroy global resolver environment.
* Deinitializes ares library.
*/
void Curl_resolver_global_cleanup(void)
{
#ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP
ares_library_cleanup();
#endif
}
static void sock_state_cb(void *data, ares_socket_t socket_fd,
int readable, int writable)
{
struct Curl_easy *easy = data;
if(!readable && !writable) {
DEBUGASSERT(easy);
Curl_multi_closed(easy, socket_fd);
}
}
/*
* Curl_resolver_init()
*
* Called from curl_easy_init() -> Curl_open() to initialize resolver
* URL-state specific environment ('resolver' member of the UrlState
* structure). Fills the passed pointer by the initialized ares_channel.
*/
CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
{
int status;
struct ares_options options;
int optmask = ARES_OPT_SOCK_STATE_CB;
options.sock_state_cb = sock_state_cb;
options.sock_state_cb_data = easy;
/*
if c ares < 1.20.0: curl set timeout to CARES_TIMEOUT_PER_ATTEMPT (2s)
if c-ares >= 1.20.0 it already has the timeout to 2s, curl does not need
to set the timeout value;
if c-ares >= 1.24.0, user can set the timeout via /etc/resolv.conf to
overwrite c-ares' timeout.
*/
DEBUGASSERT(ares_ver);
if(ares_ver < 0x011400) {
options.timeout = CARES_TIMEOUT_PER_ATTEMPT;
optmask |= ARES_OPT_TIMEOUTMS;
}
status = ares_init_options((ares_channel*)resolver, &options, optmask);
if(status != ARES_SUCCESS) {
if(status == ARES_ENOMEM)
return CURLE_OUT_OF_MEMORY;
else
return CURLE_FAILED_INIT;
}
return CURLE_OK;
/* make sure that all other returns from this function should destroy the
ares channel before returning error! */
}
/*
* Curl_resolver_cleanup()
*
* Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
* URL-state specific environment ('resolver' member of the UrlState
* structure). Destroys the ares channel.
*/
void Curl_resolver_cleanup(void *resolver)
{
ares_destroy((ares_channel)resolver);
}
/*
* Curl_resolver_duphandle()
*
* Called from curl_easy_duphandle() to duplicate resolver URL-state specific
* environment ('resolver' member of the UrlState structure). Duplicates the
* 'from' ares channel and passes the resulting channel to the 'to' pointer.
*/
CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
{
(void)from;
/*
* it would be better to call ares_dup instead, but right now
* it is not possible to set 'sock_state_cb_data' outside of
* ares_init_options
*/
return Curl_resolver_init(easy, to);
}
static void destroy_async_data(struct Curl_async *async);
/*
* Cancel all possibly still on-going resolves for this connection.
*/
void Curl_resolver_cancel(struct Curl_easy *data)
{
DEBUGASSERT(data);
if(data->state.async.resolver)
ares_cancel((ares_channel)data->state.async.resolver);
destroy_async_data(&data->state.async);
}
/*
* We're equivalent to Curl_resolver_cancel() for the c-ares resolver. We
* never block.
*/
void Curl_resolver_kill(struct Curl_easy *data)
{
/* We don't need to check the resolver state because we can be called safely
at any time and we always do the same thing. */
Curl_resolver_cancel(data);
}
/*
* destroy_async_data() cleans up async resolver data.
*/
static void destroy_async_data(struct Curl_async *async)
{
if(async->tdata) {
struct thread_data *res = async->tdata;
if(res) {
if(res->temp_ai) {
Curl_freeaddrinfo(res->temp_ai);
res->temp_ai = NULL;
}
free(res);
}
async->tdata = NULL;
}
}
/*
* Curl_resolver_getsock() is called when someone from the outside world
* (using curl_multi_fdset()) wants to get our fd_set setup and we're talking
* with ares. The caller must make sure that this function is only called when
* we have a working ares channel.
*
* Returns: sockets-in-use-bitmap
*/
int Curl_resolver_getsock(struct Curl_easy *data,
curl_socket_t *socks)
{
struct timeval maxtime;
struct timeval timebuf;
struct timeval *timeout;
long milli;
int max = ares_getsock((ares_channel)data->state.async.resolver,
(ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
maxtime.tv_usec = 0;
timeout = ares_timeout((ares_channel)data->state.async.resolver, &maxtime,
&timebuf);
milli = (long)curlx_tvtoms(timeout);
if(milli == 0)
milli += 10;
Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
return max;
}
/*
* waitperform()
*
* 1) Ask ares what sockets it currently plays with, then
* 2) wait for the timeout period to check for action on ares' sockets.
* 3) tell ares to act on all the sockets marked as "with action"
*
* return number of sockets it worked on, or -1 on error
*/
static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
{
int nfds;
int bitmask;
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
struct pollfd pfd[ARES_GETSOCK_MAXNUM];
int i;
int num = 0;
bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks,
ARES_GETSOCK_MAXNUM);
for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
pfd[i].events = 0;
pfd[i].revents = 0;
if(ARES_GETSOCK_READABLE(bitmask, i)) {
pfd[i].fd = socks[i];
pfd[i].events |= POLLRDNORM|POLLIN;
}
if(ARES_GETSOCK_WRITABLE(bitmask, i)) {
pfd[i].fd = socks[i];
pfd[i].events |= POLLWRNORM|POLLOUT;
}
if(pfd[i].events)
num++;
else
break;
}
if(num) {
nfds = Curl_poll(pfd, num, timeout_ms);
if(nfds < 0)
return -1;
}
else
nfds = 0;
if(!nfds)
/* Call ares_process() unconditionally here, even if we simply timed out
above, as otherwise the ares name resolve won't timeout! */
ares_process_fd((ares_channel)data->state.async.resolver, ARES_SOCKET_BAD,
ARES_SOCKET_BAD);
else {
/* move through the descriptors and ask for processing on them */
for(i = 0; i < num; i++)
ares_process_fd((ares_channel)data->state.async.resolver,
(pfd[i].revents & (POLLRDNORM|POLLIN))?
pfd[i].fd:ARES_SOCKET_BAD,
(pfd[i].revents & (POLLWRNORM|POLLOUT))?
pfd[i].fd:ARES_SOCKET_BAD);
}
return nfds;
}
/*
* Curl_resolver_is_resolved() is called repeatedly to check if a previous
* name resolve request has completed. It should also make sure to time-out if
* the operation seems to take too long.
*
* Returns normal CURLcode errors.
*/
CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns)
{
struct thread_data *res = data->state.async.tdata;
CURLcode result = CURLE_OK;
DEBUGASSERT(dns);
*dns = NULL;
if(waitperform(data, 0) < 0)
return CURLE_UNRECOVERABLE_POLL;
#ifndef HAVE_CARES_GETADDRINFO
/* Now that we've checked for any last minute results above, see if there are
any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer
expires. */
if(res
&& res->num_pending
/* This is only set to non-zero if the timer was started. */
&& (res->happy_eyeballs_dns_time.tv_sec
|| res->happy_eyeballs_dns_time.tv_usec)
&& (Curl_timediff(Curl_now(), res->happy_eyeballs_dns_time)
>= HAPPY_EYEBALLS_DNS_TIMEOUT)) {
/* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer
running. */
memset(
&res->happy_eyeballs_dns_time, 0, sizeof(res->happy_eyeballs_dns_time));
/* Cancel the raw c-ares request, which will fire query_completed_cb() with
ARES_ECANCELLED synchronously for all pending responses. This will
leave us with res->num_pending == 0, which is perfect for the next
block. */
ares_cancel((ares_channel)data->state.async.resolver);
DEBUGASSERT(res->num_pending == 0);
}
#endif
if(res && !res->num_pending) {
(void)Curl_addrinfo_callback(data, res->last_status, res->temp_ai);
/* temp_ai ownership is moved to the connection, so we need not free-up
them */
res->temp_ai = NULL;
if(!data->state.async.dns)
result = Curl_resolver_error(data);
else
*dns = data->state.async.dns;
destroy_async_data(&data->state.async);
}
return result;
}
/*
* Curl_resolver_wait_resolv()
*
* Waits for a resolve to finish. This function should be avoided since using
* this risk getting the multi interface to "hang".
*
* 'entry' MUST be non-NULL.
*
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
*/
CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry)
{
CURLcode result = CURLE_OK;
timediff_t timeout;
struct curltime now = Curl_now();
DEBUGASSERT(entry);
*entry = NULL; /* clear on entry */
timeout = Curl_timeleft(data, &now, TRUE);
if(timeout < 0) {
/* already expired! */
connclose(data->conn, "Timed out before name resolve started");
return CURLE_OPERATION_TIMEDOUT;
}
if(!timeout)
timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */
/* Wait for the name resolve query to complete. */
while(!result) {
struct timeval *tvp, tv, store;
int itimeout;
timediff_t timeout_ms;
#if TIMEDIFF_T_MAX > INT_MAX
itimeout = (timeout > INT_MAX) ? INT_MAX : (int)timeout;
#else
itimeout = (int)timeout;
#endif
store.tv_sec = itimeout/1000;
store.tv_usec = (itimeout%1000)*1000;
tvp = ares_timeout((ares_channel)data->state.async.resolver, &store, &tv);
/* use the timeout period ares returned to us above if less than one
second is left, otherwise just use 1000ms to make sure the progress
callback gets called frequent enough */
if(!tvp->tv_sec)
timeout_ms = (timediff_t)(tvp->tv_usec/1000);
else
timeout_ms = 1000;
if(waitperform(data, timeout_ms) < 0)
return CURLE_UNRECOVERABLE_POLL;
result = Curl_resolver_is_resolved(data, entry);
if(result || data->state.async.done)
break;
if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else {
struct curltime now2 = Curl_now();
timediff_t timediff = Curl_timediff(now2, now); /* spent time */
if(timediff <= 0)
timeout -= 1; /* always deduct at least 1 */
else if(timediff > timeout)
timeout = -1;
else
timeout -= timediff;
now = now2; /* for next loop */
}
if(timeout < 0)
result = CURLE_OPERATION_TIMEDOUT;
}
if(result)
/* failure, so we cancel the ares operation */
ares_cancel((ares_channel)data->state.async.resolver);
/* Operation complete, if the lookup was successful we now have the entry
in the cache. */
if(entry)
*entry = data->state.async.dns;
if(result)
/* close the connection, since we can't return failure here without
cleaning up this connection properly. */
connclose(data->conn, "c-ares resolve failed");
return result;
}
#ifndef HAVE_CARES_GETADDRINFO
/* Connects results to the list */
static void compound_results(struct thread_data *res,
struct Curl_addrinfo *ai)
{
if(!ai)
return;
#ifdef USE_IPV6 /* CURLRES_IPV6 */
if(res->temp_ai && res->temp_ai->ai_family == PF_INET6) {
/* We have results already, put the new IPv6 entries at the head of the
list. */
struct Curl_addrinfo *temp_ai_tail = res->temp_ai;
while(temp_ai_tail->ai_next)
temp_ai_tail = temp_ai_tail->ai_next;
temp_ai_tail->ai_next = ai;
}
else
#endif /* CURLRES_IPV6 */
{
/* Add the new results to the list of old results. */
struct Curl_addrinfo *ai_tail = ai;
while(ai_tail->ai_next)
ai_tail = ai_tail->ai_next;
ai_tail->ai_next = res->temp_ai;
res->temp_ai = ai;
}
}
/*
* ares_query_completed_cb() is the callback that ares will call when
* the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(),
* when using ares, is completed either successfully or with failure.
*/
static void query_completed_cb(void *arg, /* (struct connectdata *) */
int status,
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
int timeouts,
#endif
struct hostent *hostent)
{
struct Curl_easy *data = (struct Curl_easy *)arg;
struct thread_data *res;
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
(void)timeouts; /* ignored */
#endif
if(ARES_EDESTRUCTION == status)
/* when this ares handle is getting destroyed, the 'arg' pointer may not
be valid so only defer it when we know the 'status' says its fine! */
return;
res = data->state.async.tdata;
if(res) {
res->num_pending--;
if(CURL_ASYNC_SUCCESS == status) {
struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port);
if(ai) {
compound_results(res, ai);
}
}
/* A successful result overwrites any previous error */
if(res->last_status != ARES_SUCCESS)
res->last_status = status;
/* If there are responses still pending, we presume they must be the
complementary IPv4 or IPv6 lookups that we started in parallel in
Curl_resolver_getaddrinfo() (for Happy Eyeballs). If we've got a
"definitive" response from one of a set of parallel queries, we need to
think about how long we're willing to wait for more responses. */
if(res->num_pending
/* Only these c-ares status values count as "definitive" for these
purposes. For example, ARES_ENODATA is what we expect when there is
no IPv6 entry for a domain name, and that's not a reason to get more
aggressive in our timeouts for the other response. Other errors are
either a result of bad input (which should affect all parallel
requests), local or network conditions, non-definitive server
responses, or us cancelling the request. */
&& (status == ARES_SUCCESS || status == ARES_ENOTFOUND)) {
/* Right now, there can only be up to two parallel queries, so don't
bother handling any other cases. */
DEBUGASSERT(res->num_pending == 1);
/* It's possible that one of these parallel queries could succeed
quickly, but the other could always fail or timeout (when we're
talking to a pool of DNS servers that can only successfully resolve
IPv4 address, for example).
It's also possible that the other request could always just take
longer because it needs more time or only the second DNS server can
fulfill it successfully. But, to align with the philosophy of Happy
Eyeballs, we don't want to wait _too_ long or users will think
requests are slow when IPv6 lookups don't actually work (but IPv4 ones
do).
So, now that we have a usable answer (some IPv4 addresses, some IPv6
addresses, or "no such domain"), we start a timeout for the remaining
pending responses. Even though it is typical that this resolved
request came back quickly, that needn't be the case. It might be that
this completing request didn't get a result from the first DNS server
or even the first round of the whole DNS server pool. So it could
already be quite some time after we issued the DNS queries in the
first place. Without modifying c-ares, we can't know exactly where in
its retry cycle we are. We could guess based on how much time has
gone by, but it doesn't really matter. Happy Eyeballs tells us that,
given usable information in hand, we simply don't want to wait "too
much longer" after we get a result.
We simply wait an additional amount of time equal to the default
c-ares query timeout. That is enough time for a typical parallel
response to arrive without being "too long". Even on a network
where one of the two types of queries is failing or timing out
constantly, this will usually mean we wait a total of the default
c-ares timeout (5 seconds) plus the round trip time for the successful
request, which seems bearable. The downside is that c-ares might race
with us to issue one more retry just before we give up, but it seems
better to "waste" that request instead of trying to guess the perfect
timeout to prevent it. After all, we don't even know where in the
c-ares retry cycle each request is.
*/
res->happy_eyeballs_dns_time = Curl_now();
Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT,
EXPIRE_HAPPY_EYEBALLS_DNS);
}
}
}
#else
/* c-ares 1.16.0 or later */
/*
* ares2addr() converts an address list provided by c-ares to an internal
* libcurl compatible list
*/
static struct Curl_addrinfo *ares2addr(struct ares_addrinfo_node *node)
{
/* traverse the ares_addrinfo_node list */
struct ares_addrinfo_node *ai;
struct Curl_addrinfo *cafirst = NULL;
struct Curl_addrinfo *calast = NULL;
int error = 0;
for(ai = node; ai != NULL; ai = ai->ai_next) {
size_t ss_size;
struct Curl_addrinfo *ca;
/* ignore elements with unsupported address family, */
/* settle family-specific sockaddr structure size. */
if(ai->ai_family == AF_INET)
ss_size = sizeof(struct sockaddr_in);
#ifdef USE_IPV6
else if(ai->ai_family == AF_INET6)
ss_size = sizeof(struct sockaddr_in6);
#endif
else
continue;
/* ignore elements without required address info */
if(!ai->ai_addr || !(ai->ai_addrlen > 0))
continue;
/* ignore elements with bogus address size */
if((size_t)ai->ai_addrlen < ss_size)
continue;
ca = malloc(sizeof(struct Curl_addrinfo) + ss_size);
if(!ca) {
error = EAI_MEMORY;
break;
}
/* copy each structure member individually, member ordering, */
/* size, or padding might be different for each platform. */
ca->ai_flags = ai->ai_flags;
ca->ai_family = ai->ai_family;
ca->ai_socktype = ai->ai_socktype;
ca->ai_protocol = ai->ai_protocol;
ca->ai_addrlen = (curl_socklen_t)ss_size;
ca->ai_addr = NULL;
ca->ai_canonname = NULL;
ca->ai_next = NULL;
ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
memcpy(ca->ai_addr, ai->ai_addr, ss_size);
/* if the return list is empty, this becomes the first element */
if(!cafirst)
cafirst = ca;
/* add this element last in the return list */
if(calast)
calast->ai_next = ca;
calast = ca;
}
/* if we failed, destroy the Curl_addrinfo list */
if(error) {
Curl_freeaddrinfo(cafirst);
cafirst = NULL;
}
return cafirst;
}
static void addrinfo_cb(void *arg, int status, int timeouts,
struct ares_addrinfo *result)
{
struct Curl_easy *data = (struct Curl_easy *)arg;
struct thread_data *res = data->state.async.tdata;
(void)timeouts;
if(ARES_SUCCESS == status) {
res->temp_ai = ares2addr(result->nodes);
res->last_status = CURL_ASYNC_SUCCESS;
ares_freeaddrinfo(result);
}
res->num_pending--;
}
#endif
/*
* Curl_resolver_getaddrinfo() - when using ares
*
* Returns name information about the given hostname and port number. If
* successful, the 'hostent' is returned and the fourth argument will point to
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
struct thread_data *res = NULL;
size_t namelen = strlen(hostname);
*waitp = 0; /* default to synchronous response */
res = calloc(1, sizeof(struct thread_data) + namelen);
if(res) {
strcpy(res->hostname, hostname);
data->state.async.hostname = res->hostname;
data->state.async.port = port;
data->state.async.done = FALSE; /* not done */
data->state.async.status = 0; /* clear */
data->state.async.dns = NULL; /* clear */
data->state.async.tdata = res;
/* initial status - failed */
res->last_status = ARES_ENOTFOUND;
#ifdef HAVE_CARES_GETADDRINFO
{
struct ares_addrinfo_hints hints;
char service[12];
int pf = PF_INET;
memset(&hints, 0, sizeof(hints));
#ifdef CURLRES_IPV6
if((data->conn->ip_version != CURL_IPRESOLVE_V4) &&
Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
if(data->conn->ip_version == CURL_IPRESOLVE_V6)
pf = PF_INET6;
else
pf = PF_UNSPEC;
}
#endif /* CURLRES_IPV6 */
hints.ai_family = pf;
hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
SOCK_STREAM : SOCK_DGRAM;
/* Since the service is a numerical one, set the hint flags
* accordingly to save a call to getservbyname in inside C-Ares
*/
hints.ai_flags = ARES_AI_NUMERICSERV;
msnprintf(service, sizeof(service), "%d", port);
res->num_pending = 1;
ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname,
service, &hints, addrinfo_cb, data);
}
#else
#ifdef HAVE_CARES_IPV6
if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
res->num_pending = 2;
/* areschannel is already setup in the Curl_open() function */
ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
PF_INET, query_completed_cb, data);
ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
PF_INET6, query_completed_cb, data);
}
else
#endif
{
res->num_pending = 1;
/* areschannel is already setup in the Curl_open() function */
ares_gethostbyname((ares_channel)data->state.async.resolver,
hostname, PF_INET,
query_completed_cb, data);
}
#endif
*waitp = 1; /* expect asynchronous response */
}
return NULL; /* no struct yet */
}
CURLcode Curl_set_dns_servers(struct Curl_easy *data,
char *servers)
{
CURLcode result = CURLE_NOT_BUILT_IN;
int ares_result;
/* If server is NULL or empty, this would purge all DNS servers
* from ares library, which will cause any and all queries to fail.
* So, just return OK if none are configured and don't actually make
* any changes to c-ares. This lets c-ares use its defaults, which
* it gets from the OS (for instance from /etc/resolv.conf on Linux).
*/
if(!(servers && servers[0]))
return CURLE_OK;
#ifdef HAVE_CARES_SERVERS_CSV
#ifdef HAVE_CARES_PORTS_CSV
ares_result = ares_set_servers_ports_csv(data->state.async.resolver,
servers);
#else
ares_result = ares_set_servers_csv(data->state.async.resolver, servers);
#endif
switch(ares_result) {
case ARES_SUCCESS:
result = CURLE_OK;
break;
case ARES_ENOMEM:
result = CURLE_OUT_OF_MEMORY;
break;
case ARES_ENOTINITIALIZED:
case ARES_ENODATA:
case ARES_EBADSTR:
default:
DEBUGF(infof(data, "bad servers set"));
result = CURLE_BAD_FUNCTION_ARGUMENT;
break;
}
#else /* too old c-ares version! */
(void)data;
(void)(ares_result);
#endif
return result;
}
CURLcode Curl_set_dns_interface(struct Curl_easy *data,
const char *interf)
{
#ifdef HAVE_CARES_LOCAL_DEV
if(!interf)
interf = "";
ares_set_local_dev((ares_channel)data->state.async.resolver, interf);
return CURLE_OK;
#else /* c-ares version too old! */
(void)data;
(void)interf;
return CURLE_NOT_BUILT_IN;
#endif
}
CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
const char *local_ip4)
{
#ifdef HAVE_CARES_SET_LOCAL
struct in_addr a4;
if((!local_ip4) || (local_ip4[0] == 0)) {
a4.s_addr = 0; /* disabled: do not bind to a specific address */
}
else {
if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) {
DEBUGF(infof(data, "bad DNS IPv4 address"));
return CURLE_BAD_FUNCTION_ARGUMENT;
}
}
ares_set_local_ip4((ares_channel)data->state.async.resolver,
ntohl(a4.s_addr));
return CURLE_OK;
#else /* c-ares version too old! */
(void)data;
(void)local_ip4;
return CURLE_NOT_BUILT_IN;
#endif
}
CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
const char *local_ip6)
{
#if defined(HAVE_CARES_SET_LOCAL) && defined(USE_IPV6)
unsigned char a6[INET6_ADDRSTRLEN];
if((!local_ip6) || (local_ip6[0] == 0)) {
/* disabled: do not bind to a specific address */
memset(a6, 0, sizeof(a6));
}
else {
if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) {
DEBUGF(infof(data, "bad DNS IPv6 address"));
return CURLE_BAD_FUNCTION_ARGUMENT;
}
}
ares_set_local_ip6((ares_channel)data->state.async.resolver, a6);
return CURLE_OK;
#else /* c-ares version too old! */
(void)data;
(void)local_ip6;
return CURLE_NOT_BUILT_IN;
#endif
}
#endif /* CURLRES_ARES */

998
third_party/curl/lib/asyn-thread.c vendored Normal file
View File

@ -0,0 +1,998 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "socketpair.h"
/***********************************************************************
* Only for threaded name resolves builds
**********************************************************************/
#ifdef CURLRES_THREADED
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
#endif
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
# include <pthread.h>
#endif
#ifdef HAVE_GETADDRINFO
# define RESOLVER_ENOMEM EAI_MEMORY
#else
# define RESOLVER_ENOMEM ENOMEM
#endif
#include "system_win32.h"
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
#include "share.h"
#include "url.h"
#include "multiif.h"
#include "inet_ntop.h"
#include "curl_threads.h"
#include "connect.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
struct resdata {
struct curltime start;
};
/*
* Curl_resolver_global_init()
* Called from curl_global_init() to initialize global resolver environment.
* Does nothing here.
*/
int Curl_resolver_global_init(void)
{
return CURLE_OK;
}
/*
* Curl_resolver_global_cleanup()
* Called from curl_global_cleanup() to destroy global resolver environment.
* Does nothing here.
*/
void Curl_resolver_global_cleanup(void)
{
}
/*
* Curl_resolver_init()
* Called from curl_easy_init() -> Curl_open() to initialize resolver
* URL-state specific environment ('resolver' member of the UrlState
* structure).
*/
CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
{
(void)easy;
*resolver = calloc(1, sizeof(struct resdata));
if(!*resolver)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
/*
* Curl_resolver_cleanup()
* Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
* URL-state specific environment ('resolver' member of the UrlState
* structure).
*/
void Curl_resolver_cleanup(void *resolver)
{
free(resolver);
}
/*
* Curl_resolver_duphandle()
* Called from curl_easy_duphandle() to duplicate resolver URL state-specific
* environment ('resolver' member of the UrlState structure).
*/
CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
{
(void)from;
return Curl_resolver_init(easy, to);
}
static void destroy_async_data(struct Curl_async *);
/*
* Cancel all possibly still on-going resolves for this connection.
*/
void Curl_resolver_cancel(struct Curl_easy *data)
{
destroy_async_data(&data->state.async);
}
/* This function is used to init a threaded resolve */
static bool init_resolve_thread(struct Curl_easy *data,
const char *hostname, int port,
const struct addrinfo *hints);
#ifdef _WIN32
/* Thread sync data used by GetAddrInfoExW for win8+ */
struct thread_sync_data_w8
{
OVERLAPPED overlapped;
ADDRINFOEXW_ *res;
HANDLE cancel_ev;
ADDRINFOEXW_ hints;
};
#endif
/* Data for synchronization between resolver thread and its parent */
struct thread_sync_data {
#ifdef _WIN32
struct thread_sync_data_w8 w8;
#endif
curl_mutex_t *mtx;
int done;
int port;
char *hostname; /* hostname to resolve, Curl_async.hostname
duplicate */
#ifndef CURL_DISABLE_SOCKETPAIR
struct Curl_easy *data;
curl_socket_t sock_pair[2]; /* socket pair */
#endif
int sock_error;
struct Curl_addrinfo *res;
#ifdef HAVE_GETADDRINFO
struct addrinfo hints;
#endif
struct thread_data *td; /* for thread-self cleanup */
};
struct thread_data {
#ifdef _WIN32
HANDLE complete_ev;
#endif
curl_thread_t thread_hnd;
unsigned int poll_interval;
timediff_t interval_end;
struct thread_sync_data tsd;
};
static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data)
{
return &(data->state.async.tdata->tsd);
}
/* Destroy resolver thread synchronization data */
static
void destroy_thread_sync_data(struct thread_sync_data *tsd)
{
if(tsd->mtx) {
Curl_mutex_destroy(tsd->mtx);
free(tsd->mtx);
}
free(tsd->hostname);
if(tsd->res)
Curl_freeaddrinfo(tsd->res);
#ifndef CURL_DISABLE_SOCKETPAIR
/*
* close one end of the socket pair (may be done in resolver thread);
* the other end (for reading) is always closed in the parent thread.
*/
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
wakeup_close(tsd->sock_pair[1]);
}
#endif
memset(tsd, 0, sizeof(*tsd));
}
/* Initialize resolver thread synchronization data */
static
int init_thread_sync_data(struct thread_data *td,
const char *hostname,
int port,
const struct addrinfo *hints)
{
struct thread_sync_data *tsd = &td->tsd;
memset(tsd, 0, sizeof(*tsd));
tsd->td = td;
tsd->port = port;
/* Treat the request as done until the thread actually starts so any early
* cleanup gets done properly.
*/
tsd->done = 1;
#ifdef HAVE_GETADDRINFO
DEBUGASSERT(hints);
tsd->hints = *hints;
#else
(void) hints;
#endif
tsd->mtx = malloc(sizeof(curl_mutex_t));
if(!tsd->mtx)
goto err_exit;
Curl_mutex_init(tsd->mtx);
#ifndef CURL_DISABLE_SOCKETPAIR
/* create socket pair or pipe */
if(wakeup_create(&tsd->sock_pair[0]) < 0) {
tsd->sock_pair[0] = CURL_SOCKET_BAD;
tsd->sock_pair[1] = CURL_SOCKET_BAD;
goto err_exit;
}
#endif
tsd->sock_error = CURL_ASYNC_SUCCESS;
/* Copying hostname string because original can be destroyed by parent
* thread during gethostbyname execution.
*/
tsd->hostname = strdup(hostname);
if(!tsd->hostname)
goto err_exit;
return 1;
err_exit:
#ifndef CURL_DISABLE_SOCKETPAIR
if(tsd->sock_pair[0] != CURL_SOCKET_BAD) {
wakeup_close(tsd->sock_pair[0]);
tsd->sock_pair[0] = CURL_SOCKET_BAD;
}
#endif
destroy_thread_sync_data(tsd);
return 0;
}
static CURLcode getaddrinfo_complete(struct Curl_easy *data)
{
struct thread_sync_data *tsd = conn_thread_sync_data(data);
CURLcode result;
result = Curl_addrinfo_callback(data, tsd->sock_error, tsd->res);
/* The tsd->res structure has been copied to async.dns and perhaps the DNS
cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it.
*/
tsd->res = NULL;
return result;
}
#ifdef _WIN32
static VOID WINAPI
query_complete(DWORD err, DWORD bytes, LPWSAOVERLAPPED overlapped)
{
size_t ss_size;
const ADDRINFOEXW_ *ai;
struct Curl_addrinfo *ca;
struct Curl_addrinfo *cafirst = NULL;
struct Curl_addrinfo *calast = NULL;
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-align"
#endif
struct thread_sync_data *tsd =
CONTAINING_RECORD(overlapped, struct thread_sync_data, w8.overlapped);
#ifdef __clang__
#pragma clang diagnostic pop
#endif
struct thread_data *td = tsd->td;
const ADDRINFOEXW_ *res = tsd->w8.res;
int error = (int)err;
(void)bytes;
if(error == ERROR_SUCCESS) {
/* traverse the addrinfo list */
for(ai = res; ai != NULL; ai = ai->ai_next) {
size_t namelen = ai->ai_canonname ? wcslen(ai->ai_canonname) + 1 : 0;
/* ignore elements with unsupported address family, */
/* settle family-specific sockaddr structure size. */
if(ai->ai_family == AF_INET)
ss_size = sizeof(struct sockaddr_in);
#ifdef USE_IPV6
else if(ai->ai_family == AF_INET6)
ss_size = sizeof(struct sockaddr_in6);
#endif
else
continue;
/* ignore elements without required address info */
if(!ai->ai_addr || !(ai->ai_addrlen > 0))
continue;
/* ignore elements with bogus address size */
if((size_t)ai->ai_addrlen < ss_size)
continue;
ca = malloc(sizeof(struct Curl_addrinfo) + ss_size + namelen);
if(!ca) {
error = EAI_MEMORY;
break;
}
/* copy each structure member individually, member ordering, */
/* size, or padding might be different for each platform. */
ca->ai_flags = ai->ai_flags;
ca->ai_family = ai->ai_family;
ca->ai_socktype = ai->ai_socktype;
ca->ai_protocol = ai->ai_protocol;
ca->ai_addrlen = (curl_socklen_t)ss_size;
ca->ai_addr = NULL;
ca->ai_canonname = NULL;
ca->ai_next = NULL;
ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
memcpy(ca->ai_addr, ai->ai_addr, ss_size);
if(namelen) {
size_t i;
ca->ai_canonname = (void *)((char *)ca->ai_addr + ss_size);
for(i = 0; i < namelen; ++i) /* convert wide string to ascii */
ca->ai_canonname[i] = (char)ai->ai_canonname[i];
ca->ai_canonname[namelen] = '\0';
}
/* if the return list is empty, this becomes the first element */
if(!cafirst)
cafirst = ca;
/* add this element last in the return list */
if(calast)
calast->ai_next = ca;
calast = ca;
}
/* if we failed, also destroy the Curl_addrinfo list */
if(error) {
Curl_freeaddrinfo(cafirst);
cafirst = NULL;
}
else if(!cafirst) {
#ifdef EAI_NONAME
/* rfc3493 conformant */
error = EAI_NONAME;
#else
/* rfc3493 obsoleted */
error = EAI_NODATA;
#endif
#ifdef USE_WINSOCK
SET_SOCKERRNO(error);
#endif
}
tsd->res = cafirst;
}
if(tsd->w8.res) {
Curl_FreeAddrInfoExW(tsd->w8.res);
tsd->w8.res = NULL;
}
if(error) {
tsd->sock_error = SOCKERRNO?SOCKERRNO:error;
if(tsd->sock_error == 0)
tsd->sock_error = RESOLVER_ENOMEM;
}
else {
Curl_addrinfo_set_port(tsd->res, tsd->port);
}
Curl_mutex_acquire(tsd->mtx);
if(tsd->done) {
/* too late, gotta clean up the mess */
Curl_mutex_release(tsd->mtx);
destroy_thread_sync_data(tsd);
free(td);
}
else {
#ifndef CURL_DISABLE_SOCKETPAIR
char buf[1];
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
/* DNS has been resolved, signal client task */
buf[0] = 1;
if(swrite(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
/* update sock_erro to errno */
tsd->sock_error = SOCKERRNO;
}
}
#endif
tsd->done = 1;
Curl_mutex_release(tsd->mtx);
if(td->complete_ev)
SetEvent(td->complete_ev); /* Notify caller that the query completed */
}
}
#endif
#ifdef HAVE_GETADDRINFO
/*
* getaddrinfo_thread() resolves a name and then exits.
*
* For builds without ARES, but with USE_IPV6, create a resolver thread
* and wait on it.
*/
static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
{
struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
struct thread_data *td = tsd->td;
char service[12];
int rc;
#ifndef CURL_DISABLE_SOCKETPAIR
char buf[1];
#endif
msnprintf(service, sizeof(service), "%d", tsd->port);
rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
if(rc) {
tsd->sock_error = SOCKERRNO?SOCKERRNO:rc;
if(tsd->sock_error == 0)
tsd->sock_error = RESOLVER_ENOMEM;
}
else {
Curl_addrinfo_set_port(tsd->res, tsd->port);
}
Curl_mutex_acquire(tsd->mtx);
if(tsd->done) {
/* too late, gotta clean up the mess */
Curl_mutex_release(tsd->mtx);
destroy_thread_sync_data(tsd);
free(td);
}
else {
#ifndef CURL_DISABLE_SOCKETPAIR
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
/* DNS has been resolved, signal client task */
buf[0] = 1;
if(wakeup_write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
/* update sock_erro to errno */
tsd->sock_error = SOCKERRNO;
}
}
#endif
tsd->done = 1;
Curl_mutex_release(tsd->mtx);
}
return 0;
}
#else /* HAVE_GETADDRINFO */
/*
* gethostbyname_thread() resolves a name and then exits.
*/
static unsigned int CURL_STDCALL gethostbyname_thread(void *arg)
{
struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
struct thread_data *td = tsd->td;
tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port);
if(!tsd->res) {
tsd->sock_error = SOCKERRNO;
if(tsd->sock_error == 0)
tsd->sock_error = RESOLVER_ENOMEM;
}
Curl_mutex_acquire(tsd->mtx);
if(tsd->done) {
/* too late, gotta clean up the mess */
Curl_mutex_release(tsd->mtx);
destroy_thread_sync_data(tsd);
free(td);
}
else {
tsd->done = 1;
Curl_mutex_release(tsd->mtx);
}
return 0;
}
#endif /* HAVE_GETADDRINFO */
/*
* destroy_async_data() cleans up async resolver data and thread handle.
*/
static void destroy_async_data(struct Curl_async *async)
{
if(async->tdata) {
struct thread_data *td = async->tdata;
int done;
#ifndef CURL_DISABLE_SOCKETPAIR
curl_socket_t sock_rd = td->tsd.sock_pair[0];
struct Curl_easy *data = td->tsd.data;
#endif
/*
* if the thread is still blocking in the resolve syscall, detach it and
* let the thread do the cleanup...
*/
Curl_mutex_acquire(td->tsd.mtx);
done = td->tsd.done;
td->tsd.done = 1;
Curl_mutex_release(td->tsd.mtx);
if(!done) {
#ifdef _WIN32
if(td->complete_ev) {
CloseHandle(td->complete_ev);
td->complete_ev = NULL;
}
#endif
if(td->thread_hnd != curl_thread_t_null) {
Curl_thread_destroy(td->thread_hnd);
td->thread_hnd = curl_thread_t_null;
}
}
else {
#ifdef _WIN32
if(td->complete_ev) {
Curl_GetAddrInfoExCancel(&td->tsd.w8.cancel_ev);
WaitForSingleObject(td->complete_ev, INFINITE);
CloseHandle(td->complete_ev);
td->complete_ev = NULL;
}
#endif
if(td->thread_hnd != curl_thread_t_null)
Curl_thread_join(&td->thread_hnd);
destroy_thread_sync_data(&td->tsd);
free(async->tdata);
}
#ifndef CURL_DISABLE_SOCKETPAIR
/*
* ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
* before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
*/
Curl_multi_closed(data, sock_rd);
wakeup_close(sock_rd);
#endif
}
async->tdata = NULL;
free(async->hostname);
async->hostname = NULL;
}
/*
* init_resolve_thread() starts a new thread that performs the actual
* resolve. This function returns before the resolve is done.
*
* Returns FALSE in case of failure, otherwise TRUE.
*/
static bool init_resolve_thread(struct Curl_easy *data,
const char *hostname, int port,
const struct addrinfo *hints)
{
struct thread_data *td = calloc(1, sizeof(struct thread_data));
int err = ENOMEM;
struct Curl_async *asp = &data->state.async;
data->state.async.tdata = td;
if(!td)
goto errno_exit;
asp->port = port;
asp->done = FALSE;
asp->status = 0;
asp->dns = NULL;
td->thread_hnd = curl_thread_t_null;
#ifdef _WIN32
td->complete_ev = NULL;
#endif
if(!init_thread_sync_data(td, hostname, port, hints)) {
asp->tdata = NULL;
free(td);
goto errno_exit;
}
free(asp->hostname);
asp->hostname = strdup(hostname);
if(!asp->hostname)
goto err_exit;
/* The thread will set this to 1 when complete. */
td->tsd.done = 0;
#ifdef _WIN32
if(Curl_isWindows8OrGreater && Curl_FreeAddrInfoExW &&
Curl_GetAddrInfoExCancel && Curl_GetAddrInfoExW) {
#define MAX_NAME_LEN 256 /* max domain name is 253 chars */
#define MAX_PORT_LEN 8
WCHAR namebuf[MAX_NAME_LEN];
WCHAR portbuf[MAX_PORT_LEN];
/* calculate required length */
int w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, hostname,
-1, NULL, 0);
if((w_len > 0) && (w_len < MAX_NAME_LEN)) {
/* do utf8 conversion */
w_len = MultiByteToWideChar(CP_UTF8, 0, hostname, -1, namebuf, w_len);
if((w_len > 0) && (w_len < MAX_NAME_LEN)) {
swprintf(portbuf, MAX_PORT_LEN, L"%d", port);
td->tsd.w8.hints.ai_family = hints->ai_family;
td->tsd.w8.hints.ai_socktype = hints->ai_socktype;
td->complete_ev = CreateEvent(NULL, TRUE, FALSE, NULL);
if(!td->complete_ev) {
/* failed to start, mark it as done here for proper cleanup. */
td->tsd.done = 1;
goto err_exit;
}
err = Curl_GetAddrInfoExW(namebuf, portbuf, NS_DNS,
NULL, &td->tsd.w8.hints, &td->tsd.w8.res,
NULL, &td->tsd.w8.overlapped,
&query_complete, &td->tsd.w8.cancel_ev);
if(err != WSA_IO_PENDING)
query_complete(err, 0, &td->tsd.w8.overlapped);
return TRUE;
}
}
}
#endif
#ifdef HAVE_GETADDRINFO
td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
#else
td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd);
#endif
if(td->thread_hnd == curl_thread_t_null) {
/* The thread never started, so mark it as done here for proper cleanup. */
td->tsd.done = 1;
err = errno;
goto err_exit;
}
return TRUE;
err_exit:
destroy_async_data(asp);
errno_exit:
errno = err;
return FALSE;
}
/*
* 'entry' may be NULL and then no data is returned
*/
static CURLcode thread_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry,
bool report)
{
struct thread_data *td;
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
td = data->state.async.tdata;
DEBUGASSERT(td);
#ifdef _WIN32
DEBUGASSERT(td->complete_ev || td->thread_hnd != curl_thread_t_null);
#else
DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
#endif
/* wait for the thread to resolve the name */
#ifdef _WIN32
if(td->complete_ev) {
WaitForSingleObject(td->complete_ev, INFINITE);
CloseHandle(td->complete_ev);
td->complete_ev = NULL;
if(entry)
result = getaddrinfo_complete(data);
}
else
#endif
if(Curl_thread_join(&td->thread_hnd)) {
if(entry)
result = getaddrinfo_complete(data);
}
else
DEBUGASSERT(0);
data->state.async.done = TRUE;
if(entry)
*entry = data->state.async.dns;
if(!data->state.async.dns && report)
/* a name was not resolved, report error */
result = Curl_resolver_error(data);
destroy_async_data(&data->state.async);
if(!data->state.async.dns && report)
connclose(data->conn, "asynch resolve failed");
return result;
}
/*
* Until we gain a way to signal the resolver threads to stop early, we must
* simply wait for them and ignore their results.
*/
void Curl_resolver_kill(struct Curl_easy *data)
{
struct thread_data *td = data->state.async.tdata;
/* If we're still resolving, we must wait for the threads to fully clean up,
unfortunately. Otherwise, we can simply cancel to clean up any resolver
data. */
#ifdef _WIN32
if(td && td->complete_ev) {
Curl_GetAddrInfoExCancel(&td->tsd.w8.cancel_ev);
(void)thread_wait_resolv(data, NULL, FALSE);
}
else
#endif
if(td && td->thread_hnd != curl_thread_t_null
&& (data->set.quick_exit != 1L))
(void)thread_wait_resolv(data, NULL, FALSE);
else
Curl_resolver_cancel(data);
}
/*
* Curl_resolver_wait_resolv()
*
* Waits for a resolve to finish. This function should be avoided since using
* this risk getting the multi interface to "hang".
*
* If 'entry' is non-NULL, make it point to the resolved dns entry
*
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
*
* This is the version for resolves-in-a-thread.
*/
CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry)
{
return thread_wait_resolv(data, entry, TRUE);
}
/*
* Curl_resolver_is_resolved() is called repeatedly to check if a previous
* name resolve request has completed. It should also make sure to time-out if
* the operation seems to take too long.
*/
CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **entry)
{
struct thread_data *td = data->state.async.tdata;
int done = 0;
DEBUGASSERT(entry);
*entry = NULL;
if(!td) {
DEBUGASSERT(td);
return CURLE_COULDNT_RESOLVE_HOST;
}
Curl_mutex_acquire(td->tsd.mtx);
done = td->tsd.done;
Curl_mutex_release(td->tsd.mtx);
if(done) {
getaddrinfo_complete(data);
if(!data->state.async.dns) {
CURLcode result = Curl_resolver_error(data);
destroy_async_data(&data->state.async);
return result;
}
destroy_async_data(&data->state.async);
*entry = data->state.async.dns;
}
else {
/* poll for name lookup done with exponential backoff up to 250ms */
/* should be fine even if this converts to 32 bit */
timediff_t elapsed = Curl_timediff(Curl_now(),
data->progress.t_startsingle);
if(elapsed < 0)
elapsed = 0;
if(td->poll_interval == 0)
/* Start at 1ms poll interval */
td->poll_interval = 1;
else if(elapsed >= td->interval_end)
/* Back-off exponentially if last interval expired */
td->poll_interval *= 2;
if(td->poll_interval > 250)
td->poll_interval = 250;
td->interval_end = elapsed + td->poll_interval;
Curl_expire(data, td->poll_interval, EXPIRE_ASYNC_NAME);
}
return CURLE_OK;
}
int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
{
int ret_val = 0;
timediff_t milli;
timediff_t ms;
struct resdata *reslv = (struct resdata *)data->state.async.resolver;
#ifndef CURL_DISABLE_SOCKETPAIR
struct thread_data *td = data->state.async.tdata;
#else
(void)socks;
#endif
#ifndef CURL_DISABLE_SOCKETPAIR
if(td) {
/* return read fd to client for polling the DNS resolution status */
socks[0] = td->tsd.sock_pair[0];
td->tsd.data = data;
ret_val = GETSOCK_READSOCK(0);
}
else {
#endif
ms = Curl_timediff(Curl_now(), reslv->start);
if(ms < 3)
milli = 0;
else if(ms <= 50)
milli = ms/3;
else if(ms <= 250)
milli = 50;
else
milli = 200;
Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
#ifndef CURL_DISABLE_SOCKETPAIR
}
#endif
return ret_val;
}
#ifndef HAVE_GETADDRINFO
/*
* Curl_getaddrinfo() - for platforms without getaddrinfo
*/
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
struct resdata *reslv = (struct resdata *)data->state.async.resolver;
*waitp = 0; /* default to synchronous response */
reslv->start = Curl_now();
/* fire up a new resolver thread! */
if(init_resolve_thread(data, hostname, port, NULL)) {
*waitp = 1; /* expect asynchronous response */
return NULL;
}
failf(data, "getaddrinfo() thread failed");
return NULL;
}
#else /* !HAVE_GETADDRINFO */
/*
* Curl_resolver_getaddrinfo() - for getaddrinfo
*/
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
struct addrinfo hints;
int pf = PF_INET;
struct resdata *reslv = (struct resdata *)data->state.async.resolver;
*waitp = 0; /* default to synchronous response */
#ifdef CURLRES_IPV6
if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
if(data->conn->ip_version == CURL_IPRESOLVE_V6)
pf = PF_INET6;
else
pf = PF_UNSPEC;
}
#endif /* CURLRES_IPV6 */
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
SOCK_STREAM : SOCK_DGRAM;
reslv->start = Curl_now();
/* fire up a new resolver thread! */
if(init_resolve_thread(data, hostname, port, &hints)) {
*waitp = 1; /* expect asynchronous response */
return NULL;
}
failf(data, "getaddrinfo() thread failed to start");
return NULL;
}
#endif /* !HAVE_GETADDRINFO */
CURLcode Curl_set_dns_servers(struct Curl_easy *data,
char *servers)
{
(void)data;
(void)servers;
return CURLE_NOT_BUILT_IN;
}
CURLcode Curl_set_dns_interface(struct Curl_easy *data,
const char *interf)
{
(void)data;
(void)interf;
return CURLE_NOT_BUILT_IN;
}
CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
const char *local_ip4)
{
(void)data;
(void)local_ip4;
return CURLE_NOT_BUILT_IN;
}
CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
const char *local_ip6)
{
(void)data;
(void)local_ip6;
return CURLE_NOT_BUILT_IN;
}
#endif /* CURLRES_THREADED */

184
third_party/curl/lib/asyn.h vendored Normal file
View File

@ -0,0 +1,184 @@
#ifndef HEADER_CURL_ASYN_H
#define HEADER_CURL_ASYN_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "curl_addrinfo.h"
struct addrinfo;
struct hostent;
struct Curl_easy;
struct connectdata;
struct Curl_dns_entry;
/*
* This header defines all functions in the internal asynch resolver interface.
* All asynch resolvers need to provide these functions.
* asyn-ares.c and asyn-thread.c are the current implementations of asynch
* resolver backends.
*/
/*
* Curl_resolver_global_init()
*
* Called from curl_global_init() to initialize global resolver environment.
* Returning anything else than CURLE_OK fails curl_global_init().
*/
int Curl_resolver_global_init(void);
/*
* Curl_resolver_global_cleanup()
* Called from curl_global_cleanup() to destroy global resolver environment.
*/
void Curl_resolver_global_cleanup(void);
/*
* Curl_resolver_init()
* Called from curl_easy_init() -> Curl_open() to initialize resolver
* URL-state specific environment ('resolver' member of the UrlState
* structure). Should fill the passed pointer by the initialized handler.
* Returning anything else than CURLE_OK fails curl_easy_init() with the
* correspondent code.
*/
CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver);
/*
* Curl_resolver_cleanup()
* Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
* URL-state specific environment ('resolver' member of the UrlState
* structure). Should destroy the handler and free all resources connected to
* it.
*/
void Curl_resolver_cleanup(void *resolver);
/*
* Curl_resolver_duphandle()
* Called from curl_easy_duphandle() to duplicate resolver URL-state specific
* environment ('resolver' member of the UrlState structure). Should
* duplicate the 'from' handle and pass the resulting handle to the 'to'
* pointer. Returning anything else than CURLE_OK causes failed
* curl_easy_duphandle() call.
*/
CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to,
void *from);
/*
* Curl_resolver_cancel().
*
* It is called from inside other functions to cancel currently performing
* resolver request. Should also free any temporary resources allocated to
* perform a request. This never waits for resolver threads to complete.
*
* It is safe to call this when conn is in any state.
*/
void Curl_resolver_cancel(struct Curl_easy *data);
/*
* Curl_resolver_kill().
*
* This acts like Curl_resolver_cancel() except it will block until any threads
* associated with the resolver are complete. This never blocks for resolvers
* that do not use threads. This is intended to be the "last chance" function
* that cleans up an in-progress resolver completely (before its owner is about
* to die).
*
* It is safe to call this when conn is in any state.
*/
void Curl_resolver_kill(struct Curl_easy *data);
/* Curl_resolver_getsock()
*
* This function is called from the multi_getsock() function. 'sock' is a
* pointer to an array to hold the file descriptors, with 'numsock' being the
* size of that array (in number of entries). This function is supposed to
* return bitmask indicating what file descriptors (referring to array indexes
* in the 'sock' array) to wait for, read/write.
*/
int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *sock);
/*
* Curl_resolver_is_resolved()
*
* Called repeatedly to check if a previous name resolve request has
* completed. It should also make sure to time-out if the operation seems to
* take too long.
*
* Returns normal CURLcode errors.
*/
CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns);
/*
* Curl_resolver_wait_resolv()
*
* Waits for a resolve to finish. This function should be avoided since using
* this risk getting the multi interface to "hang".
*
* If 'entry' is non-NULL, make it point to the resolved dns entry
*
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
*/
CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **dnsentry);
/*
* Curl_resolver_getaddrinfo() - when using this resolver
*
* Returns name information about the given hostname and port number. If
* successful, the 'hostent' is returned and the fourth argument will point to
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*
* Each resolver backend must of course make sure to return data in the
* correct format to comply with this.
*/
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp);
#ifndef CURLRES_ASYNCH
/* convert these functions if an asynch resolver isn't used */
#define Curl_resolver_cancel(x) Curl_nop_stmt
#define Curl_resolver_kill(x) Curl_nop_stmt
#define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
#define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
#define Curl_resolver_duphandle(x,y,z) CURLE_OK
#define Curl_resolver_init(x,y) CURLE_OK
#define Curl_resolver_global_init() CURLE_OK
#define Curl_resolver_global_cleanup() Curl_nop_stmt
#define Curl_resolver_cleanup(x) Curl_nop_stmt
#endif
#ifdef CURLRES_ASYNCH
#define Curl_resolver_asynch() 1
#else
#define Curl_resolver_asynch() 0
#endif
/********** end of generic resolver interface functions *****************/
#endif /* HEADER_CURL_ASYN_H */

293
third_party/curl/lib/base64.c vendored Normal file
View File

@ -0,0 +1,293 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* Base64 encoding/decoding */
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_SSH) || \
!defined(CURL_DISABLE_LDAP) || \
!defined(CURL_DISABLE_SMTP) || \
!defined(CURL_DISABLE_POP3) || \
!defined(CURL_DISABLE_IMAP) || \
!defined(CURL_DISABLE_DIGEST_AUTH) || \
!defined(CURL_DISABLE_DOH) || defined(USE_SSL) || defined(BUILDING_CURL)
#include "curl/curl.h"
#include "warnless.h"
#include "curl_base64.h"
/* The last 2 #include files should be in this order */
#ifdef BUILDING_LIBCURL
#include "curl_memory.h"
#endif
#include "memdebug.h"
/* ---- Base64 Encoding/Decoding Table --- */
/* Padding character string starts at offset 64. */
static const char base64encdec[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
/* The Base 64 encoding with a URL and filename safe alphabet, RFC 4648
section 5 */
static const char base64url[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
static const unsigned char decodetable[] =
{ 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255,
255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51 };
/*
* Curl_base64_decode()
*
* Given a base64 NUL-terminated string at src, decode it and return a
* pointer in *outptr to a newly allocated memory area holding decoded
* data. Size of decoded data is returned in variable pointed by outlen.
*
* Returns CURLE_OK on success, otherwise specific error code. Function
* output shall not be considered valid unless CURLE_OK is returned.
*
* When decoded data length is 0, returns NULL in *outptr.
*
* @unittest: 1302
*/
CURLcode Curl_base64_decode(const char *src,
unsigned char **outptr, size_t *outlen)
{
size_t srclen = 0;
size_t padding = 0;
size_t i;
size_t numQuantums;
size_t fullQuantums;
size_t rawlen = 0;
unsigned char *pos;
unsigned char *newstr;
unsigned char lookup[256];
*outptr = NULL;
*outlen = 0;
srclen = strlen(src);
/* Check the length of the input string is valid */
if(!srclen || srclen % 4)
return CURLE_BAD_CONTENT_ENCODING;
/* srclen is at least 4 here */
while(src[srclen - 1 - padding] == '=') {
/* count padding characters */
padding++;
/* A maximum of two = padding characters is allowed */
if(padding > 2)
return CURLE_BAD_CONTENT_ENCODING;
}
/* Calculate the number of quantums */
numQuantums = srclen / 4;
fullQuantums = numQuantums - (padding ? 1 : 0);
/* Calculate the size of the decoded string */
rawlen = (numQuantums * 3) - padding;
/* Allocate our buffer including room for a null-terminator */
newstr = malloc(rawlen + 1);
if(!newstr)
return CURLE_OUT_OF_MEMORY;
pos = newstr;
memset(lookup, 0xff, sizeof(lookup));
memcpy(&lookup['+'], decodetable, sizeof(decodetable));
/* replaces
{
unsigned char c;
const unsigned char *p = (const unsigned char *)base64encdec;
for(c = 0; *p; c++, p++)
lookup[*p] = c;
}
*/
/* Decode the complete quantums first */
for(i = 0; i < fullQuantums; i++) {
unsigned char val;
unsigned int x = 0;
int j;
for(j = 0; j < 4; j++) {
val = lookup[(unsigned char)*src++];
if(val == 0xff) /* bad symbol */
goto bad;
x = (x << 6) | val;
}
pos[2] = x & 0xff;
pos[1] = (x >> 8) & 0xff;
pos[0] = (x >> 16) & 0xff;
pos += 3;
}
if(padding) {
/* this means either 8 or 16 bits output */
unsigned char val;
unsigned int x = 0;
int j;
size_t padc = 0;
for(j = 0; j < 4; j++) {
if(*src == '=') {
x <<= 6;
src++;
if(++padc > padding)
/* this is a badly placed '=' symbol! */
goto bad;
}
else {
val = lookup[(unsigned char)*src++];
if(val == 0xff) /* bad symbol */
goto bad;
x = (x << 6) | val;
}
}
if(padding == 1)
pos[1] = (x >> 8) & 0xff;
pos[0] = (x >> 16) & 0xff;
pos += 3 - padding;
}
/* Zero terminate */
*pos = '\0';
/* Return the decoded data */
*outptr = newstr;
*outlen = rawlen;
return CURLE_OK;
bad:
free(newstr);
return CURLE_BAD_CONTENT_ENCODING;
}
static CURLcode base64_encode(const char *table64,
const char *inputbuff, size_t insize,
char **outptr, size_t *outlen)
{
char *output;
char *base64data;
const unsigned char *in = (unsigned char *)inputbuff;
const char *padstr = &table64[64]; /* Point to padding string. */
*outptr = NULL;
*outlen = 0;
if(!insize)
insize = strlen(inputbuff);
#if SIZEOF_SIZE_T == 4
if(insize > UINT_MAX/4)
return CURLE_OUT_OF_MEMORY;
#endif
base64data = output = malloc((insize + 2) / 3 * 4 + 1);
if(!output)
return CURLE_OUT_OF_MEMORY;
while(insize >= 3) {
*output++ = table64[ in[0] >> 2 ];
*output++ = table64[ ((in[0] & 0x03) << 4) | (in[1] >> 4) ];
*output++ = table64[ ((in[1] & 0x0F) << 2) | ((in[2] & 0xC0) >> 6) ];
*output++ = table64[ in[2] & 0x3F ];
insize -= 3;
in += 3;
}
if(insize) {
/* this is only one or two bytes now */
*output++ = table64[ in[0] >> 2 ];
if(insize == 1) {
*output++ = table64[ ((in[0] & 0x03) << 4) ];
if(*padstr) {
*output++ = *padstr;
*output++ = *padstr;
}
}
else {
/* insize == 2 */
*output++ = table64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xF0) >> 4) ];
*output++ = table64[ ((in[1] & 0x0F) << 2) ];
if(*padstr)
*output++ = *padstr;
}
}
/* Zero terminate */
*output = '\0';
/* Return the pointer to the new data (allocated memory) */
*outptr = base64data;
/* Return the length of the new data */
*outlen = (size_t)(output - base64data);
return CURLE_OK;
}
/*
* Curl_base64_encode()
*
* Given a pointer to an input buffer and an input size, encode it and
* return a pointer in *outptr to a newly allocated memory area holding
* encoded data. Size of encoded data is returned in variable pointed by
* outlen.
*
* Input length of 0 indicates input buffer holds a NUL-terminated string.
*
* Returns CURLE_OK on success, otherwise specific error code. Function
* output shall not be considered valid unless CURLE_OK is returned.
*
* @unittest: 1302
*/
CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
char **outptr, size_t *outlen)
{
return base64_encode(base64encdec, inputbuff, insize, outptr, outlen);
}
/*
* Curl_base64url_encode()
*
* Given a pointer to an input buffer and an input size, encode it and
* return a pointer in *outptr to a newly allocated memory area holding
* encoded data. Size of encoded data is returned in variable pointed by
* outlen.
*
* Input length of 0 indicates input buffer holds a NUL-terminated string.
*
* Returns CURLE_OK on success, otherwise specific error code. Function
* output shall not be considered valid unless CURLE_OK is returned.
*
* @unittest: 1302
*/
CURLcode Curl_base64url_encode(const char *inputbuff, size_t insize,
char **outptr, size_t *outlen)
{
return base64_encode(base64url, inputbuff, insize, outptr, outlen);
}
#endif /* no users so disabled */

677
third_party/curl/lib/bufq.c vendored Normal file
View File

@ -0,0 +1,677 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "bufq.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
static bool chunk_is_empty(const struct buf_chunk *chunk)
{
return chunk->r_offset >= chunk->w_offset;
}
static bool chunk_is_full(const struct buf_chunk *chunk)
{
return chunk->w_offset >= chunk->dlen;
}
static size_t chunk_len(const struct buf_chunk *chunk)
{
return chunk->w_offset - chunk->r_offset;
}
static size_t chunk_space(const struct buf_chunk *chunk)
{
return chunk->dlen - chunk->w_offset;
}
static void chunk_reset(struct buf_chunk *chunk)
{
chunk->next = NULL;
chunk->r_offset = chunk->w_offset = 0;
}
static size_t chunk_append(struct buf_chunk *chunk,
const unsigned char *buf, size_t len)
{
unsigned char *p = &chunk->x.data[chunk->w_offset];
size_t n = chunk->dlen - chunk->w_offset;
DEBUGASSERT(chunk->dlen >= chunk->w_offset);
if(n) {
n = CURLMIN(n, len);
memcpy(p, buf, n);
chunk->w_offset += n;
}
return n;
}
static size_t chunk_read(struct buf_chunk *chunk,
unsigned char *buf, size_t len)
{
unsigned char *p = &chunk->x.data[chunk->r_offset];
size_t n = chunk->w_offset - chunk->r_offset;
DEBUGASSERT(chunk->w_offset >= chunk->r_offset);
if(!n) {
return 0;
}
else if(n <= len) {
memcpy(buf, p, n);
chunk->r_offset = chunk->w_offset = 0;
return n;
}
else {
memcpy(buf, p, len);
chunk->r_offset += len;
return len;
}
}
static ssize_t chunk_slurpn(struct buf_chunk *chunk, size_t max_len,
Curl_bufq_reader *reader,
void *reader_ctx, CURLcode *err)
{
unsigned char *p = &chunk->x.data[chunk->w_offset];
size_t n = chunk->dlen - chunk->w_offset; /* free amount */
ssize_t nread;
DEBUGASSERT(chunk->dlen >= chunk->w_offset);
if(!n) {
*err = CURLE_AGAIN;
return -1;
}
if(max_len && n > max_len)
n = max_len;
nread = reader(reader_ctx, p, n, err);
if(nread > 0) {
DEBUGASSERT((size_t)nread <= n);
chunk->w_offset += nread;
}
return nread;
}
static void chunk_peek(const struct buf_chunk *chunk,
const unsigned char **pbuf, size_t *plen)
{
DEBUGASSERT(chunk->w_offset >= chunk->r_offset);
*pbuf = &chunk->x.data[chunk->r_offset];
*plen = chunk->w_offset - chunk->r_offset;
}
static void chunk_peek_at(const struct buf_chunk *chunk, size_t offset,
const unsigned char **pbuf, size_t *plen)
{
offset += chunk->r_offset;
DEBUGASSERT(chunk->w_offset >= offset);
*pbuf = &chunk->x.data[offset];
*plen = chunk->w_offset - offset;
}
static size_t chunk_skip(struct buf_chunk *chunk, size_t amount)
{
size_t n = chunk->w_offset - chunk->r_offset;
DEBUGASSERT(chunk->w_offset >= chunk->r_offset);
if(n) {
n = CURLMIN(n, amount);
chunk->r_offset += n;
if(chunk->r_offset == chunk->w_offset)
chunk->r_offset = chunk->w_offset = 0;
}
return n;
}
static void chunk_list_free(struct buf_chunk **anchor)
{
struct buf_chunk *chunk;
while(*anchor) {
chunk = *anchor;
*anchor = chunk->next;
free(chunk);
}
}
void Curl_bufcp_init(struct bufc_pool *pool,
size_t chunk_size, size_t spare_max)
{
DEBUGASSERT(chunk_size > 0);
DEBUGASSERT(spare_max > 0);
memset(pool, 0, sizeof(*pool));
pool->chunk_size = chunk_size;
pool->spare_max = spare_max;
}
static CURLcode bufcp_take(struct bufc_pool *pool,
struct buf_chunk **pchunk)
{
struct buf_chunk *chunk = NULL;
if(pool->spare) {
chunk = pool->spare;
pool->spare = chunk->next;
--pool->spare_count;
chunk_reset(chunk);
*pchunk = chunk;
return CURLE_OK;
}
chunk = calloc(1, sizeof(*chunk) + pool->chunk_size);
if(!chunk) {
*pchunk = NULL;
return CURLE_OUT_OF_MEMORY;
}
chunk->dlen = pool->chunk_size;
*pchunk = chunk;
return CURLE_OK;
}
static void bufcp_put(struct bufc_pool *pool,
struct buf_chunk *chunk)
{
if(pool->spare_count >= pool->spare_max) {
free(chunk);
}
else {
chunk_reset(chunk);
chunk->next = pool->spare;
pool->spare = chunk;
++pool->spare_count;
}
}
void Curl_bufcp_free(struct bufc_pool *pool)
{
chunk_list_free(&pool->spare);
pool->spare_count = 0;
}
static void bufq_init(struct bufq *q, struct bufc_pool *pool,
size_t chunk_size, size_t max_chunks, int opts)
{
DEBUGASSERT(chunk_size > 0);
DEBUGASSERT(max_chunks > 0);
memset(q, 0, sizeof(*q));
q->chunk_size = chunk_size;
q->max_chunks = max_chunks;
q->pool = pool;
q->opts = opts;
}
void Curl_bufq_init2(struct bufq *q, size_t chunk_size, size_t max_chunks,
int opts)
{
bufq_init(q, NULL, chunk_size, max_chunks, opts);
}
void Curl_bufq_init(struct bufq *q, size_t chunk_size, size_t max_chunks)
{
bufq_init(q, NULL, chunk_size, max_chunks, BUFQ_OPT_NONE);
}
void Curl_bufq_initp(struct bufq *q, struct bufc_pool *pool,
size_t max_chunks, int opts)
{
bufq_init(q, pool, pool->chunk_size, max_chunks, opts);
}
void Curl_bufq_free(struct bufq *q)
{
chunk_list_free(&q->head);
chunk_list_free(&q->spare);
q->tail = NULL;
q->chunk_count = 0;
}
void Curl_bufq_reset(struct bufq *q)
{
struct buf_chunk *chunk;
while(q->head) {
chunk = q->head;
q->head = chunk->next;
chunk->next = q->spare;
q->spare = chunk;
}
q->tail = NULL;
}
size_t Curl_bufq_len(const struct bufq *q)
{
const struct buf_chunk *chunk = q->head;
size_t len = 0;
while(chunk) {
len += chunk_len(chunk);
chunk = chunk->next;
}
return len;
}
size_t Curl_bufq_space(const struct bufq *q)
{
size_t space = 0;
if(q->tail)
space += chunk_space(q->tail);
if(q->spare) {
struct buf_chunk *chunk = q->spare;
while(chunk) {
space += chunk->dlen;
chunk = chunk->next;
}
}
if(q->chunk_count < q->max_chunks) {
space += (q->max_chunks - q->chunk_count) * q->chunk_size;
}
return space;
}
bool Curl_bufq_is_empty(const struct bufq *q)
{
return !q->head || chunk_is_empty(q->head);
}
bool Curl_bufq_is_full(const struct bufq *q)
{
if(!q->tail || q->spare)
return FALSE;
if(q->chunk_count < q->max_chunks)
return FALSE;
if(q->chunk_count > q->max_chunks)
return TRUE;
/* we have no spares and cannot make more, is the tail full? */
return chunk_is_full(q->tail);
}
static struct buf_chunk *get_spare(struct bufq *q)
{
struct buf_chunk *chunk = NULL;
if(q->spare) {
chunk = q->spare;
q->spare = chunk->next;
chunk_reset(chunk);
return chunk;
}
if(q->chunk_count >= q->max_chunks && (!(q->opts & BUFQ_OPT_SOFT_LIMIT)))
return NULL;
if(q->pool) {
if(bufcp_take(q->pool, &chunk))
return NULL;
++q->chunk_count;
return chunk;
}
else {
chunk = calloc(1, sizeof(*chunk) + q->chunk_size);
if(!chunk)
return NULL;
chunk->dlen = q->chunk_size;
++q->chunk_count;
return chunk;
}
}
static void prune_head(struct bufq *q)
{
struct buf_chunk *chunk;
while(q->head && chunk_is_empty(q->head)) {
chunk = q->head;
q->head = chunk->next;
if(q->tail == chunk)
q->tail = q->head;
if(q->pool) {
bufcp_put(q->pool, chunk);
--q->chunk_count;
}
else if((q->chunk_count > q->max_chunks) ||
(q->opts & BUFQ_OPT_NO_SPARES)) {
/* SOFT_LIMIT allowed us more than max. free spares until
* we are at max again. Or free them if we are configured
* to not use spares. */
free(chunk);
--q->chunk_count;
}
else {
chunk->next = q->spare;
q->spare = chunk;
}
}
}
static struct buf_chunk *get_non_full_tail(struct bufq *q)
{
struct buf_chunk *chunk;
if(q->tail && !chunk_is_full(q->tail))
return q->tail;
chunk = get_spare(q);
if(chunk) {
/* new tail, and possibly new head */
if(q->tail) {
q->tail->next = chunk;
q->tail = chunk;
}
else {
DEBUGASSERT(!q->head);
q->head = q->tail = chunk;
}
}
return chunk;
}
ssize_t Curl_bufq_write(struct bufq *q,
const unsigned char *buf, size_t len,
CURLcode *err)
{
struct buf_chunk *tail;
ssize_t nwritten = 0;
size_t n;
DEBUGASSERT(q->max_chunks > 0);
while(len) {
tail = get_non_full_tail(q);
if(!tail) {
if((q->chunk_count < q->max_chunks) || (q->opts & BUFQ_OPT_SOFT_LIMIT)) {
*err = CURLE_OUT_OF_MEMORY;
return -1;
}
break;
}
n = chunk_append(tail, buf, len);
if(!n)
break;
nwritten += n;
buf += n;
len -= n;
}
if(nwritten == 0 && len) {
*err = CURLE_AGAIN;
return -1;
}
*err = CURLE_OK;
return nwritten;
}
CURLcode Curl_bufq_cwrite(struct bufq *q,
const char *buf, size_t len,
size_t *pnwritten)
{
ssize_t n;
CURLcode result;
n = Curl_bufq_write(q, (const unsigned char *)buf, len, &result);
*pnwritten = (n < 0)? 0 : (size_t)n;
return result;
}
ssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len,
CURLcode *err)
{
ssize_t nread = 0;
size_t n;
*err = CURLE_OK;
while(len && q->head) {
n = chunk_read(q->head, buf, len);
if(n) {
nread += n;
buf += n;
len -= n;
}
prune_head(q);
}
if(nread == 0) {
*err = CURLE_AGAIN;
return -1;
}
return nread;
}
CURLcode Curl_bufq_cread(struct bufq *q, char *buf, size_t len,
size_t *pnread)
{
ssize_t n;
CURLcode result;
n = Curl_bufq_read(q, (unsigned char *)buf, len, &result);
*pnread = (n < 0)? 0 : (size_t)n;
return result;
}
bool Curl_bufq_peek(struct bufq *q,
const unsigned char **pbuf, size_t *plen)
{
if(q->head && chunk_is_empty(q->head)) {
prune_head(q);
}
if(q->head && !chunk_is_empty(q->head)) {
chunk_peek(q->head, pbuf, plen);
return TRUE;
}
*pbuf = NULL;
*plen = 0;
return FALSE;
}
bool Curl_bufq_peek_at(struct bufq *q, size_t offset,
const unsigned char **pbuf, size_t *plen)
{
struct buf_chunk *c = q->head;
size_t clen;
while(c) {
clen = chunk_len(c);
if(!clen)
break;
if(offset >= clen) {
offset -= clen;
c = c->next;
continue;
}
chunk_peek_at(c, offset, pbuf, plen);
return TRUE;
}
*pbuf = NULL;
*plen = 0;
return FALSE;
}
void Curl_bufq_skip(struct bufq *q, size_t amount)
{
size_t n;
while(amount && q->head) {
n = chunk_skip(q->head, amount);
amount -= n;
prune_head(q);
}
}
ssize_t Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer,
void *writer_ctx, CURLcode *err)
{
const unsigned char *buf;
size_t blen;
ssize_t nwritten = 0;
while(Curl_bufq_peek(q, &buf, &blen)) {
ssize_t chunk_written;
chunk_written = writer(writer_ctx, buf, blen, err);
if(chunk_written < 0) {
if(!nwritten || *err != CURLE_AGAIN) {
/* blocked on first write or real error, fail */
nwritten = -1;
}
break;
}
if(!chunk_written) {
if(!nwritten) {
/* treat as blocked */
*err = CURLE_AGAIN;
nwritten = -1;
}
break;
}
Curl_bufq_skip(q, (size_t)chunk_written);
nwritten += chunk_written;
}
return nwritten;
}
ssize_t Curl_bufq_write_pass(struct bufq *q,
const unsigned char *buf, size_t len,
Curl_bufq_writer *writer, void *writer_ctx,
CURLcode *err)
{
ssize_t nwritten = 0, n;
*err = CURLE_OK;
while(len) {
if(Curl_bufq_is_full(q)) {
/* try to make room in case we are full */
n = Curl_bufq_pass(q, writer, writer_ctx, err);
if(n < 0) {
if(*err != CURLE_AGAIN) {
/* real error, fail */
return -1;
}
/* would block, bufq is full, give up */
break;
}
}
/* Add whatever is remaining now to bufq */
n = Curl_bufq_write(q, buf, len, err);
if(n < 0) {
if(*err != CURLE_AGAIN) {
/* real error, fail */
return -1;
}
/* no room in bufq */
break;
}
/* edge case of writer returning 0 (and len is >0)
* break or we might enter an infinite loop here */
if(n == 0)
break;
/* Maybe only part of `data` has been added, continue to loop */
buf += (size_t)n;
len -= (size_t)n;
nwritten += (size_t)n;
}
if(!nwritten && len) {
*err = CURLE_AGAIN;
return -1;
}
*err = CURLE_OK;
return nwritten;
}
ssize_t Curl_bufq_sipn(struct bufq *q, size_t max_len,
Curl_bufq_reader *reader, void *reader_ctx,
CURLcode *err)
{
struct buf_chunk *tail = NULL;
ssize_t nread;
*err = CURLE_AGAIN;
tail = get_non_full_tail(q);
if(!tail) {
if(q->chunk_count < q->max_chunks) {
*err = CURLE_OUT_OF_MEMORY;
return -1;
}
/* full, blocked */
*err = CURLE_AGAIN;
return -1;
}
nread = chunk_slurpn(tail, max_len, reader, reader_ctx, err);
if(nread < 0) {
return -1;
}
else if(nread == 0) {
/* eof */
*err = CURLE_OK;
}
return nread;
}
/**
* Read up to `max_len` bytes and append it to the end of the buffer queue.
* if `max_len` is 0, no limit is imposed and the call behaves exactly
* the same as `Curl_bufq_slurp()`.
* Returns the total amount of buf read (may be 0) or -1 on other
* reader errors.
* Note that even in case of a -1 chunks may have been read and
* the buffer queue will have different length than before.
*/
static ssize_t bufq_slurpn(struct bufq *q, size_t max_len,
Curl_bufq_reader *reader, void *reader_ctx,
CURLcode *err)
{
ssize_t nread = 0, n;
*err = CURLE_AGAIN;
while(1) {
n = Curl_bufq_sipn(q, max_len, reader, reader_ctx, err);
if(n < 0) {
if(!nread || *err != CURLE_AGAIN) {
/* blocked on first read or real error, fail */
nread = -1;
}
else
*err = CURLE_OK;
break;
}
else if(n == 0) {
/* eof */
*err = CURLE_OK;
break;
}
nread += (size_t)n;
if(max_len) {
DEBUGASSERT((size_t)n <= max_len);
max_len -= (size_t)n;
if(!max_len)
break;
}
/* give up slurping when we get less bytes than we asked for */
if(q->tail && !chunk_is_full(q->tail))
break;
}
return nread;
}
ssize_t Curl_bufq_slurp(struct bufq *q, Curl_bufq_reader *reader,
void *reader_ctx, CURLcode *err)
{
return bufq_slurpn(q, 0, reader, reader_ctx, err);
}

272
third_party/curl/lib/bufq.h vendored Normal file
View File

@ -0,0 +1,272 @@
#ifndef HEADER_CURL_BUFQ_H
#define HEADER_CURL_BUFQ_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include <curl/curl.h>
/**
* A chunk of bytes for reading and writing.
* The size is fixed a creation with read and write offset
* for where unread content is.
*/
struct buf_chunk {
struct buf_chunk *next; /* to keep it in a list */
size_t dlen; /* the amount of allocated x.data[] */
size_t r_offset; /* first unread bytes */
size_t w_offset; /* one after last written byte */
union {
unsigned char data[1]; /* the buffer for `dlen` bytes */
void *dummy; /* alignment */
} x;
};
/**
* A pool for providing/keeping a number of chunks of the same size
*
* The same pool can be shared by many `bufq` instances. However, a pool
* is not thread safe. All bufqs using it are supposed to operate in the
* same thread.
*/
struct bufc_pool {
struct buf_chunk *spare; /* list of available spare chunks */
size_t chunk_size; /* the size of chunks in this pool */
size_t spare_count; /* current number of spare chunks in list */
size_t spare_max; /* max number of spares to keep */
};
void Curl_bufcp_init(struct bufc_pool *pool,
size_t chunk_size, size_t spare_max);
void Curl_bufcp_free(struct bufc_pool *pool);
/**
* A queue of byte chunks for reading and writing.
* Reading is done from `head`, writing is done to `tail`.
*
* `bufq`s can be empty or full or neither. Its `len` is the number
* of bytes that can be read. For an empty bufq, `len` will be 0.
*
* By default, a bufq can hold up to `max_chunks * chunk_size` number
* of bytes. When `max_chunks` are used (in the `head` list) and the
* `tail` chunk is full, the bufq will report that it is full.
*
* On a full bufq, `len` may be less than the maximum number of bytes,
* e.g. when the head chunk is partially read. `len` may also become
* larger than the max when option `BUFQ_OPT_SOFT_LIMIT` is used.
*
* By default, writing to a full bufq will return (-1, CURLE_AGAIN). Same
* as reading from an empty bufq.
* With `BUFQ_OPT_SOFT_LIMIT` set, a bufq will allow writing becond this
* limit and use more than `max_chunks`. However it will report that it
* is full nevertheless. This is provided for situation where writes
* preferably never fail (except for memory exhaustion).
*
* By default and without a pool, a bufq will keep chunks that read
* empty in its `spare` list. Option `BUFQ_OPT_NO_SPARES` will
* disable that and free chunks once they become empty.
*
* When providing a pool to a bufq, all chunk creation and spare handling
* will be delegated to that pool.
*/
struct bufq {
struct buf_chunk *head; /* chunk with bytes to read from */
struct buf_chunk *tail; /* chunk to write to */
struct buf_chunk *spare; /* list of free chunks, unless `pool` */
struct bufc_pool *pool; /* optional pool for free chunks */
size_t chunk_count; /* current number of chunks in `head+spare` */
size_t max_chunks; /* max `head` chunks to use */
size_t chunk_size; /* size of chunks to manage */
int opts; /* options for handling queue, see below */
};
/**
* Default behaviour: chunk limit is "hard", meaning attempts to write
* more bytes than can be hold in `max_chunks` is refused and will return
* -1, CURLE_AGAIN. */
#define BUFQ_OPT_NONE (0)
/**
* Make `max_chunks` a "soft" limit. A bufq will report that it is "full"
* when `max_chunks` are used, but allows writing beyond this limit.
*/
#define BUFQ_OPT_SOFT_LIMIT (1 << 0)
/**
* Do not keep spare chunks.
*/
#define BUFQ_OPT_NO_SPARES (1 << 1)
/**
* Initialize a buffer queue that can hold up to `max_chunks` buffers
* each of size `chunk_size`. The bufq will not allow writing of
* more bytes than can be held in `max_chunks`.
*/
void Curl_bufq_init(struct bufq *q, size_t chunk_size, size_t max_chunks);
/**
* Initialize a buffer queue that can hold up to `max_chunks` buffers
* each of size `chunk_size` with the given options. See `BUFQ_OPT_*`.
*/
void Curl_bufq_init2(struct bufq *q, size_t chunk_size,
size_t max_chunks, int opts);
void Curl_bufq_initp(struct bufq *q, struct bufc_pool *pool,
size_t max_chunks, int opts);
/**
* Reset the buffer queue to be empty. Will keep any allocated buffer
* chunks around.
*/
void Curl_bufq_reset(struct bufq *q);
/**
* Free all resources held by the buffer queue.
*/
void Curl_bufq_free(struct bufq *q);
/**
* Return the total amount of data in the queue.
*/
size_t Curl_bufq_len(const struct bufq *q);
/**
* Return the total amount of free space in the queue.
* The returned length is the number of bytes that can
* be expected to be written successfully to the bufq,
* providing no memory allocations fail.
*/
size_t Curl_bufq_space(const struct bufq *q);
/**
* Returns TRUE iff there is no data in the buffer queue.
*/
bool Curl_bufq_is_empty(const struct bufq *q);
/**
* Returns TRUE iff there is no space left in the buffer queue.
*/
bool Curl_bufq_is_full(const struct bufq *q);
/**
* Write buf to the end of the buffer queue. The buf is copied
* and the amount of copied bytes is returned.
* A return code of -1 indicates an error, setting `err` to the
* cause. An err of CURLE_AGAIN is returned if the buffer queue is full.
*/
ssize_t Curl_bufq_write(struct bufq *q,
const unsigned char *buf, size_t len,
CURLcode *err);
CURLcode Curl_bufq_cwrite(struct bufq *q,
const char *buf, size_t len,
size_t *pnwritten);
/**
* Read buf from the start of the buffer queue. The buf is copied
* and the amount of copied bytes is returned.
* A return code of -1 indicates an error, setting `err` to the
* cause. An err of CURLE_AGAIN is returned if the buffer queue is empty.
*/
ssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len,
CURLcode *err);
CURLcode Curl_bufq_cread(struct bufq *q, char *buf, size_t len,
size_t *pnread);
/**
* Peek at the head chunk in the buffer queue. Returns a pointer to
* the chunk buf (at the current offset) and its length. Does not
* modify the buffer queue.
* Returns TRUE iff bytes are available. Sets `pbuf` to NULL and `plen`
* to 0 when no bytes are available.
* Repeated calls return the same information until the buffer queue
* is modified, see `Curl_bufq_skip()``
*/
bool Curl_bufq_peek(struct bufq *q,
const unsigned char **pbuf, size_t *plen);
bool Curl_bufq_peek_at(struct bufq *q, size_t offset,
const unsigned char **pbuf, size_t *plen);
/**
* Tell the buffer queue to discard `amount` buf bytes at the head
* of the queue. Skipping more buf than is currently buffered will
* just empty the queue.
*/
void Curl_bufq_skip(struct bufq *q, size_t amount);
typedef ssize_t Curl_bufq_writer(void *writer_ctx,
const unsigned char *buf, size_t len,
CURLcode *err);
/**
* Passes the chunks in the buffer queue to the writer and returns
* the amount of buf written. A writer may return -1 and CURLE_AGAIN
* to indicate blocking at which point the queue will stop and return
* the amount of buf passed so far.
* -1 is returned on any other errors reported by the writer.
* Note that in case of a -1 chunks may have been written and
* the buffer queue will have different length than before.
*/
ssize_t Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer,
void *writer_ctx, CURLcode *err);
typedef ssize_t Curl_bufq_reader(void *reader_ctx,
unsigned char *buf, size_t len,
CURLcode *err);
/**
* Read date and append it to the end of the buffer queue until the
* reader returns blocking or the queue is full. A reader returns
* -1 and CURLE_AGAIN to indicate blocking.
* Returns the total amount of buf read (may be 0) or -1 on other
* reader errors.
* Note that in case of a -1 chunks may have been read and
* the buffer queue will have different length than before.
*/
ssize_t Curl_bufq_slurp(struct bufq *q, Curl_bufq_reader *reader,
void *reader_ctx, CURLcode *err);
/**
* Read *once* up to `max_len` bytes and append it to the buffer.
* if `max_len` is 0, no limit is imposed besides the chunk space.
* Returns the total amount of buf read (may be 0) or -1 on other
* reader errors.
*/
ssize_t Curl_bufq_sipn(struct bufq *q, size_t max_len,
Curl_bufq_reader *reader, void *reader_ctx,
CURLcode *err);
/**
* Write buf to the end of the buffer queue.
* Will write bufq content or passed `buf` directly using the `writer`
* callback when it sees fit. 'buf' might get passed directly
* on or is placed into the buffer, depending on `len` and current
* amount buffered, chunk size, etc.
*/
ssize_t Curl_bufq_write_pass(struct bufq *q,
const unsigned char *buf, size_t len,
Curl_bufq_writer *writer, void *writer_ctx,
CURLcode *err);
#endif /* HEADER_CURL_BUFQ_H */

127
third_party/curl/lib/bufref.c vendored Normal file
View File

@ -0,0 +1,127 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#include "bufref.h"
#include "strdup.h"
#include "curl_memory.h"
#include "memdebug.h"
#define SIGNATURE 0x5c48e9b2 /* Random pattern. */
/*
* Init a bufref struct.
*/
void Curl_bufref_init(struct bufref *br)
{
DEBUGASSERT(br);
br->dtor = NULL;
br->ptr = NULL;
br->len = 0;
#ifdef DEBUGBUILD
br->signature = SIGNATURE;
#endif
}
/*
* Free the buffer and re-init the necessary fields. It doesn't touch the
* 'signature' field and thus this buffer reference can be reused.
*/
void Curl_bufref_free(struct bufref *br)
{
DEBUGASSERT(br);
DEBUGASSERT(br->signature == SIGNATURE);
DEBUGASSERT(br->ptr || !br->len);
if(br->ptr && br->dtor)
br->dtor((void *) br->ptr);
br->dtor = NULL;
br->ptr = NULL;
br->len = 0;
}
/*
* Set the buffer reference to new values. The previously referenced buffer
* is released before assignment.
*/
void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len,
void (*dtor)(void *))
{
DEBUGASSERT(ptr || !len);
DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH);
Curl_bufref_free(br);
br->ptr = (const unsigned char *) ptr;
br->len = len;
br->dtor = dtor;
}
/*
* Get a pointer to the referenced buffer.
*/
const unsigned char *Curl_bufref_ptr(const struct bufref *br)
{
DEBUGASSERT(br);
DEBUGASSERT(br->signature == SIGNATURE);
DEBUGASSERT(br->ptr || !br->len);
return br->ptr;
}
/*
* Get the length of the referenced buffer data.
*/
size_t Curl_bufref_len(const struct bufref *br)
{
DEBUGASSERT(br);
DEBUGASSERT(br->signature == SIGNATURE);
DEBUGASSERT(br->ptr || !br->len);
return br->len;
}
CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len)
{
unsigned char *cpy = NULL;
DEBUGASSERT(br);
DEBUGASSERT(br->signature == SIGNATURE);
DEBUGASSERT(br->ptr || !br->len);
DEBUGASSERT(ptr || !len);
DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH);
if(ptr) {
cpy = Curl_memdup0(ptr, len);
if(!cpy)
return CURLE_OUT_OF_MEMORY;
}
Curl_bufref_set(br, cpy, len, curl_free);
return CURLE_OK;
}

48
third_party/curl/lib/bufref.h vendored Normal file
View File

@ -0,0 +1,48 @@
#ifndef HEADER_CURL_BUFREF_H
#define HEADER_CURL_BUFREF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/*
* Generic buffer reference.
*/
struct bufref {
void (*dtor)(void *); /* Associated destructor. */
const unsigned char *ptr; /* Referenced data buffer. */
size_t len; /* The data size in bytes. */
#ifdef DEBUGBUILD
int signature; /* Detect API use mistakes. */
#endif
};
void Curl_bufref_init(struct bufref *br);
void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len,
void (*dtor)(void *));
const unsigned char *Curl_bufref_ptr(const struct bufref *br);
size_t Curl_bufref_len(const struct bufref *br);
CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len);
void Curl_bufref_free(struct bufref *br);
#endif

1228
third_party/curl/lib/c-hyper.c vendored Normal file

File diff suppressed because it is too large Load Diff

63
third_party/curl/lib/c-hyper.h vendored Normal file
View File

@ -0,0 +1,63 @@
#ifndef HEADER_CURL_HYPER_H
#define HEADER_CURL_HYPER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
#include <hyper.h>
struct hyp_io_ctx {
struct Curl_easy *data;
int sockindex;
};
/* per-transfer data for the Hyper backend */
struct hyptransfer {
hyper_waker *write_waker;
hyper_waker *read_waker;
const hyper_executor *exec;
hyper_waker *send_body_waker;
struct hyp_io_ctx io_ctx;
};
size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
uint8_t *buf, size_t buflen);
size_t Curl_hyper_send(void *userp, hyper_context *ctx,
const uint8_t *buf, size_t buflen);
CURLcode Curl_hyper_stream(struct Curl_easy *data,
struct connectdata *conn,
int *didwhat,
int select_res);
CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
const char *line);
void Curl_hyper_done(struct Curl_easy *);
#else
#define Curl_hyper_done(x)
#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
#endif /* HEADER_CURL_HYPER_H */

1104
third_party/curl/lib/cf-h1-proxy.c vendored Normal file

File diff suppressed because it is too large Load Diff

39
third_party/curl/lib/cf-h1-proxy.h vendored Normal file
View File

@ -0,0 +1,39 @@
#ifndef HEADER_CURL_H1_PROXY_H
#define HEADER_CURL_H1_PROXY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
CURLcode Curl_cf_h1_proxy_insert_after(struct Curl_cfilter *cf,
struct Curl_easy *data);
extern struct Curl_cftype Curl_cft_h1_proxy;
#endif /* !CURL_DISABLE_PROXY && !CURL_DISABLE_HTTP */
#endif /* HEADER_CURL_H1_PROXY_H */

1576
third_party/curl/lib/cf-h2-proxy.c vendored Normal file

File diff suppressed because it is too large Load Diff

39
third_party/curl/lib/cf-h2-proxy.h vendored Normal file
View File

@ -0,0 +1,39 @@
#ifndef HEADER_CURL_H2_PROXY_H
#define HEADER_CURL_H2_PROXY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if defined(USE_NGHTTP2) && !defined(CURL_DISABLE_PROXY)
CURLcode Curl_cf_h2_proxy_insert_after(struct Curl_cfilter *cf,
struct Curl_easy *data);
extern struct Curl_cftype Curl_cft_h2_proxy;
#endif /* defined(USE_NGHTTP2) && !defined(CURL_DISABLE_PROXY) */
#endif /* HEADER_CURL_H2_PROXY_H */

250
third_party/curl/lib/cf-haproxy.c vendored Normal file
View File

@ -0,0 +1,250 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_PROXY)
#include <curl/curl.h>
#include "urldata.h"
#include "cfilters.h"
#include "cf-haproxy.h"
#include "curl_trc.h"
#include "multiif.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
typedef enum {
HAPROXY_INIT, /* init/default/no tunnel state */
HAPROXY_SEND, /* data_out being sent */
HAPROXY_DONE /* all work done */
} haproxy_state;
struct cf_haproxy_ctx {
int state;
struct dynbuf data_out;
};
static void cf_haproxy_ctx_reset(struct cf_haproxy_ctx *ctx)
{
DEBUGASSERT(ctx);
ctx->state = HAPROXY_INIT;
Curl_dyn_reset(&ctx->data_out);
}
static void cf_haproxy_ctx_free(struct cf_haproxy_ctx *ctx)
{
if(ctx) {
Curl_dyn_free(&ctx->data_out);
free(ctx);
}
}
static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
struct Curl_easy *data)
{
struct cf_haproxy_ctx *ctx = cf->ctx;
CURLcode result;
const char *tcp_version;
const char *client_ip;
DEBUGASSERT(ctx);
DEBUGASSERT(ctx->state == HAPROXY_INIT);
#ifdef USE_UNIX_SOCKETS
if(cf->conn->unix_domain_socket)
/* the buffer is large enough to hold this! */
result = Curl_dyn_addn(&ctx->data_out, STRCONST("PROXY UNKNOWN\r\n"));
else {
#endif /* USE_UNIX_SOCKETS */
/* Emit the correct prefix for IPv6 */
tcp_version = cf->conn->bits.ipv6 ? "TCP6" : "TCP4";
if(data->set.str[STRING_HAPROXY_CLIENT_IP])
client_ip = data->set.str[STRING_HAPROXY_CLIENT_IP];
else
client_ip = data->info.primary.local_ip;
result = Curl_dyn_addf(&ctx->data_out, "PROXY %s %s %s %i %i\r\n",
tcp_version,
client_ip,
data->info.primary.remote_ip,
data->info.primary.local_port,
data->info.primary.remote_port);
#ifdef USE_UNIX_SOCKETS
}
#endif /* USE_UNIX_SOCKETS */
return result;
}
static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
{
struct cf_haproxy_ctx *ctx = cf->ctx;
CURLcode result;
size_t len;
DEBUGASSERT(ctx);
if(cf->connected) {
*done = TRUE;
return CURLE_OK;
}
result = cf->next->cft->do_connect(cf->next, data, blocking, done);
if(result || !*done)
return result;
switch(ctx->state) {
case HAPROXY_INIT:
result = cf_haproxy_date_out_set(cf, data);
if(result)
goto out;
ctx->state = HAPROXY_SEND;
FALLTHROUGH();
case HAPROXY_SEND:
len = Curl_dyn_len(&ctx->data_out);
if(len > 0) {
size_t written;
result = Curl_conn_send(data, cf->sockindex,
Curl_dyn_ptr(&ctx->data_out),
len, &written);
if(result == CURLE_AGAIN) {
result = CURLE_OK;
written = 0;
}
else if(result)
goto out;
Curl_dyn_tail(&ctx->data_out, len - written);
if(Curl_dyn_len(&ctx->data_out) > 0) {
result = CURLE_OK;
goto out;
}
}
ctx->state = HAPROXY_DONE;
FALLTHROUGH();
default:
Curl_dyn_free(&ctx->data_out);
break;
}
out:
*done = (!result) && (ctx->state == HAPROXY_DONE);
cf->connected = *done;
return result;
}
static void cf_haproxy_destroy(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
(void)data;
CURL_TRC_CF(data, cf, "destroy");
cf_haproxy_ctx_free(cf->ctx);
}
static void cf_haproxy_close(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
CURL_TRC_CF(data, cf, "close");
cf->connected = FALSE;
cf_haproxy_ctx_reset(cf->ctx);
if(cf->next)
cf->next->cft->do_close(cf->next, data);
}
static void cf_haproxy_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps)
{
if(cf->next->connected && !cf->connected) {
/* If we are not connected, but the filter "below" is
* and not waiting on something, we are sending. */
Curl_pollset_set_out_only(data, ps, Curl_conn_cf_get_socket(cf, data));
}
}
struct Curl_cftype Curl_cft_haproxy = {
"HAPROXY",
CF_TYPE_PROXY,
0,
cf_haproxy_destroy,
cf_haproxy_connect,
cf_haproxy_close,
Curl_cf_def_get_host,
cf_haproxy_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
Curl_cf_def_cntrl,
Curl_cf_def_conn_is_alive,
Curl_cf_def_conn_keep_alive,
Curl_cf_def_query,
};
static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf,
struct Curl_easy *data)
{
struct Curl_cfilter *cf = NULL;
struct cf_haproxy_ctx *ctx;
CURLcode result;
(void)data;
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
ctx->state = HAPROXY_INIT;
Curl_dyn_init(&ctx->data_out, DYN_HAXPROXY);
result = Curl_cf_create(&cf, &Curl_cft_haproxy, ctx);
if(result)
goto out;
ctx = NULL;
out:
cf_haproxy_ctx_free(ctx);
*pcf = result? NULL : cf;
return result;
}
CURLcode Curl_cf_haproxy_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data)
{
struct Curl_cfilter *cf;
CURLcode result;
result = cf_haproxy_create(&cf, data);
if(result)
goto out;
Curl_conn_cf_insert_after(cf_at, cf);
out:
return result;
}
#endif /* !CURL_DISABLE_PROXY */

39
third_party/curl/lib/cf-haproxy.h vendored Normal file
View File

@ -0,0 +1,39 @@
#ifndef HEADER_CURL_CF_HAPROXY_H
#define HEADER_CURL_CF_HAPROXY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#if !defined(CURL_DISABLE_PROXY)
CURLcode Curl_cf_haproxy_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data);
extern struct Curl_cftype Curl_cft_haproxy;
#endif /* !CURL_DISABLE_PROXY */
#endif /* HEADER_CURL_CF_HAPROXY_H */

531
third_party/curl/lib/cf-https-connect.c vendored Normal file
View File

@ -0,0 +1,531 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
#include "urldata.h"
#include <curl/curl.h>
#include "curl_trc.h"
#include "cfilters.h"
#include "connect.h"
#include "multiif.h"
#include "cf-https-connect.h"
#include "http2.h"
#include "vquic/vquic.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
typedef enum {
CF_HC_INIT,
CF_HC_CONNECT,
CF_HC_SUCCESS,
CF_HC_FAILURE
} cf_hc_state;
struct cf_hc_baller {
const char *name;
struct Curl_cfilter *cf;
CURLcode result;
struct curltime started;
int reply_ms;
bool enabled;
};
static void cf_hc_baller_reset(struct cf_hc_baller *b,
struct Curl_easy *data)
{
if(b->cf) {
Curl_conn_cf_close(b->cf, data);
Curl_conn_cf_discard_chain(&b->cf, data);
b->cf = NULL;
}
b->result = CURLE_OK;
b->reply_ms = -1;
}
static bool cf_hc_baller_is_active(struct cf_hc_baller *b)
{
return b->enabled && b->cf && !b->result;
}
static bool cf_hc_baller_has_started(struct cf_hc_baller *b)
{
return !!b->cf;
}
static int cf_hc_baller_reply_ms(struct cf_hc_baller *b,
struct Curl_easy *data)
{
if(b->reply_ms < 0)
b->cf->cft->query(b->cf, data, CF_QUERY_CONNECT_REPLY_MS,
&b->reply_ms, NULL);
return b->reply_ms;
}
static bool cf_hc_baller_data_pending(struct cf_hc_baller *b,
const struct Curl_easy *data)
{
return b->cf && !b->result && b->cf->cft->has_data_pending(b->cf, data);
}
struct cf_hc_ctx {
cf_hc_state state;
const struct Curl_dns_entry *remotehost;
struct curltime started; /* when connect started */
CURLcode result; /* overall result */
struct cf_hc_baller h3_baller;
struct cf_hc_baller h21_baller;
unsigned int soft_eyeballs_timeout_ms;
unsigned int hard_eyeballs_timeout_ms;
};
static void cf_hc_baller_init(struct cf_hc_baller *b,
struct Curl_cfilter *cf,
struct Curl_easy *data,
const char *name,
int transport)
{
struct cf_hc_ctx *ctx = cf->ctx;
struct Curl_cfilter *save = cf->next;
b->name = name;
cf->next = NULL;
b->started = Curl_now();
b->result = Curl_cf_setup_insert_after(cf, data, ctx->remotehost,
transport, CURL_CF_SSL_ENABLE);
b->cf = cf->next;
cf->next = save;
}
static CURLcode cf_hc_baller_connect(struct cf_hc_baller *b,
struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *done)
{
struct Curl_cfilter *save = cf->next;
cf->next = b->cf;
b->result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
b->cf = cf->next; /* it might mutate */
cf->next = save;
return b->result;
}
static void cf_hc_reset(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_hc_ctx *ctx = cf->ctx;
if(ctx) {
cf_hc_baller_reset(&ctx->h3_baller, data);
cf_hc_baller_reset(&ctx->h21_baller, data);
ctx->state = CF_HC_INIT;
ctx->result = CURLE_OK;
ctx->hard_eyeballs_timeout_ms = data->set.happy_eyeballs_timeout;
ctx->soft_eyeballs_timeout_ms = data->set.happy_eyeballs_timeout / 2;
}
}
static CURLcode baller_connected(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct cf_hc_baller *winner)
{
struct cf_hc_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
DEBUGASSERT(winner->cf);
if(winner != &ctx->h3_baller)
cf_hc_baller_reset(&ctx->h3_baller, data);
if(winner != &ctx->h21_baller)
cf_hc_baller_reset(&ctx->h21_baller, data);
CURL_TRC_CF(data, cf, "connect+handshake %s: %dms, 1st data: %dms",
winner->name, (int)Curl_timediff(Curl_now(), winner->started),
cf_hc_baller_reply_ms(winner, data));
cf->next = winner->cf;
winner->cf = NULL;
switch(cf->conn->alpn) {
case CURL_HTTP_VERSION_3:
infof(data, "using HTTP/3");
break;
case CURL_HTTP_VERSION_2:
#ifdef USE_NGHTTP2
/* Using nghttp2, we add the filter "below" us, so when the conn
* closes, we tear it down for a fresh reconnect */
result = Curl_http2_switch_at(cf, data);
if(result) {
ctx->state = CF_HC_FAILURE;
ctx->result = result;
return result;
}
#endif
infof(data, "using HTTP/2");
break;
default:
infof(data, "using HTTP/1.x");
break;
}
ctx->state = CF_HC_SUCCESS;
cf->connected = TRUE;
Curl_conn_cf_cntrl(cf->next, data, TRUE,
CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
return result;
}
static bool time_to_start_h21(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct curltime now)
{
struct cf_hc_ctx *ctx = cf->ctx;
timediff_t elapsed_ms;
if(!ctx->h21_baller.enabled || cf_hc_baller_has_started(&ctx->h21_baller))
return FALSE;
if(!ctx->h3_baller.enabled || !cf_hc_baller_is_active(&ctx->h3_baller))
return TRUE;
elapsed_ms = Curl_timediff(now, ctx->started);
if(elapsed_ms >= ctx->hard_eyeballs_timeout_ms) {
CURL_TRC_CF(data, cf, "hard timeout of %dms reached, starting h21",
ctx->hard_eyeballs_timeout_ms);
return TRUE;
}
if(elapsed_ms >= ctx->soft_eyeballs_timeout_ms) {
if(cf_hc_baller_reply_ms(&ctx->h3_baller, data) < 0) {
CURL_TRC_CF(data, cf, "soft timeout of %dms reached, h3 has not "
"seen any data, starting h21",
ctx->soft_eyeballs_timeout_ms);
return TRUE;
}
/* set the effective hard timeout again */
Curl_expire(data, ctx->hard_eyeballs_timeout_ms - elapsed_ms,
EXPIRE_ALPN_EYEBALLS);
}
return FALSE;
}
static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
{
struct cf_hc_ctx *ctx = cf->ctx;
struct curltime now;
CURLcode result = CURLE_OK;
(void)blocking;
if(cf->connected) {
*done = TRUE;
return CURLE_OK;
}
*done = FALSE;
now = Curl_now();
switch(ctx->state) {
case CF_HC_INIT:
DEBUGASSERT(!ctx->h3_baller.cf);
DEBUGASSERT(!ctx->h21_baller.cf);
DEBUGASSERT(!cf->next);
CURL_TRC_CF(data, cf, "connect, init");
ctx->started = now;
if(ctx->h3_baller.enabled) {
cf_hc_baller_init(&ctx->h3_baller, cf, data, "h3", TRNSPRT_QUIC);
if(ctx->h21_baller.enabled)
Curl_expire(data, ctx->soft_eyeballs_timeout_ms, EXPIRE_ALPN_EYEBALLS);
}
else if(ctx->h21_baller.enabled)
cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
cf->conn->transport);
ctx->state = CF_HC_CONNECT;
FALLTHROUGH();
case CF_HC_CONNECT:
if(cf_hc_baller_is_active(&ctx->h3_baller)) {
result = cf_hc_baller_connect(&ctx->h3_baller, cf, data, done);
if(!result && *done) {
result = baller_connected(cf, data, &ctx->h3_baller);
goto out;
}
}
if(time_to_start_h21(cf, data, now)) {
cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
cf->conn->transport);
}
if(cf_hc_baller_is_active(&ctx->h21_baller)) {
CURL_TRC_CF(data, cf, "connect, check h21");
result = cf_hc_baller_connect(&ctx->h21_baller, cf, data, done);
if(!result && *done) {
result = baller_connected(cf, data, &ctx->h21_baller);
goto out;
}
}
if((!ctx->h3_baller.enabled || ctx->h3_baller.result) &&
(!ctx->h21_baller.enabled || ctx->h21_baller.result)) {
/* both failed or disabled. we give up */
CURL_TRC_CF(data, cf, "connect, all failed");
result = ctx->result = ctx->h3_baller.enabled?
ctx->h3_baller.result : ctx->h21_baller.result;
ctx->state = CF_HC_FAILURE;
goto out;
}
result = CURLE_OK;
*done = FALSE;
break;
case CF_HC_FAILURE:
result = ctx->result;
cf->connected = FALSE;
*done = FALSE;
break;
case CF_HC_SUCCESS:
result = CURLE_OK;
cf->connected = TRUE;
*done = TRUE;
break;
}
out:
CURL_TRC_CF(data, cf, "connect -> %d, done=%d", result, *done);
return result;
}
static void cf_hc_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps)
{
if(!cf->connected) {
struct cf_hc_ctx *ctx = cf->ctx;
struct cf_hc_baller *ballers[2];
size_t i;
ballers[0] = &ctx->h3_baller;
ballers[1] = &ctx->h21_baller;
for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
struct cf_hc_baller *b = ballers[i];
if(!cf_hc_baller_is_active(b))
continue;
Curl_conn_cf_adjust_pollset(b->cf, data, ps);
}
CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
}
}
static bool cf_hc_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
struct cf_hc_ctx *ctx = cf->ctx;
if(cf->connected)
return cf->next->cft->has_data_pending(cf->next, data);
CURL_TRC_CF((struct Curl_easy *)data, cf, "data_pending");
return cf_hc_baller_data_pending(&ctx->h3_baller, data)
|| cf_hc_baller_data_pending(&ctx->h21_baller, data);
}
static struct curltime cf_get_max_baller_time(struct Curl_cfilter *cf,
struct Curl_easy *data,
int query)
{
struct cf_hc_ctx *ctx = cf->ctx;
struct Curl_cfilter *cfb;
struct curltime t, tmax;
memset(&tmax, 0, sizeof(tmax));
memset(&t, 0, sizeof(t));
cfb = ctx->h21_baller.enabled? ctx->h21_baller.cf : NULL;
if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
tmax = t;
}
memset(&t, 0, sizeof(t));
cfb = ctx->h3_baller.enabled? ctx->h3_baller.cf : NULL;
if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
tmax = t;
}
return tmax;
}
static CURLcode cf_hc_query(struct Curl_cfilter *cf,
struct Curl_easy *data,
int query, int *pres1, void *pres2)
{
if(!cf->connected) {
switch(query) {
case CF_QUERY_TIMER_CONNECT: {
struct curltime *when = pres2;
*when = cf_get_max_baller_time(cf, data, CF_QUERY_TIMER_CONNECT);
return CURLE_OK;
}
case CF_QUERY_TIMER_APPCONNECT: {
struct curltime *when = pres2;
*when = cf_get_max_baller_time(cf, data, CF_QUERY_TIMER_APPCONNECT);
return CURLE_OK;
}
default:
break;
}
}
return cf->next?
cf->next->cft->query(cf->next, data, query, pres1, pres2) :
CURLE_UNKNOWN_OPTION;
}
static void cf_hc_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
CURL_TRC_CF(data, cf, "close");
cf_hc_reset(cf, data);
cf->connected = FALSE;
if(cf->next) {
cf->next->cft->do_close(cf->next, data);
Curl_conn_cf_discard_chain(&cf->next, data);
}
}
static void cf_hc_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_hc_ctx *ctx = cf->ctx;
(void)data;
CURL_TRC_CF(data, cf, "destroy");
cf_hc_reset(cf, data);
Curl_safefree(ctx);
}
struct Curl_cftype Curl_cft_http_connect = {
"HTTPS-CONNECT",
0,
CURL_LOG_LVL_NONE,
cf_hc_destroy,
cf_hc_connect,
cf_hc_close,
Curl_cf_def_get_host,
cf_hc_adjust_pollset,
cf_hc_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
Curl_cf_def_cntrl,
Curl_cf_def_conn_is_alive,
Curl_cf_def_conn_keep_alive,
cf_hc_query,
};
static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost,
bool try_h3, bool try_h21)
{
struct Curl_cfilter *cf = NULL;
struct cf_hc_ctx *ctx;
CURLcode result = CURLE_OK;
(void)data;
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
ctx->remotehost = remotehost;
ctx->h3_baller.enabled = try_h3;
ctx->h21_baller.enabled = try_h21;
result = Curl_cf_create(&cf, &Curl_cft_http_connect, ctx);
if(result)
goto out;
ctx = NULL;
cf_hc_reset(cf, data);
out:
*pcf = result? NULL : cf;
free(ctx);
return result;
}
static CURLcode cf_http_connect_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost,
bool try_h3, bool try_h21)
{
struct Curl_cfilter *cf;
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
result = cf_hc_create(&cf, data, remotehost, try_h3, try_h21);
if(result)
goto out;
Curl_conn_cf_add(data, conn, sockindex, cf);
out:
return result;
}
CURLcode Curl_cf_https_setup(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost)
{
bool try_h3 = FALSE, try_h21 = TRUE; /* defaults, for now */
CURLcode result = CURLE_OK;
(void)sockindex;
(void)remotehost;
if(!conn->bits.tls_enable_alpn)
goto out;
if(data->state.httpwant == CURL_HTTP_VERSION_3ONLY) {
result = Curl_conn_may_http3(data, conn);
if(result) /* can't do it */
goto out;
try_h3 = TRUE;
try_h21 = FALSE;
}
else if(data->state.httpwant >= CURL_HTTP_VERSION_3) {
/* We assume that silently not even trying H3 is ok here */
/* TODO: should we fail instead? */
try_h3 = (Curl_conn_may_http3(data, conn) == CURLE_OK);
try_h21 = TRUE;
}
result = cf_http_connect_add(data, conn, sockindex, remotehost,
try_h3, try_h21);
out:
return result;
}
#endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */

58
third_party/curl/lib/cf-https-connect.h vendored Normal file
View File

@ -0,0 +1,58 @@
#ifndef HEADER_CURL_CF_HTTP_H
#define HEADER_CURL_CF_HTTP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
struct Curl_cfilter;
struct Curl_easy;
struct connectdata;
struct Curl_cftype;
struct Curl_dns_entry;
extern struct Curl_cftype Curl_cft_http_connect;
CURLcode Curl_cf_http_connect_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost,
bool try_h3, bool try_h21);
CURLcode
Curl_cf_http_connect_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost,
bool try_h3, bool try_h21);
CURLcode Curl_cf_https_setup(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost);
#endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */
#endif /* HEADER_CURL_CF_HTTP_H */

1963
third_party/curl/lib/cf-socket.c vendored Normal file

File diff suppressed because it is too large Load Diff

171
third_party/curl/lib/cf-socket.h vendored Normal file
View File

@ -0,0 +1,171 @@
#ifndef HEADER_CURL_CF_SOCKET_H
#define HEADER_CURL_CF_SOCKET_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */
#include "sockaddr.h"
struct Curl_addrinfo;
struct Curl_cfilter;
struct Curl_easy;
struct connectdata;
struct Curl_sockaddr_ex;
struct ip_quadruple;
/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
* curl_sockaddr structure with enough space available to directly hold any
* protocol-specific address structures. The variable declared here will be
* used to pass / receive data to/from the fopensocket callback if this has
* been set, before that, it is initialized from parameters.
*/
struct Curl_sockaddr_ex {
int family;
int socktype;
int protocol;
unsigned int addrlen;
union {
struct sockaddr addr;
struct Curl_sockaddr_storage buff;
} _sa_ex_u;
};
#define sa_addr _sa_ex_u.addr
/*
* Create a socket based on info from 'conn' and 'ai'.
*
* Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open
* socket callback is set, used that!
*
*/
CURLcode Curl_socket_open(struct Curl_easy *data,
const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
int transport,
curl_socket_t *sockfd);
int Curl_socket_close(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t sock);
#ifdef USE_WINSOCK
/* When you run a program that uses the Windows Sockets API, you may
experience slow performance when you copy data to a TCP server.
https://support.microsoft.com/kb/823764
Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
Buffer Size
*/
void Curl_sndbufset(curl_socket_t sockfd);
#else
#define Curl_sndbufset(y) Curl_nop_stmt
#endif
/**
* Assign the address `ai` to the Curl_sockaddr_ex `dest` and
* set the transport used.
*/
void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
const struct Curl_addrinfo *ai,
int transport);
/**
* Creates a cfilter that opens a TCP socket to the given address
* when calling its `connect` implementation.
* The filter will not touch any connection/data flags and can be
* used in happy eyeballing. Once selected for use, its `_active()`
* method needs to be called.
*/
CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport);
/**
* Creates a cfilter that opens a UDP socket to the given address
* when calling its `connect` implementation.
* The filter will not touch any connection/data flags and can be
* used in happy eyeballing. Once selected for use, its `_active()`
* method needs to be called.
*/
CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport);
/**
* Creates a cfilter that opens a UNIX socket to the given address
* when calling its `connect` implementation.
* The filter will not touch any connection/data flags and can be
* used in happy eyeballing. Once selected for use, its `_active()`
* method needs to be called.
*/
CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport);
/**
* Creates a cfilter that keeps a listening socket.
*/
CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
curl_socket_t *s);
/**
* Replace the listen socket with the accept()ed one.
*/
CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
curl_socket_t *s);
/**
* Peek at the socket and remote ip/port the socket filter is using.
* The filter owns all returned values.
* @param psock pointer to hold socket descriptor or NULL
* @param paddr pointer to hold addr reference or NULL
* @param pip pointer to get IP quadruple or NULL
* Returns error if the filter is of invalid type.
*/
CURLcode Curl_cf_socket_peek(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *psock,
const struct Curl_sockaddr_ex **paddr,
struct ip_quadruple *pip);
extern struct Curl_cftype Curl_cft_tcp;
extern struct Curl_cftype Curl_cft_udp;
extern struct Curl_cftype Curl_cft_unix;
extern struct Curl_cftype Curl_cft_tcp_accept;
#endif /* HEADER_CURL_CF_SOCKET_H */

861
third_party/curl/lib/cfilters.c vendored Normal file
View File

@ -0,0 +1,861 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#include "strerror.h"
#include "cfilters.h"
#include "connect.h"
#include "url.h" /* for Curl_safefree() */
#include "sendf.h"
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h"
#include "progress.h"
#include "select.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
#ifdef DEBUGBUILD
/* used by unit2600.c */
void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
cf->connected = FALSE;
if(cf->next)
cf->next->cft->do_close(cf->next, data);
}
#endif
static void conn_report_connect_stats(struct Curl_easy *data,
struct connectdata *conn);
void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
const char **phost, const char **pdisplay_host,
int *pport)
{
if(cf->next)
cf->next->cft->get_host(cf->next, data, phost, pdisplay_host, pport);
else {
*phost = cf->conn->host.name;
*pdisplay_host = cf->conn->host.dispname;
*pport = cf->conn->primary.remote_port;
}
}
void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps)
{
/* NOP */
(void)cf;
(void)data;
(void)ps;
}
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
return cf->next?
cf->next->cft->has_data_pending(cf->next, data) : FALSE;
}
ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
return cf->next?
cf->next->cft->do_send(cf->next, data, buf, len, err) :
CURLE_RECV_ERROR;
}
ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err)
{
return cf->next?
cf->next->cft->do_recv(cf->next, data, buf, len, err) :
CURLE_SEND_ERROR;
}
bool Curl_cf_def_conn_is_alive(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *input_pending)
{
return cf->next?
cf->next->cft->is_alive(cf->next, data, input_pending) :
FALSE; /* pessimistic in absence of data */
}
CURLcode Curl_cf_def_conn_keep_alive(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
return cf->next?
cf->next->cft->keep_alive(cf->next, data) :
CURLE_OK;
}
CURLcode Curl_cf_def_query(struct Curl_cfilter *cf,
struct Curl_easy *data,
int query, int *pres1, void *pres2)
{
return cf->next?
cf->next->cft->query(cf->next, data, query, pres1, pres2) :
CURLE_UNKNOWN_OPTION;
}
void Curl_conn_cf_discard_chain(struct Curl_cfilter **pcf,
struct Curl_easy *data)
{
struct Curl_cfilter *cfn, *cf = *pcf;
if(cf) {
*pcf = NULL;
while(cf) {
cfn = cf->next;
/* prevent destroying filter to mess with its sub-chain, since
* we have the reference now and will call destroy on it.
*/
cf->next = NULL;
cf->cft->destroy(cf, data);
free(cf);
cf = cfn;
}
}
}
void Curl_conn_cf_discard_all(struct Curl_easy *data,
struct connectdata *conn, int index)
{
Curl_conn_cf_discard_chain(&conn->cfilter[index], data);
}
void Curl_conn_close(struct Curl_easy *data, int index)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data->conn);
/* it is valid to call that without filters being present */
cf = data->conn->cfilter[index];
if(cf) {
cf->cft->do_close(cf, data);
}
}
ssize_t Curl_cf_recv(struct Curl_easy *data, int num, char *buf,
size_t len, CURLcode *code)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
*code = CURLE_OK;
cf = data->conn->cfilter[num];
while(cf && !cf->connected) {
cf = cf->next;
}
if(cf) {
ssize_t nread = cf->cft->do_recv(cf, data, buf, len, code);
DEBUGASSERT(nread >= 0 || *code);
DEBUGASSERT(nread < 0 || !*code);
return nread;
}
failf(data, "recv: no filter connected");
*code = CURLE_FAILED_INIT;
return -1;
}
ssize_t Curl_cf_send(struct Curl_easy *data, int num,
const void *mem, size_t len, CURLcode *code)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
*code = CURLE_OK;
cf = data->conn->cfilter[num];
while(cf && !cf->connected) {
cf = cf->next;
}
if(cf) {
ssize_t nwritten = cf->cft->do_send(cf, data, mem, len, code);
DEBUGASSERT(nwritten >= 0 || *code);
DEBUGASSERT(nwritten < 0 || !*code || !len);
return nwritten;
}
failf(data, "send: no filter connected");
DEBUGASSERT(0);
*code = CURLE_FAILED_INIT;
return -1;
}
CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
const struct Curl_cftype *cft,
void *ctx)
{
struct Curl_cfilter *cf;
CURLcode result = CURLE_OUT_OF_MEMORY;
DEBUGASSERT(cft);
cf = calloc(1, sizeof(*cf));
if(!cf)
goto out;
cf->cft = cft;
cf->ctx = ctx;
result = CURLE_OK;
out:
*pcf = cf;
return result;
}
void Curl_conn_cf_add(struct Curl_easy *data,
struct connectdata *conn,
int index,
struct Curl_cfilter *cf)
{
(void)data;
DEBUGASSERT(conn);
DEBUGASSERT(!cf->conn);
DEBUGASSERT(!cf->next);
cf->next = conn->cfilter[index];
cf->conn = conn;
cf->sockindex = index;
conn->cfilter[index] = cf;
CURL_TRC_CF(data, cf, "added");
}
void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
struct Curl_cfilter *cf_new)
{
struct Curl_cfilter *tail, **pnext;
DEBUGASSERT(cf_at);
DEBUGASSERT(cf_new);
DEBUGASSERT(!cf_new->conn);
tail = cf_at->next;
cf_at->next = cf_new;
do {
cf_new->conn = cf_at->conn;
cf_new->sockindex = cf_at->sockindex;
pnext = &cf_new->next;
cf_new = cf_new->next;
} while(cf_new);
*pnext = tail;
}
bool Curl_conn_cf_discard_sub(struct Curl_cfilter *cf,
struct Curl_cfilter *discard,
struct Curl_easy *data,
bool destroy_always)
{
struct Curl_cfilter **pprev = &cf->next;
bool found = FALSE;
/* remove from sub-chain and destroy */
DEBUGASSERT(cf);
while(*pprev) {
if(*pprev == cf) {
*pprev = discard->next;
discard->next = NULL;
found = TRUE;
break;
}
pprev = &((*pprev)->next);
}
if(found || destroy_always) {
discard->next = NULL;
discard->cft->destroy(discard, data);
free(discard);
}
return found;
}
CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
{
if(cf)
return cf->cft->do_connect(cf, data, blocking, done);
return CURLE_FAILED_INIT;
}
void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
if(cf)
cf->cft->do_close(cf, data);
}
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
if(cf)
return cf->cft->do_send(cf, data, buf, len, err);
*err = CURLE_SEND_ERROR;
return -1;
}
ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err)
{
if(cf)
return cf->cft->do_recv(cf, data, buf, len, err);
*err = CURLE_RECV_ERROR;
return -1;
}
CURLcode Curl_conn_connect(struct Curl_easy *data,
int sockindex,
bool blocking,
bool *done)
{
struct Curl_cfilter *cf;
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[sockindex];
DEBUGASSERT(cf);
if(!cf)
return CURLE_FAILED_INIT;
*done = cf->connected;
if(!*done) {
result = cf->cft->do_connect(cf, data, blocking, done);
if(!result && *done) {
Curl_conn_ev_update_info(data, data->conn);
conn_report_connect_stats(data, data->conn);
data->conn->keepalive = Curl_now();
}
else if(result) {
conn_report_connect_stats(data, data->conn);
}
}
return result;
}
bool Curl_conn_is_connected(struct connectdata *conn, int sockindex)
{
struct Curl_cfilter *cf;
cf = conn->cfilter[sockindex];
return cf && cf->connected;
}
bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex)
{
struct Curl_cfilter *cf;
cf = data->conn->cfilter[sockindex];
while(cf) {
if(cf->connected)
return TRUE;
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
return FALSE;
cf = cf->next;
}
return FALSE;
}
bool Curl_conn_cf_is_ssl(struct Curl_cfilter *cf)
{
for(; cf; cf = cf->next) {
if(cf->cft->flags & CF_TYPE_SSL)
return TRUE;
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
return FALSE;
}
return FALSE;
}
bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex)
{
return conn? Curl_conn_cf_is_ssl(conn->cfilter[sockindex]) : FALSE;
}
bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex)
{
struct Curl_cfilter *cf = conn? conn->cfilter[sockindex] : NULL;
for(; cf; cf = cf->next) {
if(cf->cft->flags & CF_TYPE_MULTIPLEX)
return TRUE;
if(cf->cft->flags & CF_TYPE_IP_CONNECT
|| cf->cft->flags & CF_TYPE_SSL)
return FALSE;
}
return FALSE;
}
bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
{
struct Curl_cfilter *cf;
(void)data;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[sockindex];
while(cf && !cf->connected) {
cf = cf->next;
}
if(cf) {
return cf->cft->has_data_pending(cf, data);
}
return FALSE;
}
void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps)
{
/* Get the lowest not-connected filter, if there are any */
while(cf && !cf->connected && cf->next && !cf->next->connected)
cf = cf->next;
/* From there on, give all filters a chance to adjust the pollset.
* Lower filters are called later, so they may override */
while(cf) {
cf->cft->adjust_pollset(cf, data, ps);
cf = cf->next;
}
}
void Curl_conn_adjust_pollset(struct Curl_easy *data,
struct easy_pollset *ps)
{
int i;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
for(i = 0; i < 2; ++i) {
Curl_conn_cf_adjust_pollset(data->conn->cfilter[i], data, ps);
}
}
void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
const char **phost, const char **pdisplay_host,
int *pport)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[sockindex];
if(cf) {
cf->cft->get_host(cf, data, phost, pdisplay_host, pport);
}
else {
/* Some filter ask during shutdown for this, mainly for debugging
* purposes. We hand out the defaults, however this is not always
* accurate, as the connection might be tunneled, etc. But all that
* state is already gone here. */
*phost = data->conn->host.name;
*pdisplay_host = data->conn->host.dispname;
*pport = data->conn->remote_port;
}
}
CURLcode Curl_cf_def_cntrl(struct Curl_cfilter *cf,
struct Curl_easy *data,
int event, int arg1, void *arg2)
{
(void)cf;
(void)data;
(void)event;
(void)arg1;
(void)arg2;
return CURLE_OK;
}
CURLcode Curl_conn_cf_cntrl(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool ignore_result,
int event, int arg1, void *arg2)
{
CURLcode result = CURLE_OK;
for(; cf; cf = cf->next) {
if(Curl_cf_def_cntrl == cf->cft->cntrl)
continue;
result = cf->cft->cntrl(cf, data, event, arg1, arg2);
if(!ignore_result && result)
break;
}
return result;
}
curl_socket_t Curl_conn_cf_get_socket(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
curl_socket_t sock;
if(cf && !cf->cft->query(cf, data, CF_QUERY_SOCKET, NULL, &sock))
return sock;
return CURL_SOCKET_BAD;
}
curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex)
{
struct Curl_cfilter *cf;
cf = data->conn? data->conn->cfilter[sockindex] : NULL;
/* if the top filter has not connected, ask it (and its sub-filters)
* for the socket. Otherwise conn->sock[sockindex] should have it.
*/
if(cf && !cf->connected)
return Curl_conn_cf_get_socket(cf, data);
return data->conn? data->conn->sock[sockindex] : CURL_SOCKET_BAD;
}
void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex)
{
if(data->conn) {
struct Curl_cfilter *cf = data->conn->cfilter[sockindex];
if(cf)
(void)Curl_conn_cf_cntrl(cf, data, TRUE,
CF_CTRL_FORGET_SOCKET, 0, NULL);
fake_sclose(data->conn->sock[sockindex]);
data->conn->sock[sockindex] = CURL_SOCKET_BAD;
}
}
static CURLcode cf_cntrl_all(struct connectdata *conn,
struct Curl_easy *data,
bool ignore_result,
int event, int arg1, void *arg2)
{
CURLcode result = CURLE_OK;
size_t i;
for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
result = Curl_conn_cf_cntrl(conn->cfilter[i], data, ignore_result,
event, arg1, arg2);
if(!ignore_result && result)
break;
}
return result;
}
void Curl_conn_ev_data_attach(struct connectdata *conn,
struct Curl_easy *data)
{
cf_cntrl_all(conn, data, TRUE, CF_CTRL_DATA_ATTACH, 0, NULL);
}
void Curl_conn_ev_data_detach(struct connectdata *conn,
struct Curl_easy *data)
{
cf_cntrl_all(conn, data, TRUE, CF_CTRL_DATA_DETACH, 0, NULL);
}
CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data)
{
return cf_cntrl_all(data->conn, data, FALSE,
CF_CTRL_DATA_SETUP, 0, NULL);
}
CURLcode Curl_conn_ev_data_idle(struct Curl_easy *data)
{
return cf_cntrl_all(data->conn, data, FALSE,
CF_CTRL_DATA_IDLE, 0, NULL);
}
/**
* Notify connection filters that the transfer represented by `data`
* is done with sending data (e.g. has uploaded everything).
*/
void Curl_conn_ev_data_done_send(struct Curl_easy *data)
{
cf_cntrl_all(data->conn, data, TRUE, CF_CTRL_DATA_DONE_SEND, 0, NULL);
}
/**
* Notify connection filters that the transfer represented by `data`
* is finished - eventually premature, e.g. before being complete.
*/
void Curl_conn_ev_data_done(struct Curl_easy *data, bool premature)
{
cf_cntrl_all(data->conn, data, TRUE, CF_CTRL_DATA_DONE, premature, NULL);
}
CURLcode Curl_conn_ev_data_pause(struct Curl_easy *data, bool do_pause)
{
return cf_cntrl_all(data->conn, data, FALSE,
CF_CTRL_DATA_PAUSE, do_pause, NULL);
}
void Curl_conn_ev_update_info(struct Curl_easy *data,
struct connectdata *conn)
{
cf_cntrl_all(conn, data, TRUE, CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
}
/**
* Update connection statistics
*/
static void conn_report_connect_stats(struct Curl_easy *data,
struct connectdata *conn)
{
struct Curl_cfilter *cf = conn->cfilter[FIRSTSOCKET];
if(cf) {
struct curltime connected;
struct curltime appconnected;
memset(&connected, 0, sizeof(connected));
cf->cft->query(cf, data, CF_QUERY_TIMER_CONNECT, NULL, &connected);
if(connected.tv_sec || connected.tv_usec)
Curl_pgrsTimeWas(data, TIMER_CONNECT, connected);
memset(&appconnected, 0, sizeof(appconnected));
cf->cft->query(cf, data, CF_QUERY_TIMER_APPCONNECT, NULL, &appconnected);
if(appconnected.tv_sec || appconnected.tv_usec)
Curl_pgrsTimeWas(data, TIMER_APPCONNECT, appconnected);
}
}
bool Curl_conn_is_alive(struct Curl_easy *data, struct connectdata *conn,
bool *input_pending)
{
struct Curl_cfilter *cf = conn->cfilter[FIRSTSOCKET];
return cf && !cf->conn->bits.close &&
cf->cft->is_alive(cf, data, input_pending);
}
CURLcode Curl_conn_keep_alive(struct Curl_easy *data,
struct connectdata *conn,
int sockindex)
{
struct Curl_cfilter *cf = conn->cfilter[sockindex];
return cf? cf->cft->keep_alive(cf, data) : CURLE_OK;
}
size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
struct connectdata *conn,
int sockindex)
{
CURLcode result;
int n = 0;
struct Curl_cfilter *cf = conn->cfilter[sockindex];
result = cf? cf->cft->query(cf, data, CF_QUERY_MAX_CONCURRENT,
&n, NULL) : CURLE_UNKNOWN_OPTION;
return (result || n <= 0)? 1 : (size_t)n;
}
int Curl_conn_get_stream_error(struct Curl_easy *data,
struct connectdata *conn,
int sockindex)
{
CURLcode result;
int n = 0;
struct Curl_cfilter *cf = conn->cfilter[sockindex];
result = cf? cf->cft->query(cf, data, CF_QUERY_STREAM_ERROR,
&n, NULL) : CURLE_UNKNOWN_OPTION;
return (result || n < 0)? 0 : n;
}
int Curl_conn_sockindex(struct Curl_easy *data, curl_socket_t sockfd)
{
if(data && data->conn &&
sockfd != CURL_SOCKET_BAD && sockfd == data->conn->sock[SECONDARYSOCKET])
return SECONDARYSOCKET;
return FIRSTSOCKET;
}
CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
char *buf, size_t blen, ssize_t *n)
{
CURLcode result = CURLE_OK;
ssize_t nread;
DEBUGASSERT(data->conn);
nread = data->conn->recv[sockindex](data, sockindex, buf, blen, &result);
DEBUGASSERT(nread >= 0 || result);
DEBUGASSERT(nread < 0 || !result);
*n = (nread >= 0)? (size_t)nread : 0;
return result;
}
CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t blen,
size_t *pnwritten)
{
ssize_t nwritten;
CURLcode result = CURLE_OK;
struct connectdata *conn;
DEBUGASSERT(sockindex >= 0 && sockindex < 2);
DEBUGASSERT(pnwritten);
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
conn = data->conn;
#ifdef CURLDEBUG
{
/* Allow debug builds to override this logic to force short sends
*/
char *p = getenv("CURL_SMALLSENDS");
if(p) {
size_t altsize = (size_t)strtoul(p, NULL, 10);
if(altsize)
blen = CURLMIN(blen, altsize);
}
}
#endif
nwritten = conn->send[sockindex](data, sockindex, buf, blen, &result);
DEBUGASSERT((nwritten >= 0) || result);
*pnwritten = (nwritten < 0)? 0 : (size_t)nwritten;
return result;
}
void Curl_pollset_reset(struct Curl_easy *data,
struct easy_pollset *ps)
{
size_t i;
(void)data;
memset(ps, 0, sizeof(*ps));
for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
ps->sockets[i] = CURL_SOCKET_BAD;
}
/**
*
*/
void Curl_pollset_change(struct Curl_easy *data,
struct easy_pollset *ps, curl_socket_t sock,
int add_flags, int remove_flags)
{
unsigned int i;
(void)data;
DEBUGASSERT(VALID_SOCK(sock));
if(!VALID_SOCK(sock))
return;
DEBUGASSERT(add_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
DEBUGASSERT(remove_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
DEBUGASSERT((add_flags&remove_flags) == 0); /* no overlap */
for(i = 0; i < ps->num; ++i) {
if(ps->sockets[i] == sock) {
ps->actions[i] &= (unsigned char)(~remove_flags);
ps->actions[i] |= (unsigned char)add_flags;
/* all gone? remove socket */
if(!ps->actions[i]) {
if((i + 1) < ps->num) {
memmove(&ps->sockets[i], &ps->sockets[i + 1],
(ps->num - (i + 1)) * sizeof(ps->sockets[0]));
memmove(&ps->actions[i], &ps->actions[i + 1],
(ps->num - (i + 1)) * sizeof(ps->actions[0]));
}
--ps->num;
}
return;
}
}
/* not present */
if(add_flags) {
/* Having more SOCKETS per easy handle than what is defined
* is a programming error. This indicates that we need
* to raise this limit, making easy_pollset larger.
* Since we use this in tight loops, we do not want to make
* the pollset dynamic unnecessarily.
* The current maximum in practise is HTTP/3 eyeballing where
* we have up to 4 sockets involved in connection setup.
*/
DEBUGASSERT(i < MAX_SOCKSPEREASYHANDLE);
if(i < MAX_SOCKSPEREASYHANDLE) {
ps->sockets[i] = sock;
ps->actions[i] = (unsigned char)add_flags;
ps->num = i + 1;
}
}
}
void Curl_pollset_set(struct Curl_easy *data,
struct easy_pollset *ps, curl_socket_t sock,
bool do_in, bool do_out)
{
Curl_pollset_change(data, ps, sock,
(do_in?CURL_POLL_IN:0)|(do_out?CURL_POLL_OUT:0),
(!do_in?CURL_POLL_IN:0)|(!do_out?CURL_POLL_OUT:0));
}
static void ps_add(struct Curl_easy *data, struct easy_pollset *ps,
int bitmap, curl_socket_t *socks)
{
if(bitmap) {
int i;
for(i = 0; i < MAX_SOCKSPEREASYHANDLE; ++i) {
if(!(bitmap & GETSOCK_MASK_RW(i)) || !VALID_SOCK((socks[i]))) {
break;
}
if(bitmap & GETSOCK_READSOCK(i)) {
if(bitmap & GETSOCK_WRITESOCK(i))
Curl_pollset_add_inout(data, ps, socks[i]);
else
/* is READ, since we checked MASK_RW above */
Curl_pollset_add_in(data, ps, socks[i]);
}
else
Curl_pollset_add_out(data, ps, socks[i]);
}
}
}
void Curl_pollset_add_socks(struct Curl_easy *data,
struct easy_pollset *ps,
int (*get_socks_cb)(struct Curl_easy *data,
curl_socket_t *socks))
{
curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
int bitmap;
bitmap = get_socks_cb(data, socks);
ps_add(data, ps, bitmap, socks);
}
void Curl_pollset_check(struct Curl_easy *data,
struct easy_pollset *ps, curl_socket_t sock,
bool *pwant_read, bool *pwant_write)
{
unsigned int i;
(void)data;
DEBUGASSERT(VALID_SOCK(sock));
for(i = 0; i < ps->num; ++i) {
if(ps->sockets[i] == sock) {
*pwant_read = !!(ps->actions[i] & CURL_POLL_IN);
*pwant_write = !!(ps->actions[i] & CURL_POLL_OUT);
return;
}
}
*pwant_read = *pwant_write = FALSE;
}

644
third_party/curl/lib/cfilters.h vendored Normal file
View File

@ -0,0 +1,644 @@
#ifndef HEADER_CURL_CFILTERS_H
#define HEADER_CURL_CFILTERS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
struct Curl_cfilter;
struct Curl_easy;
struct Curl_dns_entry;
struct connectdata;
/* Callback to destroy resources held by this filter instance.
* Implementations MUST NOT chain calls to cf->next.
*/
typedef void Curl_cft_destroy_this(struct Curl_cfilter *cf,
struct Curl_easy *data);
typedef void Curl_cft_close(struct Curl_cfilter *cf,
struct Curl_easy *data);
typedef CURLcode Curl_cft_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done);
/* Return the hostname and port the connection goes to.
* This may change with the connection state of filters when tunneling
* is involved.
* @param cf the filter to ask
* @param data the easy handle currently active
* @param phost on return, points to the relevant, real hostname.
* this is owned by the connection.
* @param pdisplay_host on return, points to the printable hostname.
* this is owned by the connection.
* @param pport on return, contains the port number
*/
typedef void Curl_cft_get_host(struct Curl_cfilter *cf,
struct Curl_easy *data,
const char **phost,
const char **pdisplay_host,
int *pport);
struct easy_pollset;
/* Passing in an easy_pollset for monitoring of sockets, let
* filters add or remove sockets actions (CURL_POLL_OUT, CURL_POLL_IN).
* This may add a socket or, in case no actions remain, remove
* a socket from the set.
*
* Filter implementations need to call filters "below" *after* they have
* made their adjustments. This allows lower filters to override "upper"
* actions. If a "lower" filter is unable to write, it needs to be able
* to disallow POLL_OUT.
*
* A filter without own restrictions/preferences should not modify
* the pollset. Filters, whose filter "below" is not connected, should
* also do no adjustments.
*
* Examples: a TLS handshake, while ongoing, might remove POLL_IN
* when it needs to write, or vice versa. A HTTP/2 filter might remove
* POLL_OUT when a stream window is exhausted and a WINDOW_UPDATE needs
* to be received first and add instead POLL_IN.
*
* @param cf the filter to ask
* @param data the easy handle the pollset is about
* @param ps the pollset (inout) for the easy handle
*/
typedef void Curl_cft_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps);
typedef bool Curl_cft_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
typedef ssize_t Curl_cft_send(struct Curl_cfilter *cf,
struct Curl_easy *data, /* transfer */
const void *buf, /* data to write */
size_t len, /* amount to write */
CURLcode *err); /* error to return */
typedef ssize_t Curl_cft_recv(struct Curl_cfilter *cf,
struct Curl_easy *data, /* transfer */
char *buf, /* store data here */
size_t len, /* amount to read */
CURLcode *err); /* error to return */
typedef bool Curl_cft_conn_is_alive(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *input_pending);
typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf,
struct Curl_easy *data);
/**
* Events/controls for connection filters, their arguments and
* return code handling. Filter callbacks are invoked "top down".
* Return code handling:
* "first fail" meaning that the first filter returning != CURLE_OK, will
* abort further event distribution and determine the result.
* "ignored" meaning return values are ignored and the event is distributed
* to all filters in the chain. Overall result is always CURLE_OK.
*/
/* data event arg1 arg2 return */
#define CF_CTRL_DATA_ATTACH 1 /* 0 NULL ignored */
#define CF_CTRL_DATA_DETACH 2 /* 0 NULL ignored */
#define CF_CTRL_DATA_SETUP 4 /* 0 NULL first fail */
#define CF_CTRL_DATA_IDLE 5 /* 0 NULL first fail */
#define CF_CTRL_DATA_PAUSE 6 /* on/off NULL first fail */
#define CF_CTRL_DATA_DONE 7 /* premature NULL ignored */
#define CF_CTRL_DATA_DONE_SEND 8 /* 0 NULL ignored */
/* update conn info at connection and data */
#define CF_CTRL_CONN_INFO_UPDATE (256+0) /* 0 NULL ignored */
#define CF_CTRL_FORGET_SOCKET (256+1) /* 0 NULL ignored */
/**
* Handle event/control for the filter.
* Implementations MUST NOT chain calls to cf->next.
*/
typedef CURLcode Curl_cft_cntrl(struct Curl_cfilter *cf,
struct Curl_easy *data,
int event, int arg1, void *arg2);
/**
* Queries to ask via a `Curl_cft_query *query` method on a cfilter chain.
* - MAX_CONCURRENT: the maximum number of parallel transfers the filter
* chain expects to handle at the same time.
* default: 1 if no filter overrides.
* - CONNECT_REPLY_MS: milliseconds until the first indication of a server
* response was received on a connect. For TCP, this
* reflects the time until the socket connected. On UDP
* this gives the time the first bytes from the server
* were received.
* -1 if not determined yet.
* - CF_QUERY_SOCKET: the socket used by the filter chain
*/
/* query res1 res2 */
#define CF_QUERY_MAX_CONCURRENT 1 /* number - */
#define CF_QUERY_CONNECT_REPLY_MS 2 /* number - */
#define CF_QUERY_SOCKET 3 /* - curl_socket_t */
#define CF_QUERY_TIMER_CONNECT 4 /* - struct curltime */
#define CF_QUERY_TIMER_APPCONNECT 5 /* - struct curltime */
#define CF_QUERY_STREAM_ERROR 6 /* error code - */
/**
* Query the cfilter for properties. Filters ignorant of a query will
* pass it "down" the filter chain.
*/
typedef CURLcode Curl_cft_query(struct Curl_cfilter *cf,
struct Curl_easy *data,
int query, int *pres1, void *pres2);
/**
* Type flags for connection filters. A filter can have none, one or
* many of those. Use to evaluate state/capabilities of a filter chain.
*
* CF_TYPE_IP_CONNECT: provides an IP connection or sth equivalent, like
* a CONNECT tunnel, a UNIX domain socket, a QUIC
* connection, etc.
* CF_TYPE_SSL: provide SSL/TLS
* CF_TYPE_MULTIPLEX: provides multiplexing of easy handles
* CF_TYPE_PROXY provides proxying
*/
#define CF_TYPE_IP_CONNECT (1 << 0)
#define CF_TYPE_SSL (1 << 1)
#define CF_TYPE_MULTIPLEX (1 << 2)
#define CF_TYPE_PROXY (1 << 3)
/* A connection filter type, e.g. specific implementation. */
struct Curl_cftype {
const char *name; /* name of the filter type */
int flags; /* flags of filter type */
int log_level; /* log level for such filters */
Curl_cft_destroy_this *destroy; /* destroy resources of this cf */
Curl_cft_connect *do_connect; /* establish connection */
Curl_cft_close *do_close; /* close conn */
Curl_cft_get_host *get_host; /* host filter talks to */
Curl_cft_adjust_pollset *adjust_pollset; /* adjust transfer poll set */
Curl_cft_data_pending *has_data_pending;/* conn has data pending */
Curl_cft_send *do_send; /* send data */
Curl_cft_recv *do_recv; /* receive data */
Curl_cft_cntrl *cntrl; /* events/control */
Curl_cft_conn_is_alive *is_alive; /* FALSE if conn is dead, Jim! */
Curl_cft_conn_keep_alive *keep_alive; /* try to keep it alive */
Curl_cft_query *query; /* query filter chain */
};
/* A connection filter instance, e.g. registered at a connection */
struct Curl_cfilter {
const struct Curl_cftype *cft; /* the type providing implementation */
struct Curl_cfilter *next; /* next filter in chain */
void *ctx; /* filter type specific settings */
struct connectdata *conn; /* the connection this filter belongs to */
int sockindex; /* the index the filter is installed at */
BIT(connected); /* != 0 iff this filter is connected */
};
/* Default implementations for the type functions, implementing nop. */
void Curl_cf_def_destroy_this(struct Curl_cfilter *cf,
struct Curl_easy *data);
/* Default implementations for the type functions, implementing pass-through
* the filter chain. */
void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
const char **phost, const char **pdisplay_host,
int *pport);
void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps);
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err);
ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err);
CURLcode Curl_cf_def_cntrl(struct Curl_cfilter *cf,
struct Curl_easy *data,
int event, int arg1, void *arg2);
bool Curl_cf_def_conn_is_alive(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *input_pending);
CURLcode Curl_cf_def_conn_keep_alive(struct Curl_cfilter *cf,
struct Curl_easy *data);
CURLcode Curl_cf_def_query(struct Curl_cfilter *cf,
struct Curl_easy *data,
int query, int *pres1, void *pres2);
/**
* Create a new filter instance, unattached to the filter chain.
* Use Curl_conn_cf_add() to add it to the chain.
* @param pcf on success holds the created instance
* @param cft the filter type
* @param ctx the type specific context to use
*/
CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
const struct Curl_cftype *cft,
void *ctx);
/**
* Add a filter instance to the `sockindex` filter chain at connection
* `conn`. The filter must not already be attached. It is inserted at
* the start of the chain (top).
*/
void Curl_conn_cf_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
struct Curl_cfilter *cf);
/**
* Insert a filter (chain) after `cf_at`.
* `cf_new` must not already be attached.
*/
void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
struct Curl_cfilter *cf_new);
/**
* Discard, e.g. remove and destroy `discard` iff
* it still is in the filter chain below `cf`. If `discard`
* is no longer found beneath `cf` return FALSE.
* if `destroy_always` is TRUE, will call `discard`s destroy
* function and free it even if not found in the subchain.
*/
bool Curl_conn_cf_discard_sub(struct Curl_cfilter *cf,
struct Curl_cfilter *discard,
struct Curl_easy *data,
bool destroy_always);
/**
* Discard all cfilters starting with `*pcf` and clearing it afterwards.
*/
void Curl_conn_cf_discard_chain(struct Curl_cfilter **pcf,
struct Curl_easy *data);
/**
* Remove and destroy all filters at chain `sockindex` on connection `conn`.
*/
void Curl_conn_cf_discard_all(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done);
void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data);
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err);
ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err);
CURLcode Curl_conn_cf_cntrl(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool ignore_result,
int event, int arg1, void *arg2);
/**
* Determine if the connection filter chain is using SSL to the remote host
* (or will be once connected).
*/
bool Curl_conn_cf_is_ssl(struct Curl_cfilter *cf);
/**
* Get the socket used by the filter chain starting at `cf`.
* Returns CURL_SOCKET_BAD if not available.
*/
curl_socket_t Curl_conn_cf_get_socket(struct Curl_cfilter *cf,
struct Curl_easy *data);
#define CURL_CF_SSL_DEFAULT -1
#define CURL_CF_SSL_DISABLE 0
#define CURL_CF_SSL_ENABLE 1
/**
* Bring the filter chain at `sockindex` for connection `data->conn` into
* connected state. Which will set `*done` to TRUE.
* This can be called on an already connected chain with no side effects.
* When not `blocking`, calls may return without error and `*done != TRUE`,
* while the individual filters negotiated the connection.
*/
CURLcode Curl_conn_connect(struct Curl_easy *data, int sockindex,
bool blocking, bool *done);
/**
* Check if the filter chain at `sockindex` for connection `conn` is
* completely connected.
*/
bool Curl_conn_is_connected(struct connectdata *conn, int sockindex);
/**
* Determine if we have reached the remote host on IP level, e.g.
* have a TCP connection. This turns TRUE before a possible SSL
* handshake has been started/done.
*/
bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex);
/**
* Determine if the connection is using SSL to the remote host
* (or will be once connected). This will return FALSE, if SSL
* is only used in proxying and not for the tunnel itself.
*/
bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex);
/**
* Connection provides multiplexing of easy handles at `socketindex`.
*/
bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex);
/**
* Close the filter chain at `sockindex` for connection `data->conn`.
* Filters remain in place and may be connected again afterwards.
*/
void Curl_conn_close(struct Curl_easy *data, int sockindex);
/**
* Return if data is pending in some connection filter at chain
* `sockindex` for connection `data->conn`.
*/
bool Curl_conn_data_pending(struct Curl_easy *data,
int sockindex);
/**
* Return the socket used on data's connection for the index.
* Returns CURL_SOCKET_BAD if not available.
*/
curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex);
/**
* Tell filters to forget about the socket at sockindex.
*/
void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex);
/**
* Adjust the pollset for the filter chain startgin at `cf`.
*/
void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps);
/**
* Adjust pollset from filters installed at transfer's connection.
*/
void Curl_conn_adjust_pollset(struct Curl_easy *data,
struct easy_pollset *ps);
/**
* Receive data through the filter chain at `sockindex` for connection
* `data->conn`. Copy at most `len` bytes into `buf`. Return the
* actual number of bytes copied or a negative value on error.
* The error code is placed into `*code`.
*/
ssize_t Curl_cf_recv(struct Curl_easy *data, int sockindex, char *buf,
size_t len, CURLcode *code);
/**
* Send `len` bytes of data from `buf` through the filter chain `sockindex`
* at connection `data->conn`. Return the actual number of bytes written
* or a negative value on error.
* The error code is placed into `*code`.
*/
ssize_t Curl_cf_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, CURLcode *code);
/**
* The easy handle `data` is being attached to `conn`. This does
* not mean that data will actually do a transfer. Attachment is
* also used for temporary actions on the connection.
*/
void Curl_conn_ev_data_attach(struct connectdata *conn,
struct Curl_easy *data);
/**
* The easy handle `data` is being detached (no longer served)
* by connection `conn`. All filters are informed to release any resources
* related to `data`.
* Note: there may be several `data` attached to a connection at the same
* time.
*/
void Curl_conn_ev_data_detach(struct connectdata *conn,
struct Curl_easy *data);
/**
* Notify connection filters that they need to setup data for
* a transfer.
*/
CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data);
/**
* Notify connection filters that now would be a good time to
* perform any idle, e.g. time related, actions.
*/
CURLcode Curl_conn_ev_data_idle(struct Curl_easy *data);
/**
* Notify connection filters that the transfer represented by `data`
* is done with sending data (e.g. has uploaded everything).
*/
void Curl_conn_ev_data_done_send(struct Curl_easy *data);
/**
* Notify connection filters that the transfer represented by `data`
* is finished - eventually premature, e.g. before being complete.
*/
void Curl_conn_ev_data_done(struct Curl_easy *data, bool premature);
/**
* Notify connection filters that the transfer of data is paused/unpaused.
*/
CURLcode Curl_conn_ev_data_pause(struct Curl_easy *data, bool do_pause);
/**
* Inform connection filters to update their info in `conn`.
*/
void Curl_conn_ev_update_info(struct Curl_easy *data,
struct connectdata *conn);
/**
* Check if FIRSTSOCKET's cfilter chain deems connection alive.
*/
bool Curl_conn_is_alive(struct Curl_easy *data, struct connectdata *conn,
bool *input_pending);
/**
* Try to upkeep the connection filters at sockindex.
*/
CURLcode Curl_conn_keep_alive(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data);
void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
const char **phost, const char **pdisplay_host,
int *pport);
/**
* Get the maximum number of parallel transfers the connection
* expects to be able to handle at `sockindex`.
*/
size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
/**
* Get the underlying error code for a transfer stream or 0 if not known.
*/
int Curl_conn_get_stream_error(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
/**
* Get the index of the given socket in the connection's sockets.
* Useful in calling `Curl_conn_send()/Curl_conn_recv()` with the
* correct socket index.
*/
int Curl_conn_sockindex(struct Curl_easy *data, curl_socket_t sockfd);
/*
* Receive data on the connection, using FIRSTSOCKET/SECONDARYSOCKET.
* Will return CURLE_AGAIN iff blocked on receiving.
*/
CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
char *buf, size_t buffersize,
ssize_t *pnread);
/*
* Send data on the connection, using FIRSTSOCKET/SECONDARYSOCKET.
* Will return CURLE_AGAIN iff blocked on sending.
*/
CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t blen,
size_t *pnwritten);
void Curl_pollset_reset(struct Curl_easy *data,
struct easy_pollset *ps);
/* Change the poll flags (CURL_POLL_IN/CURL_POLL_OUT) to the poll set for
* socket `sock`. If the socket is not already part of the poll set, it
* will be added.
* If the socket is present and all poll flags are cleared, it will be removed.
*/
void Curl_pollset_change(struct Curl_easy *data,
struct easy_pollset *ps, curl_socket_t sock,
int add_flags, int remove_flags);
void Curl_pollset_set(struct Curl_easy *data,
struct easy_pollset *ps, curl_socket_t sock,
bool do_in, bool do_out);
#define Curl_pollset_add_in(data, ps, sock) \
Curl_pollset_change((data), (ps), (sock), CURL_POLL_IN, 0)
#define Curl_pollset_add_out(data, ps, sock) \
Curl_pollset_change((data), (ps), (sock), CURL_POLL_OUT, 0)
#define Curl_pollset_add_inout(data, ps, sock) \
Curl_pollset_change((data), (ps), (sock), \
CURL_POLL_IN|CURL_POLL_OUT, 0)
#define Curl_pollset_set_in_only(data, ps, sock) \
Curl_pollset_change((data), (ps), (sock), \
CURL_POLL_IN, CURL_POLL_OUT)
#define Curl_pollset_set_out_only(data, ps, sock) \
Curl_pollset_change((data), (ps), (sock), \
CURL_POLL_OUT, CURL_POLL_IN)
void Curl_pollset_add_socks(struct Curl_easy *data,
struct easy_pollset *ps,
int (*get_socks_cb)(struct Curl_easy *data,
curl_socket_t *socks));
/**
* Check if the pollset, as is, wants to read and/or write regarding
* the given socket.
*/
void Curl_pollset_check(struct Curl_easy *data,
struct easy_pollset *ps, curl_socket_t sock,
bool *pwant_read, bool *pwant_write);
/**
* Types and macros used to keep the current easy handle in filter calls,
* allowing for nested invocations. See #10336.
*
* `cf_call_data` is intended to be a member of the cfilter's `ctx` type.
* A filter defines the macro `CF_CTX_CALL_DATA` to give access to that.
*
* With all values 0, the default, this indicates that there is no cfilter
* call with `data` ongoing.
* Macro `CF_DATA_SAVE` preserves the current `cf_call_data` in a local
* variable and sets the `data` given, incrementing the `depth` counter.
*
* Macro `CF_DATA_RESTORE` restores the old values from the local variable,
* while checking that `depth` values are as expected (debug build), catching
* cases where a "lower" RESTORE was not called.
*
* Finally, macro `CF_DATA_CURRENT` gives the easy handle of the current
* invocation.
*/
struct cf_call_data {
struct Curl_easy *data;
#ifdef DEBUGBUILD
int depth;
#endif
};
/**
* define to access the `struct cf_call_data for a cfilter. Normally
* a member in the cfilter's `ctx`.
*
* #define CF_CTX_CALL_DATA(cf) -> struct cf_call_data instance
*/
#ifdef DEBUGBUILD
#define CF_DATA_SAVE(save, cf, data) \
do { \
(save) = CF_CTX_CALL_DATA(cf); \
DEBUGASSERT((save).data == NULL || (save).depth > 0); \
CF_CTX_CALL_DATA(cf).depth++; \
CF_CTX_CALL_DATA(cf).data = (struct Curl_easy *)data; \
} while(0)
#define CF_DATA_RESTORE(cf, save) \
do { \
DEBUGASSERT(CF_CTX_CALL_DATA(cf).depth == (save).depth + 1); \
DEBUGASSERT((save).data == NULL || (save).depth > 0); \
CF_CTX_CALL_DATA(cf) = (save); \
} while(0)
#else /* DEBUGBUILD */
#define CF_DATA_SAVE(save, cf, data) \
do { \
(save) = CF_CTX_CALL_DATA(cf); \
CF_CTX_CALL_DATA(cf).data = (struct Curl_easy *)data; \
} while(0)
#define CF_DATA_RESTORE(cf, save) \
do { \
CF_CTX_CALL_DATA(cf) = (save); \
} while(0)
#endif /* !DEBUGBUILD */
#define CF_DATA_CURRENT(cf) \
((cf)? (CF_CTX_CALL_DATA(cf).data) : NULL)
#endif /* HEADER_CURL_CFILTERS_H */

129
third_party/curl/lib/config-amigaos.h vendored Normal file
View File

@ -0,0 +1,129 @@
#ifndef HEADER_CURL_CONFIG_AMIGAOS_H
#define HEADER_CURL_CONFIG_AMIGAOS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* ================================================================ */
/* Hand crafted config file for AmigaOS */
/* ================================================================ */
#ifdef __AMIGA__ /* Any AmigaOS flavour */
#define HAVE_ARPA_INET_H 1
#define HAVE_CLOSESOCKET_CAMEL 1
#define HAVE_IOCTLSOCKET_CAMEL 1
#define HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1
#define HAVE_LONGLONG 1
#define HAVE_NETDB_H 1
#define HAVE_NETINET_IN_H 1
#define HAVE_NET_IF_H 1
#define HAVE_PWD_H 1
#define HAVE_SELECT 1
#define HAVE_SIGNAL 1
#define HAVE_SOCKET 1
#define HAVE_STRCASECMP 1
#define HAVE_STRDUP 1
#define HAVE_STRICMP 1
#define HAVE_STRINGS_H 1
#define HAVE_STRUCT_TIMEVAL 1
#define HAVE_SYS_PARAM_H 1
#define HAVE_SYS_SOCKET_H 1
#define HAVE_SYS_SOCKIO_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_UNISTD_H 1
#define HAVE_UTIME 1
#define HAVE_UTIME_H 1
#define HAVE_WRITABLE_ARGV 1
#define HAVE_SYS_IOCTL_H 1
#define NEED_MALLOC_H 1
#define SIZEOF_INT 4
#define SIZEOF_SIZE_T 4
#ifndef SIZEOF_CURL_OFF_T
#define SIZEOF_CURL_OFF_T 8
#endif
#define USE_MANUAL 1
#define CURL_DISABLE_LDAP 1
#ifndef OS
#define OS "AmigaOS"
#endif
#define PACKAGE "curl"
#define PACKAGE_BUGREPORT "a suitable mailing list: https://curl.se/mail/"
#define PACKAGE_NAME "curl"
#define PACKAGE_STRING "curl -"
#define PACKAGE_TARNAME "curl"
#define PACKAGE_VERSION "-"
#if defined(USE_AMISSL)
#define CURL_CA_PATH "AmiSSL:Certs"
#elif defined(__MORPHOS__)
#define CURL_CA_BUNDLE "MOSSYS:Data/SSL/curl-ca-bundle.crt"
#else
#define CURL_CA_BUNDLE "s:curl-ca-bundle.crt"
#endif
#define STDC_HEADERS 1
#define in_addr_t int
#ifndef F_OK
# define F_OK 0
#endif
#ifndef O_RDONLY
# define O_RDONLY 0x0000
#endif
#ifndef LONG_MAX
# define LONG_MAX 0x7fffffffL
#endif
#ifndef LONG_MIN
# define LONG_MIN (-0x7fffffffL-1)
#endif
#define HAVE_RECV 1
#define RECV_TYPE_ARG1 long
#define RECV_TYPE_ARG2 char *
#define RECV_TYPE_ARG3 long
#define RECV_TYPE_ARG4 long
#define RECV_TYPE_RETV long
#define HAVE_SEND 1
#define SEND_TYPE_ARG1 int
#define SEND_QUAL_ARG2 const
#define SEND_TYPE_ARG2 char *
#define SEND_TYPE_ARG3 int
#define SEND_TYPE_ARG4 int
#define SEND_TYPE_RETV int
#endif /* __AMIGA__ */
#endif /* HEADER_CURL_CONFIG_AMIGAOS_H */

138
third_party/curl/lib/config-dos.h vendored Normal file
View File

@ -0,0 +1,138 @@
#ifndef HEADER_CURL_CONFIG_DOS_H
#define HEADER_CURL_CONFIG_DOS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* ================================================================ */
/* lib/config-dos.h - Hand crafted config file for DOS */
/* ================================================================ */
#ifndef OS
#if defined(DJGPP)
#define OS "MSDOS/djgpp"
#elif defined(__HIGHC__)
#define OS "MSDOS/HighC"
#else
#define OS "MSDOS/?"
#endif
#endif
#define PACKAGE "curl"
#define USE_MANUAL 1
#define HAVE_ARPA_INET_H 1
#define HAVE_FCNTL_H 1
#define HAVE_FREEADDRINFO 1
#define HAVE_GETADDRINFO 1
#define HAVE_GETTIMEOFDAY 1
#define HAVE_IO_H 1
#define HAVE_IOCTL_FIONBIO 1
#define HAVE_IOCTLSOCKET 1
#define HAVE_IOCTLSOCKET_FIONBIO 1
#define HAVE_LOCALE_H 1
#define HAVE_LONGLONG 1
#define HAVE_NETDB_H 1
#define HAVE_NETINET_IN_H 1
#define HAVE_NETINET_TCP_H 1
#define HAVE_NET_IF_H 1
#define HAVE_RECV 1
#define HAVE_SELECT 1
#define HAVE_SEND 1
#define HAVE_SETLOCALE 1
#define HAVE_SETMODE 1
#define HAVE_SIGNAL 1
#define HAVE_SOCKET 1
#define HAVE_STRDUP 1
#define HAVE_STRICMP 1
#define HAVE_STRTOLL 1
#define HAVE_STRUCT_TIMEVAL 1
#define HAVE_SYS_IOCTL_H 1
#define HAVE_SYS_SOCKET_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_UNISTD_H 1
#define NEED_MALLOC_H 1
#define SIZEOF_INT 4
#define SIZEOF_LONG 4
#define SIZEOF_SIZE_T 4
#define SIZEOF_CURL_OFF_T 8
#define STDC_HEADERS 1
/* Qualifiers for send() and recv() */
#define SEND_TYPE_ARG1 int
#define SEND_QUAL_ARG2 const
#define SEND_TYPE_ARG2 void *
#define SEND_TYPE_ARG3 int
#define SEND_TYPE_ARG4 int
#define SEND_TYPE_RETV int
#define RECV_TYPE_ARG1 int
#define RECV_TYPE_ARG2 void *
#define RECV_TYPE_ARG3 int
#define RECV_TYPE_ARG4 int
#define RECV_TYPE_RETV int
#define BSD
/* CURLDEBUG definition enables memory tracking */
/* #define CURLDEBUG */
/* to disable LDAP */
#define CURL_DISABLE_LDAP 1
#define in_addr_t u_long
#if defined(__HIGHC__) || \
(defined(__GNUC__) && (__GNUC__ < 4))
#define ssize_t int
#endif
/* Target HAVE_x section */
#if defined(DJGPP)
#define HAVE_BASENAME 1
#define HAVE_STRCASECMP 1
#define HAVE_SIGACTION 1
#define HAVE_SIGSETJMP 1
#define HAVE_SYS_TIME_H 1
#define HAVE_TERMIOS_H 1
#elif defined(__HIGHC__)
#define HAVE_SYS_TIME_H 1
#define strerror(e) strerror_s_((e))
#endif
#ifdef MSDOS /* Watt-32 */
#define HAVE_CLOSE_S 1
#endif
#undef word
#undef byte
#endif /* HEADER_CURL_CONFIG_DOS_H */

103
third_party/curl/lib/config-mac.h vendored Normal file
View File

@ -0,0 +1,103 @@
#ifndef HEADER_CURL_CONFIG_MAC_H
#define HEADER_CURL_CONFIG_MAC_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* =================================================================== */
/* Hand crafted config file for Mac OS 9 */
/* =================================================================== */
/* On Mac OS X you must run configure to generate curl_config.h file */
/* =================================================================== */
#ifndef OS
#define OS "mac"
#endif
#include <ConditionalMacros.h>
#if TYPE_LONGLONG
#define HAVE_LONGLONG 1
#endif
/* Define if you want the built-in manual */
#define USE_MANUAL 1
#define HAVE_NETINET_IN_H 1
#define HAVE_SYS_SOCKET_H 1
#define HAVE_NETDB_H 1
#define HAVE_ARPA_INET_H 1
#define HAVE_UNISTD_H 1
#define HAVE_NET_IF_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_GETTIMEOFDAY 1
#define HAVE_FCNTL_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_UTIME_H 1
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_UTIME_H 1
#define HAVE_SYS_IOCTL_H 1
#define HAVE_ALARM 1
#define HAVE_FTRUNCATE 1
#define HAVE_UTIME 1
#define HAVE_SELECT 1
#define HAVE_SOCKET 1
#define HAVE_STRUCT_TIMEVAL 1
#define HAVE_SIGACTION 1
#ifdef MACOS_SSL_SUPPORT
# define USE_OPENSSL 1
#endif
#define CURL_DISABLE_LDAP 1
#define HAVE_IOCTL_FIONBIO 1
#define SIZEOF_INT 4
#define SIZEOF_LONG 4
#define SIZEOF_SIZE_T 4
#ifdef HAVE_LONGLONG
#define SIZEOF_CURL_OFF_T 8
#else
#define SIZEOF_CURL_OFF_T 4
#endif
#define HAVE_RECV 1
#define RECV_TYPE_ARG1 int
#define RECV_TYPE_ARG2 void *
#define RECV_TYPE_ARG3 size_t
#define RECV_TYPE_ARG4 int
#define RECV_TYPE_RETV ssize_t
#define HAVE_SEND 1
#define SEND_TYPE_ARG1 int
#define SEND_QUAL_ARG2 const
#define SEND_TYPE_ARG2 void *
#define SEND_TYPE_ARG3 size_t
#define SEND_TYPE_ARG4 int
#define SEND_TYPE_RETV ssize_t
#define HAVE_EXTRA_STRICMP_H 1
#define HAVE_EXTRA_STRDUP_H 1
#endif /* HEADER_CURL_CONFIG_MAC_H */

334
third_party/curl/lib/config-os400.h vendored Normal file
View File

@ -0,0 +1,334 @@
#ifndef HEADER_CURL_CONFIG_OS400_H
#define HEADER_CURL_CONFIG_OS400_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* ================================================================ */
/* Hand crafted config file for OS/400 */
/* ================================================================ */
#pragma enum(int)
#undef PACKAGE
/* Version number of this archive. */
#undef VERSION
/* Define cpu-machine-OS */
#ifndef OS
#define OS "OS/400"
#endif
/* OS400 supports a 3-argument ASCII version of gethostbyaddr_r(), but its
* prototype is incompatible with the "standard" one (1st argument is not
* const). However, getaddrinfo() is supported (ASCII version defined as
* a local wrapper in setup-os400.h) in a threadsafe way: we can then
* configure getaddrinfo() as such and get rid of gethostbyname_r() without
* loss of threadsafeness. */
#undef HAVE_GETHOSTBYNAME_R
#undef HAVE_GETHOSTBYNAME_R_3
#undef HAVE_GETHOSTBYNAME_R_5
#undef HAVE_GETHOSTBYNAME_R_6
#define HAVE_GETADDRINFO
#define HAVE_GETADDRINFO_THREADSAFE
/* Define if you need the _REENTRANT define for some functions */
#undef NEED_REENTRANT
/* Define if you want to enable IPv6 support */
#define USE_IPV6
/* Define if struct sockaddr_in6 has the sin6_scope_id member */
#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
/* Define this to 'int' if ssize_t is not an available typedefed type */
#undef ssize_t
/* Define this as a suitable file to read random data from */
#undef RANDOM_FILE
/* Define to 1 if you have the alarm function. */
#define HAVE_ALARM 1
/* Define if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H
/* Define if you have the `closesocket' function. */
#undef HAVE_CLOSESOCKET
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H
/* Define if you have the `geteuid' function. */
#define HAVE_GETEUID
/* Define if you have the `gethostname' function. */
#define HAVE_GETHOSTNAME
/* Define if you have the `getpass_r' function. */
#undef HAVE_GETPASS_R
/* Define to 1 if you have the getpeername function. */
#define HAVE_GETPEERNAME 1
/* Define if you have the `getpwuid' function. */
#define HAVE_GETPWUID
/* Define to 1 if you have the getsockname function. */
#define HAVE_GETSOCKNAME 1
/* Define if you have the `gettimeofday' function. */
#define HAVE_GETTIMEOFDAY
/* Define if you have the `timeval' struct. */
#define HAVE_STRUCT_TIMEVAL
/* Define if you have the <io.h> header file. */
#undef HAVE_IO_H
/* Define if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET
/* Define if you have GSS API. */
#define HAVE_GSSAPI
/* Define if you have the GNU gssapi libraries */
#undef HAVE_GSSGNU
/* Define if you need the malloc.h header file even with stdlib.h */
/* #define NEED_MALLOC_H 1 */
/* Define if you have the <netdb.h> header file. */
#define HAVE_NETDB_H
/* Define if you have the <netinet/in.h> header file. */
#define HAVE_NETINET_IN_H
/* Define if you have the <net/if.h> header file. */
#define HAVE_NET_IF_H
/* Define if you have the <pwd.h> header file. */
#define HAVE_PWD_H
/* Define if you have the `select' function. */
#define HAVE_SELECT
/* Define if you have the `sigaction' function. */
#define HAVE_SIGACTION
/* Define if you have the `signal' function. */
#undef HAVE_SIGNAL
/* Define if you have the `socket' function. */
#define HAVE_SOCKET
/* The following define is needed on OS400 to enable strcmpi(), stricmp() and
strdup(). */
#define __cplusplus__strings__
/* Define if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
/* Define if you have the `strcmpi' function. */
#define HAVE_STRCMPI
/* Define if you have the `stricmp' function. */
#define HAVE_STRICMP
/* Define if you have the `strdup' function. */
#define HAVE_STRDUP
/* Define if you have the <strings.h> header file. */
#define HAVE_STRINGS_H
/* Define if you have the <stropts.h> header file. */
#undef HAVE_STROPTS_H
/* Define if you have the `strtok_r' function. */
#define HAVE_STRTOK_R
/* Define if you have the `strtoll' function. */
#undef HAVE_STRTOLL /* Allows ASCII compile on V5R1. */
/* Define if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H
/* Define if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H
/* Define if you have the <sys/sockio.h> header file. */
#undef HAVE_SYS_SOCKIO_H
/* Define if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H
/* Define if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H
/* Define if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H
/* Define if you have the <sys/un.h> header file. */
#define HAVE_SYS_UN_H
/* Define if you have the <sys/ioctl.h> header file. */
#define HAVE_SYS_IOCTL_H
/* Define if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
/* Define if you have the <termio.h> header file. */
#undef HAVE_TERMIO_H
/* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H
/* Name of package */
#undef PACKAGE
/* The size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
/* Define if the compiler supports the 'long long' data type. */
#define HAVE_LONGLONG
/* The size of a `long long', as computed by sizeof. */
#define SIZEOF_LONG_LONG 8
/* The size of `long', as computed by sizeof. */
#define SIZEOF_LONG 4
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T 4
/* The size of `curl_off_t', as computed by sizeof. */
#define SIZEOF_CURL_OFF_T 8
/* Define this if you have struct sockaddr_storage */
#define HAVE_STRUCT_SOCKADDR_STORAGE
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS
/* Define to enable HTTP3 support (experimental, requires NGTCP2, QUICHE or
MSH3) */
#undef USE_HTTP3
/* Version number of package */
#undef VERSION
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Define for large files, on AIX-style hosts. */
#define _LARGE_FILES
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* type to use in place of in_addr_t if not defined */
#define in_addr_t unsigned long
/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t
/* Define if you have a working ioctl FIONBIO function. */
#define HAVE_IOCTL_FIONBIO
/* Define if you have a working ioctl SIOCGIFADDR function. */
#define HAVE_IOCTL_SIOCGIFADDR
/* To disable LDAP */
#undef CURL_DISABLE_LDAP
/* Definition to make a library symbol externally visible. */
#define CURL_EXTERN_SYMBOL
/* Define if you have the ldap_url_parse procedure. */
/* #define HAVE_LDAP_URL_PARSE */ /* Disabled because of an IBM bug. */
/* Define if you have the recv function. */
#define HAVE_RECV
/* Define to the type of arg 1 for recv. */
#define RECV_TYPE_ARG1 int
/* Define to the type of arg 2 for recv. */
#define RECV_TYPE_ARG2 char *
/* Define to the type of arg 3 for recv. */
#define RECV_TYPE_ARG3 int
/* Define to the type of arg 4 for recv. */
#define RECV_TYPE_ARG4 int
/* Define to the function return type for recv. */
#define RECV_TYPE_RETV int
/* Define if you have the send function. */
#define HAVE_SEND
/* Define to the type of arg 1 for send. */
#define SEND_TYPE_ARG1 int
/* Define to the type qualifier of arg 2 for send. */
#define SEND_QUAL_ARG2
/* Define to the type of arg 2 for send. */
#define SEND_TYPE_ARG2 char *
/* Define to the type of arg 3 for send. */
#define SEND_TYPE_ARG3 int
/* Define to the type of arg 4 for send. */
#define SEND_TYPE_ARG4 int
/* Define to the function return type for send. */
#define SEND_TYPE_RETV int
/* Define to use the OS/400 crypto library. */
#define USE_OS400CRYPTO
/* Define to use Unix sockets. */
#define USE_UNIX_SOCKETS
/* Use the system keyring as the default CA bundle. */
#define CURL_CA_BUNDLE "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB"
/* ---------------------------------------------------------------- */
/* ADDITIONAL DEFINITIONS */
/* ---------------------------------------------------------------- */
/* The following must be defined BEFORE system header files inclusion. */
#define __ptr128 /* No teraspace. */
#define qadrt_use_fputc_inline /* Generate fputc() wrapper inline. */
#define qadrt_use_fread_inline /* Generate fread() wrapper inline. */
#define qadrt_use_fwrite_inline /* Generate fwrite() wrapper inline. */
#endif /* HEADER_CURL_CONFIG_OS400_H */

147
third_party/curl/lib/config-plan9.h vendored Normal file
View File

@ -0,0 +1,147 @@
#ifndef HEADER_CURL_CONFIG_PLAN9_H
#define HEADER_CURL_CONFIG_PLAN9_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#define BUILDING_LIBCURL 1
#define CURL_CA_BUNDLE "/sys/lib/tls/ca.pem"
#define CURL_CA_PATH "/sys/lib/tls"
#define CURL_STATICLIB 1
#define USE_IPV6 1
#define CURL_DISABLE_LDAP 1
#define NEED_REENTRANT 1
#ifndef OS
#define OS "plan9"
#endif
#define PACKAGE "curl"
#define PACKAGE_NAME "curl"
#define PACKAGE_BUGREPORT "a suitable mailing list: https://curl.se/mail/"
#define PACKAGE_STRING "curl -"
#define PACKAGE_TARNAME "curl"
#define PACKAGE_VERSION "-"
#define RANDOM_FILE "/dev/random"
#define VERSION "0.0.0" /* TODO */
#define STDC_HEADERS 1
#ifdef _BITS64
#error not implement
#else
#define SIZEOF_INT 4
#define SIZEOF_LONG 4
#define SIZEOF_OFF_T 8
#define SIZEOF_CURL_OFF_T 4 /* curl_off_t = timediff_t = int */
#define SIZEOF_SIZE_T 4
#define SIZEOF_TIME_T 4
#endif
#define HAVE_RECV 1
#define RECV_TYPE_ARG1 int
#define RECV_TYPE_ARG2 void *
#define RECV_TYPE_ARG3 int
#define RECV_TYPE_ARG4 int
#define RECV_TYPE_RETV int
#define HAVE_SELECT 1
#define HAVE_SEND 1
#define SEND_TYPE_ARG1 int
#define SEND_TYPE_ARG2 void *
#define SEND_QUAL_ARG2
#define SEND_TYPE_ARG3 int
#define SEND_TYPE_ARG4 int
#define SEND_TYPE_RETV int
#define HAVE_ALARM 1
#define HAVE_ARPA_INET_H 1
#define HAVE_BASENAME 1
#define HAVE_BOOL_T 1
#define HAVE_FCNTL 1
#define HAVE_FCNTL_H 1
#define HAVE_FREEADDRINFO 1
#define HAVE_FTRUNCATE 1
#define HAVE_GETADDRINFO 1
#define HAVE_GETEUID 1
#define HAVE_GETHOSTNAME 1
#define HAVE_GETPPID 1
#define HAVE_GETPWUID 1
#define HAVE_GETTIMEOFDAY 1
#define HAVE_GMTIME_R 1
#define HAVE_INET_NTOP 1
#define HAVE_INET_PTON 1
#define HAVE_LIBGEN_H 1
#define HAVE_LIBZ 1
#define HAVE_LOCALE_H 1
#define HAVE_LONGLONG 1
#define HAVE_NETDB_H 1
#define HAVE_NETINET_IN_H 1
#define HAVE_NETINET_TCP_H 1
#define HAVE_PWD_H 1
#define HAVE_SYS_SELECT_H 1
#define USE_OPENSSL 1
#define HAVE_PIPE 1
#define HAVE_POLL_FINE 1
#define HAVE_POLL_H 1
#define HAVE_PTHREAD_H 1
#define HAVE_SETLOCALE 1
#define HAVE_SIGACTION 1
#define HAVE_SIGNAL 1
#define HAVE_SIGSETJMP 1
#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
#define HAVE_SOCKET 1
#define HAVE_SSL_GET_SHUTDOWN 1
#define HAVE_STDBOOL_H 1
#define HAVE_STRCASECMP 1
#define HAVE_STRDUP 1
#define HAVE_STRTOK_R 1
#define HAVE_STRTOLL 1
#define HAVE_STRUCT_TIMEVAL 1
#define HAVE_SYS_IOCTL_H 1
#define HAVE_SYS_PARAM_H 1
#define HAVE_SYS_RESOURCE_H 1
#define HAVE_SYS_SOCKET_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_UN_H 1
#define HAVE_TERMIOS_H 1
#define HAVE_UNISTD_H 1
#define HAVE_UTIME 1
#define HAVE_UTIME_H 1
#define HAVE_POSIX_STRERROR_R 1
#define HAVE_STRERROR_R 1
#define USE_MANUAL 1
#define __attribute__(x)
#ifndef __cplusplus
#undef inline
#endif
#endif /* HEADER_CURL_CONFIG_PLAN9_H */

277
third_party/curl/lib/config-riscos.h vendored Normal file
View File

@ -0,0 +1,277 @@
#ifndef HEADER_CURL_CONFIG_RISCOS_H
#define HEADER_CURL_CONFIG_RISCOS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* ================================================================ */
/* Hand crafted config file for RISC OS */
/* ================================================================ */
/* Name of this package! */
#undef PACKAGE
/* Version number of this archive. */
#undef VERSION
/* Define cpu-machine-OS */
#ifndef OS
#define OS "ARM-RISC OS"
#endif
/* Define if you want the built-in manual */
#define USE_MANUAL
/* Define if you have the gethostbyname_r() function with 3 arguments */
#undef HAVE_GETHOSTBYNAME_R_3
/* Define if you have the gethostbyname_r() function with 5 arguments */
#undef HAVE_GETHOSTBYNAME_R_5
/* Define if you have the gethostbyname_r() function with 6 arguments */
#undef HAVE_GETHOSTBYNAME_R_6
/* Define if you need the _REENTRANT define for some functions */
#undef NEED_REENTRANT
/* Define if you want to enable IPv6 support */
#undef USE_IPV6
/* Define if struct sockaddr_in6 has the sin6_scope_id member */
#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
/* Define this to 'int' if ssize_t is not an available typedefed type */
#undef ssize_t
/* Define this as a suitable file to read random data from */
#undef RANDOM_FILE
/* Define if you have the alarm function. */
#define HAVE_ALARM
/* Define if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H
/* Define if you have the `closesocket' function. */
#undef HAVE_CLOSESOCKET
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H
/* Define if you have the `ftruncate' function. */
#define HAVE_FTRUNCATE
/* Define if getaddrinfo exists and works */
#define HAVE_GETADDRINFO
/* Define if you have the `geteuid' function. */
#undef HAVE_GETEUID
/* Define if you have the `gethostbyname_r' function. */
#undef HAVE_GETHOSTBYNAME_R
/* Define if you have the `gethostname' function. */
#define HAVE_GETHOSTNAME
/* Define if you have the `getpass_r' function. */
#undef HAVE_GETPASS_R
/* Define if you have the `getpwuid' function. */
#undef HAVE_GETPWUID
/* Define if you have the `gettimeofday' function. */
#define HAVE_GETTIMEOFDAY
/* Define if you have the `timeval' struct. */
#define HAVE_STRUCT_TIMEVAL
/* Define if you have the <io.h> header file. */
#undef HAVE_IO_H
/* Define if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET
/* Define if you need the malloc.h header file even with stdlib.h */
/* #define NEED_MALLOC_H 1 */
/* Define if you have the <netdb.h> header file. */
#define HAVE_NETDB_H
/* Define if you have the <netinet/in.h> header file. */
#define HAVE_NETINET_IN_H
/* Define if you have the <net/if.h> header file. */
#define HAVE_NET_IF_H
/* Define if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
/* Define if you have the `select' function. */
#define HAVE_SELECT
/* Define if you have the `sigaction' function. */
#undef HAVE_SIGACTION
/* Define if you have the `signal' function. */
#define HAVE_SIGNAL
/* Define if you have the `socket' function. */
#define HAVE_SOCKET
/* Define if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
/* Define if you have the `strcmpi' function. */
#undef HAVE_STRCMPI
/* Define if you have the `strdup' function. */
#define HAVE_STRDUP
/* Define if you have the `stricmp' function. */
#define HAVE_STRICMP
/* Define if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define if you have the `strtok_r' function. */
#undef HAVE_STRTOK_R
/* Define if you have the `strtoll' function. */
#undef HAVE_STRTOLL
/* Define if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H
/* Define if you have the <sys/sockio.h> header file. */
#undef HAVE_SYS_SOCKIO_H
/* Define if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H
/* Define if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H
/* Define if you have the <termios.h> header file. */
#define HAVE_TERMIOS_H
/* Define if you have the <termio.h> header file. */
#undef HAVE_TERMIO_H
/* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H
/* Name of package */
#undef PACKAGE
/* The size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
/* The size of `long long', as computed by sizeof. */
#undef SIZEOF_LONG_LONG
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T 4
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t
/* Define to `int' if <sys/types.h> does not define. */
#undef ssize_t
/* Define if you have a working ioctl FIONBIO function. */
#define HAVE_IOCTL_FIONBIO
/* to disable LDAP */
#define CURL_DISABLE_LDAP
/* Define if you have the recv function. */
#define HAVE_RECV 1
/* Define to the type of arg 1 for recv. */
#define RECV_TYPE_ARG1 int
/* Define to the type of arg 2 for recv. */
#define RECV_TYPE_ARG2 void *
/* Define to the type of arg 3 for recv. */
#define RECV_TYPE_ARG3 size_t
/* Define to the type of arg 4 for recv. */
#define RECV_TYPE_ARG4 int
/* Define to the function return type for recv. */
#define RECV_TYPE_RETV ssize_t
/* Define if you have the send function. */
#define HAVE_SEND 1
/* Define to the type of arg 1 for send. */
#define SEND_TYPE_ARG1 int
/* Define to the type qualifier of arg 2 for send. */
#define SEND_QUAL_ARG2 const
/* Define to the type of arg 2 for send. */
#define SEND_TYPE_ARG2 void *
/* Define to the type of arg 3 for send. */
#define SEND_TYPE_ARG3 size_t
/* Define to the type of arg 4 for send. */
#define SEND_TYPE_ARG4 int
/* Define to the function return type for send. */
#define SEND_TYPE_RETV ssize_t
#endif /* HEADER_CURL_CONFIG_RISCOS_H */

512
third_party/curl/lib/config-win32.h vendored Normal file
View File

@ -0,0 +1,512 @@
#ifndef HEADER_CURL_CONFIG_WIN32_H
#define HEADER_CURL_CONFIG_WIN32_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* ================================================================ */
/* Hand crafted config file for Windows */
/* ================================================================ */
/* ---------------------------------------------------------------- */
/* HEADER FILES */
/* ---------------------------------------------------------------- */
/* Define if you have the <arpa/inet.h> header file. */
/* #define HAVE_ARPA_INET_H 1 */
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define if you have the <io.h> header file. */
#define HAVE_IO_H 1
/* Define if you have the <locale.h> header file. */
#define HAVE_LOCALE_H 1
/* Define if you need <malloc.h> header even with <stdlib.h> header file. */
#define NEED_MALLOC_H 1
/* Define if you have the <netdb.h> header file. */
/* #define HAVE_NETDB_H 1 */
/* Define if you have the <netinet/in.h> header file. */
/* #define HAVE_NETINET_IN_H 1 */
/* Define to 1 if you have the <stdbool.h> header file. */
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__)
#define HAVE_STDBOOL_H 1
#endif
/* Define if you have the <sys/param.h> header file. */
#if defined(__MINGW32__)
#define HAVE_SYS_PARAM_H 1
#endif
/* Define if you have the <sys/select.h> header file. */
/* #define HAVE_SYS_SELECT_H 1 */
/* Define if you have the <sys/socket.h> header file. */
/* #define HAVE_SYS_SOCKET_H 1 */
/* Define if you have the <sys/sockio.h> header file. */
/* #define HAVE_SYS_SOCKIO_H 1 */
/* Define if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define if you have the <sys/time.h> header file. */
#if defined(__MINGW32__)
#define HAVE_SYS_TIME_H 1
#endif
/* Define if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define if you have the <sys/utime.h> header file. */
#define HAVE_SYS_UTIME_H 1
/* Define if you have the <termio.h> header file. */
/* #define HAVE_TERMIO_H 1 */
/* Define if you have the <termios.h> header file. */
/* #define HAVE_TERMIOS_H 1 */
/* Define if you have the <unistd.h> header file. */
#if defined(__MINGW32__)
#define HAVE_UNISTD_H 1
#endif
/* Define to 1 if you have the <libgen.h> header file. */
#if defined(__MINGW32__)
#define HAVE_LIBGEN_H 1
#endif
/* ---------------------------------------------------------------- */
/* OTHER HEADER INFO */
/* ---------------------------------------------------------------- */
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if bool is an available type. */
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__)
#define HAVE_BOOL_T 1
#endif
/* ---------------------------------------------------------------- */
/* FUNCTIONS */
/* ---------------------------------------------------------------- */
/* Define if you have the closesocket function. */
#define HAVE_CLOSESOCKET 1
/* Define if you have the ftruncate function. */
#if defined(__MINGW32__)
#define HAVE_FTRUNCATE 1
#endif
/* Define to 1 if you have the `getpeername' function. */
#define HAVE_GETPEERNAME 1
/* Define to 1 if you have the getsockname function. */
#define HAVE_GETSOCKNAME 1
/* Define if you have the gethostname function. */
#define HAVE_GETHOSTNAME 1
/* Define if you have the gettimeofday function. */
#if defined(__MINGW32__)
#define HAVE_GETTIMEOFDAY 1
#endif
/* Define if you have the ioctlsocket function. */
#define HAVE_IOCTLSOCKET 1
/* Define if you have a working ioctlsocket FIONBIO function. */
#define HAVE_IOCTLSOCKET_FIONBIO 1
/* Define if you have the select function. */
#define HAVE_SELECT 1
/* Define if you have the setlocale function. */
#define HAVE_SETLOCALE 1
/* Define if you have the setmode function. */
#define HAVE_SETMODE 1
/* Define if you have the socket function. */
#define HAVE_SOCKET 1
/* Define if you have the strcasecmp function. */
#if defined(__MINGW32__)
#define HAVE_STRCASECMP 1
#endif
/* Define if you have the strdup function. */
#define HAVE_STRDUP 1
/* Define if you have the stricmp function. */
#define HAVE_STRICMP 1
/* Define if you have the strtoll function. */
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__)
#define HAVE_STRTOLL 1
#endif
/* Define if you have the utime function. */
#define HAVE_UTIME 1
/* Define if you have the recv function. */
#define HAVE_RECV 1
/* Define to the type of arg 1 for recv. */
#define RECV_TYPE_ARG1 SOCKET
/* Define to the type of arg 2 for recv. */
#define RECV_TYPE_ARG2 char *
/* Define to the type of arg 3 for recv. */
#define RECV_TYPE_ARG3 int
/* Define to the type of arg 4 for recv. */
#define RECV_TYPE_ARG4 int
/* Define to the function return type for recv. */
#define RECV_TYPE_RETV int
/* Define if you have the send function. */
#define HAVE_SEND 1
/* Define to the type of arg 1 for send. */
#define SEND_TYPE_ARG1 SOCKET
/* Define to the type qualifier of arg 2 for send. */
#define SEND_QUAL_ARG2 const
/* Define to the type of arg 2 for send. */
#define SEND_TYPE_ARG2 char *
/* Define to the type of arg 3 for send. */
#define SEND_TYPE_ARG3 int
/* Define to the type of arg 4 for send. */
#define SEND_TYPE_ARG4 int
/* Define to the function return type for send. */
#define SEND_TYPE_RETV int
/* Define to 1 if you have the snprintf function. */
#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || defined(__MINGW32__)
#define HAVE_SNPRINTF 1
#endif
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 /* Vista */
/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
#define HAVE_INET_NTOP 1
/* Define to 1 if you have a IPv6 capable working inet_pton function. */
#define HAVE_INET_PTON 1
#endif
/* Define to 1 if you have the `basename' function. */
#if defined(__MINGW32__)
#define HAVE_BASENAME 1
#endif
/* Define to 1 if you have the strtok_r function. */
#if defined(__MINGW32__)
#define HAVE_STRTOK_R 1
#endif
/* Define to 1 if you have the signal function. */
#define HAVE_SIGNAL 1
/* ---------------------------------------------------------------- */
/* TYPEDEF REPLACEMENTS */
/* ---------------------------------------------------------------- */
/* Define if in_addr_t is not an available 'typedefed' type. */
#define in_addr_t unsigned long
/* Define if ssize_t is not an available 'typedefed' type. */
#ifndef _SSIZE_T_DEFINED
# if defined(__MINGW32__)
# elif defined(_WIN64)
# define _SSIZE_T_DEFINED
# define ssize_t __int64
# else
# define _SSIZE_T_DEFINED
# define ssize_t int
# endif
#endif
/* ---------------------------------------------------------------- */
/* TYPE SIZES */
/* ---------------------------------------------------------------- */
/* Define to the size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
/* Define to the size of `long long', as computed by sizeof. */
/* #define SIZEOF_LONG_LONG 8 */
/* Define to the size of `long', as computed by sizeof. */
#define SIZEOF_LONG 4
/* Define to the size of `size_t', as computed by sizeof. */
#if defined(_WIN64)
# define SIZEOF_SIZE_T 8
#else
# define SIZEOF_SIZE_T 4
#endif
/* Define to the size of `curl_off_t', as computed by sizeof. */
#define SIZEOF_CURL_OFF_T 8
/* ---------------------------------------------------------------- */
/* COMPILER SPECIFIC */
/* ---------------------------------------------------------------- */
/* Define to nothing if compiler does not support 'const' qualifier. */
/* #define const */
/* Define to nothing if compiler does not support 'volatile' qualifier. */
/* #define volatile */
/* Windows should not have HAVE_GMTIME_R defined */
/* #undef HAVE_GMTIME_R */
/* Define if the compiler supports the 'long long' data type. */
#if (defined(_MSC_VER) && (_MSC_VER >= 1310)) || defined(__MINGW32__)
#define HAVE_LONGLONG 1
#endif
/* Define to avoid VS2005 complaining about portable C functions. */
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define _CRT_SECURE_NO_DEPRECATE 1
#define _CRT_NONSTDC_NO_DEPRECATE 1
#endif
/* mingw-w64 and visual studio >= 2005 (MSVCR80)
all default to 64-bit time_t unless _USE_32BIT_TIME_T is defined */
#if (defined(_MSC_VER) && (_MSC_VER >= 1400)) || defined(__MINGW32__)
# ifndef _USE_32BIT_TIME_T
# define SIZEOF_TIME_T 8
# else
# define SIZEOF_TIME_T 4
# endif
#endif
/* Define some minimum and default build targets for Visual Studio */
#if defined(_MSC_VER)
/* Officially, Microsoft's Windows SDK versions 6.X does not support Windows
2000 as a supported build target. VS2008 default installations provides
an embedded Windows SDK v6.0A along with the claim that Windows 2000 is a
valid build target for VS2008. Popular belief is that binaries built with
VS2008 using Windows SDK versions v6.X and Windows 2000 as a build target
are functional. */
# define VS2008_MIN_TARGET 0x0500
/* The minimum build target for VS2012 is Vista unless Update 1 is installed
and the v110_xp toolset is chosen. */
# if defined(_USING_V110_SDK71_)
# define VS2012_MIN_TARGET 0x0501
# else
# define VS2012_MIN_TARGET 0x0600
# endif
/* VS2008 default build target is Windows Vista. We override default target
to be Windows XP. */
# define VS2008_DEF_TARGET 0x0501
/* VS2012 default build target is Windows Vista unless Update 1 is installed
and the v110_xp toolset is chosen. */
# if defined(_USING_V110_SDK71_)
# define VS2012_DEF_TARGET 0x0501
# else
# define VS2012_DEF_TARGET 0x0600
# endif
#endif
/* VS2008 default target settings and minimum build target check. */
#if defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER <= 1600)
# ifndef _WIN32_WINNT
# define _WIN32_WINNT VS2008_DEF_TARGET
# endif
# ifndef WINVER
# define WINVER VS2008_DEF_TARGET
# endif
# if (_WIN32_WINNT < VS2008_MIN_TARGET) || (WINVER < VS2008_MIN_TARGET)
# error VS2008 does not support Windows build targets prior to Windows 2000
# endif
#endif
/* VS2012 default target settings and minimum build target check. */
#if defined(_MSC_VER) && (_MSC_VER >= 1700)
# ifndef _WIN32_WINNT
# define _WIN32_WINNT VS2012_DEF_TARGET
# endif
# ifndef WINVER
# define WINVER VS2012_DEF_TARGET
# endif
# if (_WIN32_WINNT < VS2012_MIN_TARGET) || (WINVER < VS2012_MIN_TARGET)
# if defined(_USING_V110_SDK71_)
# error VS2012 does not support Windows build targets prior to Windows XP
# else
# error VS2012 does not support Windows build targets prior to Windows \
Vista
# endif
# endif
#endif
/* Windows XP is required for freeaddrinfo, getaddrinfo */
#define HAVE_FREEADDRINFO 1
#define HAVE_GETADDRINFO 1
#define HAVE_GETADDRINFO_THREADSAFE 1
/* ---------------------------------------------------------------- */
/* STRUCT RELATED */
/* ---------------------------------------------------------------- */
/* Define if you have struct sockaddr_storage. */
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
/* Define if you have struct timeval. */
#define HAVE_STRUCT_TIMEVAL 1
/* Define if struct sockaddr_in6 has the sin6_scope_id member. */
#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
/* ---------------------------------------------------------------- */
/* LARGE FILE SUPPORT */
/* ---------------------------------------------------------------- */
#if defined(_MSC_VER) && !defined(_WIN32_WCE)
# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
# define USE_WIN32_LARGE_FILES
# else
# define USE_WIN32_SMALL_FILES
# endif
#endif
#if defined(__MINGW32__) && !defined(USE_WIN32_LARGE_FILES)
# define USE_WIN32_LARGE_FILES
#endif
#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES)
# define USE_WIN32_SMALL_FILES
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#if defined(USE_WIN32_LARGE_FILES) && defined(__MINGW32__)
# ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
# endif
#endif
#ifdef USE_WIN32_LARGE_FILES
#define HAVE__FSEEKI64
#endif
/* Define to the size of `off_t', as computed by sizeof. */
#if defined(__MINGW32__) && \
defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
# define SIZEOF_OFF_T 8
#else
# define SIZEOF_OFF_T 4
#endif
/* ---------------------------------------------------------------- */
/* DNS RESOLVER SPECIALTY */
/* ---------------------------------------------------------------- */
/*
* Undefine both USE_ARES and USE_THREADS_WIN32 for synchronous DNS.
*/
/* Define to enable c-ares asynchronous DNS lookups. */
/* #define USE_ARES 1 */
/* Default define to enable threaded asynchronous DNS lookups. */
#if !defined(USE_SYNC_DNS) && !defined(USE_ARES) && \
!defined(USE_THREADS_WIN32)
# define USE_THREADS_WIN32 1
#endif
#if defined(USE_ARES) && defined(USE_THREADS_WIN32)
# error "Only one DNS lookup specialty may be defined at most"
#endif
/* ---------------------------------------------------------------- */
/* LDAP SUPPORT */
/* ---------------------------------------------------------------- */
#if defined(CURL_HAS_NOVELL_LDAPSDK)
#undef USE_WIN32_LDAP
#define HAVE_LDAP_SSL_H 1
#define HAVE_LDAP_URL_PARSE 1
#elif defined(CURL_HAS_OPENLDAP_LDAPSDK)
#undef USE_WIN32_LDAP
#define HAVE_LDAP_URL_PARSE 1
#else
#undef HAVE_LDAP_URL_PARSE
#define HAVE_LDAP_SSL 1
#define USE_WIN32_LDAP 1
#endif
/* Define to use the Windows crypto library. */
#if !defined(CURL_WINDOWS_APP)
#define USE_WIN32_CRYPTO
#endif
/* Define to use Unix sockets. */
#define USE_UNIX_SOCKETS
/* ---------------------------------------------------------------- */
/* ADDITIONAL DEFINITIONS */
/* ---------------------------------------------------------------- */
/* Define cpu-machine-OS */
#ifndef OS
#if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */
#define OS "i386-pc-win32"
#elif defined(_M_X64) || defined(__x86_64__) /* x86_64 (MSVC >=2005 or gcc) */
#define OS "x86_64-pc-win32"
#elif defined(_M_IA64) || defined(__ia64__) /* Itanium */
#define OS "ia64-pc-win32"
#elif defined(_M_ARM_NT) || defined(__arm__) /* ARMv7-Thumb2 (Windows RT) */
#define OS "thumbv7a-pc-win32"
#elif defined(_M_ARM64) || defined(__aarch64__) /* ARM64 (Windows 10) */
#define OS "aarch64-pc-win32"
#else
#define OS "unknown-pc-win32"
#endif
#endif
/* Name of package */
#define PACKAGE "curl"
/* If you want to build curl with the built-in manual */
#define USE_MANUAL 1
#endif /* HEADER_CURL_CONFIG_WIN32_H */

303
third_party/curl/lib/config-win32ce.h vendored Normal file
View File

@ -0,0 +1,303 @@
#ifndef HEADER_CURL_CONFIG_WIN32CE_H
#define HEADER_CURL_CONFIG_WIN32CE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* ================================================================ */
/* lib/config-win32ce.h - Hand crafted config file for windows ce */
/* ================================================================ */
/* ---------------------------------------------------------------- */
/* HEADER FILES */
/* ---------------------------------------------------------------- */
/* Define if you have the <arpa/inet.h> header file. */
/* #define HAVE_ARPA_INET_H 1 */
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define if you have the <io.h> header file. */
#define HAVE_IO_H 1
/* Define if you need the malloc.h header file even with stdlib.h */
#define NEED_MALLOC_H 1
/* Define if you have the <netdb.h> header file. */
/* #define HAVE_NETDB_H 1 */
/* Define if you have the <netinet/in.h> header file. */
/* #define HAVE_NETINET_IN_H 1 */
/* Define if you have the <sys/param.h> header file. */
/* #define HAVE_SYS_PARAM_H 1 */
/* Define if you have the <sys/select.h> header file. */
/* #define HAVE_SYS_SELECT_H 1 */
/* Define if you have the <sys/socket.h> header file. */
/* #define HAVE_SYS_SOCKET_H 1 */
/* Define if you have the <sys/sockio.h> header file. */
/* #define HAVE_SYS_SOCKIO_H 1 */
/* Define if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define if you have the <sys/time.h> header file */
/* #define HAVE_SYS_TIME_H 1 */
/* Define if you have the <sys/types.h> header file. */
/* #define HAVE_SYS_TYPES_H 1 */
/* Define if you have the <sys/utime.h> header file */
#define HAVE_SYS_UTIME_H 1
/* Define if you have the <termio.h> header file. */
/* #define HAVE_TERMIO_H 1 */
/* Define if you have the <termios.h> header file. */
/* #define HAVE_TERMIOS_H 1 */
/* Define if you have the <unistd.h> header file. */
#if defined(__MINGW32__)
#define HAVE_UNISTD_H 1
#endif
/* ---------------------------------------------------------------- */
/* OTHER HEADER INFO */
/* ---------------------------------------------------------------- */
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* ---------------------------------------------------------------- */
/* FUNCTIONS */
/* ---------------------------------------------------------------- */
/* Define if you have the closesocket function. */
#define HAVE_CLOSESOCKET 1
/* Define if you have the gethostname function. */
#define HAVE_GETHOSTNAME 1
/* Define if you have the gettimeofday function. */
/* #define HAVE_GETTIMEOFDAY 1 */
/* Define if you have the ioctlsocket function. */
#define HAVE_IOCTLSOCKET 1
/* Define if you have a working ioctlsocket FIONBIO function. */
#define HAVE_IOCTLSOCKET_FIONBIO 1
/* Define if you have the select function. */
#define HAVE_SELECT 1
/* Define if you have the socket function. */
#define HAVE_SOCKET 1
/* Define if you have the strcasecmp function. */
/* #define HAVE_STRCASECMP 1 */
/* Define if you have the strdup function. */
/* #define HAVE_STRDUP 1 */
/* Define if you have the stricmp function. */
/* #define HAVE_STRICMP 1 */
/* Define if you have the strtoll function. */
#if defined(__MINGW32__)
#define HAVE_STRTOLL 1
#endif
/* Define if you have the utime function */
#define HAVE_UTIME 1
/* Define if you have the recv function. */
#define HAVE_RECV 1
/* Define to the type of arg 1 for recv. */
#define RECV_TYPE_ARG1 SOCKET
/* Define to the type of arg 2 for recv. */
#define RECV_TYPE_ARG2 char *
/* Define to the type of arg 3 for recv. */
#define RECV_TYPE_ARG3 int
/* Define to the type of arg 4 for recv. */
#define RECV_TYPE_ARG4 int
/* Define to the function return type for recv. */
#define RECV_TYPE_RETV int
/* Define if you have the send function. */
#define HAVE_SEND 1
/* Define to the type of arg 1 for send. */
#define SEND_TYPE_ARG1 SOCKET
/* Define to the type qualifier of arg 2 for send. */
#define SEND_QUAL_ARG2 const
/* Define to the type of arg 2 for send. */
#define SEND_TYPE_ARG2 char *
/* Define to the type of arg 3 for send. */
#define SEND_TYPE_ARG3 int
/* Define to the type of arg 4 for send. */
#define SEND_TYPE_ARG4 int
/* Define to the function return type for send. */
#define SEND_TYPE_RETV int
/* ---------------------------------------------------------------- */
/* TYPEDEF REPLACEMENTS */
/* ---------------------------------------------------------------- */
/* Define this if in_addr_t is not an available 'typedefed' type */
#define in_addr_t unsigned long
/* Define ssize_t if it is not an available 'typedefed' type */
#if defined(_WIN64)
#define ssize_t __int64
#else
#define ssize_t int
#endif
/* ---------------------------------------------------------------- */
/* TYPE SIZES */
/* ---------------------------------------------------------------- */
/* The size of `int', as computed by sizeof. */
#define SIZEOF_INT 4
/* The size of `long long', as computed by sizeof. */
/* #define SIZEOF_LONG_LONG 8 */
/* Define to the size of `long', as computed by sizeof. */
#define SIZEOF_LONG 4
/* The size of `size_t', as computed by sizeof. */
#if defined(_WIN64)
# define SIZEOF_SIZE_T 8
#else
# define SIZEOF_SIZE_T 4
#endif
/* ---------------------------------------------------------------- */
/* STRUCT RELATED */
/* ---------------------------------------------------------------- */
/* Define this if you have struct sockaddr_storage */
/* #define HAVE_STRUCT_SOCKADDR_STORAGE 1 */
/* Define this if you have struct timeval */
#define HAVE_STRUCT_TIMEVAL 1
/* Define this if struct sockaddr_in6 has the sin6_scope_id member */
#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
/* ---------------------------------------------------------------- */
/* COMPILER SPECIFIC */
/* ---------------------------------------------------------------- */
/* Undef keyword 'const' if it does not work. */
/* #undef const */
/* Define to avoid VS2005 complaining about portable C functions */
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define _CRT_SECURE_NO_DEPRECATE 1
#define _CRT_NONSTDC_NO_DEPRECATE 1
#endif
/* VS2005 and later default size for time_t is 64-bit, unless */
/* _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
# ifndef _USE_32BIT_TIME_T
# define SIZEOF_TIME_T 8
# else
# define SIZEOF_TIME_T 4
# endif
#endif
/* ---------------------------------------------------------------- */
/* LARGE FILE SUPPORT */
/* ---------------------------------------------------------------- */
#if defined(_MSC_VER) && !defined(_WIN32_WCE)
# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
# define USE_WIN32_LARGE_FILES
# else
# define USE_WIN32_SMALL_FILES
# endif
#endif
#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES)
# define USE_WIN32_SMALL_FILES
#endif
/* ---------------------------------------------------------------- */
/* LDAP SUPPORT */
/* ---------------------------------------------------------------- */
#define USE_WIN32_LDAP 1
#undef HAVE_LDAP_URL_PARSE
/* ---------------------------------------------------------------- */
/* ADDITIONAL DEFINITIONS */
/* ---------------------------------------------------------------- */
/* Define cpu-machine-OS */
#ifndef OS
#define OS "i386-pc-win32ce"
#endif
/* Name of package */
#define PACKAGE "curl"
/* ---------------------------------------------------------------- */
/* WinCE */
/* ---------------------------------------------------------------- */
#ifndef UNICODE
# define UNICODE
#endif
#ifndef _UNICODE
# define _UNICODE
#endif
#define CURL_DISABLE_FILE 1
#define CURL_DISABLE_TELNET 1
#define CURL_DISABLE_LDAP 1
#define ENOSPC 1
#define ENOMEM 2
#define EAGAIN 3
extern int stat(const char *path, struct stat *buffer);
#endif /* HEADER_CURL_CONFIG_WIN32CE_H */

581
third_party/curl/lib/conncache.c vendored Normal file
View File

@ -0,0 +1,581 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Linus Nielsen Feltzing, <linus@haxx.se>
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include <curl/curl.h>
#include "urldata.h"
#include "url.h"
#include "progress.h"
#include "multiif.h"
#include "sendf.h"
#include "conncache.h"
#include "share.h"
#include "sigpipe.h"
#include "connect.h"
#include "strcase.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
#define HASHKEY_SIZE 128
static CURLcode bundle_create(struct connectbundle **bundlep)
{
DEBUGASSERT(*bundlep == NULL);
*bundlep = malloc(sizeof(struct connectbundle));
if(!*bundlep)
return CURLE_OUT_OF_MEMORY;
(*bundlep)->num_connections = 0;
(*bundlep)->multiuse = BUNDLE_UNKNOWN;
Curl_llist_init(&(*bundlep)->conn_list, NULL);
return CURLE_OK;
}
static void bundle_destroy(struct connectbundle *bundle)
{
free(bundle);
}
/* Add a connection to a bundle */
static void bundle_add_conn(struct connectbundle *bundle,
struct connectdata *conn)
{
Curl_llist_append(&bundle->conn_list, conn, &conn->bundle_node);
conn->bundle = bundle;
bundle->num_connections++;
}
/* Remove a connection from a bundle */
static int bundle_remove_conn(struct connectbundle *bundle,
struct connectdata *conn)
{
struct Curl_llist_element *curr;
curr = bundle->conn_list.head;
while(curr) {
if(curr->ptr == conn) {
Curl_llist_remove(&bundle->conn_list, curr, NULL);
bundle->num_connections--;
conn->bundle = NULL;
return 1; /* we removed a handle */
}
curr = curr->next;
}
DEBUGASSERT(0);
return 0;
}
static void free_bundle_hash_entry(void *freethis)
{
struct connectbundle *b = (struct connectbundle *) freethis;
bundle_destroy(b);
}
int Curl_conncache_init(struct conncache *connc, size_t size)
{
/* allocate a new easy handle to use when closing cached connections */
connc->closure_handle = curl_easy_init();
if(!connc->closure_handle)
return 1; /* bad */
connc->closure_handle->state.internal = true;
Curl_hash_init(&connc->hash, size, Curl_hash_str,
Curl_str_key_compare, free_bundle_hash_entry);
connc->closure_handle->state.conn_cache = connc;
return 0; /* good */
}
void Curl_conncache_destroy(struct conncache *connc)
{
if(connc)
Curl_hash_destroy(&connc->hash);
}
/* creates a key to find a bundle for this connection */
static void hashkey(struct connectdata *conn, char *buf, size_t len)
{
const char *hostname;
long port = conn->remote_port;
DEBUGASSERT(len >= HASHKEY_SIZE);
#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
hostname = conn->http_proxy.host.name;
port = conn->primary.remote_port;
}
else
#endif
if(conn->bits.conn_to_host)
hostname = conn->conn_to_host.name;
else
hostname = conn->host.name;
/* put the numbers first so that the hostname gets cut off if too long */
#ifdef USE_IPV6
msnprintf(buf, len, "%u/%ld/%s", conn->scope_id, port, hostname);
#else
msnprintf(buf, len, "%ld/%s", port, hostname);
#endif
Curl_strntolower(buf, buf, len);
}
/* Returns number of connections currently held in the connection cache.
Locks/unlocks the cache itself!
*/
size_t Curl_conncache_size(struct Curl_easy *data)
{
size_t num;
CONNCACHE_LOCK(data);
num = data->state.conn_cache->num_conn;
CONNCACHE_UNLOCK(data);
return num;
}
/* Look up the bundle with all the connections to the same host this
connectdata struct is setup to use.
**NOTE**: When it returns, it holds the connection cache lock! */
struct connectbundle *
Curl_conncache_find_bundle(struct Curl_easy *data,
struct connectdata *conn,
struct conncache *connc)
{
struct connectbundle *bundle = NULL;
CONNCACHE_LOCK(data);
if(connc) {
char key[HASHKEY_SIZE];
hashkey(conn, key, sizeof(key));
bundle = Curl_hash_pick(&connc->hash, key, strlen(key));
}
return bundle;
}
static void *conncache_add_bundle(struct conncache *connc,
char *key,
struct connectbundle *bundle)
{
return Curl_hash_add(&connc->hash, key, strlen(key), bundle);
}
static void conncache_remove_bundle(struct conncache *connc,
struct connectbundle *bundle)
{
struct Curl_hash_iterator iter;
struct Curl_hash_element *he;
if(!connc)
return;
Curl_hash_start_iterate(&connc->hash, &iter);
he = Curl_hash_next_element(&iter);
while(he) {
if(he->ptr == bundle) {
/* The bundle is destroyed by the hash destructor function,
free_bundle_hash_entry() */
Curl_hash_delete(&connc->hash, he->key, he->key_len);
return;
}
he = Curl_hash_next_element(&iter);
}
}
CURLcode Curl_conncache_add_conn(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
struct connectbundle *bundle = NULL;
struct connectdata *conn = data->conn;
struct conncache *connc = data->state.conn_cache;
DEBUGASSERT(conn);
/* *find_bundle() locks the connection cache */
bundle = Curl_conncache_find_bundle(data, conn, data->state.conn_cache);
if(!bundle) {
char key[HASHKEY_SIZE];
result = bundle_create(&bundle);
if(result) {
goto unlock;
}
hashkey(conn, key, sizeof(key));
if(!conncache_add_bundle(data->state.conn_cache, key, bundle)) {
bundle_destroy(bundle);
result = CURLE_OUT_OF_MEMORY;
goto unlock;
}
}
bundle_add_conn(bundle, conn);
conn->connection_id = connc->next_connection_id++;
connc->num_conn++;
DEBUGF(infof(data, "Added connection %" CURL_FORMAT_CURL_OFF_T ". "
"The cache now contains %zu members",
conn->connection_id, connc->num_conn));
unlock:
CONNCACHE_UNLOCK(data);
return result;
}
/*
* Removes the connectdata object from the connection cache, but the transfer
* still owns this connection.
*
* Pass TRUE/FALSE in the 'lock' argument depending on if the parent function
* already holds the lock or not.
*/
void Curl_conncache_remove_conn(struct Curl_easy *data,
struct connectdata *conn, bool lock)
{
struct connectbundle *bundle = conn->bundle;
struct conncache *connc = data->state.conn_cache;
/* The bundle pointer can be NULL, since this function can be called
due to a failed connection attempt, before being added to a bundle */
if(bundle) {
if(lock) {
CONNCACHE_LOCK(data);
}
bundle_remove_conn(bundle, conn);
if(bundle->num_connections == 0)
conncache_remove_bundle(connc, bundle);
conn->bundle = NULL; /* removed from it */
if(connc) {
connc->num_conn--;
DEBUGF(infof(data, "The cache now contains %zu members",
connc->num_conn));
}
if(lock) {
CONNCACHE_UNLOCK(data);
}
}
}
/* This function iterates the entire connection cache and calls the function
func() with the connection pointer as the first argument and the supplied
'param' argument as the other.
The conncache lock is still held when the callback is called. It needs it,
so that it can safely continue traversing the lists once the callback
returns.
Returns 1 if the loop was aborted due to the callback's return code.
Return 0 from func() to continue the loop, return 1 to abort it.
*/
bool Curl_conncache_foreach(struct Curl_easy *data,
struct conncache *connc,
void *param,
int (*func)(struct Curl_easy *data,
struct connectdata *conn, void *param))
{
struct Curl_hash_iterator iter;
struct Curl_llist_element *curr;
struct Curl_hash_element *he;
if(!connc)
return FALSE;
CONNCACHE_LOCK(data);
Curl_hash_start_iterate(&connc->hash, &iter);
he = Curl_hash_next_element(&iter);
while(he) {
struct connectbundle *bundle;
bundle = he->ptr;
he = Curl_hash_next_element(&iter);
curr = bundle->conn_list.head;
while(curr) {
/* Yes, we need to update curr before calling func(), because func()
might decide to remove the connection */
struct connectdata *conn = curr->ptr;
curr = curr->next;
if(1 == func(data, conn, param)) {
CONNCACHE_UNLOCK(data);
return TRUE;
}
}
}
CONNCACHE_UNLOCK(data);
return FALSE;
}
/* Return the first connection found in the cache. Used when closing all
connections.
NOTE: no locking is done here as this is presumably only done when cleaning
up a cache!
*/
static struct connectdata *
conncache_find_first_connection(struct conncache *connc)
{
struct Curl_hash_iterator iter;
struct Curl_hash_element *he;
struct connectbundle *bundle;
Curl_hash_start_iterate(&connc->hash, &iter);
he = Curl_hash_next_element(&iter);
while(he) {
struct Curl_llist_element *curr;
bundle = he->ptr;
curr = bundle->conn_list.head;
if(curr) {
return curr->ptr;
}
he = Curl_hash_next_element(&iter);
}
return NULL;
}
/*
* Give ownership of a connection back to the connection cache. Might
* disconnect the oldest existing in there to make space.
*
* Return TRUE if stored, FALSE if closed.
*/
bool Curl_conncache_return_conn(struct Curl_easy *data,
struct connectdata *conn)
{
unsigned int maxconnects = !data->multi->maxconnects ?
data->multi->num_easy * 4: data->multi->maxconnects;
struct connectdata *conn_candidate = NULL;
conn->lastused = Curl_now(); /* it was used up until now */
if(maxconnects && Curl_conncache_size(data) > maxconnects) {
infof(data, "Connection cache is full, closing the oldest one");
conn_candidate = Curl_conncache_extract_oldest(data);
if(conn_candidate) {
/* Use the closure handle for this disconnect so that anything that
happens during the disconnect is not stored and associated with the
'data' handle which already just finished a transfer and it is
important that details from this (unrelated) disconnect does not
taint meta-data in the data handle. */
struct conncache *connc = data->state.conn_cache;
Curl_disconnect(connc->closure_handle, conn_candidate,
/* dead_connection */ FALSE);
}
}
return (conn_candidate == conn) ? FALSE : TRUE;
}
/*
* This function finds the connection in the connection bundle that has been
* unused for the longest time.
*
* Does not lock the connection cache!
*
* Returns the pointer to the oldest idle connection, or NULL if none was
* found.
*/
struct connectdata *
Curl_conncache_extract_bundle(struct Curl_easy *data,
struct connectbundle *bundle)
{
struct Curl_llist_element *curr;
timediff_t highscore = -1;
timediff_t score;
struct curltime now;
struct connectdata *conn_candidate = NULL;
struct connectdata *conn;
(void)data;
now = Curl_now();
curr = bundle->conn_list.head;
while(curr) {
conn = curr->ptr;
if(!CONN_INUSE(conn)) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->lastused);
if(score > highscore) {
highscore = score;
conn_candidate = conn;
}
}
curr = curr->next;
}
if(conn_candidate) {
/* remove it to prevent another thread from nicking it */
bundle_remove_conn(bundle, conn_candidate);
data->state.conn_cache->num_conn--;
DEBUGF(infof(data, "The cache now contains %zu members",
data->state.conn_cache->num_conn));
}
return conn_candidate;
}
/*
* This function finds the connection in the connection cache that has been
* unused for the longest time and extracts that from the bundle.
*
* Returns the pointer to the connection, or NULL if none was found.
*/
struct connectdata *
Curl_conncache_extract_oldest(struct Curl_easy *data)
{
struct conncache *connc = data->state.conn_cache;
struct Curl_hash_iterator iter;
struct Curl_llist_element *curr;
struct Curl_hash_element *he;
timediff_t highscore =- 1;
timediff_t score;
struct curltime now;
struct connectdata *conn_candidate = NULL;
struct connectbundle *bundle;
struct connectbundle *bundle_candidate = NULL;
now = Curl_now();
CONNCACHE_LOCK(data);
Curl_hash_start_iterate(&connc->hash, &iter);
he = Curl_hash_next_element(&iter);
while(he) {
struct connectdata *conn;
bundle = he->ptr;
curr = bundle->conn_list.head;
while(curr) {
conn = curr->ptr;
if(!CONN_INUSE(conn) && !conn->bits.close &&
!conn->connect_only) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->lastused);
if(score > highscore) {
highscore = score;
conn_candidate = conn;
bundle_candidate = bundle;
}
}
curr = curr->next;
}
he = Curl_hash_next_element(&iter);
}
if(conn_candidate) {
/* remove it to prevent another thread from nicking it */
bundle_remove_conn(bundle_candidate, conn_candidate);
connc->num_conn--;
DEBUGF(infof(data, "The cache now contains %zu members",
connc->num_conn));
}
CONNCACHE_UNLOCK(data);
return conn_candidate;
}
void Curl_conncache_close_all_connections(struct conncache *connc)
{
struct connectdata *conn;
SIGPIPE_VARIABLE(pipe_st);
if(!connc->closure_handle)
return;
conn = conncache_find_first_connection(connc);
while(conn) {
sigpipe_ignore(connc->closure_handle, &pipe_st);
/* This will remove the connection from the cache */
connclose(conn, "kill all");
Curl_conncache_remove_conn(connc->closure_handle, conn, TRUE);
Curl_disconnect(connc->closure_handle, conn, FALSE);
sigpipe_restore(&pipe_st);
conn = conncache_find_first_connection(connc);
}
sigpipe_ignore(connc->closure_handle, &pipe_st);
Curl_hostcache_clean(connc->closure_handle,
connc->closure_handle->dns.hostcache);
Curl_close(&connc->closure_handle);
sigpipe_restore(&pipe_st);
}
#if 0
/* Useful for debugging the connection cache */
void Curl_conncache_print(struct conncache *connc)
{
struct Curl_hash_iterator iter;
struct Curl_llist_element *curr;
struct Curl_hash_element *he;
if(!connc)
return;
fprintf(stderr, "=Bundle cache=\n");
Curl_hash_start_iterate(connc->hash, &iter);
he = Curl_hash_next_element(&iter);
while(he) {
struct connectbundle *bundle;
struct connectdata *conn;
bundle = he->ptr;
fprintf(stderr, "%s -", he->key);
curr = bundle->conn_list->head;
while(curr) {
conn = curr->ptr;
fprintf(stderr, " [%p %d]", (void *)conn, conn->inuse);
curr = curr->next;
}
fprintf(stderr, "\n");
he = Curl_hash_next_element(&iter);
}
}
#endif

122
third_party/curl/lib/conncache.h vendored Normal file
View File

@ -0,0 +1,122 @@
#ifndef HEADER_CURL_CONNCACHE_H
#define HEADER_CURL_CONNCACHE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) Linus Nielsen Feltzing, <linus@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/*
* All accesses to struct fields and changing of data in the connection cache
* and connectbundles must be done with the conncache LOCKED. The cache might
* be shared.
*/
#include <curl/curl.h>
#include "timeval.h"
struct connectdata;
struct conncache {
struct Curl_hash hash;
size_t num_conn;
curl_off_t next_connection_id;
curl_off_t next_easy_id;
struct curltime last_cleanup;
/* handle used for closing cached connections */
struct Curl_easy *closure_handle;
};
#define BUNDLE_NO_MULTIUSE -1
#define BUNDLE_UNKNOWN 0 /* initial value */
#define BUNDLE_MULTIPLEX 2
#ifdef CURLDEBUG
/* the debug versions of these macros make extra certain that the lock is
never doubly locked or unlocked */
#define CONNCACHE_LOCK(x) \
do { \
if((x)->share) { \
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, \
CURL_LOCK_ACCESS_SINGLE); \
DEBUGASSERT(!(x)->state.conncache_lock); \
(x)->state.conncache_lock = TRUE; \
} \
} while(0)
#define CONNCACHE_UNLOCK(x) \
do { \
if((x)->share) { \
DEBUGASSERT((x)->state.conncache_lock); \
(x)->state.conncache_lock = FALSE; \
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \
} \
} while(0)
#else
#define CONNCACHE_LOCK(x) if((x)->share) \
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
#define CONNCACHE_UNLOCK(x) if((x)->share) \
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
#endif
struct connectbundle {
int multiuse; /* supports multi-use */
size_t num_connections; /* Number of connections in the bundle */
struct Curl_llist conn_list; /* The connectdata members of the bundle */
};
/* returns 1 on error, 0 is fine */
int Curl_conncache_init(struct conncache *, size_t size);
void Curl_conncache_destroy(struct conncache *connc);
/* return the correct bundle, to a host or a proxy */
struct connectbundle *Curl_conncache_find_bundle(struct Curl_easy *data,
struct connectdata *conn,
struct conncache *connc);
/* returns number of connections currently held in the connection cache */
size_t Curl_conncache_size(struct Curl_easy *data);
bool Curl_conncache_return_conn(struct Curl_easy *data,
struct connectdata *conn);
CURLcode Curl_conncache_add_conn(struct Curl_easy *data) WARN_UNUSED_RESULT;
void Curl_conncache_remove_conn(struct Curl_easy *data,
struct connectdata *conn,
bool lock);
bool Curl_conncache_foreach(struct Curl_easy *data,
struct conncache *connc,
void *param,
int (*func)(struct Curl_easy *data,
struct connectdata *conn,
void *param));
struct connectdata *
Curl_conncache_find_first_connection(struct conncache *connc);
struct connectdata *
Curl_conncache_extract_bundle(struct Curl_easy *data,
struct connectbundle *bundle);
struct connectdata *
Curl_conncache_extract_oldest(struct Curl_easy *data);
void Curl_conncache_close_all_connections(struct conncache *connc);
void Curl_conncache_print(struct conncache *connc);
#endif /* HEADER_CURL_CONNCACHE_H */

1446
third_party/curl/lib/connect.c vendored Normal file

File diff suppressed because it is too large Load Diff

133
third_party/curl/lib/connect.h vendored Normal file
View File

@ -0,0 +1,133 @@
#ifndef HEADER_CURL_CONNECT_H
#define HEADER_CURL_CONNECT_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */
#include "sockaddr.h"
#include "timeval.h"
struct Curl_dns_entry;
struct ip_quadruple;
/* generic function that returns how much time there's left to run, according
to the timeouts set */
timediff_t Curl_timeleft(struct Curl_easy *data,
struct curltime *nowp,
bool duringconnect);
#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
/*
* Used to extract socket and connectdata struct for the most recent
* transfer on the given Curl_easy.
*
* The returned socket will be CURL_SOCKET_BAD in case of failure!
*/
curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
struct connectdata **connp);
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
char *addr, int *port);
void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
struct ip_quadruple *ip);
/*
* Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
* argument specifies if it is the end of a connection or a stream.
*
* For stream-based protocols (such as HTTP/2), a stream close will not cause
* a connection close. Other protocols will close the connection for both
* cases.
*
* It sets the bit.close bit to TRUE (with an explanation for debug builds),
* when the connection will close.
*/
#define CONNCTRL_KEEP 0 /* undo a marked closure */
#define CONNCTRL_CONNECTION 1
#define CONNCTRL_STREAM 2
void Curl_conncontrol(struct connectdata *conn,
int closeit
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
, const char *reason
#endif
);
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM, y)
#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION, y)
#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP, y)
#else /* if !DEBUGBUILD || CURL_DISABLE_VERBOSE_STRINGS */
#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM)
#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION)
#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP)
#endif
/**
* Create a cfilter for making an "ip" connection to the
* given address, using parameters from `conn`. The "ip" connection
* can be a TCP socket, a UDP socket or even a QUIC connection.
*
* It MUST use only the supplied `ai` for its connection attempt.
*
* Such a filter may be used in "happy eyeball" scenarios, and its
* `connect` implementation needs to support non-blocking. Once connected,
* it MAY be installed in the connection filter chain to serve transfers.
*/
typedef CURLcode cf_ip_connect_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport);
CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost,
int transport,
int ssl_mode);
/**
* Setup the cfilters at `sockindex` in connection `conn`.
* If no filter chain is installed yet, inspects the configuration
* in `data` and `conn? to install a suitable filter chain.
*/
CURLcode Curl_conn_setup(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost,
int ssl_mode);
extern struct Curl_cftype Curl_cft_happy_eyeballs;
extern struct Curl_cftype Curl_cft_setup;
#ifdef DEBUGBUILD
void Curl_debug_set_transport_provider(int transport,
cf_ip_connect_create *cf_create);
#endif
#endif /* HEADER_CURL_CONNECT_H */

1079
third_party/curl/lib/content_encoding.c vendored Normal file

File diff suppressed because it is too large Load Diff

34
third_party/curl/lib/content_encoding.h vendored Normal file
View File

@ -0,0 +1,34 @@
#ifndef HEADER_CURL_CONTENT_ENCODING_H
#define HEADER_CURL_CONTENT_ENCODING_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
struct Curl_cwriter;
void Curl_all_content_encodings(char *buf, size_t blen);
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int is_transfer);
#endif /* HEADER_CURL_CONTENT_ENCODING_H */

1771
third_party/curl/lib/cookie.c vendored Normal file

File diff suppressed because it is too large Load Diff

138
third_party/curl/lib/cookie.h vendored Normal file
View File

@ -0,0 +1,138 @@
#ifndef HEADER_CURL_COOKIE_H
#define HEADER_CURL_COOKIE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include <curl/curl.h>
struct Cookie {
struct Cookie *next; /* next in the chain */
char *name; /* <this> = value */
char *value; /* name = <this> */
char *path; /* path = <this> which is in Set-Cookie: */
char *spath; /* sanitized cookie path */
char *domain; /* domain = <this> */
curl_off_t expires; /* expires = <this> */
bool tailmatch; /* whether we do tail-matching of the domain name */
bool secure; /* whether the 'secure' keyword was used */
bool livecookie; /* updated from a server, not a stored file */
bool httponly; /* true if the httponly directive is present */
int creationtime; /* time when the cookie was written */
unsigned char prefix; /* bitmap fields indicating which prefix are set */
};
/*
* Available cookie prefixes, as defined in
* draft-ietf-httpbis-rfc6265bis-02
*/
#define COOKIE_PREFIX__SECURE (1<<0)
#define COOKIE_PREFIX__HOST (1<<1)
#define COOKIE_HASH_SIZE 63
struct CookieInfo {
/* linked list of cookies we know of */
struct Cookie *cookies[COOKIE_HASH_SIZE];
curl_off_t next_expiration; /* the next time at which expiration happens */
int numcookies; /* number of cookies in the "jar" */
int lastct; /* last creation-time used in the jar */
bool running; /* state info, for cookie adding information */
bool newsession; /* new session, discard session cookies on load */
};
/* The maximum sizes we accept for cookies. RFC 6265 section 6.1 says
"general-use user agents SHOULD provide each of the following minimum
capabilities":
- At least 4096 bytes per cookie (as measured by the sum of the length of
the cookie's name, value, and attributes).
In the 6265bis draft document section 5.4 it is phrased even stronger: "If
the sum of the lengths of the name string and the value string is more than
4096 octets, abort these steps and ignore the set-cookie-string entirely."
*/
/** Limits for INCOMING cookies **/
/* The longest we allow a line to be when reading a cookie from a HTTP header
or from a cookie jar */
#define MAX_COOKIE_LINE 5000
/* Maximum length of an incoming cookie name or content we deal with. Longer
cookies are ignored. */
#define MAX_NAME 4096
/* Maximum number of Set-Cookie: lines accepted in a single response. If more
such header lines are received, they are ignored. This value must be less
than 256 since an unsigned char is used to count. */
#define MAX_SET_COOKIE_AMOUNT 50
/** Limits for OUTGOING cookies **/
/* Maximum size for an outgoing cookie line libcurl will use in an http
request. This is the default maximum length used in some versions of Apache
httpd. */
#define MAX_COOKIE_HEADER_LEN 8190
/* Maximum number of cookies libcurl will send in a single request, even if
there might be more cookies that match. One reason to cap the number is to
keep the maximum HTTP request within the maximum allowed size. */
#define MAX_COOKIE_SEND_AMOUNT 150
struct Curl_easy;
/*
* Add a cookie to the internal list of cookies. The domain and path arguments
* are only used if the header boolean is TRUE.
*/
struct Cookie *Curl_cookie_add(struct Curl_easy *data,
struct CookieInfo *c, bool header,
bool noexpiry, const char *lineptr,
const char *domain, const char *path,
bool secure);
struct Cookie *Curl_cookie_getlist(struct Curl_easy *data,
struct CookieInfo *c, const char *host,
const char *path, bool secure);
void Curl_cookie_freelist(struct Cookie *cookies);
void Curl_cookie_clearall(struct CookieInfo *cookies);
void Curl_cookie_clearsess(struct CookieInfo *cookies);
#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES)
#define Curl_cookie_list(x) NULL
#define Curl_cookie_loadfiles(x) Curl_nop_stmt
#define Curl_cookie_init(x,y,z,w) NULL
#define Curl_cookie_cleanup(x) Curl_nop_stmt
#define Curl_flush_cookies(x,y) Curl_nop_stmt
#else
void Curl_flush_cookies(struct Curl_easy *data, bool cleanup);
void Curl_cookie_cleanup(struct CookieInfo *c);
struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
const char *file, struct CookieInfo *inc,
bool newsession);
struct curl_slist *Curl_cookie_list(struct Curl_easy *data);
void Curl_cookie_loadfiles(struct Curl_easy *data);
#endif
#endif /* HEADER_CURL_COOKIE_H */

592
third_party/curl/lib/curl_addrinfo.c vendored Normal file
View File

@ -0,0 +1,592 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include <curl/curl.h>
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_NETINET_IN6_H
# include <netinet/in6.h>
#endif
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_SYS_UN_H
# include <sys/un.h>
#endif
#ifdef __VMS
# include <in.h>
# include <inet.h>
#endif
#include <stddef.h>
#include "curl_addrinfo.h"
#include "inet_pton.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
/*
* Curl_freeaddrinfo()
*
* This is used to free a linked list of Curl_addrinfo structs along
* with all its associated allocated storage. This function should be
* called once for each successful call to Curl_getaddrinfo_ex() or to
* any function call which actually allocates a Curl_addrinfo struct.
*/
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
/* workaround icc 9.1 optimizer issue */
# define vqualifier volatile
#else
# define vqualifier
#endif
void
Curl_freeaddrinfo(struct Curl_addrinfo *cahead)
{
struct Curl_addrinfo *vqualifier canext;
struct Curl_addrinfo *ca;
for(ca = cahead; ca; ca = canext) {
canext = ca->ai_next;
free(ca);
}
}
#ifdef HAVE_GETADDRINFO
/*
* Curl_getaddrinfo_ex()
*
* This is a wrapper function around system's getaddrinfo(), with
* the only difference that instead of returning a linked list of
* addrinfo structs this one returns a linked list of Curl_addrinfo
* ones. The memory allocated by this function *MUST* be free'd with
* Curl_freeaddrinfo(). For each successful call to this function
* there must be an associated call later to Curl_freeaddrinfo().
*
* There should be no single call to system's getaddrinfo() in the
* whole library, any such call should be 'routed' through this one.
*/
int
Curl_getaddrinfo_ex(const char *nodename,
const char *servname,
const struct addrinfo *hints,
struct Curl_addrinfo **result)
{
const struct addrinfo *ai;
struct addrinfo *aihead;
struct Curl_addrinfo *cafirst = NULL;
struct Curl_addrinfo *calast = NULL;
struct Curl_addrinfo *ca;
size_t ss_size;
int error;
*result = NULL; /* assume failure */
error = getaddrinfo(nodename, servname, hints, &aihead);
if(error)
return error;
/* traverse the addrinfo list */
for(ai = aihead; ai != NULL; ai = ai->ai_next) {
size_t namelen = ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0;
/* ignore elements with unsupported address family, */
/* settle family-specific sockaddr structure size. */
if(ai->ai_family == AF_INET)
ss_size = sizeof(struct sockaddr_in);
#ifdef USE_IPV6
else if(ai->ai_family == AF_INET6)
ss_size = sizeof(struct sockaddr_in6);
#endif
else
continue;
/* ignore elements without required address info */
if(!ai->ai_addr || !(ai->ai_addrlen > 0))
continue;
/* ignore elements with bogus address size */
if((size_t)ai->ai_addrlen < ss_size)
continue;
ca = malloc(sizeof(struct Curl_addrinfo) + ss_size + namelen);
if(!ca) {
error = EAI_MEMORY;
break;
}
/* copy each structure member individually, member ordering, */
/* size, or padding might be different for each platform. */
ca->ai_flags = ai->ai_flags;
ca->ai_family = ai->ai_family;
ca->ai_socktype = ai->ai_socktype;
ca->ai_protocol = ai->ai_protocol;
ca->ai_addrlen = (curl_socklen_t)ss_size;
ca->ai_addr = NULL;
ca->ai_canonname = NULL;
ca->ai_next = NULL;
ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
memcpy(ca->ai_addr, ai->ai_addr, ss_size);
if(namelen) {
ca->ai_canonname = (void *)((char *)ca->ai_addr + ss_size);
memcpy(ca->ai_canonname, ai->ai_canonname, namelen);
}
/* if the return list is empty, this becomes the first element */
if(!cafirst)
cafirst = ca;
/* add this element last in the return list */
if(calast)
calast->ai_next = ca;
calast = ca;
}
/* destroy the addrinfo list */
if(aihead)
freeaddrinfo(aihead);
/* if we failed, also destroy the Curl_addrinfo list */
if(error) {
Curl_freeaddrinfo(cafirst);
cafirst = NULL;
}
else if(!cafirst) {
#ifdef EAI_NONAME
/* rfc3493 conformant */
error = EAI_NONAME;
#else
/* rfc3493 obsoleted */
error = EAI_NODATA;
#endif
#ifdef USE_WINSOCK
SET_SOCKERRNO(error);
#endif
}
*result = cafirst;
/* This is not a CURLcode */
return error;
}
#endif /* HAVE_GETADDRINFO */
/*
* Curl_he2ai()
*
* This function returns a pointer to the first element of a newly allocated
* Curl_addrinfo struct linked list filled with the data of a given hostent.
* Curl_addrinfo is meant to work like the addrinfo struct does for a IPv6
* stack, but usable also for IPv4, all hosts and environments.
*
* The memory allocated by this function *MUST* be free'd later on calling
* Curl_freeaddrinfo(). For each successful call to this function there
* must be an associated call later to Curl_freeaddrinfo().
*
* Curl_addrinfo defined in "lib/curl_addrinfo.h"
*
* struct Curl_addrinfo {
* int ai_flags;
* int ai_family;
* int ai_socktype;
* int ai_protocol;
* curl_socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo *
* char *ai_canonname;
* struct sockaddr *ai_addr;
* struct Curl_addrinfo *ai_next;
* };
*
* hostent defined in <netdb.h>
*
* struct hostent {
* char *h_name;
* char **h_aliases;
* int h_addrtype;
* int h_length;
* char **h_addr_list;
* };
*
* for backward compatibility:
*
* #define h_addr h_addr_list[0]
*/
struct Curl_addrinfo *
Curl_he2ai(const struct hostent *he, int port)
{
struct Curl_addrinfo *ai;
struct Curl_addrinfo *prevai = NULL;
struct Curl_addrinfo *firstai = NULL;
struct sockaddr_in *addr;
#ifdef USE_IPV6
struct sockaddr_in6 *addr6;
#endif
CURLcode result = CURLE_OK;
int i;
char *curr;
if(!he)
/* no input == no output! */
return NULL;
DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL));
for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) {
size_t ss_size;
size_t namelen = strlen(he->h_name) + 1; /* include null-terminator */
#ifdef USE_IPV6
if(he->h_addrtype == AF_INET6)
ss_size = sizeof(struct sockaddr_in6);
else
#endif
ss_size = sizeof(struct sockaddr_in);
/* allocate memory to hold the struct, the address and the name */
ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + namelen);
if(!ai) {
result = CURLE_OUT_OF_MEMORY;
break;
}
/* put the address after the struct */
ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
/* then put the name after the address */
ai->ai_canonname = (char *)ai->ai_addr + ss_size;
memcpy(ai->ai_canonname, he->h_name, namelen);
if(!firstai)
/* store the pointer we want to return from this function */
firstai = ai;
if(prevai)
/* make the previous entry point to this */
prevai->ai_next = ai;
ai->ai_family = he->h_addrtype;
/* we return all names as STREAM, so when using this address for TFTP
the type must be ignored and conn->socktype be used instead! */
ai->ai_socktype = SOCK_STREAM;
ai->ai_addrlen = (curl_socklen_t)ss_size;
/* leave the rest of the struct filled with zero */
switch(ai->ai_family) {
case AF_INET:
addr = (void *)ai->ai_addr; /* storage area for this info */
memcpy(&addr->sin_addr, curr, sizeof(struct in_addr));
addr->sin_family = (CURL_SA_FAMILY_T)(he->h_addrtype);
addr->sin_port = htons((unsigned short)port);
break;
#ifdef USE_IPV6
case AF_INET6:
addr6 = (void *)ai->ai_addr; /* storage area for this info */
memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr));
addr6->sin6_family = (CURL_SA_FAMILY_T)(he->h_addrtype);
addr6->sin6_port = htons((unsigned short)port);
break;
#endif
}
prevai = ai;
}
if(result) {
Curl_freeaddrinfo(firstai);
firstai = NULL;
}
return firstai;
}
struct namebuff {
struct hostent hostentry;
union {
struct in_addr ina4;
#ifdef USE_IPV6
struct in6_addr ina6;
#endif
} addrentry;
char *h_addr_list[2];
};
/*
* Curl_ip2addr()
*
* This function takes an internet address, in binary form, as input parameter
* along with its address family and the string version of the address, and it
* returns a Curl_addrinfo chain filled in correctly with information for the
* given address/host
*/
struct Curl_addrinfo *
Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
{
struct Curl_addrinfo *ai;
#if defined(__VMS) && \
defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
#pragma pointer_size save
#pragma pointer_size short
#pragma message disable PTRMISMATCH
#endif
struct hostent *h;
struct namebuff *buf;
char *addrentry;
char *hoststr;
size_t addrsize;
DEBUGASSERT(inaddr && hostname);
buf = malloc(sizeof(struct namebuff));
if(!buf)
return NULL;
hoststr = strdup(hostname);
if(!hoststr) {
free(buf);
return NULL;
}
switch(af) {
case AF_INET:
addrsize = sizeof(struct in_addr);
addrentry = (void *)&buf->addrentry.ina4;
memcpy(addrentry, inaddr, sizeof(struct in_addr));
break;
#ifdef USE_IPV6
case AF_INET6:
addrsize = sizeof(struct in6_addr);
addrentry = (void *)&buf->addrentry.ina6;
memcpy(addrentry, inaddr, sizeof(struct in6_addr));
break;
#endif
default:
free(hoststr);
free(buf);
return NULL;
}
h = &buf->hostentry;
h->h_name = hoststr;
h->h_aliases = NULL;
h->h_addrtype = (short)af;
h->h_length = (short)addrsize;
h->h_addr_list = &buf->h_addr_list[0];
h->h_addr_list[0] = addrentry;
h->h_addr_list[1] = NULL; /* terminate list of entries */
#if defined(__VMS) && \
defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
#pragma pointer_size restore
#pragma message enable PTRMISMATCH
#endif
ai = Curl_he2ai(h, port);
free(hoststr);
free(buf);
return ai;
}
/*
* Given an IPv4 or IPv6 dotted string address, this converts it to a proper
* allocated Curl_addrinfo struct and returns it.
*/
struct Curl_addrinfo *Curl_str2addr(char *address, int port)
{
struct in_addr in;
if(Curl_inet_pton(AF_INET, address, &in) > 0)
/* This is a dotted IP address 123.123.123.123-style */
return Curl_ip2addr(AF_INET, &in, address, port);
#ifdef USE_IPV6
{
struct in6_addr in6;
if(Curl_inet_pton(AF_INET6, address, &in6) > 0)
/* This is a dotted IPv6 address ::1-style */
return Curl_ip2addr(AF_INET6, &in6, address, port);
}
#endif
return NULL; /* bad input format */
}
#ifdef USE_UNIX_SOCKETS
/**
* Given a path to a Unix domain socket, return a newly allocated Curl_addrinfo
* struct initialized with this path.
* Set '*longpath' to TRUE if the error is a too long path.
*/
struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath,
bool abstract)
{
struct Curl_addrinfo *ai;
struct sockaddr_un *sa_un;
size_t path_len;
*longpath = FALSE;
ai = calloc(1, sizeof(struct Curl_addrinfo) + sizeof(struct sockaddr_un));
if(!ai)
return NULL;
ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
sa_un = (void *) ai->ai_addr;
sa_un->sun_family = AF_UNIX;
/* sun_path must be able to store the NUL-terminated path */
path_len = strlen(path) + 1;
if(path_len > sizeof(sa_un->sun_path)) {
free(ai);
*longpath = TRUE;
return NULL;
}
ai->ai_family = AF_UNIX;
ai->ai_socktype = SOCK_STREAM; /* assume reliable transport for HTTP */
ai->ai_addrlen = (curl_socklen_t)
((offsetof(struct sockaddr_un, sun_path) + path_len) & 0x7FFFFFFF);
/* Abstract Unix domain socket have NULL prefix instead of suffix */
if(abstract)
memcpy(sa_un->sun_path + 1, path, path_len - 1);
else
memcpy(sa_un->sun_path, path, path_len); /* copy NUL byte */
return ai;
}
#endif
#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
defined(HAVE_FREEADDRINFO)
/*
* curl_dbg_freeaddrinfo()
*
* This is strictly for memory tracing and are using the same style as the
* family otherwise present in memdebug.c. I put these ones here since they
* require a bunch of structs I didn't want to include in memdebug.c
*/
void
curl_dbg_freeaddrinfo(struct addrinfo *freethis,
int line, const char *source)
{
curl_dbg_log("ADDR %s:%d freeaddrinfo(%p)\n",
source, line, (void *)freethis);
#ifdef USE_LWIPSOCK
lwip_freeaddrinfo(freethis);
#else
(freeaddrinfo)(freethis);
#endif
}
#endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */
#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
/*
* curl_dbg_getaddrinfo()
*
* This is strictly for memory tracing and are using the same style as the
* family otherwise present in memdebug.c. I put these ones here since they
* require a bunch of structs I didn't want to include in memdebug.c
*/
int
curl_dbg_getaddrinfo(const char *hostname,
const char *service,
const struct addrinfo *hints,
struct addrinfo **result,
int line, const char *source)
{
#ifdef USE_LWIPSOCK
int res = lwip_getaddrinfo(hostname, service, hints, result);
#else
int res = (getaddrinfo)(hostname, service, hints, result);
#endif
if(0 == res)
/* success */
curl_dbg_log("ADDR %s:%d getaddrinfo() = %p\n",
source, line, (void *)*result);
else
curl_dbg_log("ADDR %s:%d getaddrinfo() failed\n",
source, line);
return res;
}
#endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */
#if defined(HAVE_GETADDRINFO) && defined(USE_RESOLVE_ON_IPS)
/*
* Work-arounds the sin6_port is always zero bug on iOS 9.3.2 and Mac OS X
* 10.11.5.
*/
void Curl_addrinfo_set_port(struct Curl_addrinfo *addrinfo, int port)
{
struct Curl_addrinfo *ca;
struct sockaddr_in *addr;
#ifdef USE_IPV6
struct sockaddr_in6 *addr6;
#endif
for(ca = addrinfo; ca != NULL; ca = ca->ai_next) {
switch(ca->ai_family) {
case AF_INET:
addr = (void *)ca->ai_addr; /* storage area for this info */
addr->sin_port = htons((unsigned short)port);
break;
#ifdef USE_IPV6
case AF_INET6:
addr6 = (void *)ca->ai_addr; /* storage area for this info */
addr6->sin6_port = htons((unsigned short)port);
break;
#endif
}
}
}
#endif

108
third_party/curl/lib/curl_addrinfo.h vendored Normal file
View File

@ -0,0 +1,108 @@
#ifndef HEADER_CURL_ADDRINFO_H
#define HEADER_CURL_ADDRINFO_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef __VMS
# include <in.h>
# include <inet.h>
# include <stdlib.h>
#endif
/*
* Curl_addrinfo is our internal struct definition that we use to allow
* consistent internal handling of this data. We use this even when the
* system provides an addrinfo structure definition. And we use this for
* all sorts of IPv4 and IPV6 builds.
*/
struct Curl_addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
curl_socklen_t ai_addrlen; /* Follow rfc3493 struct addrinfo */
char *ai_canonname;
struct sockaddr *ai_addr;
struct Curl_addrinfo *ai_next;
};
void
Curl_freeaddrinfo(struct Curl_addrinfo *cahead);
#ifdef HAVE_GETADDRINFO
int
Curl_getaddrinfo_ex(const char *nodename,
const char *servname,
const struct addrinfo *hints,
struct Curl_addrinfo **result);
#endif
struct Curl_addrinfo *
Curl_he2ai(const struct hostent *he, int port);
struct Curl_addrinfo *
Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
struct Curl_addrinfo *Curl_str2addr(char *dotted, int port);
#ifdef USE_UNIX_SOCKETS
struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath,
bool abstract);
#endif
#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
defined(HAVE_FREEADDRINFO)
void
curl_dbg_freeaddrinfo(struct addrinfo *freethis, int line, const char *source);
#endif
#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
int
curl_dbg_getaddrinfo(const char *hostname, const char *service,
const struct addrinfo *hints, struct addrinfo **result,
int line, const char *source);
#endif
#ifdef HAVE_GETADDRINFO
#ifdef USE_RESOLVE_ON_IPS
void Curl_addrinfo_set_port(struct Curl_addrinfo *addrinfo, int port);
#else
#define Curl_addrinfo_set_port(x,y)
#endif
#endif
#endif /* HEADER_CURL_ADDRINFO_H */

41
third_party/curl/lib/curl_base64.h vendored Normal file
View File

@ -0,0 +1,41 @@
#ifndef HEADER_CURL_BASE64_H
#define HEADER_CURL_BASE64_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#ifndef BUILDING_LIBCURL
/* this renames functions so that the tool code can use the same code
without getting symbol collisions */
#define Curl_base64_encode(a,b,c,d) curlx_base64_encode(a,b,c,d)
#define Curl_base64url_encode(a,b,c,d) curlx_base64url_encode(a,b,c,d)
#define Curl_base64_decode(a,b,c) curlx_base64_decode(a,b,c)
#endif
CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
char **outptr, size_t *outlen);
CURLcode Curl_base64url_encode(const char *inputbuff, size_t insize,
char **outptr, size_t *outlen);
CURLcode Curl_base64_decode(const char *src,
unsigned char **outptr, size_t *outlen);
#endif /* HEADER_CURL_BASE64_H */

810
third_party/curl/lib/curl_config.h.cmake vendored Normal file
View File

@ -0,0 +1,810 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* lib/curl_config.h.in. Generated somehow by cmake. */
/* Location of default 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}"
/* Default SSL backend */
#cmakedefine CURL_DEFAULT_SSL_BACKEND "${CURL_DEFAULT_SSL_BACKEND}"
/* disables alt-svc */
#cmakedefine CURL_DISABLE_ALTSVC 1
/* disables cookies support */
#cmakedefine CURL_DISABLE_COOKIES 1
/* disables Basic authentication */
#cmakedefine CURL_DISABLE_BASIC_AUTH 1
/* disables Bearer authentication */
#cmakedefine CURL_DISABLE_BEARER_AUTH 1
/* disables Digest authentication */
#cmakedefine CURL_DISABLE_DIGEST_AUTH 1
/* disables Kerberos authentication */
#cmakedefine CURL_DISABLE_KERBEROS_AUTH 1
/* disables negotiate authentication */
#cmakedefine CURL_DISABLE_NEGOTIATE_AUTH 1
/* disables AWS-SIG4 */
#cmakedefine CURL_DISABLE_AWS 1
/* disables DICT */
#cmakedefine CURL_DISABLE_DICT 1
/* disables DNS-over-HTTPS */
#cmakedefine CURL_DISABLE_DOH 1
/* disables FILE */
#cmakedefine CURL_DISABLE_FILE 1
/* disables form api */
#cmakedefine CURL_DISABLE_FORM_API 1
/* disables FTP */
#cmakedefine CURL_DISABLE_FTP 1
/* disables curl_easy_options API for existing options to curl_easy_setopt */
#cmakedefine CURL_DISABLE_GETOPTIONS 1
/* disables GOPHER */
#cmakedefine CURL_DISABLE_GOPHER 1
/* disables headers-api support */
#cmakedefine CURL_DISABLE_HEADERS_API 1
/* disables HSTS support */
#cmakedefine CURL_DISABLE_HSTS 1
/* disables HTTP */
#cmakedefine CURL_DISABLE_HTTP 1
/* disables IMAP */
#cmakedefine CURL_DISABLE_IMAP 1
/* disables LDAP */
#cmakedefine CURL_DISABLE_LDAP 1
/* disables LDAPS */
#cmakedefine CURL_DISABLE_LDAPS 1
/* disables --libcurl option from the curl tool */
#cmakedefine CURL_DISABLE_LIBCURL_OPTION 1
/* disables MIME support */
#cmakedefine CURL_DISABLE_MIME 1
/* disables local binding support */
#cmakedefine CURL_DISABLE_BINDLOCAL 1
/* disables MQTT */
#cmakedefine CURL_DISABLE_MQTT 1
/* disables netrc parser */
#cmakedefine CURL_DISABLE_NETRC 1
/* disables NTLM support */
#cmakedefine CURL_DISABLE_NTLM 1
/* disables date parsing */
#cmakedefine CURL_DISABLE_PARSEDATE 1
/* disables POP3 */
#cmakedefine CURL_DISABLE_POP3 1
/* disables built-in progress meter */
#cmakedefine CURL_DISABLE_PROGRESS_METER 1
/* disables proxies */
#cmakedefine CURL_DISABLE_PROXY 1
/* disables RTSP */
#cmakedefine CURL_DISABLE_RTSP 1
/* disables SMB */
#cmakedefine CURL_DISABLE_SMB 1
/* disables SMTP */
#cmakedefine CURL_DISABLE_SMTP 1
/* disables use of socketpair for curl_multi_poll */
#cmakedefine CURL_DISABLE_SOCKETPAIR 1
/* disables TELNET */
#cmakedefine CURL_DISABLE_TELNET 1
/* disables TFTP */
#cmakedefine CURL_DISABLE_TFTP 1
/* disables verbose strings */
#cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1
/* to make a symbol visible */
#cmakedefine CURL_EXTERN_SYMBOL ${CURL_EXTERN_SYMBOL}
/* Ensure using CURL_EXTERN_SYMBOL is possible */
#ifndef CURL_EXTERN_SYMBOL
#define CURL_EXTERN_SYMBOL
#endif
/* Allow SMB to work on Windows */
#cmakedefine USE_WIN32_CRYPTO 1
/* Use Windows LDAP implementation */
#cmakedefine USE_WIN32_LDAP 1
/* Define if you want to enable IPv6 support */
#cmakedefine USE_IPV6 1
/* Define to 1 if you have the alarm function. */
#cmakedefine HAVE_ALARM 1
/* Define to 1 if you have the arc4random function. */
#cmakedefine HAVE_ARC4RANDOM 1
/* Define to 1 if you have the <arpa/inet.h> header file. */
#cmakedefine HAVE_ARPA_INET_H 1
/* Define to 1 if you have _Atomic support. */
#cmakedefine HAVE_ATOMIC 1
/* Define to 1 if you have the `fnmatch' function. */
#cmakedefine HAVE_FNMATCH 1
/* Define to 1 if you have the `basename' function. */
#cmakedefine HAVE_BASENAME 1
/* Define to 1 if bool is an available type. */
#cmakedefine HAVE_BOOL_T 1
/* Define to 1 if you have the __builtin_available function. */
#cmakedefine HAVE_BUILTIN_AVAILABLE 1
/* Define to 1 if you have the clock_gettime function and monotonic timer. */
#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC 1
/* Define to 1 if you have the clock_gettime function and raw monotonic timer.
*/
#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC_RAW 1
/* Define to 1 if you have the `closesocket' function. */
#cmakedefine HAVE_CLOSESOCKET 1
/* Define to 1 if you have the <dirent.h> header file. */
#cmakedefine HAVE_DIRENT_H 1
/* Define to 1 if you have the `opendir' function. */
#cmakedefine HAVE_OPENDIR 1
/* Define to 1 if you have the fcntl function. */
#cmakedefine HAVE_FCNTL 1
/* Define to 1 if you have the <fcntl.h> header file. */
#cmakedefine HAVE_FCNTL_H 1
/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
#cmakedefine HAVE_FCNTL_O_NONBLOCK 1
/* Define to 1 if you have the freeaddrinfo function. */
#cmakedefine HAVE_FREEADDRINFO 1
/* Define to 1 if you have the fseeko function. */
#cmakedefine HAVE_FSEEKO 1
/* Define to 1 if you have the fseeko declaration. */
#cmakedefine HAVE_DECL_FSEEKO 1
/* Define to 1 if you have the _fseeki64 function. */
#cmakedefine HAVE__FSEEKI64 1
/* Define to 1 if you have the ftruncate function. */
#cmakedefine HAVE_FTRUNCATE 1
/* Define to 1 if you have a working getaddrinfo function. */
#cmakedefine HAVE_GETADDRINFO 1
/* Define to 1 if the getaddrinfo function is threadsafe. */
#cmakedefine HAVE_GETADDRINFO_THREADSAFE 1
/* Define to 1 if you have the `geteuid' function. */
#cmakedefine HAVE_GETEUID 1
/* Define to 1 if you have the `getppid' function. */
#cmakedefine HAVE_GETPPID 1
/* Define to 1 if you have the gethostbyname_r function. */
#cmakedefine HAVE_GETHOSTBYNAME_R 1
/* gethostbyname_r() takes 3 args */
#cmakedefine HAVE_GETHOSTBYNAME_R_3 1
/* gethostbyname_r() takes 5 args */
#cmakedefine HAVE_GETHOSTBYNAME_R_5 1
/* gethostbyname_r() takes 6 args */
#cmakedefine HAVE_GETHOSTBYNAME_R_6 1
/* Define to 1 if you have the gethostname function. */
#cmakedefine HAVE_GETHOSTNAME 1
/* Define to 1 if you have a working getifaddrs function. */
#cmakedefine HAVE_GETIFADDRS 1
/* Define to 1 if you have the `getpass_r' function. */
#cmakedefine HAVE_GETPASS_R 1
/* Define to 1 if you have the `getpeername' function. */
#cmakedefine HAVE_GETPEERNAME 1
/* Define to 1 if you have the `getsockname' function. */
#cmakedefine HAVE_GETSOCKNAME 1
/* Define to 1 if you have the `if_nametoindex' function. */
#cmakedefine HAVE_IF_NAMETOINDEX 1
/* Define to 1 if you have the `getpwuid' function. */
#cmakedefine HAVE_GETPWUID 1
/* Define to 1 if you have the `getpwuid_r' function. */
#cmakedefine HAVE_GETPWUID_R 1
/* Define to 1 if you have the `getrlimit' function. */
#cmakedefine HAVE_GETRLIMIT 1
/* Define to 1 if you have the `gettimeofday' function. */
#cmakedefine HAVE_GETTIMEOFDAY 1
/* Define to 1 if you have a working glibc-style strerror_r function. */
#cmakedefine HAVE_GLIBC_STRERROR_R 1
/* Define to 1 if you have a working gmtime_r function. */
#cmakedefine HAVE_GMTIME_R 1
/* if you have the gssapi libraries */
#cmakedefine HAVE_GSSAPI 1
/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
#cmakedefine HAVE_GSSAPI_GSSAPI_GENERIC_H 1
/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
#cmakedefine HAVE_GSSAPI_GSSAPI_H 1
/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
#cmakedefine HAVE_GSSAPI_GSSAPI_KRB5_H 1
/* if you have the GNU gssapi libraries */
#cmakedefine HAVE_GSSGNU 1
/* Define to 1 if you have the `idna_strerror' function. */
#cmakedefine HAVE_IDNA_STRERROR 1
/* Define to 1 if you have the <ifaddrs.h> header file. */
#cmakedefine HAVE_IFADDRS_H 1
/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
#cmakedefine HAVE_INET_NTOP 1
/* Define to 1 if you have a IPv6 capable working inet_pton function. */
#cmakedefine HAVE_INET_PTON 1
/* Define to 1 if symbol `sa_family_t' exists */
#cmakedefine HAVE_SA_FAMILY_T 1
/* Define to 1 if symbol `ADDRESS_FAMILY' exists */
#cmakedefine HAVE_ADDRESS_FAMILY 1
/* Define to 1 if you have the ioctlsocket function. */
#cmakedefine HAVE_IOCTLSOCKET 1
/* Define to 1 if you have the IoctlSocket camel case function. */
#cmakedefine HAVE_IOCTLSOCKET_CAMEL 1
/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function.
*/
#cmakedefine HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1
/* Define to 1 if you have a working ioctlsocket FIONBIO function. */
#cmakedefine HAVE_IOCTLSOCKET_FIONBIO 1
/* Define to 1 if you have a working ioctl FIONBIO function. */
#cmakedefine HAVE_IOCTL_FIONBIO 1
/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
#cmakedefine HAVE_IOCTL_SIOCGIFADDR 1
/* Define to 1 if you have the <io.h> header file. */
#cmakedefine HAVE_IO_H 1
/* Define to 1 if you have the lber.h header file. */
#cmakedefine HAVE_LBER_H 1
/* Define to 1 if you have the ldap.h header file. */
#cmakedefine HAVE_LDAP_H 1
/* Use LDAPS implementation */
#cmakedefine HAVE_LDAP_SSL 1
/* Define to 1 if you have the ldap_ssl.h header file. */
#cmakedefine HAVE_LDAP_SSL_H 1
/* Define to 1 if you have the `ldap_url_parse' function. */
#cmakedefine HAVE_LDAP_URL_PARSE 1
/* Define to 1 if you have the <libgen.h> header file. */
#cmakedefine HAVE_LIBGEN_H 1
/* Define to 1 if you have the `idn2' library (-lidn2). */
#cmakedefine HAVE_LIBIDN2 1
/* Define to 1 if you have the idn2.h header file. */
#cmakedefine HAVE_IDN2_H 1
/* Define to 1 if you have the `socket' library (-lsocket). */
#cmakedefine HAVE_LIBSOCKET 1
/* Define to 1 if you have the `ssh2' library (-lssh2). */
#cmakedefine HAVE_LIBSSH2 1
/* if zlib is available */
#cmakedefine HAVE_LIBZ 1
/* if brotli is available */
#cmakedefine HAVE_BROTLI 1
/* if zstd is available */
#cmakedefine HAVE_ZSTD 1
/* Define to 1 if you have the <locale.h> header file. */
#cmakedefine HAVE_LOCALE_H 1
/* Define to 1 if the compiler supports the 'long long' data type. */
#cmakedefine HAVE_LONGLONG 1
/* Define to 1 if you have the 'suseconds_t' data type. */
#cmakedefine HAVE_SUSECONDS_T 1
/* Define to 1 if you have the MSG_NOSIGNAL flag. */
#cmakedefine HAVE_MSG_NOSIGNAL 1
/* Define to 1 if you have the <netdb.h> header file. */
#cmakedefine HAVE_NETDB_H 1
/* Define to 1 if you have the <netinet/in.h> header file. */
#cmakedefine HAVE_NETINET_IN_H 1
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#cmakedefine HAVE_NETINET_TCP_H 1
/* Define to 1 if you have the <netinet/udp.h> header file. */
#cmakedefine HAVE_NETINET_UDP_H 1
/* Define to 1 if you have the <linux/tcp.h> header file. */
#cmakedefine HAVE_LINUX_TCP_H 1
/* Define to 1 if you have the <net/if.h> header file. */
#cmakedefine HAVE_NET_IF_H 1
/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE */
#cmakedefine HAVE_OLD_GSSMIT 1
/* Define to 1 if you have the `pipe' function. */
#cmakedefine HAVE_PIPE 1
/* If you have a fine poll */
#cmakedefine HAVE_POLL_FINE 1
/* Define to 1 if you have the <poll.h> header file. */
#cmakedefine HAVE_POLL_H 1
/* Define to 1 if you have a working POSIX-style strerror_r function. */
#cmakedefine HAVE_POSIX_STRERROR_R 1
/* Define to 1 if you have the <pthread.h> header file */
#cmakedefine HAVE_PTHREAD_H 1
/* Define to 1 if you have the <pwd.h> header file. */
#cmakedefine HAVE_PWD_H 1
/* Define to 1 if OpenSSL has the `SSL_set0_wbio` function. */
#cmakedefine HAVE_SSL_SET0_WBIO 1
/* Define to 1 if you have the recv function. */
#cmakedefine HAVE_RECV 1
/* Define to 1 if you have the select function. */
#cmakedefine HAVE_SELECT 1
/* Define to 1 if you have the sched_yield function. */
#cmakedefine HAVE_SCHED_YIELD 1
/* Define to 1 if you have the send function. */
#cmakedefine HAVE_SEND 1
/* Define to 1 if you have the sendmsg function. */
#cmakedefine HAVE_SENDMSG 1
/* Define to 1 if you have the 'fsetxattr' function. */
#cmakedefine HAVE_FSETXATTR 1
/* fsetxattr() takes 5 args */
#cmakedefine HAVE_FSETXATTR_5 1
/* fsetxattr() takes 6 args */
#cmakedefine HAVE_FSETXATTR_6 1
/* Define to 1 if you have the `setlocale' function. */
#cmakedefine HAVE_SETLOCALE 1
/* Define to 1 if you have the `setmode' function. */
#cmakedefine HAVE_SETMODE 1
/* Define to 1 if you have the `setrlimit' function. */
#cmakedefine HAVE_SETRLIMIT 1
/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
#cmakedefine HAVE_SETSOCKOPT_SO_NONBLOCK 1
/* Define to 1 if you have the sigaction function. */
#cmakedefine HAVE_SIGACTION 1
/* Define to 1 if you have the siginterrupt function. */
#cmakedefine HAVE_SIGINTERRUPT 1
/* Define to 1 if you have the signal function. */
#cmakedefine HAVE_SIGNAL 1
/* Define to 1 if you have the sigsetjmp function or macro. */
#cmakedefine HAVE_SIGSETJMP 1
/* Define to 1 if you have the `snprintf' function. */
#cmakedefine HAVE_SNPRINTF 1
/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
#cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
/* Define to 1 if you have the `socket' function. */
#cmakedefine HAVE_SOCKET 1
/* Define to 1 if you have the socketpair function. */
#cmakedefine HAVE_SOCKETPAIR 1
/* Define to 1 if you have the <stdatomic.h> header file. */
#cmakedefine HAVE_STDATOMIC_H 1
/* Define to 1 if you have the <stdbool.h> header file. */
#cmakedefine HAVE_STDBOOL_H 1
/* Define to 1 if you have the strcasecmp function. */
#cmakedefine HAVE_STRCASECMP 1
/* Define to 1 if you have the strcmpi function. */
#cmakedefine HAVE_STRCMPI 1
/* Define to 1 if you have the strdup function. */
#cmakedefine HAVE_STRDUP 1
/* Define to 1 if you have the strerror_r function. */
#cmakedefine HAVE_STRERROR_R 1
/* Define to 1 if you have the stricmp function. */
#cmakedefine HAVE_STRICMP 1
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H 1
/* Define to 1 if you have the <stropts.h> header file. */
#cmakedefine HAVE_STROPTS_H 1
/* Define to 1 if you have the strtok_r function. */
#cmakedefine HAVE_STRTOK_R 1
/* Define to 1 if you have the strtoll function. */
#cmakedefine HAVE_STRTOLL 1
/* Define to 1 if you have the memrchr function. */
#cmakedefine HAVE_MEMRCHR 1
/* if struct sockaddr_storage is defined */
#cmakedefine HAVE_STRUCT_SOCKADDR_STORAGE 1
/* Define to 1 if you have the timeval struct. */
#cmakedefine HAVE_STRUCT_TIMEVAL 1
/* Define to 1 if you have the <sys/filio.h> header file. */
#cmakedefine HAVE_SYS_FILIO_H 1
/* Define to 1 if you have the <sys/wait.h> header file. */
#cmakedefine HAVE_SYS_WAIT_H 1
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#cmakedefine HAVE_SYS_IOCTL_H 1
/* Define to 1 if you have the <sys/param.h> header file. */
#cmakedefine HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/poll.h> header file. */
#cmakedefine HAVE_SYS_POLL_H 1
/* Define to 1 if you have the <sys/resource.h> header file. */
#cmakedefine HAVE_SYS_RESOURCE_H 1
/* Define to 1 if you have the <sys/select.h> header file. */
#cmakedefine HAVE_SYS_SELECT_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#cmakedefine HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/sockio.h> header file. */
#cmakedefine HAVE_SYS_SOCKIO_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/un.h> header file. */
#cmakedefine HAVE_SYS_UN_H 1
/* Define to 1 if you have the <sys/utime.h> header file. */
#cmakedefine HAVE_SYS_UTIME_H 1
/* Define to 1 if you have the <termios.h> header file. */
#cmakedefine HAVE_TERMIOS_H 1
/* Define to 1 if you have the <termio.h> header file. */
#cmakedefine HAVE_TERMIO_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1
/* Define to 1 if you have the `utime' function. */
#cmakedefine HAVE_UTIME 1
/* Define to 1 if you have the `utimes' function. */
#cmakedefine HAVE_UTIMES 1
/* Define to 1 if you have the <utime.h> header file. */
#cmakedefine HAVE_UTIME_H 1
/* Define this symbol if your OS supports changing the contents of argv */
#cmakedefine HAVE_WRITABLE_ARGV 1
/* Define to 1 if you need the lber.h header file even with ldap.h */
#cmakedefine NEED_LBER_H 1
/* Define to 1 if you need the malloc.h header file even with stdlib.h */
#cmakedefine NEED_MALLOC_H 1
/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
#cmakedefine NEED_REENTRANT 1
/* cpu-machine-OS */
#cmakedefine OS ${OS}
/* Name of package */
#cmakedefine PACKAGE ${PACKAGE}
/* Define to the address where bug reports for this package should be sent. */
#cmakedefine PACKAGE_BUGREPORT ${PACKAGE_BUGREPORT}
/* Define to the full name of this package. */
#cmakedefine PACKAGE_NAME ${PACKAGE_NAME}
/* Define to the full name and version of this package. */
#cmakedefine PACKAGE_STRING ${PACKAGE_STRING}
/* Define to the one symbol short name of this package. */
#cmakedefine PACKAGE_TARNAME ${PACKAGE_TARNAME}
/* Define to the version of this package. */
#cmakedefine PACKAGE_VERSION ${PACKAGE_VERSION}
/* a suitable file to read random data from */
#cmakedefine RANDOM_FILE "${RANDOM_FILE}"
/*
Note: SIZEOF_* variables are fetched with CMake through check_type_size().
As per CMake documentation on CheckTypeSize, C preprocessor code is
generated by CMake into SIZEOF_*_CODE. This is what we use in the
following statements.
Reference: https://cmake.org/cmake/help/latest/module/CheckTypeSize.html
*/
/* The size of `int', as computed by sizeof. */
${SIZEOF_INT_CODE}
/* The size of `long', as computed by sizeof. */
${SIZEOF_LONG_CODE}
/* The size of `long long', as computed by sizeof. */
${SIZEOF_LONG_LONG_CODE}
/* The size of `off_t', as computed by sizeof. */
${SIZEOF_OFF_T_CODE}
/* The size of `curl_off_t', as computed by sizeof. */
${SIZEOF_CURL_OFF_T_CODE}
/* The size of `curl_socket_t', as computed by sizeof. */
${SIZEOF_CURL_SOCKET_T_CODE}
/* The size of `size_t', as computed by sizeof. */
${SIZEOF_SIZE_T_CODE}
/* The size of `time_t', as computed by sizeof. */
${SIZEOF_TIME_T_CODE}
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS 1
/* Define if you want to enable c-ares support */
#cmakedefine USE_ARES 1
/* Define if you want to enable POSIX threaded DNS lookup */
#cmakedefine USE_THREADS_POSIX 1
/* Define if you want to enable WIN32 threaded DNS lookup */
#cmakedefine USE_THREADS_WIN32 1
/* if GnuTLS is enabled */
#cmakedefine USE_GNUTLS 1
/* if Secure Transport is enabled */
#cmakedefine USE_SECTRANSP 1
/* if mbedTLS is enabled */
#cmakedefine USE_MBEDTLS 1
/* if BearSSL is enabled */
#cmakedefine USE_BEARSSL 1
/* if WolfSSL is enabled */
#cmakedefine USE_WOLFSSL 1
/* if libSSH is in use */
#cmakedefine USE_LIBSSH 1
/* if libSSH2 is in use */
#cmakedefine USE_LIBSSH2 1
/* if libPSL is in use */
#cmakedefine USE_LIBPSL 1
/* if you want to use OpenLDAP code instead of legacy ldap implementation */
#cmakedefine USE_OPENLDAP 1
/* if OpenSSL is in use */
#cmakedefine USE_OPENSSL 1
/* if librtmp/rtmpdump is in use */
#cmakedefine USE_LIBRTMP 1
/* Define to 1 if you don't want the OpenSSL configuration to be loaded
automatically */
#cmakedefine CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG 1
/* to enable NGHTTP2 */
#cmakedefine USE_NGHTTP2 1
/* to enable NGTCP2 */
#cmakedefine USE_NGTCP2 1
/* to enable NGHTTP3 */
#cmakedefine USE_NGHTTP3 1
/* to enable quiche */
#cmakedefine USE_QUICHE 1
/* to enable openssl + nghttp3 */
#cmakedefine USE_OPENSSL_QUIC 1
/* Define to 1 if you have the quiche_conn_set_qlog_fd function. */
#cmakedefine HAVE_QUICHE_CONN_SET_QLOG_FD 1
/* to enable msh3 */
#cmakedefine USE_MSH3 1
/* if Unix domain sockets are enabled */
#cmakedefine USE_UNIX_SOCKETS 1
/* Define to 1 if you are building a Windows target with large file support. */
#cmakedefine USE_WIN32_LARGE_FILES 1
/* to enable SSPI support */
#cmakedefine USE_WINDOWS_SSPI 1
/* to enable Windows SSL */
#cmakedefine USE_SCHANNEL 1
/* enable multiple SSL backends */
#cmakedefine CURL_WITH_MULTI_SSL 1
/* Version number of package */
#cmakedefine VERSION ${VERSION}
/* Define to 1 if OS is AIX. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS}
/* Define for large files, on AIX-style hosts. */
#cmakedefine _LARGE_FILES ${_LARGE_FILES}
/* define this if you need it to compile thread-safe code */
#cmakedefine _THREAD_SAFE ${_THREAD_SAFE}
/* Define to empty if `const' does not conform to ANSI C. */
#cmakedefine const ${const}
/* Type to use in place of in_addr_t when system does not provide it. */
#cmakedefine in_addr_t ${in_addr_t}
/* Define to `unsigned int' if <sys/types.h> does not define. */
#cmakedefine size_t ${size_t}
/* the signed version of size_t */
#cmakedefine ssize_t ${ssize_t}
/* Define to 1 if you have the mach_absolute_time function. */
#cmakedefine HAVE_MACH_ABSOLUTE_TIME 1
/* to enable Windows IDN */
#cmakedefine USE_WIN32_IDN 1
/* to enable Apple IDN */
#cmakedefine USE_APPLE_IDN 1
/* Define to 1 to enable websocket support. */
#cmakedefine USE_WEBSOCKETS 1
/* Define to 1 if OpenSSL has the SSL_CTX_set_srp_username function. */
#cmakedefine HAVE_OPENSSL_SRP 1
/* Define to 1 if GnuTLS has the gnutls_srp_verifier function. */
#cmakedefine HAVE_GNUTLS_SRP 1
/* Define to 1 to enable TLS-SRP support. */
#cmakedefine USE_TLS_SRP 1
/* Define to 1 to query for HTTPSRR when using DoH */
#cmakedefine USE_HTTPSRR 1
/* if ECH support is available */
#cmakedefine USE_ECH 1

1001
third_party/curl/lib/curl_config.h.in vendored Normal file

File diff suppressed because it is too large Load Diff

51
third_party/curl/lib/curl_ctype.h vendored Normal file
View File

@ -0,0 +1,51 @@
#ifndef HEADER_CURL_CTYPE_H
#define HEADER_CURL_CTYPE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#define ISLOWHEXALHA(x) (((x) >= 'a') && ((x) <= 'f'))
#define ISUPHEXALHA(x) (((x) >= 'A') && ((x) <= 'F'))
#define ISLOWCNTRL(x) ((unsigned char)(x) <= 0x1f)
#define IS7F(x) ((x) == 0x7f)
#define ISLOWPRINT(x) (((x) >= 9) && ((x) <= 0x0d))
#define ISPRINT(x) (ISLOWPRINT(x) || (((x) >= ' ') && ((x) <= 0x7e)))
#define ISGRAPH(x) (ISLOWPRINT(x) || (((x) > ' ') && ((x) <= 0x7e)))
#define ISCNTRL(x) (ISLOWCNTRL(x) || IS7F(x))
#define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
#define ISXDIGIT(x) (ISDIGIT(x) || ISLOWHEXALHA(x) || ISUPHEXALHA(x))
#define ISALNUM(x) (ISDIGIT(x) || ISLOWER(x) || ISUPPER(x))
#define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
#define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
#define ISDIGIT(x) (((x) >= '0') && ((x) <= '9'))
#define ISBLANK(x) (((x) == ' ') || ((x) == '\t'))
#define ISSPACE(x) (ISBLANK(x) || (((x) >= 0xa) && ((x) <= 0x0d)))
#define ISURLPUNTCS(x) (((x) == '-') || ((x) == '.') || ((x) == '_') || \
((x) == '~'))
#define ISUNRESERVED(x) (ISALNUM(x) || ISURLPUNTCS(x))
#endif /* HEADER_CURL_CTYPE_H */

69
third_party/curl/lib/curl_des.c vendored Normal file
View File

@ -0,0 +1,69 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
(defined(USE_GNUTLS) || \
defined(USE_SECTRANSP) || \
defined(USE_OS400CRYPTO) || \
defined(USE_WIN32_CRYPTO))
#include "curl_des.h"
/*
* Curl_des_set_odd_parity()
*
* This is used to apply odd parity to the given byte array. It is typically
* used by when a cryptography engine doesn't have its own version.
*
* The function is a port of the Java based oddParity() function over at:
*
* https://davenport.sourceforge.net/ntlm.html
*
* Parameters:
*
* bytes [in/out] - The data whose parity bits are to be adjusted for
* odd parity.
* len [out] - The length of the data.
*/
void Curl_des_set_odd_parity(unsigned char *bytes, size_t len)
{
size_t i;
for(i = 0; i < len; i++) {
unsigned char b = bytes[i];
bool needs_parity = (((b >> 7) ^ (b >> 6) ^ (b >> 5) ^
(b >> 4) ^ (b >> 3) ^ (b >> 2) ^
(b >> 1)) & 0x01) == 0;
if(needs_parity)
bytes[i] |= 0x01;
else
bytes[i] &= 0xfe;
}
}
#endif

40
third_party/curl/lib/curl_des.h vendored Normal file
View File

@ -0,0 +1,40 @@
#ifndef HEADER_CURL_DES_H
#define HEADER_CURL_DES_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
(defined(USE_GNUTLS) || \
defined(USE_SECTRANSP) || \
defined(USE_OS400CRYPTO) || \
defined(USE_WIN32_CRYPTO))
/* Applies odd parity to the given byte array */
void Curl_des_set_odd_parity(unsigned char *bytes, size_t length);
#endif
#endif /* HEADER_CURL_DES_H */

84
third_party/curl/lib/curl_endian.c vendored Normal file
View File

@ -0,0 +1,84 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "curl_endian.h"
/*
* Curl_read16_le()
*
* This function converts a 16-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 2 byte buffer.
*
* Returns the integer.
*/
unsigned short Curl_read16_le(const unsigned char *buf)
{
return (unsigned short)(((unsigned short)buf[0]) |
((unsigned short)buf[1] << 8));
}
/*
* Curl_read32_le()
*
* This function converts a 32-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 4 byte buffer.
*
* Returns the integer.
*/
unsigned int Curl_read32_le(const unsigned char *buf)
{
return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
}
/*
* Curl_read16_be()
*
* This function converts a 16-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 2 byte buffer.
*
* Returns the integer.
*/
unsigned short Curl_read16_be(const unsigned char *buf)
{
return (unsigned short)(((unsigned short)buf[0] << 8) |
((unsigned short)buf[1]));
}

36
third_party/curl/lib/curl_endian.h vendored Normal file
View File

@ -0,0 +1,36 @@
#ifndef HEADER_CURL_ENDIAN_H
#define HEADER_CURL_ENDIAN_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* Converts a 16-bit integer from little endian */
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);
/* Converts a 16-bit integer from big endian */
unsigned short Curl_read16_be(const unsigned char *buf);
#endif /* HEADER_CURL_ENDIAN_H */

390
third_party/curl/lib/curl_fnmatch.c vendored Normal file
View File

@ -0,0 +1,390 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#ifndef CURL_DISABLE_FTP
#include <curl/curl.h>
#include "curl_fnmatch.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#ifndef HAVE_FNMATCH
#define CURLFNM_CHARSET_LEN (sizeof(char) * 256)
#define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
#define CURLFNM_NEGATE CURLFNM_CHARSET_LEN
#define CURLFNM_ALNUM (CURLFNM_CHARSET_LEN + 1)
#define CURLFNM_DIGIT (CURLFNM_CHARSET_LEN + 2)
#define CURLFNM_XDIGIT (CURLFNM_CHARSET_LEN + 3)
#define CURLFNM_ALPHA (CURLFNM_CHARSET_LEN + 4)
#define CURLFNM_PRINT (CURLFNM_CHARSET_LEN + 5)
#define CURLFNM_BLANK (CURLFNM_CHARSET_LEN + 6)
#define CURLFNM_LOWER (CURLFNM_CHARSET_LEN + 7)
#define CURLFNM_GRAPH (CURLFNM_CHARSET_LEN + 8)
#define CURLFNM_SPACE (CURLFNM_CHARSET_LEN + 9)
#define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10)
typedef enum {
CURLFNM_SCHS_DEFAULT = 0,
CURLFNM_SCHS_RIGHTBR,
CURLFNM_SCHS_RIGHTBRLEFTBR
} setcharset_state;
typedef enum {
CURLFNM_PKW_INIT = 0,
CURLFNM_PKW_DDOT
} parsekey_state;
typedef enum {
CCLASS_OTHER = 0,
CCLASS_DIGIT,
CCLASS_UPPER,
CCLASS_LOWER
} char_class;
#define SETCHARSET_OK 1
#define SETCHARSET_FAIL 0
static int parsekeyword(unsigned char **pattern, unsigned char *charset)
{
parsekey_state state = CURLFNM_PKW_INIT;
#define KEYLEN 10
char keyword[KEYLEN] = { 0 };
int i;
unsigned char *p = *pattern;
bool found = FALSE;
for(i = 0; !found; i++) {
char c = *p++;
if(i >= KEYLEN)
return SETCHARSET_FAIL;
switch(state) {
case CURLFNM_PKW_INIT:
if(ISLOWER(c))
keyword[i] = c;
else if(c == ':')
state = CURLFNM_PKW_DDOT;
else
return SETCHARSET_FAIL;
break;
case CURLFNM_PKW_DDOT:
if(c == ']')
found = TRUE;
else
return SETCHARSET_FAIL;
}
}
#undef KEYLEN
*pattern = p; /* move caller's pattern pointer */
if(strcmp(keyword, "digit") == 0)
charset[CURLFNM_DIGIT] = 1;
else if(strcmp(keyword, "alnum") == 0)
charset[CURLFNM_ALNUM] = 1;
else if(strcmp(keyword, "alpha") == 0)
charset[CURLFNM_ALPHA] = 1;
else if(strcmp(keyword, "xdigit") == 0)
charset[CURLFNM_XDIGIT] = 1;
else if(strcmp(keyword, "print") == 0)
charset[CURLFNM_PRINT] = 1;
else if(strcmp(keyword, "graph") == 0)
charset[CURLFNM_GRAPH] = 1;
else if(strcmp(keyword, "space") == 0)
charset[CURLFNM_SPACE] = 1;
else if(strcmp(keyword, "blank") == 0)
charset[CURLFNM_BLANK] = 1;
else if(strcmp(keyword, "upper") == 0)
charset[CURLFNM_UPPER] = 1;
else if(strcmp(keyword, "lower") == 0)
charset[CURLFNM_LOWER] = 1;
else
return SETCHARSET_FAIL;
return SETCHARSET_OK;
}
/* Return the character class. */
static char_class charclass(unsigned char c)
{
if(ISUPPER(c))
return CCLASS_UPPER;
if(ISLOWER(c))
return CCLASS_LOWER;
if(ISDIGIT(c))
return CCLASS_DIGIT;
return CCLASS_OTHER;
}
/* Include a character or a range in set. */
static void setcharorrange(unsigned char **pp, unsigned char *charset)
{
unsigned char *p = (*pp)++;
unsigned char c = *p++;
charset[c] = 1;
if(ISALNUM(c) && *p++ == '-') {
char_class cc = charclass(c);
unsigned char endrange = *p++;
if(endrange == '\\')
endrange = *p++;
if(endrange >= c && charclass(endrange) == cc) {
while(c++ != endrange)
if(charclass(c) == cc) /* Chars in class may be not consecutive. */
charset[c] = 1;
*pp = p;
}
}
}
/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */
static int setcharset(unsigned char **p, unsigned char *charset)
{
setcharset_state state = CURLFNM_SCHS_DEFAULT;
bool something_found = FALSE;
unsigned char c;
memset(charset, 0, CURLFNM_CHSET_SIZE);
for(;;) {
c = **p;
if(!c)
return SETCHARSET_FAIL;
switch(state) {
case CURLFNM_SCHS_DEFAULT:
if(c == ']') {
if(something_found)
return SETCHARSET_OK;
something_found = TRUE;
state = CURLFNM_SCHS_RIGHTBR;
charset[c] = 1;
(*p)++;
}
else if(c == '[') {
unsigned char *pp = *p + 1;
if(*pp++ == ':' && parsekeyword(&pp, charset))
*p = pp;
else {
charset[c] = 1;
(*p)++;
}
something_found = TRUE;
}
else if(c == '^' || c == '!') {
if(!something_found) {
if(charset[CURLFNM_NEGATE]) {
charset[c] = 1;
something_found = TRUE;
}
else
charset[CURLFNM_NEGATE] = 1; /* negate charset */
}
else
charset[c] = 1;
(*p)++;
}
else if(c == '\\') {
c = *(++(*p));
if(c)
setcharorrange(p, charset);
else
charset['\\'] = 1;
something_found = TRUE;
}
else {
setcharorrange(p, charset);
something_found = TRUE;
}
break;
case CURLFNM_SCHS_RIGHTBR:
if(c == '[') {
state = CURLFNM_SCHS_RIGHTBRLEFTBR;
charset[c] = 1;
(*p)++;
}
else if(c == ']') {
return SETCHARSET_OK;
}
else if(ISPRINT(c)) {
charset[c] = 1;
(*p)++;
state = CURLFNM_SCHS_DEFAULT;
}
else
/* used 'goto fail' instead of 'return SETCHARSET_FAIL' to avoid a
* nonsense warning 'statement not reached' at end of the fnc when
* compiling on Solaris */
goto fail;
break;
case CURLFNM_SCHS_RIGHTBRLEFTBR:
if(c == ']')
return SETCHARSET_OK;
state = CURLFNM_SCHS_DEFAULT;
charset[c] = 1;
(*p)++;
break;
}
}
fail:
return SETCHARSET_FAIL;
}
static int loop(const unsigned char *pattern, const unsigned char *string,
int maxstars)
{
unsigned char *p = (unsigned char *)pattern;
unsigned char *s = (unsigned char *)string;
unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 };
for(;;) {
unsigned char *pp;
switch(*p) {
case '*':
if(!maxstars)
return CURL_FNMATCH_NOMATCH;
/* Regroup consecutive stars and question marks. This can be done because
'*?*?*' can be expressed as '??*'. */
for(;;) {
if(*++p == '\0')
return CURL_FNMATCH_MATCH;
if(*p == '?') {
if(!*s++)
return CURL_FNMATCH_NOMATCH;
}
else if(*p != '*')
break;
}
/* Skip string characters until we find a match with pattern suffix. */
for(maxstars--; *s; s++) {
if(loop(p, s, maxstars) == CURL_FNMATCH_MATCH)
return CURL_FNMATCH_MATCH;
}
return CURL_FNMATCH_NOMATCH;
case '?':
if(!*s)
return CURL_FNMATCH_NOMATCH;
s++;
p++;
break;
case '\0':
return *s? CURL_FNMATCH_NOMATCH: CURL_FNMATCH_MATCH;
case '\\':
if(p[1])
p++;
if(*s++ != *p++)
return CURL_FNMATCH_NOMATCH;
break;
case '[':
pp = p + 1; /* Copy in case of syntax error in set. */
if(setcharset(&pp, charset)) {
int found = FALSE;
if(!*s)
return CURL_FNMATCH_NOMATCH;
if(charset[(unsigned int)*s])
found = TRUE;
else if(charset[CURLFNM_ALNUM])
found = ISALNUM(*s);
else if(charset[CURLFNM_ALPHA])
found = ISALPHA(*s);
else if(charset[CURLFNM_DIGIT])
found = ISDIGIT(*s);
else if(charset[CURLFNM_XDIGIT])
found = ISXDIGIT(*s);
else if(charset[CURLFNM_PRINT])
found = ISPRINT(*s);
else if(charset[CURLFNM_SPACE])
found = ISSPACE(*s);
else if(charset[CURLFNM_UPPER])
found = ISUPPER(*s);
else if(charset[CURLFNM_LOWER])
found = ISLOWER(*s);
else if(charset[CURLFNM_BLANK])
found = ISBLANK(*s);
else if(charset[CURLFNM_GRAPH])
found = ISGRAPH(*s);
if(charset[CURLFNM_NEGATE])
found = !found;
if(!found)
return CURL_FNMATCH_NOMATCH;
p = pp + 1;
s++;
break;
}
/* Syntax error in set; mismatch! */
return CURL_FNMATCH_NOMATCH;
default:
if(*p++ != *s++)
return CURL_FNMATCH_NOMATCH;
break;
}
}
}
/*
* @unittest: 1307
*/
int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
{
(void)ptr; /* the argument is specified by the curl_fnmatch_callback
prototype, but not used by Curl_fnmatch() */
if(!pattern || !string) {
return CURL_FNMATCH_FAIL;
}
return loop((unsigned char *)pattern, (unsigned char *)string, 2);
}
#else
#include <fnmatch.h>
/*
* @unittest: 1307
*/
int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
{
(void)ptr; /* the argument is specified by the curl_fnmatch_callback
prototype, but not used by Curl_fnmatch() */
if(!pattern || !string) {
return CURL_FNMATCH_FAIL;
}
switch(fnmatch(pattern, string, 0)) {
case 0:
return CURL_FNMATCH_MATCH;
case FNM_NOMATCH:
return CURL_FNMATCH_NOMATCH;
default:
return CURL_FNMATCH_FAIL;
}
/* not reached */
}
#endif
#endif /* if FTP is disabled */

46
third_party/curl/lib/curl_fnmatch.h vendored Normal file
View File

@ -0,0 +1,46 @@
#ifndef HEADER_CURL_FNMATCH_H
#define HEADER_CURL_FNMATCH_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#define CURL_FNMATCH_MATCH 0
#define CURL_FNMATCH_NOMATCH 1
#define CURL_FNMATCH_FAIL 2
/* default pattern matching function
* =================================
* Implemented with recursive backtracking, if you want to use Curl_fnmatch,
* please note that there is not implemented UTF/UNICODE support.
*
* Implemented features:
* '?' notation, does not match UTF characters
* '*' can also work with UTF string
* [a-zA-Z0-9] enumeration support
*
* keywords: alnum, digit, xdigit, alpha, print, blank, lower, graph, space
* and upper (use as "[[:alnum:]]")
*/
int Curl_fnmatch(void *ptr, const char *pattern, const char *string);
#endif /* HEADER_CURL_FNMATCH_H */

77
third_party/curl/lib/curl_get_line.c vendored Normal file
View File

@ -0,0 +1,77 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
!defined(CURL_DISABLE_HSTS) || !defined(CURL_DISABLE_NETRC)
#include "curl_get_line.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/*
* Curl_get_line() makes sure to only return complete whole lines that end
* newlines.
*/
int Curl_get_line(struct dynbuf *buf, FILE *input)
{
CURLcode result;
char buffer[128];
Curl_dyn_reset(buf);
while(1) {
char *b = fgets(buffer, sizeof(buffer), input);
if(b) {
size_t rlen = strlen(b);
if(!rlen)
break;
result = Curl_dyn_addn(buf, b, rlen);
if(result)
/* too long line or out of memory */
return 0; /* error */
else if(b[rlen-1] == '\n')
/* end of the line */
return 1; /* all good */
else if(feof(input)) {
/* append a newline */
result = Curl_dyn_addn(buf, "\n", 1);
if(result)
/* too long line or out of memory */
return 0; /* error */
return 1; /* all good */
}
}
else
break;
}
return 0;
}
#endif /* if not disabled */

32
third_party/curl/lib/curl_get_line.h vendored Normal file
View File

@ -0,0 +1,32 @@
#ifndef HEADER_CURL_GET_LINE_H
#define HEADER_CURL_GET_LINE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "dynbuf.h"
/* Curl_get_line() returns complete lines that end with a newline. */
int Curl_get_line(struct dynbuf *buf, FILE *input);
#endif /* HEADER_CURL_GET_LINE_H */

102
third_party/curl/lib/curl_gethostname.c vendored Normal file
View File

@ -0,0 +1,102 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "curl_gethostname.h"
/*
* Curl_gethostname() is a wrapper around gethostname() which allows
* overriding the host name that the function would normally return.
* This capability is used by the test suite to verify exact matching
* of NTLM authentication, which exercises libcurl's MD4 and DES code
* as well as by the SMTP module when a hostname is not provided.
*
* For libcurl debug enabled builds host name overriding takes place
* when environment variable CURL_GETHOSTNAME is set, using the value
* held by the variable to override returned host name.
*
* Note: The function always returns the un-qualified hostname rather
* than being provider dependent.
*
* For libcurl shared library release builds the test suite preloads
* another shared library named libhostname using the LD_PRELOAD
* mechanism which intercepts, and might override, the gethostname()
* function call. In this case a given platform must support the
* LD_PRELOAD mechanism and additionally have environment variable
* CURL_GETHOSTNAME set in order to override the returned host name.
*
* For libcurl static library release builds no overriding takes place.
*/
int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen)
{
#ifndef HAVE_GETHOSTNAME
/* Allow compilation and return failure when unavailable */
(void) name;
(void) namelen;
return -1;
#else
int err;
char *dot;
#ifdef DEBUGBUILD
/* Override host name when environment variable CURL_GETHOSTNAME is set */
const char *force_hostname = getenv("CURL_GETHOSTNAME");
if(force_hostname) {
strncpy(name, force_hostname, namelen - 1);
err = 0;
}
else {
name[0] = '\0';
err = gethostname(name, namelen);
}
#else /* DEBUGBUILD */
/* The call to system's gethostname() might get intercepted by the
libhostname library when libcurl is built as a non-debug shared
library when running the test suite. */
name[0] = '\0';
err = gethostname(name, namelen);
#endif
name[namelen - 1] = '\0';
if(err)
return err;
/* Truncate domain, leave only machine name */
dot = strchr(name, '.');
if(dot)
*dot = '\0';
return 0;
#endif
}

33
third_party/curl/lib/curl_gethostname.h vendored Normal file
View File

@ -0,0 +1,33 @@
#ifndef HEADER_CURL_GETHOSTNAME_H
#define HEADER_CURL_GETHOSTNAME_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* Hostname buffer size */
#define HOSTNAME_MAX 1024
/* This returns the local machine's un-qualified hostname */
int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen);
#endif /* HEADER_CURL_GETHOSTNAME_H */

152
third_party/curl/lib/curl_gssapi.c vendored Normal file
View File

@ -0,0 +1,152 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#ifdef HAVE_GSSAPI
#include "curl_gssapi.h"
#include "sendf.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
#if defined(__GNUC__)
#define CURL_ALIGN8 __attribute__ ((aligned(8)))
#else
#define CURL_ALIGN8
#endif
gss_OID_desc Curl_spnego_mech_oid CURL_ALIGN8 = {
6, (char *)"\x2b\x06\x01\x05\x05\x02"
};
gss_OID_desc Curl_krb5_mech_oid CURL_ALIGN8 = {
9, (char *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
};
OM_uint32 Curl_gss_init_sec_context(
struct Curl_easy *data,
OM_uint32 *minor_status,
gss_ctx_id_t *context,
gss_name_t target_name,
gss_OID mech_type,
gss_channel_bindings_t input_chan_bindings,
gss_buffer_t input_token,
gss_buffer_t output_token,
const bool mutual_auth,
OM_uint32 *ret_flags)
{
OM_uint32 req_flags = GSS_C_REPLAY_FLAG;
if(mutual_auth)
req_flags |= GSS_C_MUTUAL_FLAG;
if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_POLICY_FLAG) {
#ifdef GSS_C_DELEG_POLICY_FLAG
req_flags |= GSS_C_DELEG_POLICY_FLAG;
#else
infof(data, "WARNING: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not "
"compiled in");
#endif
}
if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG)
req_flags |= GSS_C_DELEG_FLAG;
return gss_init_sec_context(minor_status,
GSS_C_NO_CREDENTIAL, /* cred_handle */
context,
target_name,
mech_type,
req_flags,
0, /* time_req */
input_chan_bindings,
input_token,
NULL, /* actual_mech_type */
output_token,
ret_flags,
NULL /* time_rec */);
}
#define GSS_LOG_BUFFER_LEN 1024
static size_t display_gss_error(OM_uint32 status, int type,
char *buf, size_t len) {
OM_uint32 maj_stat;
OM_uint32 min_stat;
OM_uint32 msg_ctx = 0;
gss_buffer_desc status_string = GSS_C_EMPTY_BUFFER;
do {
maj_stat = gss_display_status(&min_stat,
status,
type,
GSS_C_NO_OID,
&msg_ctx,
&status_string);
if(maj_stat == GSS_S_COMPLETE && status_string.length > 0) {
if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) {
len += msnprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
"%.*s. ", (int)status_string.length,
(char *)status_string.value);
}
}
gss_release_buffer(&min_stat, &status_string);
} while(!GSS_ERROR(maj_stat) && msg_ctx);
return len;
}
/*
* Curl_gss_log_error()
*
* This is used to log a GSS-API error status.
*
* Parameters:
*
* data [in] - The session handle.
* prefix [in] - The prefix of the log message.
* major [in] - The major status code.
* minor [in] - The minor status code.
*/
void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
OM_uint32 major, OM_uint32 minor)
{
char buf[GSS_LOG_BUFFER_LEN];
size_t len = 0;
if(major != GSS_S_FAILURE)
len = display_gss_error(major, GSS_C_GSS_CODE, buf, len);
display_gss_error(minor, GSS_C_MECH_CODE, buf, len);
infof(data, "%s%s", prefix, buf);
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
(void)prefix;
#endif
}
#endif /* HAVE_GSSAPI */

63
third_party/curl/lib/curl_gssapi.h vendored Normal file
View File

@ -0,0 +1,63 @@
#ifndef HEADER_CURL_GSSAPI_H
#define HEADER_CURL_GSSAPI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#ifdef HAVE_GSSAPI
extern gss_OID_desc Curl_spnego_mech_oid;
extern gss_OID_desc Curl_krb5_mech_oid;
/* Common method for using GSS-API */
OM_uint32 Curl_gss_init_sec_context(
struct Curl_easy *data,
OM_uint32 *minor_status,
gss_ctx_id_t *context,
gss_name_t target_name,
gss_OID mech_type,
gss_channel_bindings_t input_chan_bindings,
gss_buffer_t input_token,
gss_buffer_t output_token,
const bool mutual_auth,
OM_uint32 *ret_flags);
/* Helper to log a GSS-API error status */
void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
OM_uint32 major, OM_uint32 minor);
/* Provide some definitions missing in old headers */
#ifdef HAVE_OLD_GSSMIT
#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
#define NCOMPAT 1
#endif
/* Define our privacy and integrity protection values */
#define GSSAUTH_P_NONE 1
#define GSSAUTH_P_INTEGRITY 2
#define GSSAUTH_P_PRIVACY 4
#endif /* HAVE_GSSAPI */
#endif /* HEADER_CURL_GSSAPI_H */

78
third_party/curl/lib/curl_hmac.h vendored Normal file
View File

@ -0,0 +1,78 @@
#ifndef HEADER_CURL_HMAC_H
#define HEADER_CURL_HMAC_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
|| !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
|| defined(USE_LIBSSH2)
#include <curl/curl.h>
#define HMAC_MD5_LENGTH 16
typedef CURLcode (* HMAC_hinit_func)(void *context);
typedef void (* HMAC_hupdate_func)(void *context,
const unsigned char *data,
unsigned int len);
typedef void (* HMAC_hfinal_func)(unsigned char *result, void *context);
/* Per-hash function HMAC parameters. */
struct HMAC_params {
HMAC_hinit_func
hmac_hinit; /* Initialize context procedure. */
HMAC_hupdate_func hmac_hupdate; /* Update context with data. */
HMAC_hfinal_func hmac_hfinal; /* Get final result procedure. */
unsigned int hmac_ctxtsize; /* Context structure size. */
unsigned int hmac_maxkeylen; /* Maximum key length (bytes). */
unsigned int hmac_resultlen; /* Result length (bytes). */
};
/* HMAC computation context. */
struct HMAC_context {
const struct HMAC_params *hmac_hash; /* Hash function definition. */
void *hmac_hashctxt1; /* Hash function context 1. */
void *hmac_hashctxt2; /* Hash function context 2. */
};
/* Prototypes. */
struct HMAC_context *Curl_HMAC_init(const struct HMAC_params *hashparams,
const unsigned char *key,
unsigned int keylen);
int Curl_HMAC_update(struct HMAC_context *context,
const unsigned char *data,
unsigned int len);
int Curl_HMAC_final(struct HMAC_context *context, unsigned char *result);
CURLcode Curl_hmacit(const struct HMAC_params *hashparams,
const unsigned char *key, const size_t keylen,
const unsigned char *data, const size_t datalen,
unsigned char *output);
#endif
#endif /* HEADER_CURL_HMAC_H */

52
third_party/curl/lib/curl_krb5.h vendored Normal file
View File

@ -0,0 +1,52 @@
#ifndef HEADER_CURL_KRB5_H
#define HEADER_CURL_KRB5_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
struct Curl_sec_client_mech {
const char *name;
size_t size;
int (*init)(void *);
int (*auth)(void *, struct Curl_easy *data, struct connectdata *);
void (*end)(void *);
int (*check_prot)(void *, int);
int (*encode)(void *, const void *, int, int, void **);
int (*decode)(void *, void *, int, int, struct connectdata *);
};
#define AUTH_OK 0
#define AUTH_CONTINUE 1
#define AUTH_ERROR 2
#ifdef HAVE_GSSAPI
int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, char *,
enum protection_level);
void Curl_sec_end(struct connectdata *);
CURLcode Curl_sec_login(struct Curl_easy *, struct connectdata *);
int Curl_sec_request_prot(struct connectdata *conn, const char *level);
#else
#define Curl_sec_end(x)
#endif
#endif /* HEADER_CURL_KRB5_H */

36
third_party/curl/lib/curl_ldap.h vendored Normal file
View File

@ -0,0 +1,36 @@
#ifndef HEADER_CURL_LDAP_H
#define HEADER_CURL_LDAP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#ifndef CURL_DISABLE_LDAP
extern const struct Curl_handler Curl_handler_ldap;
#if !defined(CURL_DISABLE_LDAPS) && \
((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
(!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
extern const struct Curl_handler Curl_handler_ldaps;
#endif
#endif
#endif /* HEADER_CURL_LDAP_H */

39
third_party/curl/lib/curl_md4.h vendored Normal file
View File

@ -0,0 +1,39 @@
#ifndef HEADER_CURL_MD4_H
#define HEADER_CURL_MD4_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include <curl/curl.h>
#if defined(USE_CURL_NTLM_CORE)
#define MD4_DIGEST_LENGTH 16
CURLcode Curl_md4it(unsigned char *output, const unsigned char *input,
const size_t len);
#endif /* defined(USE_CURL_NTLM_CORE) */
#endif /* HEADER_CURL_MD4_H */

67
third_party/curl/lib/curl_md5.h vendored Normal file
View File

@ -0,0 +1,67 @@
#ifndef HEADER_CURL_MD5_H
#define HEADER_CURL_MD5_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
|| !defined(CURL_DISABLE_DIGEST_AUTH)
#include "curl_hmac.h"
#define MD5_DIGEST_LEN 16
typedef CURLcode (* Curl_MD5_init_func)(void *context);
typedef void (* Curl_MD5_update_func)(void *context,
const unsigned char *data,
unsigned int len);
typedef void (* Curl_MD5_final_func)(unsigned char *result, void *context);
struct MD5_params {
Curl_MD5_init_func md5_init_func; /* Initialize context procedure */
Curl_MD5_update_func md5_update_func; /* Update context with data */
Curl_MD5_final_func md5_final_func; /* Get final result procedure */
unsigned int md5_ctxtsize; /* Context structure size */
unsigned int md5_resultlen; /* Result length (bytes) */
};
struct MD5_context {
const struct MD5_params *md5_hash; /* Hash function definition */
void *md5_hashctx; /* Hash function context */
};
extern const struct MD5_params Curl_DIGEST_MD5[1];
extern const struct HMAC_params Curl_HMAC_MD5[1];
CURLcode Curl_md5it(unsigned char *output, const unsigned char *input,
const size_t len);
struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params);
CURLcode Curl_MD5_update(struct MD5_context *context,
const unsigned char *data,
unsigned int len);
CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result);
#endif
#endif /* HEADER_CURL_MD5_H */

178
third_party/curl/lib/curl_memory.h vendored Normal file
View File

@ -0,0 +1,178 @@
#ifndef HEADER_CURL_MEMORY_H
#define HEADER_CURL_MEMORY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/*
* Nasty internal details ahead...
*
* File curl_memory.h must be included by _all_ *.c source files
* that use memory related functions strdup, malloc, calloc, realloc
* or free, and given source file is used to build libcurl library.
* It should be included immediately before memdebug.h as the last files
* included to avoid undesired interaction with other memory function
* headers in dependent libraries.
*
* There is nearly no exception to above rule. All libcurl source
* files in 'lib' subdirectory as well as those living deep inside
* 'packages' subdirectories and linked together in order to build
* libcurl library shall follow it.
*
* File lib/strdup.c is an exception, given that it provides a strdup
* clone implementation while using malloc. Extra care needed inside
* this one.
*
* The need for curl_memory.h inclusion is due to libcurl's feature
* of allowing library user to provide memory replacement functions,
* memory callbacks, at runtime with curl_global_init_mem()
*
* Any *.c source file used to build libcurl library that does not
* include curl_memory.h and uses any memory function of the five
* mentioned above will compile without any indication, but it will
* trigger weird memory related issues at runtime.
*
*/
#ifdef HEADER_CURL_MEMDEBUG_H
/* cleanup after memdebug.h */
#ifdef MEMDEBUG_NODEFINES
#ifdef CURLDEBUG
#undef strdup
#undef malloc
#undef calloc
#undef realloc
#undef free
#undef send
#undef recv
#ifdef _WIN32
# ifdef UNICODE
# undef wcsdup
# undef _wcsdup
# undef _tcsdup
# else
# undef _tcsdup
# endif
#endif
#undef socket
#undef accept
#ifdef HAVE_SOCKETPAIR
#undef socketpair
#endif
#ifdef HAVE_GETADDRINFO
#if defined(getaddrinfo) && defined(__osf__)
#undef ogetaddrinfo
#else
#undef getaddrinfo
#endif
#endif /* HAVE_GETADDRINFO */
#ifdef HAVE_FREEADDRINFO
#undef freeaddrinfo
#endif /* HAVE_FREEADDRINFO */
/* sclose is probably already defined, redefine it! */
#undef sclose
#undef fopen
#undef fdopen
#undef fclose
#endif /* MEMDEBUG_NODEFINES */
#endif /* CURLDEBUG */
#undef HEADER_CURL_MEMDEBUG_H
#endif /* HEADER_CURL_MEMDEBUG_H */
/*
** Following section applies even when CURLDEBUG is not defined.
*/
#undef fake_sclose
#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS /* only if not already done */
/*
* The following memory function replacement typedef's are COPIED from
* curl/curl.h and MUST match the originals. We copy them to avoid having to
* include curl/curl.h here. We avoid that include since it includes stdio.h
* and other headers that may get messed up with defines done here.
*/
typedef void *(*curl_malloc_callback)(size_t size);
typedef void (*curl_free_callback)(void *ptr);
typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
typedef char *(*curl_strdup_callback)(const char *str);
typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
#define CURL_DID_MEMORY_FUNC_TYPEDEFS
#endif
extern curl_malloc_callback Curl_cmalloc;
extern curl_free_callback Curl_cfree;
extern curl_realloc_callback Curl_crealloc;
extern curl_strdup_callback Curl_cstrdup;
extern curl_calloc_callback Curl_ccalloc;
#if defined(_WIN32) && defined(UNICODE)
extern curl_wcsdup_callback Curl_cwcsdup;
#endif
#ifndef CURLDEBUG
/*
* libcurl's 'memory tracking' system defines strdup, malloc, calloc,
* realloc and free, along with others, in memdebug.h in a different
* way although still using memory callbacks forward declared above.
* When using the 'memory tracking' system (CURLDEBUG defined) we do
* not define here the five memory functions given that definitions
* from memdebug.h are the ones that shall be used.
*/
#undef strdup
#define strdup(ptr) Curl_cstrdup(ptr)
#undef malloc
#define malloc(size) Curl_cmalloc(size)
#undef calloc
#define calloc(nbelem,size) Curl_ccalloc(nbelem, size)
#undef realloc
#define realloc(ptr,size) Curl_crealloc(ptr, size)
#undef free
#define free(ptr) Curl_cfree(ptr)
#ifdef _WIN32
# ifdef UNICODE
# undef wcsdup
# define wcsdup(ptr) Curl_cwcsdup(ptr)
# undef _wcsdup
# define _wcsdup(ptr) Curl_cwcsdup(ptr)
# undef _tcsdup
# define _tcsdup(ptr) Curl_cwcsdup(ptr)
# else
# undef _tcsdup
# define _tcsdup(ptr) Curl_cstrdup(ptr)
# endif
#endif
#endif /* CURLDEBUG */
#endif /* HEADER_CURL_MEMORY_H */

64
third_party/curl/lib/curl_memrchr.c vendored Normal file
View File

@ -0,0 +1,64 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include <curl/curl.h>
#include "curl_memrchr.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#ifndef HAVE_MEMRCHR
/*
* Curl_memrchr()
*
* Our memrchr() function clone for systems which lack this function. The
* memrchr() function is like the memchr() function, except that it searches
* backwards from the end of the n bytes pointed to by s instead of forward
* from the beginning.
*/
void *
Curl_memrchr(const void *s, int c, size_t n)
{
if(n > 0) {
const unsigned char *p = s;
const unsigned char *q = s;
p += n - 1;
while(p >= q) {
if(*p == (unsigned char)c)
return (void *)p;
p--;
}
}
return NULL;
}
#endif /* HAVE_MEMRCHR */

44
third_party/curl/lib/curl_memrchr.h vendored Normal file
View File

@ -0,0 +1,44 @@
#ifndef HEADER_CURL_MEMRCHR_H
#define HEADER_CURL_MEMRCHR_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#ifdef HAVE_MEMRCHR
#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#else /* HAVE_MEMRCHR */
void *Curl_memrchr(const void *s, int c, size_t n);
#define memrchr(x,y,z) Curl_memrchr((x),(y),(z))
#endif /* HAVE_MEMRCHR */
#endif /* HEADER_CURL_MEMRCHR_H */

162
third_party/curl/lib/curl_multibyte.c vendored Normal file
View File

@ -0,0 +1,162 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/*
* This file is 'mem-include-scan' clean, which means memdebug.h and
* curl_memory.h are purposely not included in this file. See test 1132.
*
* The functions in this file are curlx functions which are not tracked by the
* curl memory tracker memdebug.
*/
#include "curl_setup.h"
#if defined(_WIN32)
#include "curl_multibyte.h"
/*
* MultiByte conversions using Windows kernel32 library.
*/
wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8)
{
wchar_t *str_w = NULL;
if(str_utf8) {
int str_w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
str_utf8, -1, NULL, 0);
if(str_w_len > 0) {
str_w = malloc(str_w_len * sizeof(wchar_t));
if(str_w) {
if(MultiByteToWideChar(CP_UTF8, 0, str_utf8, -1, str_w,
str_w_len) == 0) {
free(str_w);
return NULL;
}
}
}
}
return str_w;
}
char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w)
{
char *str_utf8 = NULL;
if(str_w) {
int bytes = WideCharToMultiByte(CP_UTF8, 0, str_w, -1,
NULL, 0, NULL, NULL);
if(bytes > 0) {
str_utf8 = malloc(bytes);
if(str_utf8) {
if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, bytes,
NULL, NULL) == 0) {
free(str_utf8);
return NULL;
}
}
}
}
return str_utf8;
}
#endif /* _WIN32 */
#if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES)
int curlx_win32_open(const char *filename, int oflag, ...)
{
int pmode = 0;
#ifdef _UNICODE
int result = -1;
wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename);
#endif
va_list param;
va_start(param, oflag);
if(oflag & O_CREAT)
pmode = va_arg(param, int);
va_end(param);
#ifdef _UNICODE
if(filename_w) {
result = _wopen(filename_w, oflag, pmode);
curlx_unicodefree(filename_w);
}
else
errno = EINVAL;
return result;
#else
return (_open)(filename, oflag, pmode);
#endif
}
FILE *curlx_win32_fopen(const char *filename, const char *mode)
{
#ifdef _UNICODE
FILE *result = NULL;
wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename);
wchar_t *mode_w = curlx_convert_UTF8_to_wchar(mode);
if(filename_w && mode_w)
result = _wfopen(filename_w, mode_w);
else
errno = EINVAL;
curlx_unicodefree(filename_w);
curlx_unicodefree(mode_w);
return result;
#else
return (fopen)(filename, mode);
#endif
}
int curlx_win32_stat(const char *path, struct_stat *buffer)
{
#ifdef _UNICODE
int result = -1;
wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
if(path_w) {
#if defined(USE_WIN32_SMALL_FILES)
result = _wstat(path_w, buffer);
#else
result = _wstati64(path_w, buffer);
#endif
curlx_unicodefree(path_w);
}
else
errno = EINVAL;
return result;
#else
#if defined(USE_WIN32_SMALL_FILES)
return _stat(path, buffer);
#else
return _stati64(path, buffer);
#endif
#endif
}
#endif /* USE_WIN32_LARGE_FILES || USE_WIN32_SMALL_FILES */

91
third_party/curl/lib/curl_multibyte.h vendored Normal file
View File

@ -0,0 +1,91 @@
#ifndef HEADER_CURL_MULTIBYTE_H
#define HEADER_CURL_MULTIBYTE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if defined(_WIN32)
/*
* MultiByte conversions using Windows kernel32 library.
*/
wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8);
char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
#endif /* _WIN32 */
/*
* Macros curlx_convert_UTF8_to_tchar(), curlx_convert_tchar_to_UTF8()
* and curlx_unicodefree() main purpose is to minimize the number of
* preprocessor conditional directives needed by code using these
* to differentiate UNICODE from non-UNICODE builds.
*
* In the case of a non-UNICODE build the tchar strings are char strings that
* are duplicated via strdup and remain in whatever the passed in encoding is,
* which is assumed to be UTF-8 but may be other encoding. Therefore the
* significance of the conversion functions is primarily for UNICODE builds.
*
* Allocated memory should be free'd with curlx_unicodefree().
*
* Note: Because these are curlx functions their memory usage is not tracked
* by the curl memory tracker memdebug. You'll notice that curlx function-like
* macros call free and strdup in parentheses, eg (strdup)(ptr), and that's to
* ensure that the curl memdebug override macros do not replace them.
*/
#if defined(UNICODE) && defined(_WIN32)
#define curlx_convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr))
#define curlx_convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr))
typedef union {
unsigned short *tchar_ptr;
const unsigned short *const_tchar_ptr;
unsigned short *tbyte_ptr;
const unsigned short *const_tbyte_ptr;
} xcharp_u;
#else
#define curlx_convert_UTF8_to_tchar(ptr) (strdup)(ptr)
#define curlx_convert_tchar_to_UTF8(ptr) (strdup)(ptr)
typedef union {
char *tchar_ptr;
const char *const_tchar_ptr;
unsigned char *tbyte_ptr;
const unsigned char *const_tbyte_ptr;
} xcharp_u;
#endif /* UNICODE && _WIN32 */
#define curlx_unicodefree(ptr) \
do { \
if(ptr) { \
(free)(ptr); \
(ptr) = NULL; \
} \
} while(0)
#endif /* HEADER_CURL_MULTIBYTE_H */

669
third_party/curl/lib/curl_ntlm_core.c vendored Normal file
View File

@ -0,0 +1,669 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if defined(USE_CURL_NTLM_CORE)
/*
* NTLM details:
*
* https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
/* Please keep the SSL backend-specific #if branches in this order:
1. USE_OPENSSL
2. USE_WOLFSSL
3. USE_GNUTLS
4. -
5. USE_MBEDTLS
6. USE_SECTRANSP
7. USE_OS400CRYPTO
8. USE_WIN32_CRYPTO
This ensures that:
- the same SSL branch gets activated throughout this source
file even if multiple backends are enabled at the same time.
- OpenSSL has higher priority than Windows Crypt, due
to issues with the latter supporting NTLM2Session responses
in NTLM type-3 messages.
*/
#if defined(USE_OPENSSL)
#include <openssl/opensslconf.h>
#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_DEPRECATED_3_0)
#define USE_OPENSSL_DES
#endif
#endif
#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
#if defined(USE_OPENSSL)
# include <openssl/des.h>
# include <openssl/md5.h>
# include <openssl/ssl.h>
# include <openssl/rand.h>
#else
# include <wolfssl/options.h>
# include <wolfssl/openssl/des.h>
# include <wolfssl/openssl/md5.h>
# include <wolfssl/openssl/ssl.h>
# include <wolfssl/openssl/rand.h>
#endif
# if (defined(OPENSSL_VERSION_NUMBER) && \
(OPENSSL_VERSION_NUMBER < 0x00907001L)) && !defined(USE_WOLFSSL)
# define DES_key_schedule des_key_schedule
# define DES_cblock des_cblock
# define DES_set_odd_parity des_set_odd_parity
# define DES_set_key des_set_key
# define DES_ecb_encrypt des_ecb_encrypt
# define DESKEY(x) x
# define DESKEYARG(x) x
# elif defined(OPENSSL_IS_AWSLC)
# define DES_set_key_unchecked (void)DES_set_key
# define DESKEYARG(x) *x
# define DESKEY(x) &x
# else
# define DESKEYARG(x) *x
# define DESKEY(x) &x
# endif
#elif defined(USE_GNUTLS)
# include <nettle/des.h>
#elif defined(USE_MBEDTLS)
# include <mbedtls/des.h>
#elif defined(USE_SECTRANSP)
# include <CommonCrypto/CommonCryptor.h>
# include <CommonCrypto/CommonDigest.h>
#elif defined(USE_OS400CRYPTO)
# include "cipher.mih" /* mih/cipher */
#elif defined(USE_WIN32_CRYPTO)
# include <wincrypt.h>
#else
# error "Can't compile NTLM support without a crypto library with DES."
# define CURL_NTLM_NOT_SUPPORTED
#endif
#include "urldata.h"
#include "strcase.h"
#include "curl_ntlm_core.h"
#include "curl_md5.h"
#include "curl_hmac.h"
#include "warnless.h"
#include "curl_endian.h"
#include "curl_des.h"
#include "curl_md4.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
#define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00"
#define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4)
#if !defined(CURL_NTLM_NOT_SUPPORTED)
/*
* Turns a 56-bit key into being 64-bit wide.
*/
static void extend_key_56_to_64(const unsigned char *key_56, char *key)
{
key[0] = key_56[0];
key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
}
#endif
#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
/*
* Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
* key schedule ks is also set.
*/
static void setup_des_key(const unsigned char *key_56,
DES_key_schedule DESKEYARG(ks))
{
DES_cblock key;
/* Expand the 56-bit key to 64-bits */
extend_key_56_to_64(key_56, (char *) &key);
/* Set the key parity to odd */
DES_set_odd_parity(&key);
/* Set the key */
DES_set_key_unchecked(&key, ks);
}
#elif defined(USE_GNUTLS)
static void setup_des_key(const unsigned char *key_56,
struct des_ctx *des)
{
char key[8];
/* Expand the 56-bit key to 64-bits */
extend_key_56_to_64(key_56, key);
/* Set the key parity to odd */
Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
/* Set the key */
des_set_key(des, (const uint8_t *) key);
}
#elif defined(USE_MBEDTLS)
static bool encrypt_des(const unsigned char *in, unsigned char *out,
const unsigned char *key_56)
{
mbedtls_des_context ctx;
char key[8];
/* Expand the 56-bit key to 64-bits */
extend_key_56_to_64(key_56, key);
/* Set the key parity to odd */
mbedtls_des_key_set_parity((unsigned char *) key);
/* Perform the encryption */
mbedtls_des_init(&ctx);
mbedtls_des_setkey_enc(&ctx, (unsigned char *) key);
return mbedtls_des_crypt_ecb(&ctx, in, out) == 0;
}
#elif defined(USE_SECTRANSP)
static bool encrypt_des(const unsigned char *in, unsigned char *out,
const unsigned char *key_56)
{
char key[8];
size_t out_len;
CCCryptorStatus err;
/* Expand the 56-bit key to 64-bits */
extend_key_56_to_64(key_56, key);
/* Set the key parity to odd */
Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
/* Perform the encryption */
err = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode, key,
kCCKeySizeDES, NULL, in, 8 /* inbuflen */, out,
8 /* outbuflen */, &out_len);
return err == kCCSuccess;
}
#elif defined(USE_OS400CRYPTO)
static bool encrypt_des(const unsigned char *in, unsigned char *out,
const unsigned char *key_56)
{
char key[8];
_CIPHER_Control_T ctl;
/* Setup the cipher control structure */
ctl.Func_ID = ENCRYPT_ONLY;
ctl.Data_Len = sizeof(key);
/* Expand the 56-bit key to 64-bits */
extend_key_56_to_64(key_56, ctl.Crypto_Key);
/* Set the key parity to odd */
Curl_des_set_odd_parity((unsigned char *) ctl.Crypto_Key, ctl.Data_Len);
/* Perform the encryption */
_CIPHER((_SPCPTR *) &out, &ctl, (_SPCPTR *) &in);
return TRUE;
}
#elif defined(USE_WIN32_CRYPTO)
static bool encrypt_des(const unsigned char *in, unsigned char *out,
const unsigned char *key_56)
{
HCRYPTPROV hprov;
HCRYPTKEY hkey;
struct {
BLOBHEADER hdr;
unsigned int len;
char key[8];
} blob;
DWORD len = 8;
/* Acquire the crypto provider */
if(!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
return FALSE;
/* Setup the key blob structure */
memset(&blob, 0, sizeof(blob));
blob.hdr.bType = PLAINTEXTKEYBLOB;
blob.hdr.bVersion = 2;
blob.hdr.aiKeyAlg = CALG_DES;
blob.len = sizeof(blob.key);
/* Expand the 56-bit key to 64-bits */
extend_key_56_to_64(key_56, blob.key);
/* Set the key parity to odd */
Curl_des_set_odd_parity((unsigned char *) blob.key, sizeof(blob.key));
/* Import the key */
if(!CryptImportKey(hprov, (BYTE *) &blob, sizeof(blob), 0, 0, &hkey)) {
CryptReleaseContext(hprov, 0);
return FALSE;
}
memcpy(out, in, 8);
/* Perform the encryption */
CryptEncrypt(hkey, 0, FALSE, 0, out, &len, len);
CryptDestroyKey(hkey);
CryptReleaseContext(hprov, 0);
return TRUE;
}
#endif /* defined(USE_WIN32_CRYPTO) */
/*
* takes a 21 byte array and treats it as 3 56-bit DES keys. The
* 8 byte plaintext is encrypted with each key and the resulting 24
* bytes are stored in the results array.
*/
void Curl_ntlm_core_lm_resp(const unsigned char *keys,
const unsigned char *plaintext,
unsigned char *results)
{
#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
DES_key_schedule ks;
setup_des_key(keys, DESKEY(ks));
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
DESKEY(ks), DES_ENCRYPT);
setup_des_key(keys + 7, DESKEY(ks));
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 8),
DESKEY(ks), DES_ENCRYPT);
setup_des_key(keys + 14, DESKEY(ks));
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16),
DESKEY(ks), DES_ENCRYPT);
#elif defined(USE_GNUTLS)
struct des_ctx des;
setup_des_key(keys, &des);
des_encrypt(&des, 8, results, plaintext);
setup_des_key(keys + 7, &des);
des_encrypt(&des, 8, results + 8, plaintext);
setup_des_key(keys + 14, &des);
des_encrypt(&des, 8, results + 16, plaintext);
#elif defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(plaintext, results, keys);
encrypt_des(plaintext, results + 8, keys + 7);
encrypt_des(plaintext, results + 16, keys + 14);
#else
(void)keys;
(void)plaintext;
(void)results;
#endif
}
/*
* Set up lanmanager hashed password
*/
CURLcode Curl_ntlm_core_mk_lm_hash(const char *password,
unsigned char *lmbuffer /* 21 bytes */)
{
unsigned char pw[14];
#if !defined(CURL_NTLM_NOT_SUPPORTED)
static const unsigned char magic[] = {
0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
};
#endif
size_t len = CURLMIN(strlen(password), 14);
Curl_strntoupper((char *)pw, password, len);
memset(&pw[len], 0, 14 - len);
{
/* Create LanManager hashed password. */
#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
DES_key_schedule ks;
setup_des_key(pw, DESKEY(ks));
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
DESKEY(ks), DES_ENCRYPT);
setup_des_key(pw + 7, DESKEY(ks));
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8),
DESKEY(ks), DES_ENCRYPT);
#elif defined(USE_GNUTLS)
struct des_ctx des;
setup_des_key(pw, &des);
des_encrypt(&des, 8, lmbuffer, magic);
setup_des_key(pw + 7, &des);
des_encrypt(&des, 8, lmbuffer + 8, magic);
#elif defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(magic, lmbuffer, pw);
encrypt_des(magic, lmbuffer + 8, pw + 7);
#endif
memset(lmbuffer + 16, 0, 21 - 16);
}
return CURLE_OK;
}
static void ascii_to_unicode_le(unsigned char *dest, const char *src,
size_t srclen)
{
size_t i;
for(i = 0; i < srclen; i++) {
dest[2 * i] = (unsigned char)src[i];
dest[2 * i + 1] = '\0';
}
}
#if !defined(USE_WINDOWS_SSPI)
static void ascii_uppercase_to_unicode_le(unsigned char *dest,
const char *src, size_t srclen)
{
size_t i;
for(i = 0; i < srclen; i++) {
dest[2 * i] = (unsigned char)(Curl_raw_toupper(src[i]));
dest[2 * i + 1] = '\0';
}
}
#endif /* !USE_WINDOWS_SSPI */
/*
* Set up nt hashed passwords
* @unittest: 1600
*/
CURLcode Curl_ntlm_core_mk_nt_hash(const char *password,
unsigned char *ntbuffer /* 21 bytes */)
{
size_t len = strlen(password);
unsigned char *pw;
CURLcode result;
if(len > SIZE_T_MAX/2) /* avoid integer overflow */
return CURLE_OUT_OF_MEMORY;
pw = len ? malloc(len * 2) : (unsigned char *)strdup("");
if(!pw)
return CURLE_OUT_OF_MEMORY;
ascii_to_unicode_le(pw, password, len);
/* Create NT hashed password. */
result = Curl_md4it(ntbuffer, pw, 2 * len);
if(!result)
memset(ntbuffer + 16, 0, 21 - 16);
free(pw);
return result;
}
#if !defined(USE_WINDOWS_SSPI)
/* Timestamp in tenths of a microsecond since January 1, 1601 00:00:00 UTC. */
struct ms_filetime {
unsigned int dwLowDateTime;
unsigned int dwHighDateTime;
};
/* Convert a time_t to an MS FILETIME (MS-DTYP section 2.3.3). */
static void time2filetime(struct ms_filetime *ft, time_t t)
{
#if SIZEOF_TIME_T > 4
t = (t + CURL_OFF_T_C(11644473600)) * 10000000;
ft->dwLowDateTime = (unsigned int) (t & 0xFFFFFFFF);
ft->dwHighDateTime = (unsigned int) (t >> 32);
#else
unsigned int r, s;
unsigned int i;
ft->dwLowDateTime = t & 0xFFFFFFFF;
ft->dwHighDateTime = 0;
# ifndef HAVE_TIME_T_UNSIGNED
/* Extend sign if needed. */
if(ft->dwLowDateTime & 0x80000000)
ft->dwHighDateTime = ~0;
# endif
/* Bias seconds to Jan 1, 1601.
134774 days = 11644473600 seconds = 0x2B6109100 */
r = ft->dwLowDateTime;
ft->dwLowDateTime = (ft->dwLowDateTime + 0xB6109100U) & 0xFFFFFFFF;
ft->dwHighDateTime += ft->dwLowDateTime < r? 0x03: 0x02;
/* Convert to tenths of microseconds. */
ft->dwHighDateTime *= 10000000;
i = 32;
do {
i -= 8;
s = ((ft->dwLowDateTime >> i) & 0xFF) * (10000000 - 1);
r = (s << i) & 0xFFFFFFFF;
s >>= 1; /* Split shift to avoid width overflow. */
s >>= 31 - i;
ft->dwLowDateTime = (ft->dwLowDateTime + r) & 0xFFFFFFFF;
if(ft->dwLowDateTime < r)
s++;
ft->dwHighDateTime += s;
} while(i);
ft->dwHighDateTime &= 0xFFFFFFFF;
#endif
}
/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
* (uppercase UserName + Domain) as the data
*/
CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
const char *domain, size_t domlen,
unsigned char *ntlmhash,
unsigned char *ntlmv2hash)
{
/* Unicode representation */
size_t identity_len;
unsigned char *identity;
CURLcode result = CURLE_OK;
if((userlen > CURL_MAX_INPUT_LENGTH) || (domlen > CURL_MAX_INPUT_LENGTH))
return CURLE_OUT_OF_MEMORY;
identity_len = (userlen + domlen) * 2;
identity = malloc(identity_len + 1);
if(!identity)
return CURLE_OUT_OF_MEMORY;
ascii_uppercase_to_unicode_le(identity, user, userlen);
ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
result = Curl_hmacit(Curl_HMAC_MD5, ntlmhash, 16, identity, identity_len,
ntlmv2hash);
free(identity);
return result;
}
/*
* Curl_ntlm_core_mk_ntlmv2_resp()
*
* This creates the NTLMv2 response as set in the ntlm type-3 message.
*
* Parameters:
*
* ntlmv2hash [in] - The ntlmv2 hash (16 bytes)
* challenge_client [in] - The client nonce (8 bytes)
* ntlm [in] - The ntlm data struct being used to read TargetInfo
and Server challenge received in the type-2 message
* ntresp [out] - The address where a pointer to newly allocated
* memory holding the NTLMv2 response.
* ntresp_len [out] - The length of the output message.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
unsigned char *challenge_client,
struct ntlmdata *ntlm,
unsigned char **ntresp,
unsigned int *ntresp_len)
{
/* NTLMv2 response structure :
------------------------------------------------------------------------------
0 HMAC MD5 16 bytes
------BLOB--------------------------------------------------------------------
16 Signature 0x01010000
20 Reserved long (0x00000000)
24 Timestamp LE, 64-bit signed value representing the number of
tenths of a microsecond since January 1, 1601.
32 Client Nonce 8 bytes
40 Unknown 4 bytes
44 Target Info N bytes (from the type-2 message)
44+N Unknown 4 bytes
------------------------------------------------------------------------------
*/
unsigned int len = 0;
unsigned char *ptr = NULL;
unsigned char hmac_output[HMAC_MD5_LENGTH];
struct ms_filetime tw;
CURLcode result = CURLE_OK;
/* Calculate the timestamp */
#ifdef DEBUGBUILD
char *force_timestamp = getenv("CURL_FORCETIME");
if(force_timestamp)
time2filetime(&tw, (time_t) 0);
else
#endif
time2filetime(&tw, time(NULL));
/* Calculate the response len */
len = HMAC_MD5_LENGTH + NTLMv2_BLOB_LEN;
/* Allocate the response */
ptr = calloc(1, len);
if(!ptr)
return CURLE_OUT_OF_MEMORY;
/* Create the BLOB structure */
msnprintf((char *)ptr + HMAC_MD5_LENGTH, NTLMv2_BLOB_LEN,
"%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */
"%c%c%c%c" /* Reserved = 0 */
"%c%c%c%c%c%c%c%c", /* Timestamp */
NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
0, 0, 0, 0,
LONGQUARTET(tw.dwLowDateTime), LONGQUARTET(tw.dwHighDateTime));
memcpy(ptr + 32, challenge_client, 8);
if(ntlm->target_info_len)
memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len);
/* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
memcpy(ptr + 8, &ntlm->nonce[0], 8);
result = Curl_hmacit(Curl_HMAC_MD5, ntlmv2hash, HMAC_MD5_LENGTH, ptr + 8,
NTLMv2_BLOB_LEN + 8, hmac_output);
if(result) {
free(ptr);
return result;
}
/* Concatenate the HMAC MD5 output with the BLOB */
memcpy(ptr, hmac_output, HMAC_MD5_LENGTH);
/* Return the response */
*ntresp = ptr;
*ntresp_len = len;
return result;
}
/*
* Curl_ntlm_core_mk_lmv2_resp()
*
* This creates the LMv2 response as used in the ntlm type-3 message.
*
* Parameters:
*
* ntlmv2hash [in] - The ntlmv2 hash (16 bytes)
* challenge_client [in] - The client nonce (8 bytes)
* challenge_client [in] - The server challenge (8 bytes)
* lmresp [out] - The LMv2 response (24 bytes)
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
unsigned char *challenge_client,
unsigned char *challenge_server,
unsigned char *lmresp)
{
unsigned char data[16];
unsigned char hmac_output[16];
CURLcode result = CURLE_OK;
memcpy(&data[0], challenge_server, 8);
memcpy(&data[8], challenge_client, 8);
result = Curl_hmacit(Curl_HMAC_MD5, ntlmv2hash, 16, &data[0], 16,
hmac_output);
if(result)
return result;
/* Concatenate the HMAC MD5 output with the client nonce */
memcpy(lmresp, hmac_output, 16);
memcpy(lmresp + 16, challenge_client, 8);
return result;
}
#endif /* !USE_WINDOWS_SSPI */
#endif /* USE_CURL_NTLM_CORE */

79
third_party/curl/lib/curl_ntlm_core.h vendored Normal file
View File

@ -0,0 +1,79 @@
#ifndef HEADER_CURL_NTLM_CORE_H
#define HEADER_CURL_NTLM_CORE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if defined(USE_CURL_NTLM_CORE)
#if defined(USE_OPENSSL)
# include <openssl/ssl.h>
#elif defined(USE_WOLFSSL)
# include <wolfssl/options.h>
# include <wolfssl/openssl/ssl.h>
#endif
/* Helpers to generate function byte arguments in little endian order */
#define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff))
#define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \
((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff))
void Curl_ntlm_core_lm_resp(const unsigned char *keys,
const unsigned char *plaintext,
unsigned char *results);
CURLcode Curl_ntlm_core_mk_lm_hash(const char *password,
unsigned char *lmbuffer /* 21 bytes */);
CURLcode Curl_ntlm_core_mk_nt_hash(const char *password,
unsigned char *ntbuffer /* 21 bytes */);
#if !defined(USE_WINDOWS_SSPI)
CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
const unsigned char *data, unsigned int datalen,
unsigned char *output);
CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
const char *domain, size_t domlen,
unsigned char *ntlmhash,
unsigned char *ntlmv2hash);
CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
unsigned char *challenge_client,
struct ntlmdata *ntlm,
unsigned char **ntresp,
unsigned int *ntresp_len);
CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
unsigned char *challenge_client,
unsigned char *challenge_server,
unsigned char *lmresp);
#endif /* !USE_WINDOWS_SSPI */
#endif /* USE_CURL_NTLM_CORE */
#endif /* HEADER_CURL_NTLM_CORE_H */

203
third_party/curl/lib/curl_path.c vendored Normal file
View File

@ -0,0 +1,203 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl AND ISC
*
***************************************************************************/
#include "curl_setup.h"
#if defined(USE_SSH)
#include <curl/curl.h>
#include "curl_memory.h"
#include "curl_path.h"
#include "escape.h"
#include "memdebug.h"
#define MAX_SSHPATH_LEN 100000 /* arbitrary */
/* figure out the path to work with in this particular request */
CURLcode Curl_getworkingpath(struct Curl_easy *data,
char *homedir, /* when SFTP is used */
char **path) /* returns the allocated
real path to work with */
{
char *working_path;
size_t working_path_len;
struct dynbuf npath;
CURLcode result =
Curl_urldecode(data->state.up.path, 0, &working_path,
&working_path_len, REJECT_ZERO);
if(result)
return result;
/* new path to switch to in case we need to */
Curl_dyn_init(&npath, MAX_SSHPATH_LEN);
/* Check for /~/, indicating relative to the user's home directory */
if((data->conn->handler->protocol & CURLPROTO_SCP) &&
(working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) {
/* It is referenced to the home directory, so strip the leading '/~/' */
if(Curl_dyn_addn(&npath, &working_path[3], working_path_len - 3)) {
free(working_path);
return CURLE_OUT_OF_MEMORY;
}
}
else if((data->conn->handler->protocol & CURLPROTO_SFTP) &&
(!strcmp("/~", working_path) ||
((working_path_len > 2) && !memcmp(working_path, "/~/", 3)))) {
if(Curl_dyn_add(&npath, homedir)) {
free(working_path);
return CURLE_OUT_OF_MEMORY;
}
if(working_path_len > 2) {
size_t len;
const char *p;
int copyfrom = 3;
/* Copy a separating '/' if homedir does not end with one */
len = Curl_dyn_len(&npath);
p = Curl_dyn_ptr(&npath);
if(len && (p[len-1] != '/'))
copyfrom = 2;
if(Curl_dyn_addn(&npath,
&working_path[copyfrom], working_path_len - copyfrom)) {
free(working_path);
return CURLE_OUT_OF_MEMORY;
}
}
}
if(Curl_dyn_len(&npath)) {
free(working_path);
/* store the pointer for the caller to receive */
*path = Curl_dyn_ptr(&npath);
}
else
*path = working_path;
return CURLE_OK;
}
/* The original get_pathname() function came from OpenSSH sftp.c version
4.6p1. */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define MAX_PATHLENGTH 65535 /* arbitrary long */
CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir)
{
const char *cp = *cpp, *end;
char quot;
unsigned int i;
static const char WHITESPACE[] = " \t\r\n";
struct dynbuf out;
CURLcode result;
DEBUGASSERT(homedir);
*path = NULL;
*cpp = NULL;
if(!*cp || !homedir)
return CURLE_QUOTE_ERROR;
Curl_dyn_init(&out, MAX_PATHLENGTH);
/* Ignore leading whitespace */
cp += strspn(cp, WHITESPACE);
/* Check for quoted filenames */
if(*cp == '\"' || *cp == '\'') {
quot = *cp++;
/* Search for terminating quote, unescape some chars */
for(i = 0; i <= strlen(cp); i++) {
if(cp[i] == quot) { /* Found quote */
i++;
break;
}
if(cp[i] == '\0') { /* End of string */
goto fail;
}
if(cp[i] == '\\') { /* Escaped characters */
i++;
if(cp[i] != '\'' && cp[i] != '\"' &&
cp[i] != '\\') {
goto fail;
}
}
result = Curl_dyn_addn(&out, &cp[i], 1);
if(result)
return result;
}
if(!Curl_dyn_len(&out))
goto fail;
/* return pointer to second parameter if it exists */
*cpp = &cp[i] + strspn(&cp[i], WHITESPACE);
}
else {
/* Read to end of filename - either to whitespace or terminator */
end = strpbrk(cp, WHITESPACE);
if(!end)
end = strchr(cp, '\0');
/* return pointer to second parameter if it exists */
*cpp = end + strspn(end, WHITESPACE);
/* Handling for relative path - prepend home directory */
if(cp[0] == '/' && cp[1] == '~' && cp[2] == '/') {
result = Curl_dyn_add(&out, homedir);
if(!result)
result = Curl_dyn_addn(&out, "/", 1);
if(result)
return result;
cp += 3;
}
/* Copy path name up until first "whitespace" */
result = Curl_dyn_addn(&out, cp, (end - cp));
if(result)
return result;
}
*path = Curl_dyn_ptr(&out);
return CURLE_OK;
fail:
Curl_dyn_free(&out);
return CURLE_QUOTE_ERROR;
}
#endif /* if SSH is used */

49
third_party/curl/lib/curl_path.h vendored Normal file
View File

@ -0,0 +1,49 @@
#ifndef HEADER_CURL_PATH_H
#define HEADER_CURL_PATH_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include <curl/curl.h>
#include "urldata.h"
#ifdef _WIN32
# undef PATH_MAX
# define PATH_MAX MAX_PATH
# ifndef R_OK
# define R_OK 4
# endif
#endif
#ifndef PATH_MAX
#define PATH_MAX 1024 /* just an extra precaution since there are systems that
have their definition hidden well */
#endif
CURLcode Curl_getworkingpath(struct Curl_easy *data,
char *homedir,
char **path);
CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir);
#endif /* HEADER_CURL_PATH_H */

55
third_party/curl/lib/curl_printf.h vendored Normal file
View File

@ -0,0 +1,55 @@
#ifndef HEADER_CURL_PRINTF_H
#define HEADER_CURL_PRINTF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/*
* This header should be included by ALL code in libcurl that uses any
* *rintf() functions.
*/
#include <curl/mprintf.h>
#define MERR_OK 0
#define MERR_MEM 1
#define MERR_TOO_LARGE 2
# undef printf
# undef fprintf
# undef msnprintf
# undef vprintf
# undef vfprintf
# undef vsnprintf
# undef mvsnprintf
# undef aprintf
# undef vaprintf
# define printf curl_mprintf
# define fprintf curl_mfprintf
# define msnprintf curl_msnprintf
# define vprintf curl_mvprintf
# define vfprintf curl_mvfprintf
# define mvsnprintf curl_mvsnprintf
# define aprintf curl_maprintf
# define vaprintf curl_mvaprintf
#endif /* HEADER_CURL_PRINTF_H */

96
third_party/curl/lib/curl_range.c vendored Normal file
View File

@ -0,0 +1,96 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include <curl/curl.h>
#include "curl_range.h"
#include "sendf.h"
#include "strtoofft.h"
/* Only include this function if one or more of FTP, FILE are enabled. */
#if !defined(CURL_DISABLE_FTP) || !defined(CURL_DISABLE_FILE)
/*
Check if this is a range download, and if so, set the internal variables
properly.
*/
CURLcode Curl_range(struct Curl_easy *data)
{
curl_off_t from, to;
char *ptr;
char *ptr2;
if(data->state.use_range && data->state.range) {
CURLofft from_t;
CURLofft to_t;
from_t = curlx_strtoofft(data->state.range, &ptr, 10, &from);
if(from_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
ptr++;
to_t = curlx_strtoofft(ptr, &ptr2, 10, &to);
if(to_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
if((to_t == CURL_OFFT_INVAL) && !from_t) {
/* X - */
data->state.resume_from = from;
DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file",
from));
}
else if((from_t == CURL_OFFT_INVAL) && !to_t) {
/* -Y */
data->req.maxdownload = to;
data->state.resume_from = -to;
DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes",
to));
}
else {
/* X-Y */
curl_off_t totalsize;
/* Ensure the range is sensible - to should follow from. */
if(from > to)
return CURLE_RANGE_ERROR;
totalsize = to - from;
if(totalsize == CURL_OFF_T_MAX)
return CURLE_RANGE_ERROR;
data->req.maxdownload = totalsize + 1; /* include last byte */
data->state.resume_from = from;
DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T
" getting %" CURL_FORMAT_CURL_OFF_T " bytes",
from, data->req.maxdownload));
}
DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T
" to %" CURL_FORMAT_CURL_OFF_T ", totally %"
CURL_FORMAT_CURL_OFF_T " bytes",
from, to, data->req.maxdownload));
}
else
data->req.maxdownload = -1;
return CURLE_OK;
}
#endif

31
third_party/curl/lib/curl_range.h vendored Normal file
View File

@ -0,0 +1,31 @@
#ifndef HEADER_CURL_RANGE_H
#define HEADER_CURL_RANGE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
CURLcode Curl_range(struct Curl_easy *data);
#endif /* HEADER_CURL_RANGE_H */

362
third_party/curl/lib/curl_rtmp.c vendored Normal file
View File

@ -0,0 +1,362 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) Howard Chu, <hyc@highlandsun.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#ifdef USE_LIBRTMP
#include "curl_rtmp.h"
#include "urldata.h"
#include "nonblock.h" /* for curlx_nonblock */
#include "progress.h" /* for Curl_pgrsSetUploadSize */
#include "transfer.h"
#include "warnless.h"
#include <curl/curl.h>
#include <librtmp/rtmp.h>
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
#if defined(_WIN32) && !defined(USE_LWIPSOCK)
#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
#define SET_RCVTIMEO(tv,s) int tv = s*1000
#elif defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD)
#define SET_RCVTIMEO(tv,s) int tv = s*1000
#else
#define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0}
#endif
#define DEF_BUFTIME (2*60*60*1000) /* 2 hours */
static CURLcode rtmp_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
static CURLcode rtmp_do(struct Curl_easy *data, bool *done);
static CURLcode rtmp_done(struct Curl_easy *data, CURLcode, bool premature);
static CURLcode rtmp_connect(struct Curl_easy *data, bool *done);
static CURLcode rtmp_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead);
static Curl_recv rtmp_recv;
static Curl_send rtmp_send;
/*
* RTMP protocol handler.h, based on https://rtmpdump.mplayerhq.hu
*/
const struct Curl_handler Curl_handler_rtmp = {
"rtmp", /* scheme */
rtmp_setup_connection, /* setup_connection */
rtmp_do, /* do_it */
rtmp_done, /* done */
ZERO_NULL, /* do_more */
rtmp_connect, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* write_resp */
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_RTMP, /* defport */
CURLPROTO_RTMP, /* protocol */
CURLPROTO_RTMP, /* family */
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmpt = {
"rtmpt", /* scheme */
rtmp_setup_connection, /* setup_connection */
rtmp_do, /* do_it */
rtmp_done, /* done */
ZERO_NULL, /* do_more */
rtmp_connect, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* write_resp */
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPT, /* protocol */
CURLPROTO_RTMPT, /* family */
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmpe = {
"rtmpe", /* scheme */
rtmp_setup_connection, /* setup_connection */
rtmp_do, /* do_it */
rtmp_done, /* done */
ZERO_NULL, /* do_more */
rtmp_connect, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* write_resp */
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_RTMP, /* defport */
CURLPROTO_RTMPE, /* protocol */
CURLPROTO_RTMPE, /* family */
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmpte = {
"rtmpte", /* scheme */
rtmp_setup_connection, /* setup_connection */
rtmp_do, /* do_it */
rtmp_done, /* done */
ZERO_NULL, /* do_more */
rtmp_connect, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* write_resp */
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPTE, /* protocol */
CURLPROTO_RTMPTE, /* family */
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmps = {
"rtmps", /* scheme */
rtmp_setup_connection, /* setup_connection */
rtmp_do, /* do_it */
rtmp_done, /* done */
ZERO_NULL, /* do_more */
rtmp_connect, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* write_resp */
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPS, /* protocol */
CURLPROTO_RTMP, /* family */
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmpts = {
"rtmpts", /* scheme */
rtmp_setup_connection, /* setup_connection */
rtmp_do, /* do_it */
rtmp_done, /* done */
ZERO_NULL, /* do_more */
rtmp_connect, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* write_resp */
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPTS, /* protocol */
CURLPROTO_RTMPT, /* family */
PROTOPT_NONE /* flags */
};
static CURLcode rtmp_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
RTMP *r = RTMP_Alloc();
if(!r)
return CURLE_OUT_OF_MEMORY;
RTMP_Init(r);
RTMP_SetBufferMS(r, DEF_BUFTIME);
if(!RTMP_SetupURL(r, data->state.url)) {
RTMP_Free(r);
return CURLE_URL_MALFORMAT;
}
conn->proto.rtmp = r;
return CURLE_OK;
}
static CURLcode rtmp_connect(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp;
SET_RCVTIMEO(tv, 10);
r->m_sb.sb_socket = (int)conn->sock[FIRSTSOCKET];
/* We have to know if it's a write before we send the
* connect request packet
*/
if(data->state.upload)
r->Link.protocol |= RTMP_FEATURE_WRITE;
/* For plain streams, use the buffer toggle trick to keep data flowing */
if(!(r->Link.lFlags & RTMP_LF_LIVE) &&
!(r->Link.protocol & RTMP_FEATURE_HTTP))
r->Link.lFlags |= RTMP_LF_BUFX;
(void)curlx_nonblock(r->m_sb.sb_socket, FALSE);
setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO,
(char *)&tv, sizeof(tv));
if(!RTMP_Connect1(r, NULL))
return CURLE_FAILED_INIT;
/* Clients must send a periodic BytesReceived report to the server */
r->m_bSendCounter = true;
*done = TRUE;
conn->recv[FIRSTSOCKET] = rtmp_recv;
conn->send[FIRSTSOCKET] = rtmp_send;
return CURLE_OK;
}
static CURLcode rtmp_do(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp;
if(!RTMP_ConnectStream(r, 0))
return CURLE_FAILED_INIT;
if(data->state.upload) {
Curl_pgrsSetUploadSize(data, data->state.infilesize);
Curl_xfer_setup(data, -1, -1, FALSE, FIRSTSOCKET);
}
else
Curl_xfer_setup(data, FIRSTSOCKET, -1, FALSE, -1);
*done = TRUE;
return CURLE_OK;
}
static CURLcode rtmp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
(void)data; /* unused */
(void)status; /* unused */
(void)premature; /* unused */
return CURLE_OK;
}
static CURLcode rtmp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection)
{
RTMP *r = conn->proto.rtmp;
(void)data;
(void)dead_connection;
if(r) {
conn->proto.rtmp = NULL;
RTMP_Close(r);
RTMP_Free(r);
}
return CURLE_OK;
}
static ssize_t rtmp_recv(struct Curl_easy *data, int sockindex, char *buf,
size_t len, CURLcode *err)
{
struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp;
ssize_t nread;
(void)sockindex; /* unused */
nread = RTMP_Read(r, buf, curlx_uztosi(len));
if(nread < 0) {
if(r->m_read.status == RTMP_READ_COMPLETE ||
r->m_read.status == RTMP_READ_EOF) {
data->req.size = data->req.bytecount;
nread = 0;
}
else
*err = CURLE_RECV_ERROR;
}
return nread;
}
static ssize_t rtmp_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, CURLcode *err)
{
struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp;
ssize_t num;
(void)sockindex; /* unused */
num = RTMP_Write(r, (char *)buf, curlx_uztosi(len));
if(num < 0)
*err = CURLE_SEND_ERROR;
return num;
}
void Curl_rtmp_version(char *version, size_t len)
{
char suff[2];
if(RTMP_LIB_VERSION & 0xff) {
suff[0] = (RTMP_LIB_VERSION & 0xff) + 'a' - 1;
suff[1] = '\0';
}
else
suff[0] = '\0';
msnprintf(version, len, "librtmp/%d.%d%s",
RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
suff);
}
#endif /* USE_LIBRTMP */

37
third_party/curl/lib/curl_rtmp.h vendored Normal file
View File

@ -0,0 +1,37 @@
#ifndef HEADER_CURL_RTMP_H
#define HEADER_CURL_RTMP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Howard Chu, <hyc@highlandsun.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#ifdef USE_LIBRTMP
extern const struct Curl_handler Curl_handler_rtmp;
extern const struct Curl_handler Curl_handler_rtmpt;
extern const struct Curl_handler Curl_handler_rtmpe;
extern const struct Curl_handler Curl_handler_rtmpte;
extern const struct Curl_handler Curl_handler_rtmps;
extern const struct Curl_handler Curl_handler_rtmpts;
void Curl_rtmp_version(char *version, size_t len);
#endif
#endif /* HEADER_CURL_RTMP_H */

760
third_party/curl/lib/curl_sasl.c vendored Normal file
View File

@ -0,0 +1,760 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
* RFC2195 CRAM-MD5 authentication
* RFC2617 Basic and Digest Access Authentication
* RFC2831 DIGEST-MD5 authentication
* RFC4422 Simple Authentication and Security Layer (SASL)
* RFC4616 PLAIN authentication
* RFC5802 SCRAM-SHA-1 authentication
* RFC7677 SCRAM-SHA-256 authentication
* RFC6749 OAuth 2.0 Authorization Framework
* RFC7628 A Set of SASL Mechanisms for OAuth
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \
!defined(CURL_DISABLE_POP3) || \
(!defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP))
#include <curl/curl.h>
#include "urldata.h"
#include "curl_base64.h"
#include "curl_md5.h"
#include "vauth/vauth.h"
#include "cfilters.h"
#include "vtls/vtls.h"
#include "curl_hmac.h"
#include "curl_sasl.h"
#include "warnless.h"
#include "strtok.h"
#include "sendf.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
/* Supported mechanisms */
static const struct {
const char *name; /* Name */
size_t len; /* Name length */
unsigned short bit; /* Flag bit */
} mechtable[] = {
{ "LOGIN", 5, SASL_MECH_LOGIN },
{ "PLAIN", 5, SASL_MECH_PLAIN },
{ "CRAM-MD5", 8, SASL_MECH_CRAM_MD5 },
{ "DIGEST-MD5", 10, SASL_MECH_DIGEST_MD5 },
{ "GSSAPI", 6, SASL_MECH_GSSAPI },
{ "EXTERNAL", 8, SASL_MECH_EXTERNAL },
{ "NTLM", 4, SASL_MECH_NTLM },
{ "XOAUTH2", 7, SASL_MECH_XOAUTH2 },
{ "OAUTHBEARER", 11, SASL_MECH_OAUTHBEARER },
{ "SCRAM-SHA-1", 11, SASL_MECH_SCRAM_SHA_1 },
{ "SCRAM-SHA-256",13, SASL_MECH_SCRAM_SHA_256 },
{ ZERO_NULL, 0, 0 }
};
/*
* Curl_sasl_cleanup()
*
* This is used to cleanup any libraries or curl modules used by the sasl
* functions.
*
* Parameters:
*
* conn [in] - The connection data.
* authused [in] - The authentication mechanism used.
*/
void Curl_sasl_cleanup(struct connectdata *conn, unsigned short authused)
{
(void)conn;
(void)authused;
#if defined(USE_KERBEROS5)
/* Cleanup the gssapi structure */
if(authused == SASL_MECH_GSSAPI) {
Curl_auth_cleanup_gssapi(&conn->krb5);
}
#endif
#if defined(USE_GSASL)
/* Cleanup the GSASL structure */
if(authused & (SASL_MECH_SCRAM_SHA_1 | SASL_MECH_SCRAM_SHA_256)) {
Curl_auth_gsasl_cleanup(&conn->gsasl);
}
#endif
#if defined(USE_NTLM)
/* Cleanup the NTLM structure */
if(authused == SASL_MECH_NTLM) {
Curl_auth_cleanup_ntlm(&conn->ntlm);
}
#endif
}
/*
* Curl_sasl_decode_mech()
*
* Convert a SASL mechanism name into a token.
*
* Parameters:
*
* ptr [in] - The mechanism string.
* maxlen [in] - Maximum mechanism string length.
* len [out] - If not NULL, effective name length.
*
* Returns the SASL mechanism token or 0 if no match.
*/
unsigned short Curl_sasl_decode_mech(const char *ptr, size_t maxlen,
size_t *len)
{
unsigned int i;
char c;
for(i = 0; mechtable[i].name; i++) {
if(maxlen >= mechtable[i].len &&
!memcmp(ptr, mechtable[i].name, mechtable[i].len)) {
if(len)
*len = mechtable[i].len;
if(maxlen == mechtable[i].len)
return mechtable[i].bit;
c = ptr[mechtable[i].len];
if(!ISUPPER(c) && !ISDIGIT(c) && c != '-' && c != '_')
return mechtable[i].bit;
}
}
return 0;
}
/*
* Curl_sasl_parse_url_auth_option()
*
* Parse the URL login options.
*/
CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
const char *value, size_t len)
{
CURLcode result = CURLE_OK;
size_t mechlen;
if(!len)
return CURLE_URL_MALFORMAT;
if(sasl->resetprefs) {
sasl->resetprefs = FALSE;
sasl->prefmech = SASL_AUTH_NONE;
}
if(!strncmp(value, "*", len))
sasl->prefmech = SASL_AUTH_DEFAULT;
else {
unsigned short mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
if(mechbit && mechlen == len)
sasl->prefmech |= mechbit;
else
result = CURLE_URL_MALFORMAT;
}
return result;
}
/*
* Curl_sasl_init()
*
* Initializes the SASL structure.
*/
void Curl_sasl_init(struct SASL *sasl, struct Curl_easy *data,
const struct SASLproto *params)
{
unsigned long auth = data->set.httpauth;
sasl->params = params; /* Set protocol dependent parameters */
sasl->state = SASL_STOP; /* Not yet running */
sasl->curmech = NULL; /* No mechanism yet. */
sasl->authmechs = SASL_AUTH_NONE; /* No known authentication mechanism yet */
sasl->prefmech = params->defmechs; /* Default preferred mechanisms */
sasl->authused = SASL_AUTH_NONE; /* The authentication mechanism used */
sasl->resetprefs = TRUE; /* Reset prefmech upon AUTH parsing. */
sasl->mutual_auth = FALSE; /* No mutual authentication (GSSAPI only) */
sasl->force_ir = FALSE; /* Respect external option */
if(auth != CURLAUTH_BASIC) {
unsigned short mechs = SASL_AUTH_NONE;
/* If some usable http authentication options have been set, determine
new defaults from them. */
if(auth & CURLAUTH_BASIC)
mechs |= SASL_MECH_PLAIN | SASL_MECH_LOGIN;
if(auth & CURLAUTH_DIGEST)
mechs |= SASL_MECH_DIGEST_MD5;
if(auth & CURLAUTH_NTLM)
mechs |= SASL_MECH_NTLM;
if(auth & CURLAUTH_BEARER)
mechs |= SASL_MECH_OAUTHBEARER | SASL_MECH_XOAUTH2;
if(auth & CURLAUTH_GSSAPI)
mechs |= SASL_MECH_GSSAPI;
if(mechs != SASL_AUTH_NONE)
sasl->prefmech = mechs;
}
}
/*
* sasl_state()
*
* This is the ONLY way to change SASL state!
*/
static void sasl_state(struct SASL *sasl, struct Curl_easy *data,
saslstate newstate)
{
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[]={
"STOP",
"PLAIN",
"LOGIN",
"LOGIN_PASSWD",
"EXTERNAL",
"CRAMMD5",
"DIGESTMD5",
"DIGESTMD5_RESP",
"NTLM",
"NTLM_TYPE2MSG",
"GSSAPI",
"GSSAPI_TOKEN",
"GSSAPI_NO_DATA",
"OAUTH2",
"OAUTH2_RESP",
"GSASL",
"CANCEL",
"FINAL",
/* LAST */
};
if(sasl->state != newstate)
infof(data, "SASL %p state change from %s to %s",
(void *)sasl, names[sasl->state], names[newstate]);
#else
(void) data;
#endif
sasl->state = newstate;
}
#if defined(USE_NTLM) || defined(USE_GSASL) || defined(USE_KERBEROS5) || \
!defined(CURL_DISABLE_DIGEST_AUTH)
/* Get the SASL server message and convert it to binary. */
static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
struct bufref *out)
{
CURLcode result = CURLE_OK;
result = sasl->params->getmessage(data, out);
if(!result && (sasl->params->flags & SASL_FLAG_BASE64)) {
unsigned char *msg;
size_t msglen;
const char *serverdata = (const char *) Curl_bufref_ptr(out);
if(!*serverdata || *serverdata == '=')
Curl_bufref_set(out, NULL, 0, NULL);
else {
result = Curl_base64_decode(serverdata, &msg, &msglen);
if(!result)
Curl_bufref_set(out, msg, msglen, curl_free);
}
}
return result;
}
#endif
/* Encode the outgoing SASL message. */
static CURLcode build_message(struct SASL *sasl, struct bufref *msg)
{
CURLcode result = CURLE_OK;
if(sasl->params->flags & SASL_FLAG_BASE64) {
if(!Curl_bufref_ptr(msg)) /* Empty message. */
Curl_bufref_set(msg, "", 0, NULL);
else if(!Curl_bufref_len(msg)) /* Explicit empty response. */
Curl_bufref_set(msg, "=", 1, NULL);
else {
char *base64;
size_t base64len;
result = Curl_base64_encode((const char *) Curl_bufref_ptr(msg),
Curl_bufref_len(msg), &base64, &base64len);
if(!result)
Curl_bufref_set(msg, base64, base64len, curl_free);
}
}
return result;
}
/*
* Curl_sasl_can_authenticate()
*
* Check if we have enough auth data and capabilities to authenticate.
*/
bool Curl_sasl_can_authenticate(struct SASL *sasl, struct Curl_easy *data)
{
/* Have credentials been provided? */
if(data->state.aptr.user)
return TRUE;
/* EXTERNAL can authenticate without a user name and/or password */
if(sasl->authmechs & sasl->prefmech & SASL_MECH_EXTERNAL)
return TRUE;
return FALSE;
}
/*
* Curl_sasl_start()
*
* Calculate the required login details for SASL authentication.
*/
CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
bool force_ir, saslprogress *progress)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
unsigned short enabledmechs;
const char *mech = NULL;
struct bufref resp;
saslstate state1 = SASL_STOP;
saslstate state2 = SASL_FINAL;
const char *hostname, *disp_hostname;
int port;
#if defined(USE_KERBEROS5) || defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
sasl->params->service;
#endif
const char *oauth_bearer = data->set.str[STRING_BEARER];
struct bufref nullmsg;
Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &disp_hostname, &port);
Curl_bufref_init(&nullmsg);
Curl_bufref_init(&resp);
sasl->force_ir = force_ir; /* Latch for future use */
sasl->authused = 0; /* No mechanism used yet */
enabledmechs = sasl->authmechs & sasl->prefmech;
*progress = SASL_IDLE;
/* Calculate the supported authentication mechanism, by decreasing order of
security, as well as the initial response where appropriate */
if((enabledmechs & SASL_MECH_EXTERNAL) && !conn->passwd[0]) {
mech = SASL_MECH_STRING_EXTERNAL;
state1 = SASL_EXTERNAL;
sasl->authused = SASL_MECH_EXTERNAL;
if(force_ir || data->set.sasl_ir)
Curl_auth_create_external_message(conn->user, &resp);
}
else if(data->state.aptr.user) {
#if defined(USE_KERBEROS5)
if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() &&
Curl_auth_user_contains_domain(conn->user)) {
sasl->mutual_auth = FALSE;
mech = SASL_MECH_STRING_GSSAPI;
state1 = SASL_GSSAPI;
state2 = SASL_GSSAPI_TOKEN;
sasl->authused = SASL_MECH_GSSAPI;
if(force_ir || data->set.sasl_ir)
result = Curl_auth_create_gssapi_user_message(data, conn->user,
conn->passwd,
service,
conn->host.name,
sasl->mutual_auth,
NULL, &conn->krb5,
&resp);
}
else
#endif
#ifdef USE_GSASL
if((enabledmechs & SASL_MECH_SCRAM_SHA_256) &&
Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_256,
&conn->gsasl)) {
mech = SASL_MECH_STRING_SCRAM_SHA_256;
sasl->authused = SASL_MECH_SCRAM_SHA_256;
state1 = SASL_GSASL;
state2 = SASL_GSASL;
result = Curl_auth_gsasl_start(data, conn->user,
conn->passwd, &conn->gsasl);
if(result == CURLE_OK && (force_ir || data->set.sasl_ir))
result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp);
}
else if((enabledmechs & SASL_MECH_SCRAM_SHA_1) &&
Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_1,
&conn->gsasl)) {
mech = SASL_MECH_STRING_SCRAM_SHA_1;
sasl->authused = SASL_MECH_SCRAM_SHA_1;
state1 = SASL_GSASL;
state2 = SASL_GSASL;
result = Curl_auth_gsasl_start(data, conn->user,
conn->passwd, &conn->gsasl);
if(result == CURLE_OK && (force_ir || data->set.sasl_ir))
result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp);
}
else
#endif
#ifndef CURL_DISABLE_DIGEST_AUTH
if((enabledmechs & SASL_MECH_DIGEST_MD5) &&
Curl_auth_is_digest_supported()) {
mech = SASL_MECH_STRING_DIGEST_MD5;
state1 = SASL_DIGESTMD5;
sasl->authused = SASL_MECH_DIGEST_MD5;
}
else if(enabledmechs & SASL_MECH_CRAM_MD5) {
mech = SASL_MECH_STRING_CRAM_MD5;
state1 = SASL_CRAMMD5;
sasl->authused = SASL_MECH_CRAM_MD5;
}
else
#endif
#ifdef USE_NTLM
if((enabledmechs & SASL_MECH_NTLM) && Curl_auth_is_ntlm_supported()) {
mech = SASL_MECH_STRING_NTLM;
state1 = SASL_NTLM;
state2 = SASL_NTLM_TYPE2MSG;
sasl->authused = SASL_MECH_NTLM;
if(force_ir || data->set.sasl_ir)
result = Curl_auth_create_ntlm_type1_message(data,
conn->user, conn->passwd,
service,
hostname,
&conn->ntlm, &resp);
}
else
#endif
if((enabledmechs & SASL_MECH_OAUTHBEARER) && oauth_bearer) {
mech = SASL_MECH_STRING_OAUTHBEARER;
state1 = SASL_OAUTH2;
state2 = SASL_OAUTH2_RESP;
sasl->authused = SASL_MECH_OAUTHBEARER;
if(force_ir || data->set.sasl_ir)
result = Curl_auth_create_oauth_bearer_message(conn->user,
hostname,
port,
oauth_bearer,
&resp);
}
else if((enabledmechs & SASL_MECH_XOAUTH2) && oauth_bearer) {
mech = SASL_MECH_STRING_XOAUTH2;
state1 = SASL_OAUTH2;
sasl->authused = SASL_MECH_XOAUTH2;
if(force_ir || data->set.sasl_ir)
result = Curl_auth_create_xoauth_bearer_message(conn->user,
oauth_bearer,
&resp);
}
else if(enabledmechs & SASL_MECH_PLAIN) {
mech = SASL_MECH_STRING_PLAIN;
state1 = SASL_PLAIN;
sasl->authused = SASL_MECH_PLAIN;
if(force_ir || data->set.sasl_ir)
result = Curl_auth_create_plain_message(conn->sasl_authzid,
conn->user, conn->passwd,
&resp);
}
else if(enabledmechs & SASL_MECH_LOGIN) {
mech = SASL_MECH_STRING_LOGIN;
state1 = SASL_LOGIN;
state2 = SASL_LOGIN_PASSWD;
sasl->authused = SASL_MECH_LOGIN;
if(force_ir || data->set.sasl_ir)
Curl_auth_create_login_message(conn->user, &resp);
}
}
if(!result && mech) {
sasl->curmech = mech;
if(Curl_bufref_ptr(&resp))
result = build_message(sasl, &resp);
if(sasl->params->maxirlen &&
strlen(mech) + Curl_bufref_len(&resp) > sasl->params->maxirlen)
Curl_bufref_free(&resp);
if(!result)
result = sasl->params->sendauth(data, mech, &resp);
if(!result) {
*progress = SASL_INPROGRESS;
sasl_state(sasl, data, Curl_bufref_ptr(&resp) ? state2 : state1);
}
}
Curl_bufref_free(&resp);
return result;
}
/*
* Curl_sasl_continue()
*
* Continue the authentication.
*/
CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
int code, saslprogress *progress)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
saslstate newstate = SASL_FINAL;
struct bufref resp;
const char *hostname, *disp_hostname;
int port;
#if defined(USE_KERBEROS5) || defined(USE_NTLM) \
|| !defined(CURL_DISABLE_DIGEST_AUTH)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
sasl->params->service;
#endif
const char *oauth_bearer = data->set.str[STRING_BEARER];
struct bufref serverdata;
Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &disp_hostname, &port);
Curl_bufref_init(&serverdata);
Curl_bufref_init(&resp);
*progress = SASL_INPROGRESS;
if(sasl->state == SASL_FINAL) {
if(code != sasl->params->finalcode)
result = CURLE_LOGIN_DENIED;
*progress = SASL_DONE;
sasl_state(sasl, data, SASL_STOP);
return result;
}
if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP &&
code != sasl->params->contcode) {
*progress = SASL_DONE;
sasl_state(sasl, data, SASL_STOP);
return CURLE_LOGIN_DENIED;
}
switch(sasl->state) {
case SASL_STOP:
*progress = SASL_DONE;
return result;
case SASL_PLAIN:
result = Curl_auth_create_plain_message(conn->sasl_authzid,
conn->user, conn->passwd, &resp);
break;
case SASL_LOGIN:
Curl_auth_create_login_message(conn->user, &resp);
newstate = SASL_LOGIN_PASSWD;
break;
case SASL_LOGIN_PASSWD:
Curl_auth_create_login_message(conn->passwd, &resp);
break;
case SASL_EXTERNAL:
Curl_auth_create_external_message(conn->user, &resp);
break;
#ifdef USE_GSASL
case SASL_GSASL:
result = get_server_message(sasl, data, &serverdata);
if(!result)
result = Curl_auth_gsasl_token(data, &serverdata, &conn->gsasl, &resp);
if(!result && Curl_bufref_len(&resp) > 0)
newstate = SASL_GSASL;
break;
#endif
#ifndef CURL_DISABLE_DIGEST_AUTH
case SASL_CRAMMD5:
result = get_server_message(sasl, data, &serverdata);
if(!result)
result = Curl_auth_create_cram_md5_message(&serverdata, conn->user,
conn->passwd, &resp);
break;
case SASL_DIGESTMD5:
result = get_server_message(sasl, data, &serverdata);
if(!result)
result = Curl_auth_create_digest_md5_message(data, &serverdata,
conn->user, conn->passwd,
service, &resp);
if(!result && (sasl->params->flags & SASL_FLAG_BASE64))
newstate = SASL_DIGESTMD5_RESP;
break;
case SASL_DIGESTMD5_RESP:
/* Keep response NULL to output an empty line. */
break;
#endif
#ifdef USE_NTLM
case SASL_NTLM:
/* Create the type-1 message */
result = Curl_auth_create_ntlm_type1_message(data,
conn->user, conn->passwd,
service, hostname,
&conn->ntlm, &resp);
newstate = SASL_NTLM_TYPE2MSG;
break;
case SASL_NTLM_TYPE2MSG:
/* Decode the type-2 message */
result = get_server_message(sasl, data, &serverdata);
if(!result)
result = Curl_auth_decode_ntlm_type2_message(data, &serverdata,
&conn->ntlm);
if(!result)
result = Curl_auth_create_ntlm_type3_message(data, conn->user,
conn->passwd, &conn->ntlm,
&resp);
break;
#endif
#if defined(USE_KERBEROS5)
case SASL_GSSAPI:
result = Curl_auth_create_gssapi_user_message(data, conn->user,
conn->passwd,
service,
conn->host.name,
sasl->mutual_auth, NULL,
&conn->krb5,
&resp);
newstate = SASL_GSSAPI_TOKEN;
break;
case SASL_GSSAPI_TOKEN:
result = get_server_message(sasl, data, &serverdata);
if(!result) {
if(sasl->mutual_auth) {
/* Decode the user token challenge and create the optional response
message */
result = Curl_auth_create_gssapi_user_message(data, NULL, NULL,
NULL, NULL,
sasl->mutual_auth,
&serverdata,
&conn->krb5,
&resp);
newstate = SASL_GSSAPI_NO_DATA;
}
else
/* Decode the security challenge and create the response message */
result = Curl_auth_create_gssapi_security_message(data,
conn->sasl_authzid,
&serverdata,
&conn->krb5,
&resp);
}
break;
case SASL_GSSAPI_NO_DATA:
/* Decode the security challenge and create the response message */
result = get_server_message(sasl, data, &serverdata);
if(!result)
result = Curl_auth_create_gssapi_security_message(data,
conn->sasl_authzid,
&serverdata,
&conn->krb5,
&resp);
break;
#endif
case SASL_OAUTH2:
/* Create the authorization message */
if(sasl->authused == SASL_MECH_OAUTHBEARER) {
result = Curl_auth_create_oauth_bearer_message(conn->user,
hostname,
port,
oauth_bearer,
&resp);
/* Failures maybe sent by the server as continuations for OAUTHBEARER */
newstate = SASL_OAUTH2_RESP;
}
else
result = Curl_auth_create_xoauth_bearer_message(conn->user,
oauth_bearer,
&resp);
break;
case SASL_OAUTH2_RESP:
/* The continuation is optional so check the response code */
if(code == sasl->params->finalcode) {
/* Final response was received so we are done */
*progress = SASL_DONE;
sasl_state(sasl, data, SASL_STOP);
return result;
}
else if(code == sasl->params->contcode) {
/* Acknowledge the continuation by sending a 0x01 response. */
Curl_bufref_set(&resp, "\x01", 1, NULL);
break;
}
else {
*progress = SASL_DONE;
sasl_state(sasl, data, SASL_STOP);
return CURLE_LOGIN_DENIED;
}
case SASL_CANCEL:
/* Remove the offending mechanism from the supported list */
sasl->authmechs ^= sasl->authused;
/* Start an alternative SASL authentication */
return Curl_sasl_start(sasl, data, sasl->force_ir, progress);
default:
failf(data, "Unsupported SASL authentication mechanism");
result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */
break;
}
Curl_bufref_free(&serverdata);
switch(result) {
case CURLE_BAD_CONTENT_ENCODING:
/* Cancel dialog */
result = sasl->params->cancelauth(data, sasl->curmech);
newstate = SASL_CANCEL;
break;
case CURLE_OK:
result = build_message(sasl, &resp);
if(!result)
result = sasl->params->contauth(data, sasl->curmech, &resp);
break;
default:
newstate = SASL_STOP; /* Stop on error */
*progress = SASL_DONE;
break;
}
Curl_bufref_free(&resp);
sasl_state(sasl, data, newstate);
return result;
}
#endif /* protocols are enabled that use SASL */

165
third_party/curl/lib/curl_sasl.h vendored Normal file
View File

@ -0,0 +1,165 @@
#ifndef HEADER_CURL_SASL_H
#define HEADER_CURL_SASL_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include <curl/curl.h>
#include "bufref.h"
struct Curl_easy;
struct connectdata;
/* Authentication mechanism flags */
#define SASL_MECH_LOGIN (1 << 0)
#define SASL_MECH_PLAIN (1 << 1)
#define SASL_MECH_CRAM_MD5 (1 << 2)
#define SASL_MECH_DIGEST_MD5 (1 << 3)
#define SASL_MECH_GSSAPI (1 << 4)
#define SASL_MECH_EXTERNAL (1 << 5)
#define SASL_MECH_NTLM (1 << 6)
#define SASL_MECH_XOAUTH2 (1 << 7)
#define SASL_MECH_OAUTHBEARER (1 << 8)
#define SASL_MECH_SCRAM_SHA_1 (1 << 9)
#define SASL_MECH_SCRAM_SHA_256 (1 << 10)
/* Authentication mechanism values */
#define SASL_AUTH_NONE 0
#define SASL_AUTH_ANY 0xffff
#define SASL_AUTH_DEFAULT (SASL_AUTH_ANY & ~SASL_MECH_EXTERNAL)
/* Authentication mechanism strings */
#define SASL_MECH_STRING_LOGIN "LOGIN"
#define SASL_MECH_STRING_PLAIN "PLAIN"
#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5"
#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5"
#define SASL_MECH_STRING_GSSAPI "GSSAPI"
#define SASL_MECH_STRING_EXTERNAL "EXTERNAL"
#define SASL_MECH_STRING_NTLM "NTLM"
#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2"
#define SASL_MECH_STRING_OAUTHBEARER "OAUTHBEARER"
#define SASL_MECH_STRING_SCRAM_SHA_1 "SCRAM-SHA-1"
#define SASL_MECH_STRING_SCRAM_SHA_256 "SCRAM-SHA-256"
/* SASL flags */
#define SASL_FLAG_BASE64 0x0001 /* Messages are base64-encoded */
/* SASL machine states */
typedef enum {
SASL_STOP,
SASL_PLAIN,
SASL_LOGIN,
SASL_LOGIN_PASSWD,
SASL_EXTERNAL,
SASL_CRAMMD5,
SASL_DIGESTMD5,
SASL_DIGESTMD5_RESP,
SASL_NTLM,
SASL_NTLM_TYPE2MSG,
SASL_GSSAPI,
SASL_GSSAPI_TOKEN,
SASL_GSSAPI_NO_DATA,
SASL_OAUTH2,
SASL_OAUTH2_RESP,
SASL_GSASL,
SASL_CANCEL,
SASL_FINAL
} saslstate;
/* Progress indicator */
typedef enum {
SASL_IDLE,
SASL_INPROGRESS,
SASL_DONE
} saslprogress;
/* Protocol dependent SASL parameters */
struct SASLproto {
const char *service; /* The service name */
CURLcode (*sendauth)(struct Curl_easy *data, const char *mech,
const struct bufref *ir);
/* Send authentication command */
CURLcode (*contauth)(struct Curl_easy *data, const char *mech,
const struct bufref *contauth);
/* Send authentication continuation */
CURLcode (*cancelauth)(struct Curl_easy *data, const char *mech);
/* Cancel authentication. */
CURLcode (*getmessage)(struct Curl_easy *data, struct bufref *out);
/* Get SASL response message */
size_t maxirlen; /* Maximum initial response + mechanism length,
or zero if no max. This is normally the max
command length - other characters count.
This has to be zero for non-base64 protocols. */
int contcode; /* Code to receive when continuation is expected */
int finalcode; /* Code to receive upon authentication success */
unsigned short defmechs; /* Mechanisms enabled by default */
unsigned short flags; /* Configuration flags. */
};
/* Per-connection parameters */
struct SASL {
const struct SASLproto *params; /* Protocol dependent parameters */
saslstate state; /* Current machine state */
const char *curmech; /* Current mechanism id. */
unsigned short authmechs; /* Accepted authentication mechanisms */
unsigned short prefmech; /* Preferred authentication mechanism */
unsigned short authused; /* Auth mechanism used for the connection */
BIT(resetprefs); /* For URL auth option parsing. */
BIT(mutual_auth); /* Mutual authentication enabled (GSSAPI only) */
BIT(force_ir); /* Protocol always supports initial response */
};
/* This is used to test whether the line starts with the given mechanism */
#define sasl_mech_equal(line, wordlen, mech) \
(wordlen == (sizeof(mech) - 1) / sizeof(char) && \
!memcmp(line, mech, wordlen))
/* This is used to cleanup any libraries or curl modules used by the sasl
functions */
void Curl_sasl_cleanup(struct connectdata *conn, unsigned short authused);
/* Convert a mechanism name to a token */
unsigned short Curl_sasl_decode_mech(const char *ptr,
size_t maxlen, size_t *len);
/* Parse the URL login options */
CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
const char *value, size_t len);
/* Initializes an SASL structure */
void Curl_sasl_init(struct SASL *sasl, struct Curl_easy *data,
const struct SASLproto *params);
/* Check if we have enough auth data and capabilities to authenticate */
bool Curl_sasl_can_authenticate(struct SASL *sasl, struct Curl_easy *data);
/* Calculate the required login details for SASL authentication */
CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
bool force_ir, saslprogress *progress);
/* Continue an SASL authentication */
CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
int code, saslprogress *progress);
#endif /* HEADER_CURL_SASL_H */

921
third_party/curl/lib/curl_setup.h vendored Normal file
View File

@ -0,0 +1,921 @@
#ifndef HEADER_CURL_SETUP_H
#define HEADER_CURL_SETUP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#if defined(BUILDING_LIBCURL) && !defined(CURL_NO_OLDIES)
#define CURL_NO_OLDIES
#endif
/* FIXME: Delete this once the warnings have been fixed. */
#if !defined(CURL_WARN_SIGN_CONVERSION)
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#endif
/* Set default _WIN32_WINNT */
#ifdef __MINGW32__
#include <_mingw.h>
#endif
/*
* Disable Visual Studio warnings:
* 4127 "conditional expression is constant"
*/
#ifdef _MSC_VER
#pragma warning(disable:4127)
#endif
#ifdef _WIN32
/*
* Don't include unneeded stuff in Windows headers to avoid compiler
* warnings and macro clashes.
* Make sure to define this macro before including any Windows headers.
*/
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# ifndef NOGDI
# define NOGDI
# endif
/* Detect Windows App environment which has a restricted access
* to the Win32 APIs. */
# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
defined(WINAPI_FAMILY)
# include <winapifamily.h>
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
# define CURL_WINDOWS_APP
# endif
# endif
#endif
/* Compatibility */
#if defined(ENABLE_IPV6)
# define USE_IPV6 1
#endif
/*
* Include configuration script results or hand-crafted
* configuration file for platforms which lack config tool.
*/
#ifdef HAVE_CONFIG_H
#include "curl_config.h"
#else /* HAVE_CONFIG_H */
#ifdef _WIN32_WCE
# include "config-win32ce.h"
#else
# ifdef _WIN32
# include "config-win32.h"
# endif
#endif
#ifdef macintosh
# include "config-mac.h"
#endif
#ifdef __riscos__
# include "config-riscos.h"
#endif
#ifdef __AMIGA__
# include "config-amigaos.h"
#endif
#ifdef __OS400__
# include "config-os400.h"
#endif
#ifdef __PLAN9__
# include "config-plan9.h"
#endif
#ifdef MSDOS
# include "config-dos.h"
#endif
#endif /* HAVE_CONFIG_H */
/* ================================================================ */
/* Definition of preprocessor macros/symbols which modify compiler */
/* behavior or generated code characteristics must be done here, */
/* as appropriate, before any system header file is included. It is */
/* also possible to have them defined in the config file included */
/* before this point. As a result of all this we frown inclusion of */
/* system header files in our config files, avoid this at any cost. */
/* ================================================================ */
/*
* AIX 4.3 and newer needs _THREAD_SAFE defined to build
* proper reentrant code. Others may also need it.
*/
#ifdef NEED_THREAD_SAFE
# ifndef _THREAD_SAFE
# define _THREAD_SAFE
# endif
#endif
/*
* Tru64 needs _REENTRANT set for a few function prototypes and
* things to appear in the system header files. Unixware needs it
* to build proper reentrant code. Others may also need it.
*/
#ifdef NEED_REENTRANT
# ifndef _REENTRANT
# define _REENTRANT
# endif
#endif
/* Solaris needs this to get a POSIX-conformant getpwuid_r */
#if defined(sun) || defined(__sun)
# ifndef _POSIX_PTHREAD_SEMANTICS
# define _POSIX_PTHREAD_SEMANTICS 1
# endif
#endif
/* ================================================================ */
/* If you need to include a system header file for your platform, */
/* please, do it beyond the point further indicated in this file. */
/* ================================================================ */
/*
* Disable other protocols when http is the only one desired.
*/
#ifdef HTTP_ONLY
# ifndef CURL_DISABLE_DICT
# define CURL_DISABLE_DICT
# endif
# ifndef CURL_DISABLE_FILE
# define CURL_DISABLE_FILE
# endif
# ifndef CURL_DISABLE_FTP
# define CURL_DISABLE_FTP
# endif
# ifndef CURL_DISABLE_GOPHER
# define CURL_DISABLE_GOPHER
# endif
# ifndef CURL_DISABLE_IMAP
# define CURL_DISABLE_IMAP
# endif
# ifndef CURL_DISABLE_LDAP
# define CURL_DISABLE_LDAP
# endif
# ifndef CURL_DISABLE_LDAPS
# define CURL_DISABLE_LDAPS
# endif
# ifndef CURL_DISABLE_MQTT
# define CURL_DISABLE_MQTT
# endif
# ifndef CURL_DISABLE_POP3
# define CURL_DISABLE_POP3
# endif
# ifndef CURL_DISABLE_RTSP
# define CURL_DISABLE_RTSP
# endif
# ifndef CURL_DISABLE_SMB
# define CURL_DISABLE_SMB
# endif
# ifndef CURL_DISABLE_SMTP
# define CURL_DISABLE_SMTP
# endif
# ifndef CURL_DISABLE_TELNET
# define CURL_DISABLE_TELNET
# endif
# ifndef CURL_DISABLE_TFTP
# define CURL_DISABLE_TFTP
# endif
#endif
/*
* When http is disabled rtsp is not supported.
*/
#if defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_RTSP)
# define CURL_DISABLE_RTSP
#endif
/*
* When HTTP is disabled, disable HTTP-only features
*/
#if defined(CURL_DISABLE_HTTP)
# define CURL_DISABLE_ALTSVC 1
# define CURL_DISABLE_COOKIES 1
# define CURL_DISABLE_BASIC_AUTH 1
# define CURL_DISABLE_BEARER_AUTH 1
# define CURL_DISABLE_AWS 1
# define CURL_DISABLE_DOH 1
# define CURL_DISABLE_FORM_API 1
# define CURL_DISABLE_HEADERS_API 1
# define CURL_DISABLE_HSTS 1
# define CURL_DISABLE_HTTP_AUTH 1
#endif
/* ================================================================ */
/* No system header file shall be included in this file before this */
/* point. */
/* ================================================================ */
/*
* OS/400 setup file includes some system headers.
*/
#ifdef __OS400__
# include "setup-os400.h"
#endif
/*
* VMS setup file includes some system headers.
*/
#ifdef __VMS
# include "setup-vms.h"
#endif
/*
* Windows setup file includes some system headers.
*/
#ifdef _WIN32
# include "setup-win32.h"
#endif
#include <curl/system.h>
/* Helper macro to expand and concatenate two macros.
* Direct macros concatenation does not work because macros
* are not expanded before direct concatenation.
*/
#define CURL_CONC_MACROS_(A,B) A ## B
#define CURL_CONC_MACROS(A,B) CURL_CONC_MACROS_(A,B)
/* curl uses its own printf() function internally. It understands the GNU
* format. Use this format, so that is matches the GNU format attribute we
* use with the mingw compiler, allowing it to verify them at compile-time.
*/
#ifdef __MINGW32__
# undef CURL_FORMAT_CURL_OFF_T
# undef CURL_FORMAT_CURL_OFF_TU
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
#endif
/* based on logic in "curl/mprintf.h" */
#if (defined(__GNUC__) || defined(__clang__) || \
defined(__IAR_SYSTEMS_ICC__)) && \
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
!defined(CURL_NO_FMT_CHECKS)
#if defined(__MINGW32__) && !defined(__clang__)
#define CURL_PRINTF(fmt, arg) \
__attribute__((format(gnu_printf, fmt, arg)))
#else
#define CURL_PRINTF(fmt, arg) \
__attribute__((format(__printf__, fmt, arg)))
#endif
#else
#define CURL_PRINTF(fmt, arg)
#endif
/*
* Use getaddrinfo to resolve the IPv4 address literal. If the current network
* interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
* performing this task will result in a synthesized IPv6 address.
*/
#if defined(__APPLE__) && !defined(USE_ARES)
#include <TargetConditionals.h>
#define USE_RESOLVE_ON_IPS 1
# if TARGET_OS_MAC && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && \
defined(USE_IPV6)
# define CURL_MACOS_CALL_COPYPROXIES 1
# endif
#endif
#ifdef USE_LWIPSOCK
# include <lwip/init.h>
# include <lwip/sockets.h>
# include <lwip/netdb.h>
#endif
#ifdef HAVE_EXTRA_STRICMP_H
# include <extra/stricmp.h>
#endif
#ifdef HAVE_EXTRA_STRDUP_H
# include <extra/strdup.h>
#endif
#ifdef __AMIGA__
# ifdef __amigaos4__
# define __USE_INLINE__
/* use our own resolver which uses runtime feature detection */
# define CURLRES_AMIGA
/* getaddrinfo() currently crashes bsdsocket.library, so disable */
# undef HAVE_GETADDRINFO
# if !(defined(__NEWLIB__) || \
(defined(__CLIB2__) && defined(__THREAD_SAFE)))
/* disable threaded resolver with clib2 - requires newlib or clib-ts */
# undef USE_THREADS_POSIX
# endif
# endif
# include <exec/types.h>
# include <exec/execbase.h>
# include <proto/exec.h>
# include <proto/dos.h>
# include <unistd.h>
# if defined(HAVE_PROTO_BSDSOCKET_H) && \
(!defined(__amigaos4__) || defined(USE_AMISSL))
/* use bsdsocket.library directly, instead of libc networking functions */
# define _SYS_MBUF_H /* m_len define clashes with curl */
# include <proto/bsdsocket.h>
# ifdef __amigaos4__
int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *errorfds, struct timeval *timeout);
# define select(a,b,c,d,e) Curl_amiga_select(a,b,c,d,e)
# else
# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
# endif
/* must not use libc's fcntl() on bsdsocket.library sockfds! */
# undef HAVE_FCNTL
# undef HAVE_FCNTL_O_NONBLOCK
# else
/* use libc networking and hence close() and fnctl() */
# undef HAVE_CLOSESOCKET_CAMEL
# undef HAVE_IOCTLSOCKET_CAMEL
# endif
/*
* In clib2 arpa/inet.h warns that some prototypes may clash
* with bsdsocket.library. This avoids the definition of those.
*/
# define __NO_NET_API
#endif
#include <stdio.h>
#include <assert.h>
#ifdef __TANDEM /* for ns*-tandem-nsk systems */
# if ! defined __LP64
# include <floss.h> /* FLOSS is only used for 32-bit builds. */
# endif
#endif
#ifndef STDC_HEADERS /* no standard C headers! */
#include <curl/stdcheaders.h>
#endif
/*
* Large file (>2Gb) support using WIN32 functions.
*/
#ifdef USE_WIN32_LARGE_FILES
# include <io.h>
# include <sys/types.h>
# include <sys/stat.h>
# undef lseek
# define lseek(fdes,offset,whence) _lseeki64(fdes, offset, whence)
# undef fstat
# define fstat(fdes,stp) _fstati64(fdes, stp)
# undef stat
# define stat(fname,stp) curlx_win32_stat(fname, stp)
# define struct_stat struct _stati64
# define LSEEK_ERROR (__int64)-1
# define open curlx_win32_open
# define fopen(fname,mode) curlx_win32_fopen(fname, mode)
int curlx_win32_open(const char *filename, int oflag, ...);
int curlx_win32_stat(const char *path, struct_stat *buffer);
FILE *curlx_win32_fopen(const char *filename, const char *mode);
#endif
/*
* Small file (<2Gb) support using WIN32 functions.
*/
#ifdef USE_WIN32_SMALL_FILES
# include <io.h>
# include <sys/types.h>
# include <sys/stat.h>
# ifndef _WIN32_WCE
# undef lseek
# define lseek(fdes,offset,whence) _lseek(fdes, (long)offset, whence)
# define fstat(fdes,stp) _fstat(fdes, stp)
# define stat(fname,stp) curlx_win32_stat(fname, stp)
# define struct_stat struct _stat
# define open curlx_win32_open
# define fopen(fname,mode) curlx_win32_fopen(fname, mode)
int curlx_win32_stat(const char *path, struct_stat *buffer);
int curlx_win32_open(const char *filename, int oflag, ...);
FILE *curlx_win32_fopen(const char *filename, const char *mode);
# endif
# define LSEEK_ERROR (long)-1
#endif
#ifndef struct_stat
# define struct_stat struct stat
#endif
#ifndef LSEEK_ERROR
# define LSEEK_ERROR (off_t)-1
#endif
#ifndef SIZEOF_TIME_T
/* assume default size of time_t to be 32 bit */
#define SIZEOF_TIME_T 4
#endif
#ifndef SIZEOF_CURL_SOCKET_T
/* configure and cmake check and set the define */
# ifdef _WIN64
# define SIZEOF_CURL_SOCKET_T 8
# else
/* default guess */
# define SIZEOF_CURL_SOCKET_T 4
# endif
#endif
#if SIZEOF_CURL_SOCKET_T < 8
# define CURL_FORMAT_SOCKET_T "d"
#elif defined(__MINGW32__)
# define CURL_FORMAT_SOCKET_T "zd"
#else
# define CURL_FORMAT_SOCKET_T "qd"
#endif
/*
* Default sizeof(off_t) in case it hasn't been defined in config file.
*/
#ifndef SIZEOF_OFF_T
# if defined(__VMS) && !defined(__VAX)
# if defined(_LARGEFILE)
# define SIZEOF_OFF_T 8
# endif
# elif defined(__OS400__) && defined(__ILEC400__)
# if defined(_LARGE_FILES)
# define SIZEOF_OFF_T 8
# endif
# elif defined(__MVS__) && defined(__IBMC__)
# if defined(_LP64) || defined(_LARGE_FILES)
# define SIZEOF_OFF_T 8
# endif
# elif defined(__370__) && defined(__IBMC__)
# if defined(_LP64) || defined(_LARGE_FILES)
# define SIZEOF_OFF_T 8
# endif
# endif
# ifndef SIZEOF_OFF_T
# define SIZEOF_OFF_T 4
# endif
#endif
#if (SIZEOF_CURL_OFF_T < 8)
#error "too small curl_off_t"
#else
/* assume SIZEOF_CURL_OFF_T == 8 */
# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF)
#endif
#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1))
#if (SIZEOF_CURL_OFF_T != 8)
# error "curl_off_t must be exactly 64 bits"
#else
typedef unsigned CURL_TYPEOF_CURL_OFF_T curl_uint64_t;
typedef CURL_TYPEOF_CURL_OFF_T curl_int64_t;
# ifndef CURL_SUFFIX_CURL_OFF_TU
# error "CURL_SUFFIX_CURL_OFF_TU must be defined"
# endif
# define CURL_UINT64_SUFFIX CURL_SUFFIX_CURL_OFF_TU
# define CURL_UINT64_C(val) CURL_CONC_MACROS(val,CURL_UINT64_SUFFIX)
# define CURL_PRId64 CURL_FORMAT_CURL_OFF_T
# define CURL_PRIu64 CURL_FORMAT_CURL_OFF_TU
#endif
#if (SIZEOF_TIME_T == 4)
# ifdef HAVE_TIME_T_UNSIGNED
# define TIME_T_MAX UINT_MAX
# define TIME_T_MIN 0
# else
# define TIME_T_MAX INT_MAX
# define TIME_T_MIN INT_MIN
# endif
#else
# ifdef HAVE_TIME_T_UNSIGNED
# define TIME_T_MAX 0xFFFFFFFFFFFFFFFF
# define TIME_T_MIN 0
# else
# define TIME_T_MAX 0x7FFFFFFFFFFFFFFF
# define TIME_T_MIN (-TIME_T_MAX - 1)
# endif
#endif
#ifndef SIZE_T_MAX
/* some limits.h headers have this defined, some don't */
#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4)
#define SIZE_T_MAX 18446744073709551615U
#else
#define SIZE_T_MAX 4294967295U
#endif
#endif
#ifndef SSIZE_T_MAX
/* some limits.h headers have this defined, some don't */
#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4)
#define SSIZE_T_MAX 9223372036854775807
#else
#define SSIZE_T_MAX 2147483647
#endif
#endif
/*
* Arg 2 type for gethostname in case it hasn't been defined in config file.
*/
#ifndef GETHOSTNAME_TYPE_ARG2
# ifdef USE_WINSOCK
# define GETHOSTNAME_TYPE_ARG2 int
# else
# define GETHOSTNAME_TYPE_ARG2 size_t
# endif
#endif
/* Below we define some functions. They should
4. set the SIGALRM signal timeout
5. set dir/file naming defines
*/
#ifdef _WIN32
# define DIR_CHAR "\\"
#else /* _WIN32 */
# ifdef MSDOS /* Watt-32 */
# include <sys/ioctl.h>
# define select(n,r,w,x,t) select_s(n,r,w,x,t)
# define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z))
# include <tcp.h>
# ifdef word
# undef word
# endif
# ifdef byte
# undef byte
# endif
# endif /* MSDOS */
# ifdef __minix
/* Minix 3 versions up to at least 3.1.3 are missing these prototypes */
extern char *strtok_r(char *s, const char *delim, char **last);
extern struct tm *gmtime_r(const time_t * const timep, struct tm *tmp);
# endif
# define DIR_CHAR "/"
#endif /* _WIN32 */
/* ---------------------------------------------------------------- */
/* resolver specialty compile-time defines */
/* CURLRES_* defines to use in the host*.c sources */
/* ---------------------------------------------------------------- */
/*
* MSVC threads support requires a multi-threaded runtime library.
* _beginthreadex() is not available in single-threaded ones.
*/
#if defined(_MSC_VER) && !defined(_MT)
# undef USE_THREADS_POSIX
# undef USE_THREADS_WIN32
#endif
/*
* Mutually exclusive CURLRES_* definitions.
*/
#if defined(USE_IPV6) && defined(HAVE_GETADDRINFO)
# define CURLRES_IPV6
#elif defined(USE_IPV6) && (defined(_WIN32) || defined(__CYGWIN__))
/* assume on Windows that IPv6 without getaddrinfo is a broken build */
# error "Unexpected build: IPv6 is enabled but getaddrinfo was not found."
#else
# define CURLRES_IPV4
#endif
#ifdef USE_ARES
# define CURLRES_ASYNCH
# define CURLRES_ARES
/* now undef the stock libc functions just to avoid them being used */
# undef HAVE_GETADDRINFO
# undef HAVE_FREEADDRINFO
#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
# define CURLRES_ASYNCH
# define CURLRES_THREADED
#else
# define CURLRES_SYNCH
#endif
/* ---------------------------------------------------------------- */
#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && \
!defined(USE_WIN32_IDN) && !defined(USE_APPLE_IDN)
/* The lib and header are present */
#define USE_LIBIDN2
#endif
#if defined(USE_LIBIDN2) && (defined(USE_WIN32_IDN) || defined(USE_APPLE_IDN))
#error "libidn2 cannot be enabled with WinIDN or AppleIDN, choose one."
#endif
#define LIBIDN_REQUIRED_VERSION "0.4.1"
#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_BEARSSL) || defined(USE_RUSTLS)
#define USE_SSL /* SSL support has been enabled */
#endif
/* Single point where USE_SPNEGO definition might be defined */
#if !defined(CURL_DISABLE_NEGOTIATE_AUTH) && \
(defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
#define USE_SPNEGO
#endif
/* Single point where USE_KERBEROS5 definition might be defined */
#if !defined(CURL_DISABLE_KERBEROS_AUTH) && \
(defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
#define USE_KERBEROS5
#endif
/* Single point where USE_NTLM definition might be defined */
#if !defined(CURL_DISABLE_NTLM)
# if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
defined(USE_GNUTLS) || defined(USE_SECTRANSP) || \
defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
(defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT))
# define USE_CURL_NTLM_CORE
# endif
# if defined(USE_CURL_NTLM_CORE) || defined(USE_WINDOWS_SSPI)
# define USE_NTLM
# endif
#endif
#ifdef CURL_WANTS_CA_BUNDLE_ENV
#error "No longer supported. Set CURLOPT_CAINFO at runtime instead."
#endif
#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) || defined(USE_WOLFSSH)
#define USE_SSH
#endif
/*
* Provide a mechanism to silence picky compilers, such as gcc 4.6+.
* Parameters should of course normally not be unused, but for example when
* we have multiple implementations of the same interface it may happen.
*/
#if defined(__GNUC__) && ((__GNUC__ >= 3) || \
((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7)))
# define UNUSED_PARAM __attribute__((__unused__))
# define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#elif defined(__IAR_SYSTEMS_ICC__)
# define UNUSED_PARAM __attribute__((__unused__))
# if (__VER__ >= 9040001)
# define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
# else
# define WARN_UNUSED_RESULT
# endif
#else
# define UNUSED_PARAM /* NOTHING */
# define WARN_UNUSED_RESULT
#endif
/* noreturn attribute */
#if !defined(CURL_NORETURN)
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__) || \
defined(__IAR_SYSTEMS_ICC__)
# define CURL_NORETURN __attribute__((__noreturn__))
#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
# define CURL_NORETURN __declspec(noreturn)
#else
# define CURL_NORETURN
#endif
#endif
/* fallthrough attribute */
#if !defined(FALLTHROUGH)
#if (defined(__GNUC__) && __GNUC__ >= 7) || \
(defined(__clang__) && __clang_major__ >= 10)
# define FALLTHROUGH() __attribute__((fallthrough))
#else
# define FALLTHROUGH() do {} while (0)
#endif
#endif
/*
* Include macros and defines that should only be processed once.
*/
#ifndef HEADER_CURL_SETUP_ONCE_H
#include "curl_setup_once.h"
#endif
/*
* Definition of our NOP statement Object-like macro
*/
#ifndef Curl_nop_stmt
# define Curl_nop_stmt do { } while(0)
#endif
/*
* Ensure that Winsock and lwIP TCP/IP stacks are not mixed.
*/
#if defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)
# if defined(SOCKET) || defined(USE_WINSOCK)
# error "WinSock and lwIP TCP/IP stack definitions shall not coexist!"
# endif
#endif
/*
* shutdown() flags for systems that don't define them
*/
#ifndef SHUT_RD
#define SHUT_RD 0x00
#endif
#ifndef SHUT_WR
#define SHUT_WR 0x01
#endif
#ifndef SHUT_RDWR
#define SHUT_RDWR 0x02
#endif
/* Define S_ISREG if not defined by system headers, e.g. MSVC */
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
/* Define S_ISDIR if not defined by system headers, e.g. MSVC */
#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
/* In Windows the default file mode is text but an application can override it.
Therefore we specify it explicitly. https://github.com/curl/curl/pull/258
*/
#if defined(_WIN32) || defined(MSDOS)
#define FOPEN_READTEXT "rt"
#define FOPEN_WRITETEXT "wt"
#define FOPEN_APPENDTEXT "at"
#elif defined(__CYGWIN__)
/* Cygwin has specific behavior we need to address when WIN32 is not defined.
https://cygwin.com/cygwin-ug-net/using-textbinary.html
For write we want our output to have line endings of LF and be compatible with
other Cygwin utilities. For read we want to handle input that may have line
endings either CRLF or LF so 't' is appropriate.
*/
#define FOPEN_READTEXT "rt"
#define FOPEN_WRITETEXT "w"
#define FOPEN_APPENDTEXT "a"
#else
#define FOPEN_READTEXT "r"
#define FOPEN_WRITETEXT "w"
#define FOPEN_APPENDTEXT "a"
#endif
/* for systems that don't detect this in configure */
#ifndef CURL_SA_FAMILY_T
# if defined(HAVE_SA_FAMILY_T)
# define CURL_SA_FAMILY_T sa_family_t
# elif defined(HAVE_ADDRESS_FAMILY)
# define CURL_SA_FAMILY_T ADDRESS_FAMILY
# else
/* use a sensible default */
# define CURL_SA_FAMILY_T unsigned short
# endif
#endif
/* Some convenience macros to get the larger/smaller value out of two given.
We prefix with CURL to prevent name collisions. */
#define CURLMAX(x,y) ((x)>(y)?(x):(y))
#define CURLMIN(x,y) ((x)<(y)?(x):(y))
/* A convenience macro to provide both the string literal and the length of
the string literal in one go, useful for functions that take "string,len"
as their argument */
#define STRCONST(x) x,sizeof(x)-1
/* Some versions of the Android SDK is missing the declaration */
#if defined(HAVE_GETPWUID_R) && defined(HAVE_DECL_GETPWUID_R_MISSING)
struct passwd;
int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
size_t buflen, struct passwd **result);
#endif
#ifdef DEBUGBUILD
#define UNITTEST
#else
#define UNITTEST static
#endif
/* Hyper supports HTTP2 also, but Curl's integration with Hyper does not */
#if defined(USE_NGHTTP2)
#define USE_HTTP2
#endif
#if (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \
(defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)) || \
defined(USE_QUICHE) || defined(USE_MSH3)
#ifdef CURL_WITH_MULTI_SSL
#error "Multi-SSL combined with QUIC is not supported"
#endif
#define USE_HTTP3
#endif
/* Certain Windows implementations are not aligned with what curl expects,
so always use the local one on this platform. E.g. the mingw-w64
implementation can return wrong results for non-ASCII inputs. */
#if defined(HAVE_BASENAME) && defined(_WIN32)
#undef HAVE_BASENAME
#endif
#if defined(USE_UNIX_SOCKETS) && defined(_WIN32)
# if !defined(UNIX_PATH_MAX)
/* Replicating logic present in afunix.h
(distributed with newer Windows 10 SDK versions only) */
# define UNIX_PATH_MAX 108
/* !checksrc! disable TYPEDEFSTRUCT 1 */
typedef struct sockaddr_un {
ADDRESS_FAMILY sun_family;
char sun_path[UNIX_PATH_MAX];
} SOCKADDR_UN, *PSOCKADDR_UN;
# define WIN32_SOCKADDR_UN
# endif
#endif
/* OpenSSLv3 marks DES, MD5 and ENGINE functions deprecated but we have no
replacements (yet) so tell the compiler to not warn for them. */
#ifdef USE_OPENSSL
#define OPENSSL_SUPPRESS_DEPRECATED
#endif
#if defined(inline)
/* 'inline' is defined as macro and assumed to be correct */
/* No need for 'inline' replacement */
#elif defined(__cplusplus)
/* The code is compiled with C++ compiler.
C++ always supports 'inline'. */
/* No need for 'inline' replacement */
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901
/* C99 (and later) supports 'inline' keyword */
/* No need for 'inline' replacement */
#elif defined(__GNUC__) && __GNUC__ >= 3
/* GCC supports '__inline__' as an extension */
# define inline __inline__
#elif defined(_MSC_VER) && _MSC_VER >= 1400
/* MSC supports '__inline' from VS 2005 (or even earlier) */
# define inline __inline
#else
/* Probably 'inline' is not supported by compiler.
Define to the empty string to be on the safe side. */
# define inline /* empty */
#endif
#endif /* HEADER_CURL_SETUP_H */

403
third_party/curl/lib/curl_setup_once.h vendored Normal file
View File

@ -0,0 +1,403 @@
#ifndef HEADER_CURL_SETUP_ONCE_H
#define HEADER_CURL_SETUP_ONCE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/*
* Inclusion of common header files.
*/
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef NEED_MALLOC_H
#include <malloc.h>
#endif
#ifdef NEED_MEMORY_H
#include <memory.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#endif
#if defined(HAVE_STDBOOL_H) && defined(HAVE_BOOL_T)
#include <stdbool.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef USE_WOLFSSL
#include <stdint.h>
#endif
#ifdef USE_SCHANNEL
/* Must set this before <schannel.h> is included directly or indirectly by
another Windows header. */
#define SCHANNEL_USE_BLACKLISTS 1
#endif
#ifdef __hpux
#if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
#ifdef _APP32_64BIT_OFF_T
#define OLD_APP32_64BIT_OFF_T _APP32_64BIT_OFF_T
#undef _APP32_64BIT_OFF_T
#else
#undef OLD_APP32_64BIT_OFF_T
#endif
#endif
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include "functypes.h"
#ifdef __hpux
#if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
#ifdef OLD_APP32_64BIT_OFF_T
#define _APP32_64BIT_OFF_T OLD_APP32_64BIT_OFF_T
#undef OLD_APP32_64BIT_OFF_T
#endif
#endif
#endif
/*
* Definition of timeval struct for platforms that don't have it.
*/
#ifdef __GLIBC__
#if !defined(_POSIX_C_SOURCE) && !defined(_POSIX_SOURCE)
#ifndef HAVE_STRUCT_TIMEVAL
struct timeval {
long tv_sec;
long tv_usec;
};
#endif
#endif // _POSIX_C_SOURCE
#endif // __GLIBC__
/*
* If we have the MSG_NOSIGNAL define, make sure we use
* it as the fourth argument of function send()
*/
#ifdef HAVE_MSG_NOSIGNAL
#define SEND_4TH_ARG MSG_NOSIGNAL
#else
#define SEND_4TH_ARG 0
#endif
#if defined(__minix)
/* Minix doesn't support recv on TCP sockets */
#define sread(x, y, z) \
(ssize_t) read((RECV_TYPE_ARG1)(x), (RECV_TYPE_ARG2)(y), (RECV_TYPE_ARG3)(z))
#elif defined(HAVE_RECV)
/*
* The definitions for the return type and arguments types
* of functions recv() and send() belong and come from the
* configuration file. Do not define them in any other place.
*
* HAVE_RECV is defined if you have a function named recv()
* which is used to read incoming data from sockets. If your
* function has another name then don't define HAVE_RECV.
*
* If HAVE_RECV is defined then RECV_TYPE_ARG1, RECV_TYPE_ARG2,
* RECV_TYPE_ARG3, RECV_TYPE_ARG4 and RECV_TYPE_RETV must also
* be defined.
*
* HAVE_SEND is defined if you have a function named send()
* which is used to write outgoing data on a connected socket.
* If yours has another name then don't define HAVE_SEND.
*
* If HAVE_SEND is defined then SEND_TYPE_ARG1, SEND_QUAL_ARG2,
* SEND_TYPE_ARG2, SEND_TYPE_ARG3, SEND_TYPE_ARG4 and
* SEND_TYPE_RETV must also be defined.
*/
#define sread(x, y, z) \
(ssize_t) recv((RECV_TYPE_ARG1)(x), (RECV_TYPE_ARG2)(y), \
(RECV_TYPE_ARG3)(z), (RECV_TYPE_ARG4)(0))
#else /* HAVE_RECV */
#ifndef sread
#error "Missing definition of macro sread!"
#endif
#endif /* HAVE_RECV */
#if defined(__minix)
/* Minix doesn't support send on TCP sockets */
#define swrite(x, y, z) \
(ssize_t) write((SEND_TYPE_ARG1)(x), (SEND_TYPE_ARG2)(y), (SEND_TYPE_ARG3)(z))
#elif defined(HAVE_SEND)
#define swrite(x, y, z) \
(ssize_t) send((SEND_TYPE_ARG1)(x), (SEND_QUAL_ARG2 SEND_TYPE_ARG2)(y), \
(SEND_TYPE_ARG3)(z), (SEND_TYPE_ARG4)(SEND_4TH_ARG))
#else /* HAVE_SEND */
#ifndef swrite
#error "Missing definition of macro swrite!"
#endif
#endif /* HAVE_SEND */
/*
* Function-like macro definition used to close a socket.
*/
#if defined(HAVE_CLOSESOCKET)
#define sclose(x) closesocket((x))
#elif defined(HAVE_CLOSESOCKET_CAMEL)
#define sclose(x) CloseSocket((x))
#elif defined(HAVE_CLOSE_S)
#define sclose(x) close_s((x))
#elif defined(USE_LWIPSOCK)
#define sclose(x) lwip_close((x))
#else
#define sclose(x) close((x))
#endif
/*
* Stack-independent version of fcntl() on sockets:
*/
#if defined(USE_LWIPSOCK)
#define sfcntl lwip_fcntl
#else
#define sfcntl fcntl
#endif
/*
* 'bool' stuff compatible with HP-UX headers.
*/
#if defined(__hpux) && !defined(HAVE_BOOL_T)
typedef int bool;
#define false 0
#define true 1
#define HAVE_BOOL_T
#endif
/*
* 'bool' exists on platforms with <stdbool.h>, i.e. C99 platforms.
* On non-C99 platforms there's no bool, so define an enum for that.
* On C99 platforms 'false' and 'true' also exist. Enum uses a
* global namespace though, so use bool_false and bool_true.
*/
#ifndef HAVE_BOOL_T
typedef enum { bool_false = 0, bool_true = 1 } bool;
/*
* Use a define to let 'true' and 'false' use those enums. There
* are currently no use of true and false in libcurl proper, but
* there are some in the examples. This will cater for any later
* code happening to use true and false.
*/
#define false bool_false
#define true bool_true
#define HAVE_BOOL_T
#endif
/* the type we use for storing a single boolean bit */
#ifdef _MSC_VER
typedef bool bit;
#define BIT(x) bool x
#else
typedef unsigned int bit;
#define BIT(x) bit x : 1
#endif
/*
* Redefine TRUE and FALSE too, to catch current use. With this
* change, 'bool found = 1' will give a warning on MIPSPro, but
* 'bool found = TRUE' will not. Change tested on IRIX/MIPSPro,
* AIX 5.1/Xlc, Tru64 5.1/cc, w/make test too.
*/
#ifndef TRUE
#define TRUE true
#endif
#ifndef FALSE
#define FALSE false
#endif
#include "curl_ctype.h"
/*
* Macro used to include code only in debug builds.
*/
#ifdef DEBUGBUILD
#define DEBUGF(x) x
#else
#define DEBUGF(x) \
do { \
} while (0)
#endif
/*
* Macro used to include assertion code only in debug builds.
*/
#undef DEBUGASSERT
#if defined(DEBUGBUILD)
#define DEBUGASSERT(x) assert(x)
#else
#define DEBUGASSERT(x) \
do { \
} while (0)
#endif
/*
* Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno
* (or equivalent) on this platform to hide platform details to code using it.
*/
#ifdef USE_WINSOCK
#define SOCKERRNO ((int)WSAGetLastError())
#define SET_SOCKERRNO(x) (WSASetLastError((int)(x)))
#else
#define SOCKERRNO (errno)
#define SET_SOCKERRNO(x) (errno = (x))
#endif
/*
* Portable error number symbolic names defined to Winsock error codes.
*/
#ifdef USE_WINSOCK
#undef EBADF /* override definition in errno.h */
#define EBADF WSAEBADF
#undef EINTR /* override definition in errno.h */
#define EINTR WSAEINTR
#undef EINVAL /* override definition in errno.h */
#define EINVAL WSAEINVAL
#undef EWOULDBLOCK /* override definition in errno.h */
#define EWOULDBLOCK WSAEWOULDBLOCK
#undef EINPROGRESS /* override definition in errno.h */
#define EINPROGRESS WSAEINPROGRESS
#undef EALREADY /* override definition in errno.h */
#define EALREADY WSAEALREADY
#undef ENOTSOCK /* override definition in errno.h */
#define ENOTSOCK WSAENOTSOCK
#undef EDESTADDRREQ /* override definition in errno.h */
#define EDESTADDRREQ WSAEDESTADDRREQ
#undef EMSGSIZE /* override definition in errno.h */
#define EMSGSIZE WSAEMSGSIZE
#undef EPROTOTYPE /* override definition in errno.h */
#define EPROTOTYPE WSAEPROTOTYPE
#undef ENOPROTOOPT /* override definition in errno.h */
#define ENOPROTOOPT WSAENOPROTOOPT
#undef EPROTONOSUPPORT /* override definition in errno.h */
#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
#undef EOPNOTSUPP /* override definition in errno.h */
#define EOPNOTSUPP WSAEOPNOTSUPP
#define EPFNOSUPPORT WSAEPFNOSUPPORT
#undef EAFNOSUPPORT /* override definition in errno.h */
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#undef EADDRINUSE /* override definition in errno.h */
#define EADDRINUSE WSAEADDRINUSE
#undef EADDRNOTAVAIL /* override definition in errno.h */
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
#undef ENETDOWN /* override definition in errno.h */
#define ENETDOWN WSAENETDOWN
#undef ENETUNREACH /* override definition in errno.h */
#define ENETUNREACH WSAENETUNREACH
#undef ENETRESET /* override definition in errno.h */
#define ENETRESET WSAENETRESET
#undef ECONNABORTED /* override definition in errno.h */
#define ECONNABORTED WSAECONNABORTED
#undef ECONNRESET /* override definition in errno.h */
#define ECONNRESET WSAECONNRESET
#undef ENOBUFS /* override definition in errno.h */
#define ENOBUFS WSAENOBUFS
#undef EISCONN /* override definition in errno.h */
#define EISCONN WSAEISCONN
#undef ENOTCONN /* override definition in errno.h */
#define ENOTCONN WSAENOTCONN
#define ESHUTDOWN WSAESHUTDOWN
#define ETOOMANYREFS WSAETOOMANYREFS
#undef ETIMEDOUT /* override definition in errno.h */
#define ETIMEDOUT WSAETIMEDOUT
#undef ECONNREFUSED /* override definition in errno.h */
#define ECONNREFUSED WSAECONNREFUSED
#undef ELOOP /* override definition in errno.h */
#define ELOOP WSAELOOP
#ifndef ENAMETOOLONG /* possible previous definition in errno.h */
#define ENAMETOOLONG WSAENAMETOOLONG
#endif
#define EHOSTDOWN WSAEHOSTDOWN
#undef EHOSTUNREACH /* override definition in errno.h */
#define EHOSTUNREACH WSAEHOSTUNREACH
#ifndef ENOTEMPTY /* possible previous definition in errno.h */
#define ENOTEMPTY WSAENOTEMPTY
#endif
#define EPROCLIM WSAEPROCLIM
#define EUSERS WSAEUSERS
#define EDQUOT WSAEDQUOT
#define ESTALE WSAESTALE
#define EREMOTE WSAEREMOTE
#endif
/*
* Macro argv_item_t hides platform details to code using it.
*/
#ifdef __VMS
#define argv_item_t __char_ptr32
#elif defined(_UNICODE)
#define argv_item_t wchar_t *
#else
#define argv_item_t char *
#endif
/*
* We use this ZERO_NULL to avoid picky compiler warnings,
* when assigning a NULL pointer to a function pointer var.
*/
#define ZERO_NULL 0
#endif /* HEADER_CURL_SETUP_ONCE_H */

50
third_party/curl/lib/curl_sha256.h vendored Normal file
View File

@ -0,0 +1,50 @@
#ifndef HEADER_CURL_SHA256_H
#define HEADER_CURL_SHA256_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Florin Petriuc, <petriuc.florin@gmail.com>
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#if !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
|| defined(USE_LIBSSH2)
#include <curl/curl.h>
#include "curl_hmac.h"
extern const struct HMAC_params Curl_HMAC_SHA256[1];
#ifdef USE_WOLFSSL
/* SHA256_DIGEST_LENGTH is an enum value in wolfSSL. Need to import it from
* sha.h */
#include <wolfssl/options.h>
#include <wolfssl/openssl/sha.h>
#else
#define SHA256_DIGEST_LENGTH 32
#endif
CURLcode Curl_sha256it(unsigned char *outbuffer, const unsigned char *input,
const size_t len);
#endif
#endif /* HEADER_CURL_SHA256_H */

850
third_party/curl/lib/curl_sha512_256.c vendored Normal file
View File

@ -0,0 +1,850 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Evgeny Grin (Karlson2k), <k2k@narod.ru>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_DIGEST_AUTH) && !defined(CURL_DISABLE_SHA512_256)
#include "curl_sha512_256.h"
#include "warnless.h"
/* The recommended order of the TLS backends:
* * OpenSSL
* * GnuTLS
* * wolfSSL
* * Schannel SSPI
* * SecureTransport (Darwin)
* * mbedTLS
* * BearSSL
* * rustls
* Skip the backend if it does not support the required algorithm */
#if defined(USE_OPENSSL)
# include <openssl/opensslv.h>
# if (!defined(LIBRESSL_VERSION_NUMBER) && \
defined(OPENSSL_VERSION_NUMBER) && \
(OPENSSL_VERSION_NUMBER >= 0x10101000L)) || \
(defined(LIBRESSL_VERSION_NUMBER) && \
(LIBRESSL_VERSION_NUMBER >= 0x3080000fL))
# include <openssl/opensslconf.h>
# if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA512)
# include <openssl/evp.h>
# define USE_OPENSSL_SHA512_256 1
# define HAS_SHA512_256_IMPLEMENTATION 1
# ifdef __NetBSD__
/* Some NetBSD versions has a bug in SHA-512/256.
* See https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=58039
* The problematic versions:
* - NetBSD before 9.4
* - NetBSD 9 all development versions (9.99.x)
* - NetBSD 10 development versions (10.99.x) before 10.99.11
* The bug was fixed in NetBSD 9.4 release, NetBSD 10.0 release,
* NetBSD 10.99.11 development.
* It is safe to apply the workaround even if the bug is not present, as
* the workaround just reduces performance slightly. */
# include <sys/param.h>
# if __NetBSD_Version__ < 904000000 || \
(__NetBSD_Version__ >= 999000000 && \
__NetBSD_Version__ < 1000000000) || \
(__NetBSD_Version__ >= 1099000000 && \
__NetBSD_Version__ < 1099001100)
# define NEED_NETBSD_SHA512_256_WORKAROUND 1
# include <string.h>
# endif
# endif
# endif
# endif
#endif /* USE_OPENSSL */
#if !defined(HAS_SHA512_256_IMPLEMENTATION) && defined(USE_GNUTLS)
# include <nettle/sha.h>
# if defined(SHA512_256_DIGEST_SIZE)
# define USE_GNUTLS_SHA512_256 1
# define HAS_SHA512_256_IMPLEMENTATION 1
# endif
#endif /* ! HAS_SHA512_256_IMPLEMENTATION && USE_GNUTLS */
#if defined(USE_OPENSSL_SHA512_256)
/* OpenSSL does not provide macros for SHA-512/256 sizes */
/**
* Size of the SHA-512/256 single processing block in bytes.
*/
#define SHA512_256_BLOCK_SIZE 128
/**
* Size of the SHA-512/256 resulting digest in bytes.
* This is the final digest size, not intermediate hash.
*/
#define SHA512_256_DIGEST_SIZE SHA512_256_DIGEST_LENGTH
/**
* Context type used for SHA-512/256 calculations
*/
typedef EVP_MD_CTX *Curl_sha512_256_ctx;
/**
* Initialise structure for SHA-512/256 calculation.
*
* @param context the calculation context
* @return CURLE_OK if succeed,
* error code otherwise
*/
static CURLcode
Curl_sha512_256_init(void *context)
{
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
*ctx = EVP_MD_CTX_create();
if(!*ctx)
return CURLE_OUT_OF_MEMORY;
if(EVP_DigestInit_ex(*ctx, EVP_sha512_256(), NULL)) {
/* Check whether the header and this file use the same numbers */
DEBUGASSERT(EVP_MD_CTX_size(*ctx) == SHA512_256_DIGEST_SIZE);
/* Check whether the block size is correct */
DEBUGASSERT(EVP_MD_CTX_block_size(*ctx) == SHA512_256_BLOCK_SIZE);
return CURLE_OK; /* Success */
}
/* Cleanup */
EVP_MD_CTX_destroy(*ctx);
return CURLE_FAILED_INIT;
}
/**
* Process portion of bytes.
*
* @param context the calculation context
* @param data bytes to add to hash
* @return CURLE_OK if succeed,
* error code otherwise
*/
static CURLcode
Curl_sha512_256_update(void *context,
const unsigned char *data,
size_t length)
{
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
if(!EVP_DigestUpdate(*ctx, data, length))
return CURLE_SSL_CIPHER;
return CURLE_OK;
}
/**
* Finalise SHA-512/256 calculation, return digest.
*
* @param context the calculation context
* @param[out] digest set to the hash, must be #SHA512_256_DIGEST_SIZE bytes
* @return CURLE_OK if succeed,
* error code otherwise
*/
static CURLcode
Curl_sha512_256_finish(unsigned char *digest,
void *context)
{
CURLcode ret;
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
#ifdef NEED_NETBSD_SHA512_256_WORKAROUND
/* Use a larger buffer to work around a bug in NetBSD:
https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=58039 */
unsigned char tmp_digest[SHA512_256_DIGEST_SIZE * 2];
ret = EVP_DigestFinal_ex(*ctx,
tmp_digest, NULL) ? CURLE_OK : CURLE_SSL_CIPHER;
if(ret == CURLE_OK)
memcpy(digest, tmp_digest, SHA512_256_DIGEST_SIZE);
explicit_memset(tmp_digest, 0, sizeof(tmp_digest));
#else /* ! NEED_NETBSD_SHA512_256_WORKAROUND */
ret = EVP_DigestFinal_ex(*ctx, digest, NULL) ? CURLE_OK : CURLE_SSL_CIPHER;
#endif /* ! NEED_NETBSD_SHA512_256_WORKAROUND */
EVP_MD_CTX_destroy(*ctx);
*ctx = NULL;
return ret;
}
#elif defined(USE_GNUTLS_SHA512_256)
/**
* Context type used for SHA-512/256 calculations
*/
typedef struct sha512_256_ctx Curl_sha512_256_ctx;
/**
* Initialise structure for SHA-512/256 calculation.
*
* @param context the calculation context
* @return always CURLE_OK
*/
static CURLcode
Curl_sha512_256_init(void *context)
{
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
/* Check whether the header and this file use the same numbers */
DEBUGASSERT(SHA512_256_DIGEST_LENGTH == SHA512_256_DIGEST_SIZE);
sha512_256_init(ctx);
return CURLE_OK;
}
/**
* Process portion of bytes.
*
* @param context the calculation context
* @param data bytes to add to hash
* @param length number of bytes in @a data
* @return always CURLE_OK
*/
static CURLcode
Curl_sha512_256_update(void *context,
const unsigned char *data,
size_t length)
{
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
DEBUGASSERT((data != NULL) || (length == 0));
sha512_256_update(ctx, length, (const uint8_t *)data);
return CURLE_OK;
}
/**
* Finalise SHA-512/256 calculation, return digest.
*
* @param context the calculation context
* @param[out] digest set to the hash, must be #SHA512_256_DIGEST_SIZE bytes
* @return always CURLE_OK
*/
static CURLcode
Curl_sha512_256_finish(unsigned char *digest,
void *context)
{
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
sha512_256_digest(ctx, (size_t)SHA512_256_DIGEST_SIZE, (uint8_t *)digest);
return CURLE_OK;
}
#else /* No system or TLS backend SHA-512/256 implementation available */
/* Use local implementation */
#define HAS_SHA512_256_IMPLEMENTATION 1
/* ** This implementation of SHA-512/256 hash calculation was originally ** *
* ** written by Evgeny Grin (Karlson2k) for GNU libmicrohttpd. ** *
* ** The author ported the code to libcurl. The ported code is provided ** *
* ** under curl license. ** *
* ** This is a minimal version with minimal optimisations. Performance ** *
* ** can be significantly improved. Big-endian store and load macros ** *
* ** are obvious targets for optimisation. ** */
#ifdef __GNUC__
# if defined(__has_attribute) && defined(__STDC_VERSION__)
# if __has_attribute(always_inline) && __STDC_VERSION__ >= 199901
# define MHDX_INLINE inline __attribute__((always_inline))
# endif
# endif
#endif
#if !defined(MHDX_INLINE) && \
defined(_MSC_VER) && !defined(__GNUC__) && !defined(__clang__)
# if _MSC_VER >= 1400
# define MHDX_INLINE __forceinline
# endif
#endif
#if !defined(MHDX_INLINE)
/* Assume that 'inline' keyword works or the
* macro was already defined correctly. */
# define MHDX_INLINE inline
#endif
/* Bits manipulation macros and functions.
Can be moved to other headers to reuse. */
#define MHDX_GET_64BIT_BE(ptr) \
( ((curl_uint64_t)(((const unsigned char*)(ptr))[0]) << 56) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[1]) << 48) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[2]) << 40) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[3]) << 32) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[4]) << 24) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[5]) << 16) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[6]) << 8) | \
(curl_uint64_t)(((const unsigned char*)(ptr))[7]) )
#define MHDX_PUT_64BIT_BE(ptr,val) do { \
((unsigned char*)(ptr))[7]=(unsigned char)((curl_uint64_t)(val)); \
((unsigned char*)(ptr))[6]=(unsigned char)(((curl_uint64_t)(val)) >> 8); \
((unsigned char*)(ptr))[5]=(unsigned char)(((curl_uint64_t)(val)) >> 16); \
((unsigned char*)(ptr))[4]=(unsigned char)(((curl_uint64_t)(val)) >> 24); \
((unsigned char*)(ptr))[3]=(unsigned char)(((curl_uint64_t)(val)) >> 32); \
((unsigned char*)(ptr))[2]=(unsigned char)(((curl_uint64_t)(val)) >> 40); \
((unsigned char*)(ptr))[1]=(unsigned char)(((curl_uint64_t)(val)) >> 48); \
((unsigned char*)(ptr))[0]=(unsigned char)(((curl_uint64_t)(val)) >> 56); \
} while(0)
/* Defined as a function. The macro version may duplicate the binary code
* size as each argument is used twice, so if any calculation is used
* as an argument, the calculation could be done twice. */
static MHDX_INLINE curl_uint64_t
MHDx_rotr64(curl_uint64_t value, unsigned int bits)
{
bits %= 64;
if(0 == bits)
return value;
/* Defined in a form which modern compiler could optimise. */
return (value >> bits) | (value << (64 - bits));
}
/* SHA-512/256 specific data */
/**
* Number of bits in a single SHA-512/256 word.
*/
#define SHA512_256_WORD_SIZE_BITS 64
/**
* Number of bytes in a single SHA-512/256 word.
*/
#define SHA512_256_BYTES_IN_WORD (SHA512_256_WORD_SIZE_BITS / 8)
/**
* Hash is kept internally as 8 64-bit words.
* This is the intermediate hash size, used during computing the final digest.
*/
#define SHA512_256_HASH_SIZE_WORDS 8
/**
* Size of the SHA-512/256 resulting digest in words.
* This is the final digest size, not intermediate hash.
*/
#define SHA512_256_DIGEST_SIZE_WORDS (SHA512_256_HASH_SIZE_WORDS / 2)
/**
* Size of the SHA-512/256 resulting digest in bytes
* This is the final digest size, not intermediate hash.
*/
#define SHA512_256_DIGEST_SIZE \
(SHA512_256_DIGEST_SIZE_WORDS * SHA512_256_BYTES_IN_WORD)
/**
* Size of the SHA-512/256 single processing block in bits.
*/
#define SHA512_256_BLOCK_SIZE_BITS 1024
/**
* Size of the SHA-512/256 single processing block in bytes.
*/
#define SHA512_256_BLOCK_SIZE (SHA512_256_BLOCK_SIZE_BITS / 8)
/**
* Size of the SHA-512/256 single processing block in words.
*/
#define SHA512_256_BLOCK_SIZE_WORDS \
(SHA512_256_BLOCK_SIZE_BITS / SHA512_256_WORD_SIZE_BITS)
/**
* SHA-512/256 calculation context
*/
struct mhdx_sha512_256ctx
{
/**
* Intermediate hash value. The variable is properly aligned. Smart
* compilers may automatically use fast load/store instruction for big
* endian data on little endian machine.
*/
curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS];
/**
* SHA-512/256 input data buffer. The buffer is properly aligned. Smart
* compilers may automatically use fast load/store instruction for big
* endian data on little endian machine.
*/
curl_uint64_t buffer[SHA512_256_BLOCK_SIZE_WORDS];
/**
* The number of bytes, lower part
*/
curl_uint64_t count;
/**
* The number of bits, high part. Unlike lower part, this counts the number
* of bits, not bytes.
*/
curl_uint64_t count_bits_hi;
};
/**
* Context type used for SHA-512/256 calculations
*/
typedef struct mhdx_sha512_256ctx Curl_sha512_256_ctx;
/**
* Initialise structure for SHA-512/256 calculation.
*
* @param context the calculation context
* @return always CURLE_OK
*/
static CURLcode
MHDx_sha512_256_init(void *context)
{
struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *) context;
/* Check whether the header and this file use the same numbers */
DEBUGASSERT(SHA512_256_DIGEST_LENGTH == SHA512_256_DIGEST_SIZE);
DEBUGASSERT(sizeof(curl_uint64_t) == 8);
/* Initial hash values, see FIPS PUB 180-4 section 5.3.6.2 */
/* Values generated by "IV Generation Function" as described in
* section 5.3.6 */
ctx->H[0] = CURL_UINT64_C(0x22312194FC2BF72C);
ctx->H[1] = CURL_UINT64_C(0x9F555FA3C84C64C2);
ctx->H[2] = CURL_UINT64_C(0x2393B86B6F53B151);
ctx->H[3] = CURL_UINT64_C(0x963877195940EABD);
ctx->H[4] = CURL_UINT64_C(0x96283EE2A88EFFE3);
ctx->H[5] = CURL_UINT64_C(0xBE5E1E2553863992);
ctx->H[6] = CURL_UINT64_C(0x2B0199FC2C85B8AA);
ctx->H[7] = CURL_UINT64_C(0x0EB72DDC81C52CA2);
/* Initialise number of bytes and high part of number of bits. */
ctx->count = CURL_UINT64_C(0);
ctx->count_bits_hi = CURL_UINT64_C(0);
return CURLE_OK;
}
/**
* Base of the SHA-512/256 transformation.
* Gets a full 128 bytes block of data and updates hash values;
* @param H hash values
* @param data the data buffer with #SHA512_256_BLOCK_SIZE bytes block
*/
static void
MHDx_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS],
const void *data)
{
/* Working variables,
see FIPS PUB 180-4 section 6.7, 6.4. */
curl_uint64_t a = H[0];
curl_uint64_t b = H[1];
curl_uint64_t c = H[2];
curl_uint64_t d = H[3];
curl_uint64_t e = H[4];
curl_uint64_t f = H[5];
curl_uint64_t g = H[6];
curl_uint64_t h = H[7];
/* Data buffer, used as a cyclic buffer.
See FIPS PUB 180-4 section 5.2.2, 6.7, 6.4. */
curl_uint64_t W[16];
/* 'Ch' and 'Maj' macro functions are defined with widely-used optimisation.
See FIPS PUB 180-4 formulae 4.8, 4.9. */
#define Ch(x,y,z) ( (z) ^ ((x) & ((y) ^ (z))) )
#define Maj(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )
/* Four 'Sigma' macro functions.
See FIPS PUB 180-4 formulae 4.10, 4.11, 4.12, 4.13. */
#define SIG0(x) \
( MHDx_rotr64((x), 28) ^ MHDx_rotr64((x), 34) ^ MHDx_rotr64((x), 39) )
#define SIG1(x) \
( MHDx_rotr64((x), 14) ^ MHDx_rotr64((x), 18) ^ MHDx_rotr64((x), 41) )
#define sig0(x) \
( MHDx_rotr64((x), 1) ^ MHDx_rotr64((x), 8) ^ ((x) >> 7) )
#define sig1(x) \
( MHDx_rotr64((x), 19) ^ MHDx_rotr64((x), 61) ^ ((x) >> 6) )
if(1) {
unsigned int t;
/* K constants array.
See FIPS PUB 180-4 section 4.2.3 for K values. */
static const curl_uint64_t K[80] = {
CURL_UINT64_C(0x428a2f98d728ae22), CURL_UINT64_C(0x7137449123ef65cd),
CURL_UINT64_C(0xb5c0fbcfec4d3b2f), CURL_UINT64_C(0xe9b5dba58189dbbc),
CURL_UINT64_C(0x3956c25bf348b538), CURL_UINT64_C(0x59f111f1b605d019),
CURL_UINT64_C(0x923f82a4af194f9b), CURL_UINT64_C(0xab1c5ed5da6d8118),
CURL_UINT64_C(0xd807aa98a3030242), CURL_UINT64_C(0x12835b0145706fbe),
CURL_UINT64_C(0x243185be4ee4b28c), CURL_UINT64_C(0x550c7dc3d5ffb4e2),
CURL_UINT64_C(0x72be5d74f27b896f), CURL_UINT64_C(0x80deb1fe3b1696b1),
CURL_UINT64_C(0x9bdc06a725c71235), CURL_UINT64_C(0xc19bf174cf692694),
CURL_UINT64_C(0xe49b69c19ef14ad2), CURL_UINT64_C(0xefbe4786384f25e3),
CURL_UINT64_C(0x0fc19dc68b8cd5b5), CURL_UINT64_C(0x240ca1cc77ac9c65),
CURL_UINT64_C(0x2de92c6f592b0275), CURL_UINT64_C(0x4a7484aa6ea6e483),
CURL_UINT64_C(0x5cb0a9dcbd41fbd4), CURL_UINT64_C(0x76f988da831153b5),
CURL_UINT64_C(0x983e5152ee66dfab), CURL_UINT64_C(0xa831c66d2db43210),
CURL_UINT64_C(0xb00327c898fb213f), CURL_UINT64_C(0xbf597fc7beef0ee4),
CURL_UINT64_C(0xc6e00bf33da88fc2), CURL_UINT64_C(0xd5a79147930aa725),
CURL_UINT64_C(0x06ca6351e003826f), CURL_UINT64_C(0x142929670a0e6e70),
CURL_UINT64_C(0x27b70a8546d22ffc), CURL_UINT64_C(0x2e1b21385c26c926),
CURL_UINT64_C(0x4d2c6dfc5ac42aed), CURL_UINT64_C(0x53380d139d95b3df),
CURL_UINT64_C(0x650a73548baf63de), CURL_UINT64_C(0x766a0abb3c77b2a8),
CURL_UINT64_C(0x81c2c92e47edaee6), CURL_UINT64_C(0x92722c851482353b),
CURL_UINT64_C(0xa2bfe8a14cf10364), CURL_UINT64_C(0xa81a664bbc423001),
CURL_UINT64_C(0xc24b8b70d0f89791), CURL_UINT64_C(0xc76c51a30654be30),
CURL_UINT64_C(0xd192e819d6ef5218), CURL_UINT64_C(0xd69906245565a910),
CURL_UINT64_C(0xf40e35855771202a), CURL_UINT64_C(0x106aa07032bbd1b8),
CURL_UINT64_C(0x19a4c116b8d2d0c8), CURL_UINT64_C(0x1e376c085141ab53),
CURL_UINT64_C(0x2748774cdf8eeb99), CURL_UINT64_C(0x34b0bcb5e19b48a8),
CURL_UINT64_C(0x391c0cb3c5c95a63), CURL_UINT64_C(0x4ed8aa4ae3418acb),
CURL_UINT64_C(0x5b9cca4f7763e373), CURL_UINT64_C(0x682e6ff3d6b2b8a3),
CURL_UINT64_C(0x748f82ee5defb2fc), CURL_UINT64_C(0x78a5636f43172f60),
CURL_UINT64_C(0x84c87814a1f0ab72), CURL_UINT64_C(0x8cc702081a6439ec),
CURL_UINT64_C(0x90befffa23631e28), CURL_UINT64_C(0xa4506cebde82bde9),
CURL_UINT64_C(0xbef9a3f7b2c67915), CURL_UINT64_C(0xc67178f2e372532b),
CURL_UINT64_C(0xca273eceea26619c), CURL_UINT64_C(0xd186b8c721c0c207),
CURL_UINT64_C(0xeada7dd6cde0eb1e), CURL_UINT64_C(0xf57d4f7fee6ed178),
CURL_UINT64_C(0x06f067aa72176fba), CURL_UINT64_C(0x0a637dc5a2c898a6),
CURL_UINT64_C(0x113f9804bef90dae), CURL_UINT64_C(0x1b710b35131c471b),
CURL_UINT64_C(0x28db77f523047d84), CURL_UINT64_C(0x32caab7b40c72493),
CURL_UINT64_C(0x3c9ebe0a15c9bebc), CURL_UINT64_C(0x431d67c49c100d4c),
CURL_UINT64_C(0x4cc5d4becb3e42b6), CURL_UINT64_C(0x597f299cfc657e2a),
CURL_UINT64_C(0x5fcb6fab3ad6faec), CURL_UINT64_C(0x6c44198c4a475817)
};
/* One step of SHA-512/256 computation,
see FIPS PUB 180-4 section 6.4.2 step 3.
* Note: this macro updates working variables in-place, without rotation.
* Note: the first (vH += SIG1(vE) + Ch(vE,vF,vG) + kt + wt) equals T1 in
FIPS PUB 180-4 section 6.4.2 step 3.
the second (vH += SIG0(vA) + Maj(vE,vF,vC) equals T1 + T2 in
FIPS PUB 180-4 section 6.4.2 step 3.
* Note: 'wt' must be used exactly one time in this macro as macro for
'wt' calculation may change other data as well every time when
used. */
#define SHA2STEP64(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \
(vD) += ((vH) += SIG1 ((vE)) + Ch ((vE),(vF),(vG)) + (kt) + (wt)); \
(vH) += SIG0 ((vA)) + Maj ((vA),(vB),(vC)); } while (0)
/* One step of SHA-512/256 computation with working variables rotation,
see FIPS PUB 180-4 section 6.4.2 step 3. This macro version reassigns
all working variables on each step. */
#define SHA2STEP64RV(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \
curl_uint64_t tmp_h_ = (vH); \
SHA2STEP64((vA),(vB),(vC),(vD),(vE),(vF),(vG),tmp_h_,(kt),(wt)); \
(vH) = (vG); \
(vG) = (vF); \
(vF) = (vE); \
(vE) = (vD); \
(vD) = (vC); \
(vC) = (vB); \
(vB) = (vA); \
(vA) = tmp_h_; } while(0)
/* Get value of W(t) from input data buffer for 0 <= t <= 15,
See FIPS PUB 180-4 section 6.2.
Input data must be read in big-endian bytes order,
see FIPS PUB 180-4 section 3.1.2. */
#define SHA512_GET_W_FROM_DATA(buf,t) \
MHDX_GET_64BIT_BE( \
((const unsigned char*) (buf)) + (t) * SHA512_256_BYTES_IN_WORD)
/* During first 16 steps, before making any calculation on each step, the
W element is read from the input data buffer as a big-endian value and
stored in the array of W elements. */
for(t = 0; t < 16; ++t) {
SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], \
W[t] = SHA512_GET_W_FROM_DATA(data, t));
}
/* 'W' generation and assignment for 16 <= t <= 79.
See FIPS PUB 180-4 section 6.4.2.
As only the last 16 'W' are used in calculations, it is possible to
use 16 elements array of W as a cyclic buffer.
Note: ((t-16) & 15) have same value as (t & 15) */
#define Wgen(w,t) \
(curl_uint64_t)( (w)[(t - 16) & 15] + sig1((w)[((t) - 2) & 15]) \
+ (w)[((t) - 7) & 15] + sig0((w)[((t) - 15) & 15]) )
/* During the last 64 steps, before making any calculation on each step,
current W element is generated from other W elements of the cyclic
buffer and the generated value is stored back in the cyclic buffer. */
for(t = 16; t < 80; ++t) {
SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], \
W[t & 15] = Wgen(W, t));
}
}
/* Compute and store the intermediate hash.
See FIPS PUB 180-4 section 6.4.2 step 4. */
H[0] += a;
H[1] += b;
H[2] += c;
H[3] += d;
H[4] += e;
H[5] += f;
H[6] += g;
H[7] += h;
}
/**
* Process portion of bytes.
*
* @param context the calculation context
* @param data bytes to add to hash
* @param length number of bytes in @a data
* @return always CURLE_OK
*/
static CURLcode
MHDx_sha512_256_update(void *context,
const unsigned char *data,
size_t length)
{
unsigned int bytes_have; /**< Number of bytes in the context buffer */
struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *)context;
/* the void pointer here is required to mute Intel compiler warning */
void *const ctx_buf = ctx->buffer;
DEBUGASSERT((data != NULL) || (length == 0));
if(0 == length)
return CURLE_OK; /* Shortcut, do nothing */
/* Note: (count & (SHA512_256_BLOCK_SIZE-1))
equals (count % SHA512_256_BLOCK_SIZE) for this block size. */
bytes_have = (unsigned int) (ctx->count & (SHA512_256_BLOCK_SIZE - 1));
ctx->count += length;
if(length > ctx->count)
ctx->count_bits_hi += 1U << 3; /* Value wrap */
ctx->count_bits_hi += ctx->count >> 61;
ctx->count &= CURL_UINT64_C(0x1FFFFFFFFFFFFFFF);
if(0 != bytes_have) {
unsigned int bytes_left = SHA512_256_BLOCK_SIZE - bytes_have;
if(length >= bytes_left) {
/* Combine new data with data in the buffer and process the full
block. */
memcpy(((unsigned char *) ctx_buf) + bytes_have,
data,
bytes_left);
data += bytes_left;
length -= bytes_left;
MHDx_sha512_256_transform(ctx->H, ctx->buffer);
bytes_have = 0;
}
}
while(SHA512_256_BLOCK_SIZE <= length) {
/* Process any full blocks of new data directly,
without copying to the buffer. */
MHDx_sha512_256_transform(ctx->H, data);
data += SHA512_256_BLOCK_SIZE;
length -= SHA512_256_BLOCK_SIZE;
}
if(0 != length) {
/* Copy incomplete block of new data (if any)
to the buffer. */
memcpy(((unsigned char *) ctx_buf) + bytes_have, data, length);
}
return CURLE_OK;
}
/**
* Size of "length" insertion in bits.
* See FIPS PUB 180-4 section 5.1.2.
*/
#define SHA512_256_SIZE_OF_LEN_ADD_BITS 128
/**
* Size of "length" insertion in bytes.
*/
#define SHA512_256_SIZE_OF_LEN_ADD (SHA512_256_SIZE_OF_LEN_ADD_BITS / 8)
/**
* Finalise SHA-512/256 calculation, return digest.
*
* @param context the calculation context
* @param[out] digest set to the hash, must be #SHA512_256_DIGEST_SIZE bytes
* @return always CURLE_OK
*/
static CURLcode
MHDx_sha512_256_finish(unsigned char *digest,
void *context)
{
struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *)context;
curl_uint64_t num_bits; /**< Number of processed bits */
unsigned int bytes_have; /**< Number of bytes in the context buffer */
/* the void pointer here is required to mute Intel compiler warning */
void *const ctx_buf = ctx->buffer;
/* Memorise the number of processed bits.
The padding and other data added here during the postprocessing must
not change the amount of hashed data. */
num_bits = ctx->count << 3;
/* Note: (count & (SHA512_256_BLOCK_SIZE-1))
equals (count % SHA512_256_BLOCK_SIZE) for this block size. */
bytes_have = (unsigned int) (ctx->count & (SHA512_256_BLOCK_SIZE - 1));
/* Input data must be padded with a single bit "1", then with zeros and
the finally the length of data in bits must be added as the final bytes
of the last block.
See FIPS PUB 180-4 section 5.1.2. */
/* Data is always processed in form of bytes (not by individual bits),
therefore position of the first padding bit in byte is always
predefined (0x80). */
/* Buffer always have space at least for one byte (as full buffers are
processed when formed). */
((unsigned char *) ctx_buf)[bytes_have++] = 0x80U;
if(SHA512_256_BLOCK_SIZE - bytes_have < SHA512_256_SIZE_OF_LEN_ADD) {
/* No space in the current block to put the total length of message.
Pad the current block with zeros and process it. */
if(bytes_have < SHA512_256_BLOCK_SIZE)
memset(((unsigned char *) ctx_buf) + bytes_have, 0,
SHA512_256_BLOCK_SIZE - bytes_have);
/* Process the full block. */
MHDx_sha512_256_transform(ctx->H, ctx->buffer);
/* Start the new block. */
bytes_have = 0;
}
/* Pad the rest of the buffer with zeros. */
memset(((unsigned char *) ctx_buf) + bytes_have, 0,
SHA512_256_BLOCK_SIZE - SHA512_256_SIZE_OF_LEN_ADD - bytes_have);
/* Put high part of number of bits in processed message and then lower
part of number of bits as big-endian values.
See FIPS PUB 180-4 section 5.1.2. */
/* Note: the target location is predefined and buffer is always aligned */
MHDX_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
+ SHA512_256_BLOCK_SIZE \
- SHA512_256_SIZE_OF_LEN_ADD, \
ctx->count_bits_hi);
MHDX_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
+ SHA512_256_BLOCK_SIZE \
- SHA512_256_SIZE_OF_LEN_ADD \
+ SHA512_256_BYTES_IN_WORD, \
num_bits);
/* Process the full final block. */
MHDx_sha512_256_transform(ctx->H, ctx->buffer);
/* Put in BE mode the leftmost part of the hash as the final digest.
See FIPS PUB 180-4 section 6.7. */
MHDX_PUT_64BIT_BE((digest + 0 * SHA512_256_BYTES_IN_WORD), ctx->H[0]);
MHDX_PUT_64BIT_BE((digest + 1 * SHA512_256_BYTES_IN_WORD), ctx->H[1]);
MHDX_PUT_64BIT_BE((digest + 2 * SHA512_256_BYTES_IN_WORD), ctx->H[2]);
MHDX_PUT_64BIT_BE((digest + 3 * SHA512_256_BYTES_IN_WORD), ctx->H[3]);
/* Erase potentially sensitive data. */
memset(ctx, 0, sizeof(struct mhdx_sha512_256ctx));
return CURLE_OK;
}
/* Map to the local implementation */
#define Curl_sha512_256_init MHDx_sha512_256_init
#define Curl_sha512_256_update MHDx_sha512_256_update
#define Curl_sha512_256_finish MHDx_sha512_256_finish
#endif /* Local SHA-512/256 code */
/**
* Compute SHA-512/256 hash for the given data in one function call
* @param[out] output the pointer to put the hash
* @param[in] input the pointer to the data to process
* @param input_size the size of the data pointed by @a input
* @return always #CURLE_OK
*/
CURLcode
Curl_sha512_256it(unsigned char *output, const unsigned char *input,
size_t input_size)
{
Curl_sha512_256_ctx ctx;
CURLcode res;
res = Curl_sha512_256_init(&ctx);
if(res != CURLE_OK)
return res;
res = Curl_sha512_256_update(&ctx, (const void *) input, input_size);
if(res != CURLE_OK) {
(void) Curl_sha512_256_finish(output, &ctx);
return res;
}
return Curl_sha512_256_finish(output, &ctx);
}
/* Wrapper function, takes 'unsigned int' as length type, returns void */
static void
Curl_sha512_256_update_i(void *context,
const unsigned char *data,
unsigned int length)
{
/* Hypothetically the function may fail, but assume it does not */
(void) Curl_sha512_256_update(context, data, length);
}
/* Wrapper function, returns void */
static void
Curl_sha512_256_finish_v(unsigned char *result,
void *context)
{
/* Hypothetically the function may fail, but assume it does not */
(void) Curl_sha512_256_finish(result, context);
}
/* Wrapper function, takes 'unsigned int' as length type, returns void */
const struct HMAC_params Curl_HMAC_SHA512_256[] = {
{
/* Initialize context procedure. */
Curl_sha512_256_init,
/* Update context with data. */
Curl_sha512_256_update_i,
/* Get final result procedure. */
Curl_sha512_256_finish_v,
/* Context structure size. */
sizeof(Curl_sha512_256_ctx),
/* Maximum key length (bytes). */
SHA512_256_BLOCK_SIZE,
/* Result length (bytes). */
SHA512_256_DIGEST_SIZE
}
};
#endif /* !CURL_DISABLE_DIGEST_AUTH && !CURL_DISABLE_SHA512_256 */

44
third_party/curl/lib/curl_sha512_256.h vendored Normal file
View File

@ -0,0 +1,44 @@
#ifndef HEADER_CURL_SHA512_256_H
#define HEADER_CURL_SHA512_256_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Evgeny Grin (Karlson2k), <k2k@narod.ru>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#if !defined(CURL_DISABLE_DIGEST_AUTH) && !defined(CURL_DISABLE_SHA512_256)
#include <curl/curl.h>
#include "curl_hmac.h"
#define CURL_HAVE_SHA512_256
extern const struct HMAC_params Curl_HMAC_SHA512_256[1];
#define SHA512_256_DIGEST_LENGTH 32
CURLcode
Curl_sha512_256it(unsigned char *output, const unsigned char *input,
size_t input_size);
#endif /* !CURL_DISABLE_DIGEST_AUTH && !CURL_DISABLE_SHA512_256 */
#endif /* HEADER_CURL_SHA256_H */

239
third_party/curl/lib/curl_sspi.c vendored Normal file
View File

@ -0,0 +1,239 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#ifdef USE_WINDOWS_SSPI
#include <curl/curl.h>
#include "curl_sspi.h"
#include "curl_multibyte.h"
#include "system_win32.h"
#include "version_win32.h"
#include "warnless.h"
/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"
/* We use our own typedef here since some headers might lack these */
typedef PSecurityFunctionTable (APIENTRY *INITSECURITYINTERFACE_FN)(VOID);
/* See definition of SECURITY_ENTRYPOINT in sspi.h */
#ifdef UNICODE
# ifdef _WIN32_WCE
# define SECURITYENTRYPOINT L"InitSecurityInterfaceW"
# else
# define SECURITYENTRYPOINT "InitSecurityInterfaceW"
# endif
#else
# define SECURITYENTRYPOINT "InitSecurityInterfaceA"
#endif
/* Handle of security.dll or secur32.dll, depending on Windows version */
HMODULE s_hSecDll = NULL;
/* Pointer to SSPI dispatch table */
PSecurityFunctionTable s_pSecFn = NULL;
/*
* Curl_sspi_global_init()
*
* This is used to load the Security Service Provider Interface (SSPI)
* dynamic link library portably across all Windows versions, without
* the need to directly link libcurl, nor the application using it, at
* build time.
*
* Once this function has been executed, Windows SSPI functions can be
* called through the Security Service Provider Interface dispatch table.
*
* Parameters:
*
* None.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_sspi_global_init(void)
{
INITSECURITYINTERFACE_FN pInitSecurityInterface;
/* If security interface is not yet initialized try to do this */
if(!s_hSecDll) {
/* Security Service Provider Interface (SSPI) functions are located in
* security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP
* have both these DLLs (security.dll forwards calls to secur32.dll) */
/* Load SSPI dll into the address space of the calling process */
if(curlx_verify_windows_version(4, 0, 0, PLATFORM_WINNT, VERSION_EQUAL))
s_hSecDll = Curl_load_library(TEXT("security.dll"));
else
s_hSecDll = Curl_load_library(TEXT("secur32.dll"));
if(!s_hSecDll)
return CURLE_FAILED_INIT;
/* Get address of the InitSecurityInterfaceA function from the SSPI dll */
pInitSecurityInterface =
CURLX_FUNCTION_CAST(INITSECURITYINTERFACE_FN,
(GetProcAddress(s_hSecDll, SECURITYENTRYPOINT)));
if(!pInitSecurityInterface)
return CURLE_FAILED_INIT;
/* Get pointer to Security Service Provider Interface dispatch table */
s_pSecFn = pInitSecurityInterface();
if(!s_pSecFn)
return CURLE_FAILED_INIT;
}
return CURLE_OK;
}
/*
* Curl_sspi_global_cleanup()
*
* This deinitializes the Security Service Provider Interface from libcurl.
*
* Parameters:
*
* None.
*/
void Curl_sspi_global_cleanup(void)
{
if(s_hSecDll) {
FreeLibrary(s_hSecDll);
s_hSecDll = NULL;
s_pSecFn = NULL;
}
}
/*
* Curl_create_sspi_identity()
*
* This is used to populate a SSPI identity structure based on the supplied
* username and password.
*
* Parameters:
*
* userp [in] - The user name in the format User or Domain\User.
* passwdp [in] - The user's password.
* identity [in/out] - The identity structure.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
SEC_WINNT_AUTH_IDENTITY *identity)
{
xcharp_u useranddomain;
xcharp_u user, dup_user;
xcharp_u domain, dup_domain;
xcharp_u passwd, dup_passwd;
size_t domlen = 0;
domain.const_tchar_ptr = TEXT("");
/* Initialize the identity */
memset(identity, 0, sizeof(*identity));
useranddomain.tchar_ptr = curlx_convert_UTF8_to_tchar((char *)userp);
if(!useranddomain.tchar_ptr)
return CURLE_OUT_OF_MEMORY;
user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('\\'));
if(!user.const_tchar_ptr)
user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('/'));
if(user.tchar_ptr) {
domain.tchar_ptr = useranddomain.tchar_ptr;
domlen = user.tchar_ptr - useranddomain.tchar_ptr;
user.tchar_ptr++;
}
else {
user.tchar_ptr = useranddomain.tchar_ptr;
domain.const_tchar_ptr = TEXT("");
domlen = 0;
}
/* Setup the identity's user and length */
dup_user.tchar_ptr = _tcsdup(user.tchar_ptr);
if(!dup_user.tchar_ptr) {
curlx_unicodefree(useranddomain.tchar_ptr);
return CURLE_OUT_OF_MEMORY;
}
identity->User = dup_user.tbyte_ptr;
identity->UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr));
dup_user.tchar_ptr = NULL;
/* Setup the identity's domain and length */
dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1));
if(!dup_domain.tchar_ptr) {
curlx_unicodefree(useranddomain.tchar_ptr);
return CURLE_OUT_OF_MEMORY;
}
_tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen);
*(dup_domain.tchar_ptr + domlen) = TEXT('\0');
identity->Domain = dup_domain.tbyte_ptr;
identity->DomainLength = curlx_uztoul(domlen);
dup_domain.tchar_ptr = NULL;
curlx_unicodefree(useranddomain.tchar_ptr);
/* Setup the identity's password and length */
passwd.tchar_ptr = curlx_convert_UTF8_to_tchar((char *)passwdp);
if(!passwd.tchar_ptr)
return CURLE_OUT_OF_MEMORY;
dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr);
if(!dup_passwd.tchar_ptr) {
curlx_unicodefree(passwd.tchar_ptr);
return CURLE_OUT_OF_MEMORY;
}
identity->Password = dup_passwd.tbyte_ptr;
identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr));
dup_passwd.tchar_ptr = NULL;
curlx_unicodefree(passwd.tchar_ptr);
/* Setup the identity's flags */
identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY;
return CURLE_OK;
}
/*
* Curl_sspi_free_identity()
*
* This is used to free the contents of a SSPI identifier structure.
*
* Parameters:
*
* identity [in/out] - The identity structure.
*/
void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity)
{
if(identity) {
Curl_safefree(identity->User);
Curl_safefree(identity->Password);
Curl_safefree(identity->Domain);
}
}
#endif /* USE_WINDOWS_SSPI */

123
third_party/curl/lib/curl_sspi.h vendored Normal file
View File

@ -0,0 +1,123 @@
#ifndef HEADER_CURL_SSPI_H
#define HEADER_CURL_SSPI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#ifdef USE_WINDOWS_SSPI
#include <curl/curl.h>
/*
* When including the following three headers, it is mandatory to define either
* SECURITY_WIN32 or SECURITY_KERNEL, indicating who is compiling the code.
*/
#undef SECURITY_WIN32
#undef SECURITY_KERNEL
#define SECURITY_WIN32 1
#include <security.h>
#include <sspi.h>
#include <rpc.h>
CURLcode Curl_sspi_global_init(void);
void Curl_sspi_global_cleanup(void);
/* This is used to populate the domain in a SSPI identity structure */
CURLcode Curl_override_sspi_http_realm(const char *chlg,
SEC_WINNT_AUTH_IDENTITY *identity);
/* This is used to generate an SSPI identity structure */
CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
SEC_WINNT_AUTH_IDENTITY *identity);
/* This is used to free an SSPI identity structure */
void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity);
/* Forward-declaration of global variables defined in curl_sspi.c */
extern HMODULE s_hSecDll;
extern PSecurityFunctionTable s_pSecFn;
/* Provide some definitions missing in old headers */
#define SP_NAME_DIGEST "WDigest"
#define SP_NAME_NTLM "NTLM"
#define SP_NAME_NEGOTIATE "Negotiate"
#define SP_NAME_KERBEROS "Kerberos"
#ifndef ISC_REQ_USE_HTTP_STYLE
#define ISC_REQ_USE_HTTP_STYLE 0x01000000
#endif
#ifndef SEC_E_INVALID_PARAMETER
# define SEC_E_INVALID_PARAMETER ((HRESULT)0x8009035DL)
#endif
#ifndef SEC_E_DELEGATION_POLICY
# define SEC_E_DELEGATION_POLICY ((HRESULT)0x8009035EL)
#endif
#ifndef SEC_E_POLICY_NLTM_ONLY
# define SEC_E_POLICY_NLTM_ONLY ((HRESULT)0x8009035FL)
#endif
#ifndef SEC_I_SIGNATURE_NEEDED
# define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL)
#endif
#ifndef CRYPT_E_REVOKED
# define CRYPT_E_REVOKED ((HRESULT)0x80092010L)
#endif
#ifndef CRYPT_E_NO_REVOCATION_DLL
# define CRYPT_E_NO_REVOCATION_DLL ((HRESULT)0x80092011L)
#endif
#ifndef CRYPT_E_NO_REVOCATION_CHECK
# define CRYPT_E_NO_REVOCATION_CHECK ((HRESULT)0x80092012L)
#endif
#ifndef CRYPT_E_REVOCATION_OFFLINE
# define CRYPT_E_REVOCATION_OFFLINE ((HRESULT)0x80092013L)
#endif
#ifndef CRYPT_E_NOT_IN_REVOCATION_DATABASE
# define CRYPT_E_NOT_IN_REVOCATION_DATABASE ((HRESULT)0x80092014L)
#endif
#ifdef UNICODE
# define SECFLAG_WINNT_AUTH_IDENTITY \
(unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE
#else
# define SECFLAG_WINNT_AUTH_IDENTITY \
(unsigned long)SEC_WINNT_AUTH_IDENTITY_ANSI
#endif
/*
* Definitions required from ntsecapi.h are directly provided below this point
* to avoid including ntsecapi.h due to a conflict with OpenSSL's safestack.h
*/
#define KERB_WRAP_NO_ENCRYPT 0x80000001
#endif /* USE_WINDOWS_SSPI */
#endif /* HEADER_CURL_SSPI_H */

154
third_party/curl/lib/curl_threads.c vendored Normal file
View File

@ -0,0 +1,154 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include <curl/curl.h>
#if defined(USE_THREADS_POSIX)
# ifdef HAVE_PTHREAD_H
# include <pthread.h>
# endif
#elif defined(USE_THREADS_WIN32)
# include <process.h>
#endif
#include "curl_threads.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#if defined(USE_THREADS_POSIX)
struct Curl_actual_call {
unsigned int (*func)(void *);
void *arg;
};
static void *curl_thread_create_thunk(void *arg)
{
struct Curl_actual_call *ac = arg;
unsigned int (*func)(void *) = ac->func;
void *real_arg = ac->arg;
free(ac);
(*func)(real_arg);
return 0;
}
curl_thread_t Curl_thread_create(unsigned int (*func) (void *), void *arg)
{
curl_thread_t t = malloc(sizeof(pthread_t));
struct Curl_actual_call *ac = malloc(sizeof(struct Curl_actual_call));
if(!(ac && t))
goto err;
ac->func = func;
ac->arg = arg;
if(pthread_create(t, NULL, curl_thread_create_thunk, ac) != 0)
goto err;
return t;
err:
free(t);
free(ac);
return curl_thread_t_null;
}
void Curl_thread_destroy(curl_thread_t hnd)
{
if(hnd != curl_thread_t_null) {
pthread_detach(*hnd);
free(hnd);
}
}
int Curl_thread_join(curl_thread_t *hnd)
{
int ret = (pthread_join(**hnd, NULL) == 0);
free(*hnd);
*hnd = curl_thread_t_null;
return ret;
}
#elif defined(USE_THREADS_WIN32)
/* !checksrc! disable SPACEBEFOREPAREN 1 */
curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
void *arg)
{
#ifdef _WIN32_WCE
typedef HANDLE curl_win_thread_handle_t;
#else
typedef uintptr_t curl_win_thread_handle_t;
#endif
curl_thread_t t;
curl_win_thread_handle_t thread_handle;
#ifdef _WIN32_WCE
thread_handle = CreateThread(NULL, 0, func, arg, 0, NULL);
#else
thread_handle = _beginthreadex(NULL, 0, func, arg, 0, NULL);
#endif
t = (curl_thread_t)thread_handle;
if((t == 0) || (t == LongToHandle(-1L))) {
#ifdef _WIN32_WCE
DWORD gle = GetLastError();
errno = ((gle == ERROR_ACCESS_DENIED ||
gle == ERROR_NOT_ENOUGH_MEMORY) ?
EACCES : EINVAL);
#endif
return curl_thread_t_null;
}
return t;
}
void Curl_thread_destroy(curl_thread_t hnd)
{
if(hnd != curl_thread_t_null)
CloseHandle(hnd);
}
int Curl_thread_join(curl_thread_t *hnd)
{
#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
(_WIN32_WINNT < _WIN32_WINNT_VISTA)
int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0);
#else
int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0);
#endif
Curl_thread_destroy(*hnd);
*hnd = curl_thread_t_null;
return ret;
}
#endif /* USE_THREADS_* */

65
third_party/curl/lib/curl_threads.h vendored Normal file
View File

@ -0,0 +1,65 @@
#ifndef HEADER_CURL_THREADS_H
#define HEADER_CURL_THREADS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if defined(USE_THREADS_POSIX)
# define CURL_STDCALL
# define curl_mutex_t pthread_mutex_t
# define curl_thread_t pthread_t *
# define curl_thread_t_null (pthread_t *)0
# define Curl_mutex_init(m) pthread_mutex_init(m, NULL)
# define Curl_mutex_acquire(m) pthread_mutex_lock(m)
# define Curl_mutex_release(m) pthread_mutex_unlock(m)
# define Curl_mutex_destroy(m) pthread_mutex_destroy(m)
#elif defined(USE_THREADS_WIN32)
# define CURL_STDCALL __stdcall
# define curl_mutex_t CRITICAL_SECTION
# define curl_thread_t HANDLE
# define curl_thread_t_null (HANDLE)0
# if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
(_WIN32_WINNT < _WIN32_WINNT_VISTA)
# define Curl_mutex_init(m) InitializeCriticalSection(m)
# else
# define Curl_mutex_init(m) InitializeCriticalSectionEx(m, 0, 1)
# endif
# define Curl_mutex_acquire(m) EnterCriticalSection(m)
# define Curl_mutex_release(m) LeaveCriticalSection(m)
# define Curl_mutex_destroy(m) DeleteCriticalSection(m)
#endif
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
/* !checksrc! disable SPACEBEFOREPAREN 1 */
curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
void *arg);
void Curl_thread_destroy(curl_thread_t hnd);
int Curl_thread_join(curl_thread_t *hnd);
#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */
#endif /* HEADER_CURL_THREADS_H */

331
third_party/curl/lib/curl_trc.c vendored Normal file
View File

@ -0,0 +1,331 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include <curl/curl.h>
#include "curl_trc.h"
#include "urldata.h"
#include "easyif.h"
#include "cfilters.h"
#include "timeval.h"
#include "multiif.h"
#include "strcase.h"
#include "cf-socket.h"
#include "connect.h"
#include "doh.h"
#include "http2.h"
#include "http_proxy.h"
#include "cf-h1-proxy.h"
#include "cf-h2-proxy.h"
#include "cf-haproxy.h"
#include "cf-https-connect.h"
#include "socks.h"
#include "strtok.h"
#include "vtls/vtls.h"
#include "vquic/vquic.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
void Curl_debug(struct Curl_easy *data, curl_infotype type,
char *ptr, size_t size)
{
if(data->set.verbose) {
static const char s_infotype[CURLINFO_END][3] = {
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
if(data->set.fdebug) {
bool inCallback = Curl_is_in_callback(data);
Curl_set_in_callback(data, true);
(void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
Curl_set_in_callback(data, inCallback);
}
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);
break;
default: /* nada */
break;
}
}
}
}
/* Curl_failf() is for messages stating why we failed.
* The message SHALL NOT include any LF or CR.
*/
void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
{
DEBUGASSERT(!strchr(fmt, '\n'));
if(data->set.verbose || data->set.errorbuffer) {
va_list ap;
int len;
char error[CURL_ERROR_SIZE + 2];
va_start(ap, fmt);
len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
if(data->set.errorbuffer && !data->state.errorbuf) {
strcpy(data->set.errorbuffer, error);
data->state.errorbuf = TRUE; /* wrote error string */
}
error[len++] = '\n';
error[len] = '\0';
Curl_debug(data, CURLINFO_TEXT, error, len);
va_end(ap);
}
}
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* Curl_infof() is for info message along the way */
#define MAXINFO 2048
static void trc_infof(struct Curl_easy *data, struct curl_trc_feat *feat,
const char * const fmt, va_list ap) CURL_PRINTF(3, 0);
static void trc_infof(struct Curl_easy *data, struct curl_trc_feat *feat,
const char * const fmt, va_list ap)
{
int len = 0;
char buffer[MAXINFO + 2];
if(feat)
len = msnprintf(buffer, MAXINFO, "[%s] ", feat->name);
len += mvsnprintf(buffer + len, MAXINFO - len, fmt, ap);
buffer[len++] = '\n';
buffer[len] = '\0';
Curl_debug(data, CURLINFO_TEXT, buffer, len);
}
void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
{
DEBUGASSERT(!strchr(fmt, '\n'));
if(Curl_trc_is_verbose(data)) {
va_list ap;
va_start(ap, fmt);
trc_infof(data, data->state.feat, fmt, ap);
va_end(ap);
}
}
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...)
{
DEBUGASSERT(cf);
if(Curl_trc_cf_is_verbose(cf, data)) {
va_list ap;
int len = 0;
char buffer[MAXINFO + 2];
if(data->state.feat)
len += msnprintf(buffer + len, MAXINFO - len, "[%s] ",
data->state.feat->name);
if(cf->sockindex)
len += msnprintf(buffer + len, MAXINFO - len, "[%s-%d] ",
cf->cft->name, cf->sockindex);
else
len += msnprintf(buffer + len, MAXINFO - len, "[%s] ", cf->cft->name);
va_start(ap, fmt);
len += mvsnprintf(buffer + len, MAXINFO - len, fmt, ap);
va_end(ap);
buffer[len++] = '\n';
buffer[len] = '\0';
Curl_debug(data, CURLINFO_TEXT, buffer, len);
}
}
struct curl_trc_feat Curl_trc_feat_read = {
"READ",
CURL_LOG_LVL_NONE,
};
struct curl_trc_feat Curl_trc_feat_write = {
"WRITE",
CURL_LOG_LVL_NONE,
};
void Curl_trc_read(struct Curl_easy *data, const char *fmt, ...)
{
DEBUGASSERT(!strchr(fmt, '\n'));
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_read)) {
va_list ap;
va_start(ap, fmt);
trc_infof(data, &Curl_trc_feat_read, fmt, ap);
va_end(ap);
}
}
void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...)
{
DEBUGASSERT(!strchr(fmt, '\n'));
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_write)) {
va_list ap;
va_start(ap, fmt);
trc_infof(data, &Curl_trc_feat_write, fmt, ap);
va_end(ap);
}
}
#ifndef CURL_DISABLE_FTP
struct curl_trc_feat Curl_trc_feat_ftp = {
"FTP",
CURL_LOG_LVL_NONE,
};
void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...)
{
DEBUGASSERT(!strchr(fmt, '\n'));
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ftp)) {
va_list ap;
va_start(ap, fmt);
trc_infof(data, &Curl_trc_feat_ftp, fmt, ap);
va_end(ap);
}
}
#endif /* !CURL_DISABLE_FTP */
static struct curl_trc_feat *trc_feats[] = {
&Curl_trc_feat_read,
&Curl_trc_feat_write,
#ifndef CURL_DISABLE_FTP
&Curl_trc_feat_ftp,
#endif
#ifndef CURL_DISABLE_DOH
&Curl_doh_trc,
#endif
NULL,
};
static struct Curl_cftype *cf_types[] = {
&Curl_cft_tcp,
&Curl_cft_udp,
&Curl_cft_unix,
&Curl_cft_tcp_accept,
&Curl_cft_happy_eyeballs,
&Curl_cft_setup,
#ifdef USE_NGHTTP2
&Curl_cft_nghttp2,
#endif
#ifdef USE_SSL
&Curl_cft_ssl,
#ifndef CURL_DISABLE_PROXY
&Curl_cft_ssl_proxy,
#endif
#endif
#if !defined(CURL_DISABLE_PROXY)
#if !defined(CURL_DISABLE_HTTP)
&Curl_cft_h1_proxy,
#ifdef USE_NGHTTP2
&Curl_cft_h2_proxy,
#endif
&Curl_cft_http_proxy,
#endif /* !CURL_DISABLE_HTTP */
&Curl_cft_haproxy,
&Curl_cft_socks_proxy,
#endif /* !CURL_DISABLE_PROXY */
#ifdef USE_HTTP3
&Curl_cft_http3,
#endif
#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
&Curl_cft_http_connect,
#endif
NULL,
};
CURLcode Curl_trc_opt(const char *config)
{
char *token, *tok_buf, *tmp;
size_t i;
int lvl;
tmp = strdup(config);
if(!tmp)
return CURLE_OUT_OF_MEMORY;
token = strtok_r(tmp, ", ", &tok_buf);
while(token) {
switch(*token) {
case '-':
lvl = CURL_LOG_LVL_NONE;
++token;
break;
case '+':
lvl = CURL_LOG_LVL_INFO;
++token;
break;
default:
lvl = CURL_LOG_LVL_INFO;
break;
}
for(i = 0; cf_types[i]; ++i) {
if(strcasecompare(token, "all")) {
cf_types[i]->log_level = lvl;
}
else if(strcasecompare(token, cf_types[i]->name)) {
cf_types[i]->log_level = lvl;
break;
}
}
for(i = 0; trc_feats[i]; ++i) {
if(strcasecompare(token, "all")) {
trc_feats[i]->log_level = lvl;
}
else if(strcasecompare(token, trc_feats[i]->name)) {
trc_feats[i]->log_level = lvl;
break;
}
}
token = strtok_r(NULL, ", ", &tok_buf);
}
free(tmp);
return CURLE_OK;
}
CURLcode Curl_trc_init(void)
{
#ifdef DEBUGBUILD
/* WIP: we use the auto-init from an env var only in DEBUG builds for
* convenience. */
const char *config = getenv("CURL_DEBUG");
if(config) {
return Curl_trc_opt(config);
}
#endif /* DEBUGBUILD */
return CURLE_OK;
}
#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
CURLcode Curl_trc_init(void)
{
return CURLE_OK;
}
#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */

200
third_party/curl/lib/curl_trc.h vendored Normal file
View File

@ -0,0 +1,200 @@
#ifndef HEADER_CURL_TRC_H
#define HEADER_CURL_TRC_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
struct Curl_easy;
struct Curl_cfilter;
/**
* Init logging, return != 0 on failure.
*/
CURLcode Curl_trc_init(void);
/**
* Configure tracing. May be called several times during global
* initialization. Later calls may not take effect.
*
* Configuration format supported:
* - comma-separated list of component names to enable logging on.
* E.g. 'http/2,ssl'. Unknown names are ignored. Names are compared
* case-insensitive.
* - component 'all' applies to all known log components
* - prefixing a component with '+' or '-' will en-/disable logging for
* that component
* Example: 'all,-ssl' would enable logging for all components but the
* SSL filters.
*
* @param config configuration string
*/
CURLcode Curl_trc_opt(const char *config);
/* the function used to output verbose information */
void Curl_debug(struct Curl_easy *data, curl_infotype type,
char *ptr, size_t size);
/**
* Output a failure message on registered callbacks for transfer.
*/
void Curl_failf(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
#define failf Curl_failf
#define CURL_LOG_LVL_NONE 0
#define CURL_LOG_LVL_INFO 1
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define CURL_HAVE_C99
#endif
#ifdef CURL_HAVE_C99
#define infof(data, ...) \
do { if(Curl_trc_is_verbose(data)) \
Curl_infof(data, __VA_ARGS__); } while(0)
#define CURL_TRC_CF(data, cf, ...) \
do { if(Curl_trc_cf_is_verbose(cf, data)) \
Curl_trc_cf_infof(data, cf, __VA_ARGS__); } while(0)
#define CURL_TRC_WRITE(data, ...) \
do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_write)) \
Curl_trc_write(data, __VA_ARGS__); } while(0)
#define CURL_TRC_READ(data, ...) \
do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_read)) \
Curl_trc_read(data, __VA_ARGS__); } while(0)
#ifndef CURL_DISABLE_FTP
#define CURL_TRC_FTP(data, ...) \
do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ftp)) \
Curl_trc_ftp(data, __VA_ARGS__); } while(0)
#endif /* !CURL_DISABLE_FTP */
#else /* CURL_HAVE_C99 */
#define infof Curl_infof
#define CURL_TRC_CF Curl_trc_cf_infof
#define CURL_TRC_WRITE Curl_trc_write
#define CURL_TRC_READ Curl_trc_read
#ifndef CURL_DISABLE_FTP
#define CURL_TRC_FTP Curl_trc_ftp
#endif
#endif /* !CURL_HAVE_C99 */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
/* informational messages enabled */
struct curl_trc_feat {
const char *name;
int log_level;
};
extern struct curl_trc_feat Curl_trc_feat_read;
extern struct curl_trc_feat Curl_trc_feat_write;
#define Curl_trc_is_verbose(data) \
((data) && (data)->set.verbose && \
(!(data)->state.feat || \
((data)->state.feat->log_level >= CURL_LOG_LVL_INFO)))
#define Curl_trc_cf_is_verbose(cf, data) \
(Curl_trc_is_verbose(data) && \
(cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO)
#define Curl_trc_ft_is_verbose(data, ft) \
(Curl_trc_is_verbose(data) && \
(ft)->log_level >= CURL_LOG_LVL_INFO)
/**
* Output an informational message when transfer's verbose logging is enabled.
*/
void Curl_infof(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
/**
* Output an informational message when both transfer's verbose logging
* and connection filters verbose logging are enabled.
*/
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...) CURL_PRINTF(3, 4);
void Curl_trc_ft_infof(struct Curl_easy *data, struct curl_trc_feat *ft,
const char *fmt, ...) CURL_PRINTF(3, 4);
void Curl_trc_write(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
void Curl_trc_read(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
#ifndef CURL_DISABLE_FTP
extern struct curl_trc_feat Curl_trc_feat_ftp;
void Curl_trc_ftp(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
#endif
#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
/* All informational messages are not compiled in for size savings */
#define Curl_trc_is_verbose(d) (FALSE)
#define Curl_trc_cf_is_verbose(x,y) (FALSE)
#define Curl_trc_ft_is_verbose(x,y) (FALSE)
static void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
static void Curl_trc_cf_infof(struct Curl_easy *data,
struct Curl_cfilter *cf,
const char *fmt, ...)
{
(void)data; (void)cf; (void)fmt;
}
struct curl_trc_feat;
static void Curl_trc_ft_infof(struct Curl_easy *data,
struct curl_trc_feat *ft,
const char *fmt, ...)
{
(void)data; (void)ft; (void)fmt;
}
static void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
static void Curl_trc_read(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
#ifndef CURL_DISABLE_FTP
static void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
#endif
#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
#endif /* HEADER_CURL_TRC_H */

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