Compare commits

..

1 Commits

Author SHA1 Message Date
Daniel Stenberg
7cfd58457e
GHA: re-introduce CodeQL
This mostly reverts commit 173805b2e7.

Add "queries: security-and-quality" which should make a difference
compared to before.
2025-02-22 15:15:10 +01:00
166 changed files with 2563 additions and 3269 deletions

View File

@ -3,117 +3,55 @@
# #
# SPDX-License-Identifier: curl # SPDX-License-Identifier: curl
# #
# Input: cmdline docs markdown files, they get modified *in place* # Input: a cmdline docs markdown, it gets modified *in place*
#
# Strip off the leading meta-data/header part, remove all known curl symbols
# and long command line options. Also clean up whatever else the spell checker
# might have a problem with that we still deem is fine.
# #
# The main purpose is to strip off the leading meta-data part, but also to
# clean up whatever else the spell checker might have a problem with that we
# still deem is fine.
open(S, "<./docs/libcurl/symbols-in-versions") my $header = 1;
|| die "can't find symbols-in-versions"; while(1) {
while(<S>) { # set this if the markdown has no meta-data header to skip
if(/^([^ ]*) /) { if($ARGV[0] eq "--no-header") {
push @asyms, $1; shift @ARGV;
$header = 0;
}
else {
last;
} }
} }
close(S);
# init the opts table with "special" options not easy to figure out my $f = $ARGV[0];
my @aopts = (
'--ftp-ssl-reqd', # old alias
);
open(O, "<./docs/options-in-versions") open(F, "<$f") or die;
|| die "can't find options-in-versions";
while(<O>) {
chomp;
if(/^([^ ]+)/) {
my $o = $1;
push @aopts, $o;
if($o =~ /^--no-(.*)/) {
# for the --no options, also make one without it
push @aopts, "--$1";
}
elsif($o =~ /^--disable-(.*)/) {
# for the --disable options, also make the special ones
push @aopts, "--$1";
push @aopts, "--no-$1";
}
}
}
close(O);
open(C, "<./.github/scripts/spellcheck.curl") my $ignore = $header;
|| die "can't find spellcheck.curl"; my $sepcount = 0;
while(<C>) { my @out;
if(/^\#/) { while(<F>) {
next; if(/^---/ && $header) {
} if(++$sepcount == 2) {
chomp;
if(/^([^ ]+)/) {
push @asyms, $1;
}
}
close(C);
# longest symbols first
my @syms = sort { length($b) <=> length($a) } @asyms;
# longest cmdline options first
my @opts = sort { length($b) <=> length($a) } @aopts;
sub process {
my ($f) = @_;
my $ignore = 0;
my $sepcount = 0;
my $out;
my $line = 0;
open(F, "<$f") or die;
while(<F>) {
$line++;
if(/^---/ && ($line == 1)) {
$ignore = 1;
next;
}
elsif(/^---/ && $ignore) {
$ignore = 0; $ignore = 0;
}
next; next;
} }
next if($ignore); next if($ignore);
my $l = $_;
# strip out backticked words # strip out backticked words
$l =~ s/`[^`]+`//g; $_ =~ s/`[^`]+`//g;
# **bold** # strip out all long command line options
$l =~ s/\*\*(\S.*?)\*\*//g; $_ =~ s/--[a-z0-9-]+//g;
# *italics*
$l =~ s/\*(\S.*?)\*//g;
# strip out https URLs, we don't want them spellchecked # strip out https URLs, we don't want them spellchecked
$l =~ s!https://[a-z0-9\#_/.-]+!!gi; $_ =~ s!https://[a-z0-9\#_/.-]+!!gi;
$out .= $l; push @out, $_;
} }
close(F); close(F);
# cut out all known curl cmdline options if(!$ignore) {
map { $out =~ s/$_//g; } (@opts);
# cut out all known curl symbols
map { $out =~ s/\b$_\b//g; } (@syms);
if(!$ignore) {
open(O, ">$f") or die; open(O, ">$f") or die;
print O $out; print O @out;
close(O); close(O);
}
}
for my $f (@ARGV) {
process($f);
} }

86
.github/scripts/cleanspell.pl vendored Executable file
View File

@ -0,0 +1,86 @@
#!/usr/bin/env perl
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
#
# Given: a libcurl curldown man page
# Outputs: the same file, minus the SYNOPSIS and the EXAMPLE sections
#
my $f = $ARGV[0];
open(F, "<$f") or die;
my @out;
my $ignore = 0;
while(<F>) {
if($_ =~ /^# (SYNOPSIS|EXAMPLE)/) {
$ignore = 1;
}
elsif($ignore && ($_ =~ /^# [A-Z]/)) {
$ignore = 0;
}
elsif(!$ignore) {
# **bold**
$_ =~ s/\*\*(\S.*?)\*\*//g;
# *italics*
$_ =~ s/\*(\S.*?)\*//g;
$_ =~ s/CURL(M|SH|U|H)code//g;
$_ =~ s/CURL_[A-Z0-9_]*//g;
$_ =~ s/CURLALTSVC_[A-Z0-9_]*//g;
$_ =~ s/CURLAUTH_[A-Z0-9_]*//g;
$_ =~ s/CURLE_[A-Z0-9_]*//g;
$_ =~ s/CURLFORM_[A-Z0-9_]*//g;
$_ =~ s/CURLFTP_[A-Z0-9_]*//g;
$_ =~ s/CURLFTPAUTH_[A-Z0-9_]*//g;
$_ =~ s/CURLFTPMETHOD_[A-Z0-9_]*//g;
$_ =~ s/CURLFTPSSL_[A-Z0-9_]*//g;
$_ =~ s/CURLGSSAPI_[A-Z0-9_]*//g;
$_ =~ s/CURLHEADER_[A-Z0-9_]*//g;
$_ =~ s/CURLINFO_[A-Z0-9_]*//g;
$_ =~ s/CURLM_[A-Z0-9_]*//g;
$_ =~ s/CURLMIMEOPT_[A-Z0-9_]*//g;
$_ =~ s/CURLMOPT_[A-Z0-9_]*//g;
$_ =~ s/CURLOPT_[A-Z0-9_]*//g;
$_ =~ s/CURLPIPE_[A-Z0-9_]*//g;
$_ =~ s/CURLPROTO_[A-Z0-9_]*//g;
$_ =~ s/CURLPROXY_[A-Z0-9_]*//g;
$_ =~ s/CURLPX_[A-Z0-9_]*//g;
$_ =~ s/CURLSHE_[A-Z0-9_]*//g;
$_ =~ s/CURLSHOPT_[A-Z0-9_]*//g;
$_ =~ s/CURLSSLOPT_[A-Z0-9_]*//g;
$_ =~ s/CURLSSH_[A-Z0-9_]*//g;
$_ =~ s/CURLSSLBACKEND_[A-Z0-9_]*//g;
$_ =~ s/CURLU_[A-Z0-9_]*//g;
$_ =~ s/CURLUPART_[A-Z0-9_]*//g;
#$_ =~ s/\bCURLU\b//g; # stand-alone CURLU
$_ =~ s/CURLUE_[A-Z0-9_]*//g;
$_ =~ s/CURLHE_[A-Z0-9_]*//g;
$_ =~ s/CURLWS_[A-Z0-9_]*//g;
$_ =~ s/CURLKH[A-Z0-9_]*//g;
$_ =~ s/CURLUPART_[A-Z0-9_]*//g;
$_ =~ s/CURLUSESSL_[A-Z0-9_]*//g;
$_ =~ s/CURLPAUSE_[A-Z0-9_]*//g;
$_ =~ s/CURLHSTS_[A-Z0-9_]*//g;
$_ =~ s/curl_global_([a-z_]*)//g;
$_ =~ s/curl_(strequal|strnequal|formadd|waitfd|formget|getdate|formfree)//g;
$_ =~ s/curl_easy_([a-z]*)//g;
$_ =~ s/curl_multi_([a-z_]*)//g;
$_ =~ s/curl_mime_(subparts|addpart|filedata|data_cb)//g;
$_ =~ s/curl_ws_(send|recv|meta)//g;
$_ =~ s/curl_url_(dup)//g;
$_ =~ s/curl_pushheader_by(name|num)//g;
$_ =~ s/libcurl-(env|ws)//g;
$_ =~ s/libcurl\\-(env|ws)//g;
$_ =~ s/(^|\W)((tftp|https|http|ftp):\/\/[a-z0-9\-._~%:\/?\#\[\]\@!\$&'()*+,;=\\]+)//gi;
push @out, $_;
}
}
close(F);
open(O, ">$f") or die;
for my $l (@out) {
print O $l;
}
close(O);

View File

@ -1,151 +0,0 @@
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
#
# common variable types + structs
# callback typedefs
# public functions names
# some man page names
curl_fileinfo
curl_forms
curl_hstsentry
curl_httppost
curl_index
curl_khkey
curl_pushheaders
curl_waitfd
CURLcode
CURLformoption
CURLHcode
CURLMcode
CURLMsg
CURLSHcode
CURLUcode
curl_calloc_callback
curl_chunk_bgn_callback
curl_chunk_end_callback
curl_conv_callback
curl_debug_callback
curl_fnmatch_callback
curl_formget_callback
curl_free_callback
curl_hstsread_callback
curl_hstswrite_callback
curl_ioctl_callback
curl_malloc_callback
curl_multi_timer_callback
curl_opensocket_callback
curl_prereq_callback
curl_progress_callback
curl_push_callback
curl_read_callback
curl_realloc_callback
curl_resolver_start_callback
curl_seek_callback
curl_socket_callback
curl_sockopt_callback
curl_ssl_ctx_callback
curl_strdup_callback
curl_trailer_callback
curl_write_callback
curl_xferinfo_callback
curl_strequal
curl_strnequal
curl_mime_init
curl_mime_free
curl_mime_addpart
curl_mime_name
curl_mime_filename
curl_mime_type
curl_mime_encoder
curl_mime_data
curl_mime_filedata
curl_mime_data_cb
curl_mime_subparts
curl_mime_headers
curl_formadd
curl_formget
curl_formfree
curl_getdate
curl_getenv
curl_version
curl_easy_escape
curl_escape
curl_easy_unescape
curl_unescape
curl_free
curl_global_init
curl_global_init_mem
curl_global_cleanup
curl_global_trace
curl_global_sslset
curl_slist_append
curl_slist_free_all
curl_getdate
curl_share_init
curl_share_setopt
curl_share_cleanup
curl_version_info
curl_easy_strerror
curl_share_strerror
curl_easy_pause
curl_easy_ssls_import
curl_easy_ssls_export
curl_easy_init
curl_easy_setopt
curl_easy_perform
curl_easy_cleanup
curl_easy_getinfo
curl_easy_duphandle
curl_easy_reset
curl_easy_recv
curl_easy_send
curl_easy_upkeep
curl_easy_header
curl_easy_nextheader
curl_mprintf
curl_mfprintf
curl_msprintf
curl_msnprintf
curl_mvprintf
curl_mvfprintf
curl_mvsprintf
curl_mvsnprintf
curl_maprintf
curl_mvaprintf
curl_multi_init
curl_multi_add_handle
curl_multi_remove_handle
curl_multi_fdset
curl_multi_waitfds
curl_multi_wait
curl_multi_poll
curl_multi_wakeup
curl_multi_perform
curl_multi_cleanup
curl_multi_info_read
curl_multi_strerror
curl_multi_socket
curl_multi_socket_action
curl_multi_socket_all
curl_multi_timeout
curl_multi_setopt
curl_multi_assign
curl_multi_get_handles
curl_pushheader_bynum
curl_pushheader_byname
curl_multi_waitfds
curl_easy_option_by_name
curl_easy_option_by_id
curl_easy_option_next
curl_url
curl_url_cleanup
curl_url_dup
curl_url_get
curl_url_set
curl_url_strerror
curl_ws_recv
curl_ws_send
curl_ws_meta
libcurl-env
libcurl-ws

View File

@ -121,6 +121,8 @@ CMakeLists
CNA CNA
CNAME CNAME
CNAMEs CNAMEs
CodeQL
codeql
CODESET CODESET
codeset codeset
CodeSonar CodeSonar
@ -251,7 +253,6 @@ Feltzing
ffi ffi
filesize filesize
filesystem filesystem
FindCURL
FLOSS FLOSS
fnmatch fnmatch
footguns footguns
@ -951,6 +952,7 @@ winbuild
WinIDN WinIDN
WinLDAP WinLDAP
winsock winsock
winssl
Wireshark Wireshark
wolfSSH wolfSSH
wolfSSL wolfSSL

View File

@ -107,8 +107,20 @@ jobs:
persist-credentials: false persist-credentials: false
name: checkout name: checkout
- name: trim all *.md files in docs/ - name: trim all man page *.md files
run: .github/scripts/cleancmd.pl $(find docs -name "*.md") run: find docs -name "*.md" ! -name "_*" -print0 | xargs -0 -n1 .github/scripts/cleancmd.pl
- name: trim libcurl man page *.md files
run: find docs/libcurl \( -name "curl_*.md" -o -name "libcurl*.md" \) -print0 | xargs -0 -n1 .github/scripts/cleanspell.pl
- name: trim libcurl option man page *.md files
run: find docs/libcurl/opts -name "CURL*.md" -print0 | xargs -0 -n1 .github/scripts/cleanspell.pl
- name: trim cmdline docs markdown _*.md files
run: find docs/cmdline-opts -name "_*.md" -print0 | xargs -0 -n1 .github/scripts/cleancmd.pl --no-header
- name: trim docs/ markdown _*.md files
run: git ls-files docs/*.md docs/internals/*.md | xargs -n1 .github/scripts/cleancmd.pl --no-header
- name: setup the custom wordlist - name: setup the custom wordlist
run: grep -v '^#' .github/scripts/spellcheck.words > wordlist.txt run: grep -v '^#' .github/scripts/spellcheck.words > wordlist.txt

85
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,85 @@
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
name: CodeQL
'on':
push:
branches:
- master
- '*/ci'
paths-ignore:
- '**/*.md'
- '.circleci/**'
- 'appveyor.*'
- 'docs/**'
- 'packages/**'
- 'plan9/**'
- 'projects/**'
- 'tests/data/**'
- 'winbuild/**'
pull_request:
branches:
- master
paths-ignore:
- '**/*.md'
- '.circleci/**'
- 'appveyor.*'
- 'docs/**'
- 'packages/**'
- 'plan9/**'
- 'projects/**'
- 'tests/data/**'
- 'winbuild/**'
schedule:
- cron: '0 0 * * 4'
concurrency:
group: ${{ github.workflow }}
permissions: {}
jobs:
codeql:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- name: 'install prereqs'
run: |
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get -o Dpkg::Use-Pty=0 update
sudo apt-get -o Dpkg::Use-Pty=0 install \
libpsl-dev
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
persist-credentials: false
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3
with:
languages: cpp
queries: security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
# - run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3

View File

@ -19,9 +19,6 @@ concurrency:
permissions: {} permissions: {}
env:
MAKEFLAGS: -j 5
jobs: jobs:
maketgz-and-verify-in-tree: maketgz-and-verify-in-tree:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -58,9 +55,9 @@ jobs:
tar xvf curl-99.98.97.tar.gz tar xvf curl-99.98.97.tar.gz
pushd curl-99.98.97 pushd curl-99.98.97
./configure --prefix=$HOME/temp --without-ssl --without-libpsl ./configure --prefix=$HOME/temp --without-ssl --without-libpsl
make make -j5
make test-ci make -j5 test-ci
make install make -j5 install
popd popd
# basic check of the installed files # basic check of the installed files
bash scripts/installcheck.sh $HOME/temp bash scripts/installcheck.sh $HOME/temp
@ -83,8 +80,8 @@ jobs:
mkdir build mkdir build
pushd build pushd build
../curl-99.98.97/configure --without-ssl --without-libpsl ../curl-99.98.97/configure --without-ssl --without-libpsl
make make -j5
make test-ci make -j5 test-ci
popd popd
rm -rf build rm -rf build
rm -rf curl-99.98.97 rm -rf curl-99.98.97
@ -106,9 +103,9 @@ jobs:
mkdir build mkdir build
pushd build pushd build
../configure --without-ssl --enable-debug "--prefix=${PWD}/pkg" --without-libpsl ../configure --without-ssl --enable-debug "--prefix=${PWD}/pkg" --without-libpsl
make make -j5
make test-ci make -j5 test-ci
make install make -j5 install
verify-out-of-tree-cmake: verify-out-of-tree-cmake:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -125,7 +122,7 @@ jobs:
tar xvf curl-99.98.97.tar.gz tar xvf curl-99.98.97.tar.gz
pushd curl-99.98.97 pushd curl-99.98.97
cmake -B build -DCURL_WERROR=ON -DCURL_USE_LIBPSL=OFF cmake -B build -DCURL_WERROR=ON -DCURL_USE_LIBPSL=OFF
make -C build make -C build -j5
missing-files: missing-files:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -434,45 +434,46 @@ jobs:
export PKG_CONFIG_PATH="${{ matrix.build.PKG_CONFIG_PATH }}" export PKG_CONFIG_PATH="${{ matrix.build.PKG_CONFIG_PATH }}"
fi fi
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake -B bld -G Ninja \ cmake -B . -G Ninja \
-DCMAKE_C_COMPILER_TARGET=$(uname -m)-pc-linux-gnu -DBUILD_STATIC_LIBS=ON \ -DCMAKE_C_COMPILER_TARGET=$(uname -m)-pc-linux-gnu -DBUILD_STATIC_LIBS=ON \
-DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON -DCURL_WERROR=ON \ -DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON -DCURL_WERROR=ON \
${{ matrix.build.generate }} ${{ matrix.build.generate }}
else else
mkdir bld && cd bld && ../configure --enable-unity --enable-test-bundles --enable-warnings --enable-werror \ ./configure --disable-dependency-tracking --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
--disable-dependency-tracking \
${{ matrix.build.configure }} ${{ matrix.build.configure }}
fi fi
- name: 'configure log' - name: 'configure log'
if: ${{ !cancelled() }} if: ${{ !cancelled() }}
run: cat bld/config.log bld/CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true run: cat config.log CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true
- name: 'curl_config.h' - name: 'curl_config.h'
run: | run: |
echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::' echo '::group::raw'; cat lib/curl_config.h || true; echo '::endgroup::'
grep -F '#define' bld/lib/curl_config.h | sort || true grep -F '#define' lib/curl_config.h | sort || true
- name: 'test configs' - name: 'test configs'
run: grep -H -v '^#' bld/tests/config bld/tests/http/config.ini || true run: |
cat tests/config || true
cat tests/http/config.ini || true
- name: 'build' - name: 'build'
run: | run: |
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake --build bld --verbose cmake --build . --verbose
else else
make -C bld V=1 make V=1
fi fi
- name: 'check curl -V output' - name: 'check curl -V output'
run: bld/src/curl -V run: ./src/curl -V
- name: 'build tests' - name: 'build tests'
run: | run: |
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake --build bld --verbose --target testdeps cmake --build . --verbose --target testdeps
else else
make -C bld V=1 -C tests make V=1 -C tests
fi fi
- name: 'install test prereqs' - name: 'install test prereqs'
@ -486,9 +487,9 @@ jobs:
run: | run: |
source $HOME/venv/bin/activate source $HOME/venv/bin/activate
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake --build bld --verbose --target test-ci cmake --build . --verbose --target test-ci
else else
make -C bld V=1 test-ci make V=1 test-ci
fi fi
- name: 'install pytest prereqs' - name: 'install pytest prereqs'
@ -498,21 +499,22 @@ jobs:
- name: 'run pytest event based' - name: 'run pytest event based'
env: env:
TFLAGS: '${{ matrix.build.tflags }}'
CURL_TEST_EVENT: 1 CURL_TEST_EVENT: 1
CURL_CI: github CURL_CI: github
PYTEST_ADDOPTS: '--color=yes' PYTEST_ADDOPTS: '--color=yes'
run: | run: |
source $HOME/venv/bin/activate source $HOME/venv/bin/activate
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake --build bld --verbose --target curl-pytest-ci cmake --build . --verbose --target curl-pytest-ci
else else
make -C bld V=1 pytest-ci make V=1 pytest-ci
fi fi
- name: 'build examples' - name: 'build examples'
run: | run: |
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake --build bld --verbose --target curl-examples cmake --build . --verbose --target curl-examples
else else
make -C bld V=1 examples make V=1 examples
fi fi

View File

@ -304,8 +304,7 @@ jobs:
libtool autoconf automake pkgconf ninja-build \ libtool autoconf automake pkgconf ninja-build \
${{ matrix.build.install_steps != 'skipall' && matrix.build.install_steps != 'skiprun' && 'stunnel4' || '' }} \ ${{ matrix.build.install_steps != 'skipall' && matrix.build.install_steps != 'skiprun' && 'stunnel4' || '' }} \
libpsl-dev libbrotli-dev libzstd-dev \ libpsl-dev libbrotli-dev libzstd-dev \
${{ matrix.build.install_packages }} \ ${{ matrix.build.install_packages }}
${{ contains(matrix.build.install_steps, 'pytest') && 'apache2 apache2-dev libnghttp2-dev vsftpd' || '' }}
python3 -m venv $HOME/venv python3 -m venv $HOME/venv
- name: 'install prereqs' - name: 'install prereqs'
@ -320,6 +319,11 @@ jobs:
${{ matrix.build.install_packages }} ${{ matrix.build.install_packages }}
python3 -m venv $HOME/venv python3 -m venv $HOME/venv
- name: 'install prereqs for pytest'
if: contains(matrix.build.install_steps, 'pytest')
run: |
sudo apt-get -o Dpkg::Use-Pty=0 install apache2 apache2-dev libnghttp2-dev vsftpd
- name: 'install dependencies' - name: 'install dependencies'
if: startsWith(matrix.build.container, 'alpine') if: startsWith(matrix.build.container, 'alpine')
run: | run: |
@ -556,7 +560,7 @@ jobs:
cd $HOME cd $HOME
curl -sSf --compressed https://sh.rustup.rs/ | sh -s -- -y curl -sSf --compressed https://sh.rustup.rs/ | sh -s -- -y
source $HOME/.cargo/env source $HOME/.cargo/env
rustup toolchain install stable --profile minimal rustup toolchain install nightly
- name: 'build rustls' - name: 'build rustls'
if: contains(matrix.build.install_steps, 'rustls') && steps.cache-rustls.outputs.cache-hit != 'true' if: contains(matrix.build.install_steps, 'rustls') && steps.cache-rustls.outputs.cache-hit != 'true'
@ -589,37 +593,37 @@ jobs:
export PKG_CONFIG_PATH="${{ matrix.build.PKG_CONFIG_PATH }}" export PKG_CONFIG_PATH="${{ matrix.build.PKG_CONFIG_PATH }}"
fi fi
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake -B bld -G Ninja \ cmake -B . -G Ninja \
-DCMAKE_INSTALL_PREFIX="$HOME/curl" \ -DCMAKE_INSTALL_PREFIX="$HOME/curl" \
-DCMAKE_C_COMPILER_TARGET=$(uname -m)-pc-linux-gnu -DBUILD_STATIC_LIBS=ON \ -DCMAKE_C_COMPILER_TARGET=$(uname -m)-pc-linux-gnu -DBUILD_STATIC_LIBS=ON \
-DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON -DCURL_WERROR=ON \ -DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON -DCURL_WERROR=ON \
${{ matrix.build.generate }} ${{ matrix.build.generate }}
else else
mkdir bld && cd bld && \
${{ matrix.build.configure-prefix }} \ ${{ matrix.build.configure-prefix }} \
../configure --enable-unity --enable-test-bundles --enable-warnings --enable-werror \ ./configure --disable-dependency-tracking --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
--disable-dependency-tracking \
${{ matrix.build.configure }} ${{ matrix.build.configure }}
fi fi
- name: 'configure log' - name: 'configure log'
if: ${{ !cancelled() }} if: ${{ !cancelled() }}
run: cat bld/config.log bld/CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true run: cat config.log CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true
- name: 'curl_config.h' - name: 'curl_config.h'
run: | run: |
echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::' echo '::group::raw'; cat lib/curl_config.h || true; echo '::endgroup::'
grep -F '#define' bld/lib/curl_config.h | sort || true grep -F '#define' lib/curl_config.h | sort || true
- name: 'test configs' - name: 'test configs'
run: grep -H -v '^#' bld/tests/config bld/tests/http/config.ini || true run: |
cat tests/config || true
cat tests/http/config.ini || true
- name: 'build' - name: 'build'
run: | run: |
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
${{ matrix.build.make-prefix }} cmake --build bld --verbose ${{ matrix.build.make-prefix }} cmake --build . --verbose
else else
${{ matrix.build.make-prefix }} make -C bld V=1 ${{ matrix.build.make-custom-target }} ${{ matrix.build.make-prefix }} make V=1 ${{ matrix.build.make-custom-target }}
fi fi
- name: 'single-use function check' - name: 'single-use function check'
@ -627,27 +631,27 @@ jobs:
run: | run: |
git config --global --add safe.directory "*" git config --global --add safe.directory "*"
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
libcurla=bld/lib/libcurl.a libcurla=lib/libcurl.a
else else
libcurla=bld/lib/.libs/libcurl.a libcurla=lib/.libs/libcurl.a
fi fi
./scripts/singleuse.pl --unit ${libcurla} ./scripts/singleuse.pl --unit ${libcurla}
- name: 'check curl -V output' - name: 'check curl -V output'
if: ${{ matrix.build.make-custom-target != 'tidy' }} if: ${{ matrix.build.make-custom-target != 'tidy' }}
run: bld/src/curl -V run: ./src/curl -V
- name: 'cmake install' - name: 'cmake install'
if: ${{ matrix.build.generate }} if: ${{ matrix.build.generate }}
run: cmake --install bld --strip run: cmake --install . --strip
- name: 'build tests' - name: 'build tests'
if: ${{ matrix.build.install_steps != 'skipall' }} if: ${{ matrix.build.install_steps != 'skipall' }}
run: | run: |
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake --build bld --verbose --target testdeps cmake --build . --verbose --target testdeps
else else
make -C bld V=1 -C tests make V=1 -C tests
fi fi
- name: 'install test prereqs' - name: 'install test prereqs'
@ -674,9 +678,9 @@ jobs:
fi fi
[ -x "$HOME/venv/bin/activate" ] && source $HOME/venv/bin/activate [ -x "$HOME/venv/bin/activate" ] && source $HOME/venv/bin/activate
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake --build bld --verbose --target ${{ matrix.build.torture && 'test-torture' || 'test-ci' }} cmake --build . --verbose --target ${{ matrix.build.torture && 'test-torture' || 'test-ci' }}
else else
make -C bld V=1 ${{ matrix.build.torture && 'test-torture' || 'test-ci' }} make V=1 ${{ matrix.build.torture && 'test-torture' || 'test-ci' }}
fi fi
- name: 'install pytest prereqs' - name: 'install pytest prereqs'
@ -688,21 +692,22 @@ jobs:
- name: 'run pytest' - name: 'run pytest'
if: contains(matrix.build.install_steps, 'pytest') if: contains(matrix.build.install_steps, 'pytest')
env: env:
TFLAGS: '${{ matrix.build.tflags }}'
CURL_CI: github CURL_CI: github
PYTEST_ADDOPTS: '--color=yes' PYTEST_ADDOPTS: '--color=yes'
run: | run: |
[ -x "$HOME/venv/bin/activate" ] && source $HOME/venv/bin/activate [ -x "$HOME/venv/bin/activate" ] && source $HOME/venv/bin/activate
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake --build bld --verbose --target curl-pytest-ci cmake --build . --verbose --target curl-pytest-ci
else else
make -C bld V=1 pytest-ci make V=1 pytest-ci
fi fi
- name: 'build examples' - name: 'build examples'
if: ${{ matrix.build.make-custom-target != 'tidy' }} if: ${{ matrix.build.make-custom-target != 'tidy' }}
run: | run: |
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
${{ matrix.build.make-prefix }} cmake --build bld --verbose --target curl-examples ${{ matrix.build.make-prefix }} cmake --build . --verbose --target curl-examples
else else
${{ matrix.build.make-prefix }} make -C bld V=1 examples ${{ matrix.build.make-prefix }} make V=1 examples
fi fi

View File

@ -47,8 +47,8 @@ permissions: {}
# newer than the 10.8 required by `CFURLCreateDataAndPropertiesFromResource`. # newer than the 10.8 required by `CFURLCreateDataAndPropertiesFromResource`.
env: env:
MAKEFLAGS: -j 4
LDFLAGS: -w # suppress 'object file was built for newer macOS version than being linked' warnings LDFLAGS: -w # suppress 'object file was built for newer macOS version than being linked' warnings
MAKEFLAGS: -j 4
jobs: jobs:
macos: macos:
@ -123,10 +123,9 @@ jobs:
compiler: clang compiler: clang
configure: --enable-debug --with-openssl=$(brew --prefix openssl) configure: --enable-debug --with-openssl=$(brew --prefix openssl)
tflags: --test-event tflags: --test-event
- name: 'quictls libssh2 !ldap 10.15' - name: 'OpenSSL libssh2 !ldap 10.15'
compiler: clang compiler: clang
install: quictls configure: --enable-debug --disable-ldap --with-openssl=$(brew --prefix openssl)
configure: --enable-debug --disable-ldap --with-openssl=$(brew --prefix quictls) LDFLAGS="${LDFLAGS} -L$(brew --prefix quictls)/lib"
macos-version-min: '10.15' macos-version-min: '10.15'
# cmake # cmake
- name: 'OpenSSL gsasl rtmp AppleIDN' - name: 'OpenSSL gsasl rtmp AppleIDN'
@ -137,9 +136,9 @@ jobs:
generate: -DOPENSSL_ROOT_DIR=$(brew --prefix openssl) -DUSE_APPLE_IDN=ON -DCURL_CLANG_TIDY=ON -DCLANG_TIDY=$(brew --prefix llvm)/bin/clang-tidy generate: -DOPENSSL_ROOT_DIR=$(brew --prefix openssl) -DUSE_APPLE_IDN=ON -DCURL_CLANG_TIDY=ON -DCLANG_TIDY=$(brew --prefix llvm)/bin/clang-tidy
clang-tidy: true clang-tidy: true
chkprefill: _chkprefill chkprefill: _chkprefill
- name: 'quictls +static libssh +examples' - name: 'OpenSSL +static libssh +examples'
install: quictls libssh install: libssh
generate: -DOPENSSL_ROOT_DIR=$(brew --prefix quictls) -DBUILD_STATIC_LIBS=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=ON generate: -DOPENSSL_ROOT_DIR=$(brew --prefix openssl) -DBUILD_STATIC_LIBS=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=ON
- name: 'SecureTransport debug' - name: 'SecureTransport debug'
generate: -DCURL_USE_SECTRANSP=ON -DENABLE_DEBUG=ON generate: -DCURL_USE_SECTRANSP=ON -DENABLE_DEBUG=ON
macos-version-min: '10.8' macos-version-min: '10.8'
@ -185,12 +184,11 @@ jobs:
run: | run: |
echo ${{ matrix.build.generate && 'ninja' || 'automake libtool' }} \ echo ${{ matrix.build.generate && 'ninja' || 'automake libtool' }} \
pkgconf libpsl libssh2 \ pkgconf libpsl libssh2 \
${{ !matrix.build.clang-tidy && 'libnghttp2 stunnel' || '' }} \ ${{ !matrix.build.clang-tidy && 'nghttp2 stunnel' || '' }} \
${{ matrix.build.install }} | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile ${{ matrix.build.install }} | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done
- name: 'brew unlink openssl' - name: 'brew unlink openssl'
if: ${{ contains(matrix.build.install, 'libressl') || contains(matrix.build.install, 'quictls') }}
run: | run: |
if test -d $(brew --prefix)/include/openssl; then if test -d $(brew --prefix)/include/openssl; then
brew unlink openssl brew unlink openssl
@ -315,6 +313,7 @@ jobs:
if [ -z '${{ matrix.build.torture }}' ]; then if [ -z '${{ matrix.build.torture }}' ]; then
TFLAGS+=' ~2037 ~2041' # flaky TFLAGS+=' ~2037 ~2041' # flaky
if [[ '${{ matrix.compiler }}' = 'gcc'* ]]; then if [[ '${{ matrix.compiler }}' = 'gcc'* ]]; then
TFLAGS+=' ~RTSP' # 567 568 569 570 571 572 577 689 3100
TFLAGS+=' ~1156 ~1539' # HTTP Content-Range, Content-Length TFLAGS+=' ~1156 ~1539' # HTTP Content-Range, Content-Length
if [[ -n '${{ matrix.build.configure }}' || \ if [[ -n '${{ matrix.build.configure }}' || \
'${{ matrix.build.generate }}' = *'-DCURL_USE_SECTRANSP=ON'* ]]; then '${{ matrix.build.generate }}' = *'-DCURL_USE_SECTRANSP=ON'* ]]; then
@ -345,7 +344,7 @@ jobs:
if: ${{ contains(matrix.build.name, '+examples') }} if: ${{ contains(matrix.build.name, '+examples') }}
run: | run: |
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake --build bld --verbose --target curl-examples cmake --build bld --target curl-examples --verbose
else else
make -C bld examples V=1 make -C bld examples V=1
fi fi

View File

@ -59,21 +59,21 @@ jobs:
time cmake -B bld -G Ninja \ time cmake -B bld -G Ninja \
-DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \ -DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
-DCURL_WERROR=ON \ -DCURL_WERROR=ON \
-DENABLE_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug \ -DENABLE_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG= \
-DCURL_USE_OPENSSL=ON \ -DCURL_USE_OPENSSL=ON \
-DCURL_USE_GSSAPI=ON \ -DCURL_USE_GSSAPI=ON \
|| { cat bld/CMakeFiles/CMake*.yaml; false; } || { cat bld/CMakeFiles/CMake*.yaml; false; }
echo '::group::curl_config.h (raw)'; cat bld/lib/curl_config.h || true; echo '::endgroup::' echo '::group::curl_config.h (raw)'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
echo '::group::curl_config.h'; grep -F '#define' bld/lib/curl_config.h | sort || true; echo '::endgroup::' echo '::group::curl_config.h'; grep -F '#define' bld/lib/curl_config.h | sort || true; echo '::endgroup::'
time cmake --build bld time cmake --build bld --config Debug
bld/src/curl --disable --version bld/src/curl --disable --version
if [ '${{ matrix.arch }}' = 'x86_64' ]; then # Slow on emulated CPU if [ '${{ matrix.arch }}' = 'x86_64' ]; then # Slow on emulated CPU
time cmake --build bld --target testdeps time cmake --build bld --config Debug --target testdeps
export TFLAGS='-j4' export TFLAGS='-j4'
time cmake --build bld --target test-ci time cmake --build bld --config Debug --target test-ci
fi fi
echo '::group::build examples' echo '::group::build examples'
time cmake --build bld --target curl-examples time cmake --build bld --config Debug --target curl-examples
echo '::endgroup::' echo '::endgroup::'
openbsd: openbsd:
@ -100,20 +100,20 @@ jobs:
time cmake -B bld -G Ninja \ time cmake -B bld -G Ninja \
-DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \ -DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
-DCURL_WERROR=ON \ -DCURL_WERROR=ON \
-DENABLE_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug \ -DENABLE_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG= \
-DCURL_USE_OPENSSL=ON \ -DCURL_USE_OPENSSL=ON \
|| { cat bld/CMakeFiles/CMake*.yaml; false; } || { cat bld/CMakeFiles/CMake*.yaml; false; }
echo '::group::curl_config.h (raw)'; cat bld/lib/curl_config.h || true; echo '::endgroup::' echo '::group::curl_config.h (raw)'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
echo '::group::curl_config.h'; grep -F '#define' bld/lib/curl_config.h | sort || true; echo '::endgroup::' echo '::group::curl_config.h'; grep -F '#define' bld/lib/curl_config.h | sort || true; echo '::endgroup::'
time cmake --build bld time cmake --build bld --config Debug
bld/src/curl --disable --version bld/src/curl --disable --version
if [ '${{ matrix.arch }}' = 'x86_64' ]; then # Slow on emulated CPU if [ '${{ matrix.arch }}' = 'x86_64' ]; then # Slow on emulated CPU
time cmake --build bld --target testdeps time cmake --build bld --config Debug --target testdeps
export TFLAGS='-j8 ~3017 ~TFTP ~FTP' # FIXME: TFTP requests executed twice? Related: `curl: (69) TFTP: Access Violation`? export TFLAGS='-j8 ~3017 ~TFTP ~FTP' # FIXME: TFTP requests executed twice? Related: `curl: (69) TFTP: Access Violation`?
time cmake --build bld --target test-ci time cmake --build bld --config Debug --target test-ci
fi fi
echo '::group::build examples' echo '::group::build examples'
time cmake --build bld --target curl-examples time cmake --build bld --config Debug --target curl-examples
echo '::endgroup::' echo '::endgroup::'
freebsd: freebsd:
@ -140,7 +140,6 @@ jobs:
version: '14.1' version: '14.1'
architecture: ${{ matrix.arch }} architecture: ${{ matrix.arch }}
run: | run: |
export MAKEFLAGS=-j3
# https://ports.freebsd.org/ # https://ports.freebsd.org/
time sudo pkg install -y autoconf automake libtool \ time sudo pkg install -y autoconf automake libtool \
pkgconf brotli openldap26-client libidn2 libnghttp2 stunnel py311-impacket pkgconf brotli openldap26-client libidn2 libnghttp2 stunnel py311-impacket
@ -155,18 +154,18 @@ jobs:
|| { tail -n 1000 config.log; false; } || { tail -n 1000 config.log; false; }
echo '::group::curl_config.h (raw)'; cat lib/curl_config.h || true; echo '::endgroup::' echo '::group::curl_config.h (raw)'; cat lib/curl_config.h || true; echo '::endgroup::'
echo '::group::curl_config.h'; grep -F '#define' lib/curl_config.h | sort || true; echo '::endgroup::' echo '::group::curl_config.h'; grep -F '#define' lib/curl_config.h | sort || true; echo '::endgroup::'
time make install time make -j3 install
src/curl --disable --version src/curl --disable --version
desc='${{ matrix.desc }}' desc='${{ matrix.desc }}'
if [ '${{ matrix.arch }}' = 'x86_64' ]; then # Slow on emulated CPU if [ '${{ matrix.arch }}' = 'x86_64' ]; then # Slow on emulated CPU
time make -C tests time make -j3 -C tests
if [ "${desc#*!runtests*}" = "${desc}" ]; then if [ "${desc#*!runtests*}" = "${desc}" ]; then
time make test-ci V=1 TFLAGS='-j4' time make test-ci V=1 TFLAGS='-j4'
fi fi
fi fi
if [ "${desc#*!examples*}" = "${desc}" ]; then if [ "${desc#*!examples*}" = "${desc}" ]; then
echo '::group::build examples' echo '::group::build examples'
time make examples time make -j3 examples
echo '::endgroup::' echo '::endgroup::'
fi fi
@ -185,25 +184,25 @@ jobs:
-DCMAKE_C_COMPILER='${{ matrix.compiler }}' \ -DCMAKE_C_COMPILER='${{ matrix.compiler }}' \
-DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \ -DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
-DCURL_WERROR=ON \ -DCURL_WERROR=ON \
-DENABLE_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug \ -DENABLE_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG= \
-DCURL_USE_OPENSSL=ON \ -DCURL_USE_OPENSSL=ON \
-DCURL_USE_GSSAPI=ON \ -DCURL_USE_GSSAPI=ON \
${{ matrix.options }} \ ${{ matrix.options }} \
|| { cat bld/CMakeFiles/CMake*.yaml; false; } || { cat bld/CMakeFiles/CMake*.yaml; false; }
echo '::group::curl_config.h (raw)'; cat bld/lib/curl_config.h || true; echo '::endgroup::' echo '::group::curl_config.h (raw)'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
echo '::group::curl_config.h'; grep -F '#define' bld/lib/curl_config.h | sort || true; echo '::endgroup::' echo '::group::curl_config.h'; grep -F '#define' bld/lib/curl_config.h | sort || true; echo '::endgroup::'
time cmake --build bld time cmake --build bld --config Debug
bld/src/curl --disable --version bld/src/curl --disable --version
desc='${{ matrix.desc }}' desc='${{ matrix.desc }}'
if [ '${{ matrix.arch }}' = 'x86_64' ]; then # Slow on emulated CPU if [ '${{ matrix.arch }}' = 'x86_64' ]; then # Slow on emulated CPU
time cmake --build bld --target testdeps time cmake --build bld --config Debug --target testdeps
if [ "${desc#*!runtests*}" = "${desc}" ]; then if [ "${desc#*!runtests*}" = "${desc}" ]; then
time cmake --build bld --target test-ci time cmake --build bld --config Debug --target test-ci
fi fi
fi fi
if [ "${desc#*!examples*}" = "${desc}" ]; then if [ "${desc#*!examples*}" = "${desc}" ]; then
echo '::group::build examples' echo '::group::build examples'
time cmake --build bld --target curl-examples time cmake --build bld --config Debug --target curl-examples
echo '::endgroup::' echo '::endgroup::'
fi fi
@ -224,7 +223,6 @@ jobs:
run: | run: |
set -e set -e
ln -s /usr/bin/gcpp /usr/bin/cpp # Some tests expect `cpp`, which is named `gcpp` in this env. ln -s /usr/bin/gcpp /usr/bin/cpp # Some tests expect `cpp`, which is named `gcpp` in this env.
export MAKEFLAGS=-j3
time autoreconf -fi time autoreconf -fi
mkdir bld && cd bld && time ../configure --enable-unity --enable-test-bundles --enable-debug --enable-warnings --enable-werror \ mkdir bld && cd bld && time ../configure --enable-unity --enable-test-bundles --enable-debug --enable-warnings --enable-werror \
--prefix="${HOME}"/install \ --prefix="${HOME}"/install \
@ -233,12 +231,12 @@ jobs:
|| { tail -n 1000 config.log; false; } || { tail -n 1000 config.log; false; }
echo '::group::curl_config.h (raw)'; cat lib/curl_config.h || true; echo '::endgroup::' echo '::group::curl_config.h (raw)'; cat lib/curl_config.h || true; echo '::endgroup::'
echo '::group::curl_config.h'; grep -F '#define' lib/curl_config.h | sort || true; echo '::endgroup::' echo '::group::curl_config.h'; grep -F '#define' lib/curl_config.h | sort || true; echo '::endgroup::'
time gmake install time gmake -j3 install
src/curl --disable --version src/curl --disable --version
time gmake -C tests time gmake -j3 -C tests
time gmake test-ci V=1 time gmake test-ci V=1
echo '::group::build examples' echo '::group::build examples'
time gmake examples time gmake -j3 examples
echo '::endgroup::' echo '::endgroup::'
ios: ios:
@ -246,9 +244,9 @@ jobs:
runs-on: 'macos-latest' runs-on: 'macos-latest'
timeout-minutes: 10 timeout-minutes: 10
env: env:
MAKEFLAGS: -j 4
DEVELOPER_DIR: "/Applications/Xcode${{ matrix.build.xcode && format('_{0}', matrix.build.xcode) || '' }}.app/Contents/Developer" DEVELOPER_DIR: "/Applications/Xcode${{ matrix.build.xcode && format('_{0}', matrix.build.xcode) || '' }}.app/Contents/Developer"
CC: ${{ matrix.build.compiler || 'clang' }} CC: ${{ matrix.build.compiler || 'clang' }}
MAKEFLAGS: -j 4
# renovate: datasource=github-tags depName=libressl-portable/portable versioning=semver registryUrl=https://github.com # renovate: datasource=github-tags depName=libressl-portable/portable versioning=semver registryUrl=https://github.com
libressl-version: 4.0.0 libressl-version: 4.0.0
strategy: strategy:
@ -263,7 +261,6 @@ jobs:
install_steps: libressl install_steps: libressl
# FIXME: Could not make OPENSSL_ROOT_DIR work. CMake seems to prepend sysroot to it. # FIXME: Could not make OPENSSL_ROOT_DIR work. CMake seems to prepend sysroot to it.
generate: >- generate: >-
-DCMAKE_BUILD_TYPE=Release -DCMAKE_UNITY_BUILD_BATCH_SIZE=50
-DOPENSSL_INCLUDE_DIR="$HOME/libressl/include" -DOPENSSL_INCLUDE_DIR="$HOME/libressl/include"
-DOPENSSL_SSL_LIBRARY="$HOME/libressl/lib/libssl.a" -DOPENSSL_SSL_LIBRARY="$HOME/libressl/lib/libssl.a"
-DOPENSSL_CRYPTO_LIBRARY="$HOME/libressl/lib/libcrypto.a" -DOPENSSL_CRYPTO_LIBRARY="$HOME/libressl/lib/libcrypto.a"
@ -272,7 +269,6 @@ jobs:
- name: 'libressl' - name: 'libressl'
install_steps: libressl install_steps: libressl
generator: Xcode generator: Xcode
options: --config Debug
generate: >- generate: >-
-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=OFF -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=OFF
-DMACOSX_BUNDLE_GUI_IDENTIFIER=se.curl -DMACOSX_BUNDLE_GUI_IDENTIFIER=se.curl
@ -365,7 +361,7 @@ jobs:
- name: 'build' - name: 'build'
run: | run: |
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake --build bld ${{ matrix.build.options }} --parallel 4 --verbose cmake --build bld --verbose
else else
make -C bld V=1 make -C bld V=1
fi fi
@ -376,7 +372,7 @@ jobs:
- name: 'build tests' - name: 'build tests'
run: | run: |
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake --build bld ${{ matrix.build.options }} --parallel 4 --target testdeps --verbose cmake --build bld --target testdeps --verbose
else else
make -C bld V=1 -C tests make -C bld V=1 -C tests
fi fi
@ -384,7 +380,7 @@ jobs:
- name: 'build examples' - name: 'build examples'
run: | run: |
if [ -n '${{ matrix.build.generate }}' ]; then if [ -n '${{ matrix.build.generate }}' ]; then
cmake --build bld ${{ matrix.build.options }} --parallel 4 --target curl-examples --verbose cmake --build bld --target curl-examples --verbose
else else
make -C bld examples V=1 make -C bld examples V=1
fi fi
@ -394,9 +390,9 @@ jobs:
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
timeout-minutes: 25 timeout-minutes: 25
env: env:
MAKEFLAGS: -j 5
VCPKG_BINARY_SOURCES: 'clear;x-gha,readwrite' VCPKG_BINARY_SOURCES: 'clear;x-gha,readwrite'
VCPKG_DISABLE_METRICS: '1' VCPKG_DISABLE_METRICS: '1'
MAKEFLAGS: -j 5
strategy: strategy:
matrix: matrix:
include: include:
@ -494,7 +490,7 @@ jobs:
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --verbose cmake --build bld --verbose
else else
make -C bld V=1 make -j5 -C bld V=1
fi fi
- name: 'curl info' - name: 'curl info'
@ -505,7 +501,7 @@ jobs:
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target testdeps cmake --build bld --target testdeps
else else
make -C bld -C tests make -j5 -C bld -C tests
fi fi
- name: 'build examples' - name: 'build examples'
@ -513,7 +509,7 @@ jobs:
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target curl-examples cmake --build bld --target curl-examples
else else
make -C bld examples make -j5 -C bld examples
fi fi
amiga: amiga:
@ -521,7 +517,6 @@ jobs:
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
timeout-minutes: 5 timeout-minutes: 5
env: env:
MAKEFLAGS: -j 5
amissl-version: 5.18 amissl-version: 5.18
strategy: strategy:
matrix: matrix:
@ -589,9 +584,9 @@ jobs:
- name: 'build' - name: 'build'
run: | run: |
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld cmake --build bld --parallel 5
else else
make -C bld make -j5 -C bld
fi fi
- name: 'curl info' - name: 'curl info'
@ -601,18 +596,18 @@ jobs:
if: ${{ matrix.build == 'cmake' }} # skip for autotools to save time if: ${{ matrix.build == 'cmake' }} # skip for autotools to save time
run: | run: |
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target testdeps cmake --build bld --parallel 5 --target testdeps
else else
make -C bld -C tests make -j5 -C bld -C tests
fi fi
- name: 'build examples' - name: 'build examples'
if: ${{ matrix.build == 'cmake' }} # skip for autotools to save time if: ${{ matrix.build == 'cmake' }} # skip for autotools to save time
run: | run: |
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target curl-examples cmake --build bld --parallel 5 --target curl-examples
else else
make -C bld examples make -j5 -C bld examples
fi fi
msdos: msdos:
@ -620,7 +615,6 @@ jobs:
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
timeout-minutes: 5 timeout-minutes: 5
env: env:
MAKEFLAGS: -j 5
toolchain-version: '3.4' toolchain-version: '3.4'
strategy: strategy:
matrix: matrix:
@ -700,7 +694,7 @@ jobs:
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld cmake --build bld
else else
make -C bld make -j5 -C bld
fi fi
- name: 'curl info' - name: 'curl info'
@ -712,7 +706,7 @@ jobs:
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target testdeps cmake --build bld --target testdeps
else else
make -C bld -C tests make -j5 -C bld -C tests
fi fi
- name: 'build examples' - name: 'build examples'
@ -721,5 +715,5 @@ jobs:
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target curl-examples cmake --build bld --target curl-examples
else else
make -C bld examples make -j5 -C bld examples
fi fi

View File

@ -44,7 +44,6 @@ jobs:
run: run:
shell: C:\cygwin\bin\bash.exe '{0}' shell: C:\cygwin\bin\bash.exe '{0}'
env: env:
MAKEFLAGS: -j 5
SHELLOPTS: 'igncr' SHELLOPTS: 'igncr'
strategy: strategy:
matrix: matrix:
@ -84,13 +83,14 @@ jobs:
- name: 'configure' - name: 'configure'
timeout-minutes: 5 timeout-minutes: 5
run: | run: |
PATH=/usr/bin
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
PATH="/usr/bin:$(cygpath "${SYSTEMROOT}")/System32"
cmake -B bld -G Ninja -D_CURL_PREFILL=ON ${options} \ cmake -B bld -G Ninja -D_CURL_PREFILL=ON ${options} \
-DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_BATCH_SIZE=30 -DCURL_TEST_BUNDLES=ON \ -DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_BATCH_SIZE=30 -DCURL_TEST_BUNDLES=ON \
-DCURL_WERROR=ON \ -DCURL_WERROR=ON \
${{ matrix.config }} ${{ matrix.config }}
else else
PATH="/usr/bin:$(cygpath "${SYSTEMROOT}")/System32"
mkdir bld && cd bld && ../configure --enable-unity --enable-test-bundles --enable-warnings --enable-werror \ mkdir bld && cd bld && ../configure --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
--prefix="${HOME}"/install \ --prefix="${HOME}"/install \
--with-openssl \ --with-openssl \
@ -112,9 +112,9 @@ jobs:
timeout-minutes: 10 timeout-minutes: 10
run: | run: |
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld cmake --build bld --config '${{ matrix.type }}'
else else
make -C bld V=1 install make -C bld -j5 V=1 install
fi fi
- name: 'curl version' - name: 'curl version'
@ -131,9 +131,9 @@ jobs:
timeout-minutes: 15 timeout-minutes: 15
run: | run: |
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target testdeps cmake --build bld --config '${{ matrix.type }}' --target testdeps
else else
make -C bld V=1 -C tests make -C bld -j5 V=1 -C tests
fi fi
- name: 'run tests' - name: 'run tests'
@ -146,9 +146,9 @@ jobs:
fi fi
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
PATH="$PWD/bld/lib:$PATH" PATH="$PWD/bld/lib:$PATH"
cmake --build bld --target test-ci cmake --build bld --config '${{ matrix.type }}' --target test-ci
else else
make -C bld V=1 test-ci make -C bld -j5 V=1 test-ci
fi fi
- name: 'build examples' - name: 'build examples'
@ -156,9 +156,9 @@ jobs:
timeout-minutes: 5 timeout-minutes: 5
run: | run: |
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target curl-examples cmake --build bld --config '${{ matrix.type }}' --target curl-examples
else else
make -C bld V=1 examples make -C bld -j5 V=1 examples
fi fi
msys2: # both msys and mingw-w64 msys2: # both msys and mingw-w64
@ -168,8 +168,6 @@ jobs:
defaults: defaults:
run: run:
shell: msys2 {0} shell: msys2 {0}
env:
MAKEFLAGS: -j 5
strategy: strategy:
matrix: matrix:
include: include:
@ -207,7 +205,6 @@ jobs:
libnghttp2-devel libnghttp2-devel
libpsl-devel libpsl-devel
libssh2-devel libssh2-devel
${{ matrix.chkprefill == '_chkprefill' && 'diffutils' || '' }}
- uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # v2 - uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # v2
if: ${{ matrix.sys != 'msys' }} if: ${{ matrix.sys != 'msys' }}
@ -253,6 +250,8 @@ jobs:
fi fi
[ '${{ matrix.sys }}' = 'msys' ] && options+=' -D_CURL_PREFILL=ON' [ '${{ matrix.sys }}' = 'msys' ] && options+=' -D_CURL_PREFILL=ON'
[ '${{ matrix.test }}' = 'uwp' ] && options+=' -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0' [ '${{ matrix.test }}' = 'uwp' ] && options+=' -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0'
[ '${{ matrix.type }}' = 'Debug' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG='
[ '${{ matrix.type }}' = 'Release' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE='
[ "${_chkprefill}" = '_chkprefill' ] && options+=' -D_CURL_PREFILL=OFF' [ "${_chkprefill}" = '_chkprefill' ] && options+=' -D_CURL_PREFILL=OFF'
cmake -B "bld${_chkprefill}" -G Ninja ${options} \ cmake -B "bld${_chkprefill}" -G Ninja ${options} \
-DCMAKE_C_FLAGS="${{ matrix.cflags }} ${CFLAGS_CMAKE} ${CPPFLAGS}" \ -DCMAKE_C_FLAGS="${{ matrix.cflags }} ${CFLAGS_CMAKE} ${CPPFLAGS}" \
@ -287,9 +286,9 @@ jobs:
timeout-minutes: 10 timeout-minutes: 10
run: | run: |
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld cmake --build bld --config '${{ matrix.type }}'
else else
make -C bld V=1 install make -C bld -j5 V=1 install
fi fi
- name: 'curl version' - name: 'curl version'
@ -312,9 +311,9 @@ jobs:
timeout-minutes: 10 timeout-minutes: 10
run: | run: |
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target testdeps cmake --build bld --config '${{ matrix.type }}' --target testdeps
else else
make -C bld V=1 -C tests make -C bld -j5 V=1 -C tests
fi fi
if [ '${{ matrix.build }}' != 'cmake' ]; then if [ '${{ matrix.build }}' != 'cmake' ]; then
# avoid libtool's .exe wrappers # avoid libtool's .exe wrappers
@ -348,10 +347,10 @@ jobs:
PATH="$PATH:/c/Program Files (x86)/stunnel/bin" PATH="$PATH:/c/Program Files (x86)/stunnel/bin"
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
PATH="$PWD/bld/lib:$PATH" PATH="$PWD/bld/lib:$PATH"
cmake --build bld --target test-ci cmake --build bld --config '${{ matrix.type }}' --target test-ci
else else
PATH="$PWD/bld/lib/.libs:$PATH" PATH="$PWD/bld/lib/.libs:$PATH"
make -C bld V=1 test-ci make -C bld -j5 V=1 test-ci
fi fi
- name: 'build examples' - name: 'build examples'
@ -359,9 +358,9 @@ jobs:
timeout-minutes: 5 timeout-minutes: 5
run: | run: |
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target curl-examples cmake --build bld --config '${{ matrix.type }}' --target curl-examples
else else
make -C bld V=1 examples make -C bld -j5 V=1 examples
fi fi
mingw-w64-standalone-downloads: mingw-w64-standalone-downloads:
@ -371,8 +370,6 @@ jobs:
defaults: defaults:
run: run:
shell: C:\msys64\usr\bin\bash.exe {0} shell: C:\msys64\usr\bin\bash.exe {0}
env:
MAKEFLAGS: -j 5
strategy: strategy:
matrix: matrix:
include: include:
@ -429,21 +426,15 @@ jobs:
timeout-minutes: 5 timeout-minutes: 5
run: | run: |
PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH" PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH"
for _chkprefill in '' ${{ matrix.chkprefill }}; do [ '${{ matrix.type }}' = 'Debug' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG='
options='' [ '${{ matrix.type }}' = 'Release' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE='
[ "${_chkprefill}" = '_chkprefill' ] && options+=' -D_CURL_PREFILL=OFF' cmake -B bld -G 'MSYS Makefiles' ${options} \
cmake -B "bld${_chkprefill}" -G 'MSYS Makefiles' ${options} \
-DCMAKE_C_COMPILER=gcc \ -DCMAKE_C_COMPILER=gcc \
-DCMAKE_BUILD_TYPE='${{ matrix.type }}' \ -DCMAKE_BUILD_TYPE='${{ matrix.type }}' \
-DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_BATCH_SIZE=30 -DCURL_TEST_BUNDLES=ON \ -DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_BATCH_SIZE=30 -DCURL_TEST_BUNDLES=ON \
-DCURL_WERROR=ON \ -DCURL_WERROR=ON \
-DCURL_USE_LIBPSL=OFF \ -DCURL_USE_LIBPSL=OFF \
${{ matrix.config }} ${{ matrix.config }}
done
if [ -d bld_chkprefill ] && ! diff -u bld/lib/curl_config.h bld_chkprefill/lib/curl_config.h; then
echo '::group::reference configure log'; cat bld_chkprefill/CMakeFiles/CMake*.yaml 2>/dev/null || true; echo '::endgroup::'
false
fi
- name: 'configure log' - name: 'configure log'
if: ${{ !cancelled() }} if: ${{ !cancelled() }}
@ -458,7 +449,7 @@ jobs:
timeout-minutes: 5 timeout-minutes: 5
run: | run: |
PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH" PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH"
cmake --build bld cmake --build bld --config '${{ matrix.type }}' --parallel 5
- name: 'curl version' - name: 'curl version'
timeout-minutes: 1 timeout-minutes: 1
@ -472,7 +463,7 @@ jobs:
timeout-minutes: 10 timeout-minutes: 10
run: | run: |
PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH" PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH"
cmake --build bld --target testdeps cmake --build bld --config '${{ matrix.type }}' --parallel 5 --target testdeps
- name: 'install test prereqs' - name: 'install test prereqs'
if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }} if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
@ -501,29 +492,27 @@ jobs:
TFLAGS+=" -ac $(cygpath "${SYSTEMROOT}/System32/curl.exe")" TFLAGS+=" -ac $(cygpath "${SYSTEMROOT}/System32/curl.exe")"
fi fi
PATH="$PWD/bld/lib:$PATH:/c/Program Files (x86)/stunnel/bin" PATH="$PWD/bld/lib:$PATH:/c/Program Files (x86)/stunnel/bin"
cmake --build bld --target test-ci cmake --build bld --config '${{ matrix.type }}' --target test-ci
- name: 'build examples' - name: 'build examples'
timeout-minutes: 5 timeout-minutes: 5
run: | run: |
PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH" PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH"
cmake --build bld --target curl-examples cmake --build bld --config '${{ matrix.type }}' --parallel 5 --target curl-examples
linux-cross-mingw-w64: linux-cross-mingw-w64:
name: "linux-mingw, ${{ matrix.build == 'cmake' && 'CM' || 'AM' }} ${{ matrix.compiler }}" name: "linux-mingw, ${{ matrix.build == 'cmake' && 'CM' || 'AM' }} ${{ matrix.compiler }}"
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 15 timeout-minutes: 15
env:
MAKEFLAGS: -j 5
TRIPLET: 'x86_64-w64-mingw32'
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
build: [autotools, cmake] build: [autotools, cmake]
compiler: [gcc] compiler: [gcc]
env:
TRIPLET: 'x86_64-w64-mingw32'
steps: steps:
- name: 'install packages' - name: 'install packages'
timeout-minutes: 5
run: sudo apt-get -o Dpkg::Use-Pty=0 install mingw-w64 ${{ matrix.build == 'cmake' && 'ninja-build' || '' }} run: sudo apt-get -o Dpkg::Use-Pty=0 install mingw-w64 ${{ matrix.build == 'cmake' && 'ninja-build' || '' }}
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
@ -567,7 +556,7 @@ jobs:
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld cmake --build bld
else else
make -C bld make -C bld -j5
fi fi
- name: 'curl info' - name: 'curl info'
@ -579,7 +568,7 @@ jobs:
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target testdeps cmake --build bld --target testdeps
else else
make -C bld -C tests make -C bld -j5 -C tests
fi fi
- name: 'build examples' - name: 'build examples'
@ -587,7 +576,7 @@ jobs:
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target curl-examples cmake --build bld --target curl-examples
else else
make -C bld examples make -C bld -j5 examples
fi fi
wince: wince:
@ -595,7 +584,6 @@ jobs:
runs-on: 'macos-latest' runs-on: 'macos-latest'
timeout-minutes: 10 timeout-minutes: 10
env: env:
MAKEFLAGS: -j 4
toolchain-version: '0.59.1' toolchain-version: '0.59.1'
strategy: strategy:
matrix: matrix:
@ -604,7 +592,6 @@ jobs:
steps: steps:
- name: 'install packages' - name: 'install packages'
if: ${{ matrix.build == 'autotools' }} if: ${{ matrix.build == 'autotools' }}
timeout-minutes: 5
run: | run: |
echo automake libtool | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile echo automake libtool | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done
@ -618,7 +605,6 @@ jobs:
- name: 'install compiler (mingw32ce)' - name: 'install compiler (mingw32ce)'
if: ${{ steps.cache-compiler.outputs.cache-hit != 'true' }} if: ${{ steps.cache-compiler.outputs.cache-hit != 'true' }}
timeout-minutes: 5
run: | run: |
cd "${HOME}" || exit 1 cd "${HOME}" || exit 1
curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 3 --retry-connrefused --proto-redir =https \ curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 3 --retry-connrefused --proto-redir =https \
@ -629,19 +615,18 @@ jobs:
- name: 'configure' - name: 'configure'
run: | run: |
PATH="$HOME/opt/mingw32ce/bin:$PATH" MINGW32CE_ROOT="${HOME}/opt/mingw32ce"
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake -B bld \ cmake -B bld \
-DCMAKE_SYSTEM_NAME=WindowsCE \ -DCMAKE_SYSTEM_NAME=WindowsCE \
-DCMAKE_SYSTEM_VERSION=8.0 \ -DCMAKE_SYSTEM_VERSION=8.0 \
-DCMAKE_SYSTEM_PROCESSOR=arm \ -DCMAKE_SYSTEM_PROCESSOR=arm \
-DCMAKE_C_FLAGS='-O3 -DNDEBUG' \ -DCMAKE_C_COMPILER_TARGET=arm-wince-mingw32ce \
-DCMAKE_C_COMPILER_TARGET=arm-mingw32ce \ -DCMAKE_C_COMPILER="${MINGW32CE_ROOT}/bin/arm-mingw32ce-gcc" \
-DCMAKE_C_COMPILER=arm-mingw32ce-gcc \ -DCMAKE_RC_COMPILER="${MINGW32CE_ROOT}/bin/arm-mingw32ce-windres" \
-DCMAKE_RC_COMPILER=arm-mingw32ce-windres \ -DMINGW32CE_LIBRARY_DIR="${MINGW32CE_ROOT}/arm-mingw32ce/lib" \
-DMINGW32CE_LIBRARY_DIR="$HOME/opt/mingw32ce/arm-mingw32ce/lib" \
-DCMAKE_IGNORE_PREFIX_PATH="$(brew --prefix)" \ -DCMAKE_IGNORE_PREFIX_PATH="$(brew --prefix)" \
-DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_BATCH_SIZE=50 -DCURL_TEST_BUNDLES=ON \ -DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
-DBUILD_SHARED_LIBS=ON -DBUILD_STATIC_LIBS=ON -DBUILD_STATIC_CURL=OFF \ -DBUILD_SHARED_LIBS=ON -DBUILD_STATIC_LIBS=ON -DBUILD_STATIC_CURL=OFF \
-DCURL_WERROR=ON \ -DCURL_WERROR=ON \
-DCURL_USE_SCHANNEL=ON \ -DCURL_USE_SCHANNEL=ON \
@ -649,7 +634,12 @@ jobs:
else else
autoreconf -fi autoreconf -fi
mkdir bld && cd bld && ../configure --disable-dependency-tracking --enable-unity --enable-test-bundles --enable-warnings --enable-werror \ mkdir bld && cd bld && ../configure --disable-dependency-tracking --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
--host=arm-mingw32ce \ ac_cv_prog_cc_c99=no \
CC="${MINGW32CE_ROOT}/bin/arm-mingw32ce-gcc" \
AR="${MINGW32CE_ROOT}/bin/arm-mingw32ce-ar" \
RANLIB="${MINGW32CE_ROOT}/bin/arm-mingw32ce-ranlib" \
RC="${MINGW32CE_ROOT}/bin/arm-mingw32ce-windres" \
--host=arm-wince-mingw32ce \
--with-schannel \ --with-schannel \
--without-libpsl \ --without-libpsl \
--disable-shared --disable-shared
@ -666,11 +656,10 @@ jobs:
- name: 'build' - name: 'build'
run: | run: |
PATH="$HOME/opt/mingw32ce/bin:$PATH"
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld cmake --build bld
else else
make -C bld make -j5 -C bld
fi fi
- name: 'curl info' - name: 'curl info'
@ -680,21 +669,19 @@ jobs:
- name: 'build tests' - name: 'build tests'
if: ${{ matrix.build == 'cmake' }} # skip for autotools to save time if: ${{ matrix.build == 'cmake' }} # skip for autotools to save time
run: | run: |
PATH="$HOME/opt/mingw32ce/bin:$PATH"
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target testdeps cmake --build bld --target testdeps
else else
make -C bld -C tests make -j5 -C bld -C tests
fi fi
- name: 'build examples' - name: 'build examples'
if: ${{ matrix.build == 'cmake' }} # skip for autotools to save time if: ${{ matrix.build == 'cmake' }} # skip for autotools to save time
run: | run: |
PATH="$HOME/opt/mingw32ce/bin:$PATH"
if [ '${{ matrix.build }}' = 'cmake' ]; then if [ '${{ matrix.build }}' = 'cmake' ]; then
cmake --build bld --target curl-examples cmake --build bld --target curl-examples
else else
make -C bld examples make -j5 -C bld examples
fi fi
msvc: msvc:
@ -710,16 +697,16 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- name: 'openssl' - name: 'schannel MultiSSL U'
install: 'brotli zlib zstd nghttp2 nghttp3 openssl libssh2' install: 'brotli zlib zstd libpsl nghttp2 libssh2[core,zlib] pkgconf gsasl openssl mbedtls wolfssl'
arch: 'x64' arch: 'x64'
plat: 'uwp' plat: 'windows'
type: 'Debug' type: 'Debug'
tflags: 'skiprun' tflags: '~1516 ~2301 ~2302 ~2303 ~2307 ~2310'
config: >- config: >-
-DCURL_USE_LIBSSH2=ON -DCURL_USE_LIBSSH2=ON
-DCURL_USE_SCHANNEL=OFF -DCURL_USE_OPENSSL=ON -DUSE_OPENSSL_QUIC=ON -DCURL_USE_SCHANNEL=ON -DCURL_USE_OPENSSL=ON -DCURL_USE_MBEDTLS=ON -DCURL_USE_WOLFSSL=ON -DCURL_DEFAULT_SSL_BACKEND=schannel
-DCURL_USE_LIBPSL=OFF -DCURL_USE_GSASL=ON -DUSE_WIN32_IDN=ON -DENABLE_UNICODE=ON -DUSE_SSLS_EXPORT=ON
- name: 'openssl' - name: 'openssl'
install: 'brotli zlib zstd libpsl nghttp2 nghttp3 openssl libssh2 pkgconf gsasl c-ares libuv krb5' install: 'brotli zlib zstd libpsl nghttp2 nghttp3 openssl libssh2 pkgconf gsasl c-ares libuv krb5'
@ -732,16 +719,16 @@ jobs:
-DCURL_USE_SCHANNEL=OFF -DCURL_USE_OPENSSL=ON -DUSE_OPENSSL_QUIC=ON -DCURL_USE_SCHANNEL=OFF -DCURL_USE_OPENSSL=ON -DUSE_OPENSSL_QUIC=ON
-DCURL_USE_GSASL=ON -DENABLE_ARES=ON -DCURL_USE_LIBUV=ON -DCURL_USE_GSSAPI=ON -DCURL_USE_GSASL=ON -DENABLE_ARES=ON -DCURL_USE_LIBUV=ON -DCURL_USE_GSSAPI=ON
- name: 'schannel MultiSSL U' - name: 'openssl'
install: 'brotli zlib zstd libpsl nghttp2 libssh2[core,zlib] pkgconf gsasl openssl mbedtls wolfssl' install: 'brotli zlib zstd nghttp2 nghttp3 openssl libssh2'
arch: 'x64' arch: 'x64'
plat: 'windows' plat: 'uwp'
type: 'Debug' type: 'Debug'
tflags: '~1516 ~2301 ~2302 ~2303 ~2307 ~2310' tflags: 'skiprun'
config: >- config: >-
-DCURL_USE_LIBSSH2=ON -DCURL_USE_LIBSSH2=ON
-DCURL_USE_SCHANNEL=ON -DCURL_USE_OPENSSL=ON -DCURL_USE_MBEDTLS=ON -DCURL_USE_WOLFSSL=ON -DCURL_DEFAULT_SSL_BACKEND=schannel -DCURL_USE_SCHANNEL=OFF -DCURL_USE_OPENSSL=ON -DUSE_OPENSSL_QUIC=ON
-DCURL_USE_GSASL=ON -DUSE_WIN32_IDN=ON -DENABLE_UNICODE=ON -DUSE_SSLS_EXPORT=ON -DCURL_USE_LIBPSL=OFF
- name: 'libressl' - name: 'libressl'
install: 'brotli zlib zstd libpsl nghttp2 libressl libssh2[core,zlib] pkgconf ngtcp2[libressl] nghttp3' install: 'brotli zlib zstd libpsl nghttp2 libressl libssh2[core,zlib] pkgconf ngtcp2[libressl] nghttp3'
@ -840,6 +827,8 @@ jobs:
-DCMAKE_EXE_LINKER_FLAGS="-INCREMENTAL:NO ${ldflags}" \ -DCMAKE_EXE_LINKER_FLAGS="-INCREMENTAL:NO ${ldflags}" \
-DCMAKE_SHARED_LINKER_FLAGS="-INCREMENTAL:NO ${ldflags}" \ -DCMAKE_SHARED_LINKER_FLAGS="-INCREMENTAL:NO ${ldflags}" \
-DCMAKE_VS_GLOBALS="TrackFileAccess=false${vsglobals}" \ -DCMAKE_VS_GLOBALS="TrackFileAccess=false${vsglobals}" \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG= \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE= \
-DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \ -DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
-DCURL_WERROR=ON \ -DCURL_WERROR=ON \
-DBUILD_SHARED_LIBS=OFF \ -DBUILD_SHARED_LIBS=OFF \
@ -869,10 +858,10 @@ jobs:
- name: 'curl version' - name: 'curl version'
timeout-minutes: 1 timeout-minutes: 1
run: | run: |
PATH=/usr/bin find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' -o -name '*.pdb' \) -exec file '{}' \; PATH=/usr/bin find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' \) -exec file '{}' \;
if [ '${{ matrix.plat }}' != 'uwp' ]; then # Missing: ucrtbased.dll, VCRUNTIME140D.dll, VCRUNTIME140D_APP.dll if [ '${{ matrix.plat }}' != 'uwp' ]; then # Missing: ucrtbased.dll, VCRUNTIME140D.dll, VCRUNTIME140D_APP.dll
PATH="$PWD/bld/lib/${{ matrix.type }}:$PATH" PATH="$PWD/bld/lib:$PATH"
'bld/src/${{ matrix.type }}/curl.exe' --disable --version bld/src/curl.exe --disable --version
fi fi
- name: 'build tests' - name: 'build tests'
@ -907,14 +896,13 @@ jobs:
if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }} if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
timeout-minutes: 10 timeout-minutes: 10
run: | run: |
export CURL_DIRSUFFIX='${{ matrix.type }}'
export TFLAGS='-j8 ~WebSockets ~SCP ~612 ${{ matrix.tflags }}' export TFLAGS='-j8 ~WebSockets ~SCP ~612 ${{ matrix.tflags }}'
if [[ '${{ matrix.install }}' = *'libssh2[core,zlib]'* ]]; then if [[ '${{ matrix.install }}' = *'libssh2[core,zlib]'* ]]; then
TFLAGS+=' ~SFTP' TFLAGS+=' ~SFTP'
elif [[ '${{ matrix.install }}' = *'libssh '* ]]; then elif [[ '${{ matrix.install }}' = *'libssh '* ]]; then
TFLAGS+=' ~614' # 'SFTP pre-quote chmod' SFTP, pre-quote, directory TFLAGS+=' ~614' # 'SFTP pre-quote chmod' SFTP, pre-quote, directory
fi fi
PATH="$PWD/bld/lib/${{ matrix.type }}:$PATH:/c/Program Files (x86)/stunnel/bin:/c/Program Files/OpenSSH-Win64" PATH="$PWD/bld/lib:$PATH:/c/Program Files (x86)/stunnel/bin:/c/Program Files/OpenSSH-Win64"
PATH="/c/msys64/usr/bin:$PATH" PATH="/c/msys64/usr/bin:$PATH"
cmake --build bld --config '${{ matrix.type }}' --target test-ci cmake --build bld --config '${{ matrix.type }}' --target test-ci

View File

@ -87,10 +87,3 @@ macro(curl_required_libpaths _libpaths_arg)
list(APPEND CMAKE_REQUIRED_LINK_DIRECTORIES "${_libpaths_arg}") list(APPEND CMAKE_REQUIRED_LINK_DIRECTORIES "${_libpaths_arg}")
endif() endif()
endmacro() endmacro()
# Pre-fill variables set by a check_type_size() call.
macro(curl_prefill_type_size _type _size)
set(HAVE_SIZEOF_${_type} TRUE)
set(SIZEOF_${_type} ${_size})
set(SIZEOF_${_type}_CODE "#define SIZEOF_${_type} ${_size}")
endmacro()

View File

@ -182,7 +182,6 @@ if(PICKY_COMPILER)
-Wold-style-declaration # gcc 4.3 -Wold-style-declaration # gcc 4.3
-Wpragmas # clang 3.5 gcc 4.1 appleclang 6.0 -Wpragmas # clang 3.5 gcc 4.1 appleclang 6.0
-Wstrict-aliasing=3 # gcc 4.0 -Wstrict-aliasing=3 # gcc 4.0
-ftree-vrp # gcc 4.3 (required for -Warray-bounds, included in -Wall)
) )
endif() endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5) if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5)
@ -205,7 +204,7 @@ if(PICKY_COMPILER)
endif() endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0) if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0)
list(APPEND _picky_enable list(APPEND _picky_enable
-Warray-bounds=2 # clang 3.0 gcc 5.0 (clang default: -Warray-bounds) -Warray-bounds=2 -ftree-vrp # clang 3.0 gcc 5.0 (clang default: -Warray-bounds)
) )
endif() endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.0) if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.0)

View File

@ -44,6 +44,10 @@ if(MINGW)
set(HAVE_UTIME_H 1) # wrapper to sys/utime.h set(HAVE_UTIME_H 1) # wrapper to sys/utime.h
set(HAVE_DIRENT_H 1) set(HAVE_DIRENT_H 1)
set(HAVE_OPENDIR 1) set(HAVE_OPENDIR 1)
if(MINGW32CE)
set(HAVE_STRTOK_R 0)
set(HAVE_FILE_OFFSET_BITS 0)
endif()
else() else()
set(HAVE_LIBGEN_H 0) set(HAVE_LIBGEN_H 0)
set(HAVE_FTRUNCATE 0) set(HAVE_FTRUNCATE 0)
@ -74,6 +78,7 @@ else()
set(HAVE_SNPRINTF 0) set(HAVE_SNPRINTF 0)
endif() endif()
set(HAVE_BASENAME 0) set(HAVE_BASENAME 0)
set(HAVE_FILE_OFFSET_BITS 0)
endif() endif()
endif() endif()
@ -191,37 +196,6 @@ set(STDC_HEADERS 1)
set(HAVE_SIZEOF_SUSECONDS_T 0) set(HAVE_SIZEOF_SUSECONDS_T 0)
set(HAVE_SIZEOF_SA_FAMILY_T 0) set(HAVE_SIZEOF_SA_FAMILY_T 0)
if(MINGW OR MSVC)
curl_prefill_type_size("INT" 4)
curl_prefill_type_size("LONG" 4)
curl_prefill_type_size("LONG_LONG" 8)
curl_prefill_type_size("__INT64" 8)
curl_prefill_type_size("CURL_OFF_T" 8)
# CURL_SOCKET_T, SIZE_T: 8 for _WIN64, 4 otherwise
# TIME_T: 8 for _WIN64 or UCRT or MSVC and not Windows CE, 4 otherwise
# Also 4 for non-UCRT 32-bit when _USE_32BIT_TIME_T is set.
# mingw-w64 sets _USE_32BIT_TIME_T unless __MINGW_USE_VC2005_COMPAT is explicit defined.
if(MSVC)
set(HAVE_SIZEOF_SSIZE_T 0)
set(HAVE_FILE_OFFSET_BITS 0)
curl_prefill_type_size("OFF_T" 4)
curl_prefill_type_size("ADDRESS_FAMILY" 2)
else()
# SSIZE_T: 8 for _WIN64, 4 otherwise
if(MINGW64_VERSION)
if(NOT MINGW64_VERSION VERSION_LESS 3.0)
set(HAVE_FILE_OFFSET_BITS 1)
curl_prefill_type_size("OFF_T" 8)
endif()
if(NOT MINGW64_VERSION VERSION_LESS 2.0)
curl_prefill_type_size("ADDRESS_FAMILY" 2)
else()
set(HAVE_SIZEOF_ADDRESS_FAMILY 0)
endif()
endif()
endif()
endif()
if(WINCE) # Windows CE exceptions if(WINCE) # Windows CE exceptions
set(HAVE_LOCALE_H 0) set(HAVE_LOCALE_H 0)
set(HAVE_GETADDRINFO 0) set(HAVE_GETADDRINFO 0)
@ -230,15 +204,7 @@ if(WINCE) # Windows CE exceptions
set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 0) set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 0)
set(HAVE_SIGNAL 0) set(HAVE_SIGNAL 0)
set(HAVE_SETMODE 0) set(HAVE_SETMODE 0)
curl_prefill_type_size("CURL_SOCKET_T" 4)
curl_prefill_type_size("TIME_T" 4)
curl_prefill_type_size("SIZE_T" 4)
if(MINGW32CE) if(MINGW32CE)
set(HAVE_STRTOK_R 0)
set(HAVE__SETMODE 0) set(HAVE__SETMODE 0)
set(HAVE_FILE_OFFSET_BITS 0)
set(HAVE_SIZEOF_ADDRESS_FAMILY 0)
curl_prefill_type_size("SSIZE_T" 4)
curl_prefill_type_size("OFF_T" 4)
endif() endif()
endif() endif()

View File

@ -217,6 +217,13 @@ option(ENABLE_ARES "Enable c-ares support" OFF)
option(CURL_DISABLE_INSTALL "Disable installation targets" OFF) option(CURL_DISABLE_INSTALL "Disable installation targets" OFF)
if(WIN32) if(WIN32)
option(CURL_STATIC_CRT "Build libcurl with static CRT with MSVC (/MT)" OFF)
if(CURL_STATIC_CRT AND MSVC)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
string(APPEND CMAKE_C_FLAGS_RELEASE " -MT")
string(APPEND CMAKE_C_FLAGS_DEBUG " -MTd")
endif()
option(ENABLE_UNICODE "Use the Unicode version of the Windows API functions" OFF) option(ENABLE_UNICODE "Use the Unicode version of the Windows API functions" OFF)
if(WINDOWS_STORE OR WINCE) if(WINDOWS_STORE OR WINCE)
set(ENABLE_UNICODE ON) set(ENABLE_UNICODE ON)
@ -257,10 +264,8 @@ if(WIN32)
if(MINGW64_VERSION) if(MINGW64_VERSION)
string(REGEX MATCH "MINGW64_VERSION=[0-9]+\.[0-9]+" CURL_TEST_OUTPUT "${CURL_TEST_OUTPUT}") string(REGEX MATCH "MINGW64_VERSION=[0-9]+\.[0-9]+" CURL_TEST_OUTPUT "${CURL_TEST_OUTPUT}")
string(REGEX REPLACE "MINGW64_VERSION=" "" MINGW64_VERSION "${CURL_TEST_OUTPUT}") string(REGEX REPLACE "MINGW64_VERSION=" "" MINGW64_VERSION "${CURL_TEST_OUTPUT}")
if(MINGW64_VERSION)
message(STATUS "Found MINGW64_VERSION=${MINGW64_VERSION}") message(STATUS "Found MINGW64_VERSION=${MINGW64_VERSION}")
endif() endif()
endif()
unset(MINGW64_VERSION CACHE) # Avoid storing in CMake cache unset(MINGW64_VERSION CACHE) # Avoid storing in CMake cache
endif() endif()
elseif(DOS OR AMIGA) elseif(DOS OR AMIGA)
@ -349,19 +354,6 @@ else()
set(LIB_SELECTED ${LIB_STATIC}) set(LIB_SELECTED ${LIB_STATIC})
endif() endif()
if(WIN32)
option(CURL_STATIC_CRT "Build libcurl with static CRT with MSVC (/MT)" OFF)
if(CURL_STATIC_CRT AND MSVC)
if(BUILD_STATIC_CURL OR NOT BUILD_CURL_EXE)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
string(APPEND CMAKE_C_FLAGS_RELEASE " -MT")
string(APPEND CMAKE_C_FLAGS_DEBUG " -MTd")
else()
message(WARNING "Static CRT requires static or no curl executable.")
endif()
endif()
endif()
# Override to force-disable or force-enable the use of pkg-config. # Override to force-disable or force-enable the use of pkg-config.
if((UNIX AND NOT ANDROID AND (NOT APPLE OR CMAKE_SYSTEM_NAME MATCHES "Darwin")) OR if((UNIX AND NOT ANDROID AND (NOT APPLE OR CMAKE_SYSTEM_NAME MATCHES "Darwin")) OR
VCPKG_TOOLCHAIN OR VCPKG_TOOLCHAIN OR
@ -827,6 +819,9 @@ if(CURL_USE_OPENSSL)
set(_openssl "AmiSSL") set(_openssl "AmiSSL")
else() else()
set(_openssl "OpenSSL") set(_openssl "OpenSSL")
if(OPENSSL_VERSION VERSION_LESS 1.1.1)
message(WARNING "OpenSSL ${OPENSSL_VERSION} does not support TLS 1.3.")
endif()
endif() endif()
endif() endif()
@ -1953,6 +1948,22 @@ endif()
# Some other minor tests # Some other minor tests
if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
include(CheckCCompilerFlag)
check_c_compiler_flag("-Wno-long-double" HAVE_C_FLAG_Wno_long_double)
if(HAVE_C_FLAG_Wno_long_double)
# The Mac version of GCC warns about use of long double. Disable it.
get_source_file_property(_mprintf_compile_flags "mprintf.c" COMPILE_FLAGS)
if(_mprintf_compile_flags)
string(APPEND _mprintf_compile_flags " -Wno-long-double")
else()
set(_mprintf_compile_flags "-Wno-long-double")
endif()
set_source_files_properties("mprintf.c" PROPERTIES
COMPILE_FLAGS ${_mprintf_compile_flags})
endif()
endif()
if(_cmake_try_compile_target_type_save) if(_cmake_try_compile_target_type_save)
set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_cmake_try_compile_target_type_save}) set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_cmake_try_compile_target_type_save})
unset(_cmake_try_compile_target_type_save) unset(_cmake_try_compile_target_type_save)
@ -1972,6 +1983,9 @@ if(WIN32)
set(USE_WIN32_LARGE_FILES ON) set(USE_WIN32_LARGE_FILES ON)
endif() endif()
# Use the manifest embedded in the Windows Resource
string(APPEND CMAKE_RC_FLAGS " -DCURL_EMBED_MANIFEST")
# We use crypto functions that are not available for UWP apps # We use crypto functions that are not available for UWP apps
if(NOT WINDOWS_STORE) if(NOT WINDOWS_STORE)
set(USE_WIN32_CRYPTO ON) set(USE_WIN32_CRYPTO ON)
@ -1987,6 +2001,9 @@ if(WIN32)
endif() endif()
if(MSVC) if(MSVC)
# Disable default manifest added by CMake
string(APPEND CMAKE_EXE_LINKER_FLAGS " -MANIFEST:NO")
string(APPEND CMAKE_C_FLAGS " -MP") # Parallel compilation string(APPEND CMAKE_C_FLAGS " -MP") # Parallel compilation
endif() endif()

View File

@ -4,15 +4,10 @@ curl and libcurl 8.13.0
Command line options: 267 Command line options: 267
curl_easy_setopt() options: 306 curl_easy_setopt() options: 306
Public functions in libcurl: 96 Public functions in libcurl: 96
Contributors: 3354 Contributors: 3349
This release includes the following changes: This release includes the following changes:
o curl: add write-out variable 'tls_earlydata' [79]
o rustls: add support for CERTINFO [106]
o tool_getparam: make --url support a file with URLs [104]
o var: add a '64dec' function that can base64 decode a string [78]
o wolfssl: tls early data support [50]
This release includes the following bugfixes: This release includes the following bugfixes:
@ -21,111 +16,67 @@ This release includes the following bugfixes:
o asyn-thread: avoid the separate curl_mutex_t alloc [6] o asyn-thread: avoid the separate curl_mutex_t alloc [6]
o asyn-thread: do not allocate thread_data separately [21] o asyn-thread: do not allocate thread_data separately [21]
o asyn-thread: remove 'status' from struct Curl_async [36] o asyn-thread: remove 'status' from struct Curl_async [36]
o build: add Windows CE / CeGCC support, with CI jobs [87]
o build: drop unused `getpart` tool [107]
o build: enable -Wjump-misses-init for GCC 4.5+ [62] o build: enable -Wjump-misses-init for GCC 4.5+ [62]
o build: fix compiler warnings in feature detections [39] o build: fix compiler warnings in feature detections [39]
o build: set `HAVE_WRITABLE_ARGV` for Apple cross-builds [8] o build: set `HAVE_WRITABLE_ARGV` for Apple cross-builds [8]
o build: silence bogus `-Wconversion` warnings with gcc 5.1-5.4 [68] o build: silence bogus `-Wconversion` warnings with gcc 5.1-5.4 [68]
o c-ares: error out for unsupported versions, drop unused macros [85]
o ca-native.md: sync with CURLSSLOPT_NATIVE_CA [72] o ca-native.md: sync with CURLSSLOPT_NATIVE_CA [72]
o cf-socket: deduplicate Windows Vista detection [11] o cf-socket: deduplicate Windows Vista detection [11]
o client writer: handle pause before deocding [61] o client writer: handle pause before deocding [61]
o cmake: `SHARE_LIB_OBJECT=ON` requires CMake 3.12 or newer [46] o cmake: `SHARE_LIB_OBJECT=ON` requires CMake 3.12 or newer [46]
o cmake: add pre-fill for Unix, enable in GHA/macos, verify pre-fills [42] o cmake: add pre-fill for Unix, enable in GHA/macos, verify pre-fills [42]
o cmake: allow empty `IMPORT_LIB_SUFFIX`, add suffix collision detection [41] o cmake: allow empty custom `IMPORT_LIB_SUFFIX`, add suffix collision detection [41]
o cmake: avoid `-Wnonnull` warning in `HAVE_FSETXATTR_5` detection [81]
o cmake: disable HTTPS-proxy as a feature if proxy is disabled [77]
o cmake: drop `CURL_DISABLE_TESTS` option [94]
o cmake: drop `HAVE_IN_ADDR_T` from pre-fill too o cmake: drop `HAVE_IN_ADDR_T` from pre-fill too
o cmake: drop two stray TLS feature checks for wolfSSL [9] o cmake: drop two stray TLS feature checks for wolfSSL [9]
o cmake: fix `HAVE_ATOMIC`/`HAVE_STDATOMIC` pre-fill for clang-cl [28] o cmake: fix `HAVE_ATOMIC`/`HAVE_STDATOMIC` pre-fill for clang-cl [28]
o cmake: fix ECH detection in custom-patched OpenSSL [32] o cmake: fix ECH detection in custom-patched OpenSSL [32]
o cmake: hide empty `MINGW64_VERSION` output for mingw32ce [114]
o cmake: mention 'insecure' in the debug build warning [15] o cmake: mention 'insecure' in the debug build warning [15]
o cmake: misc tidy-ups [38] o cmake: misc tidy-ups [38]
o cmake: pre-fill known type sizes for Windows OSes [100]
o cmake: restrict static CRT builds to static curl exe, test in CI [113]
o cmake: sync cutoff version with autotools for picky option `-ftree-vrp` [99]
o cmake: sync OpenSSL(-fork) feature checks with `./configure` [49] o cmake: sync OpenSSL(-fork) feature checks with `./configure` [49]
o CODE_STYLE: readability and banned functions [35] o CODE_STYLE: readability and banned functions [35]
o configure: silence compiler warnings in feature checks, drop duplicates [86]
o configure: use `curl_cv_apple` variable [40] o configure: use `curl_cv_apple` variable [40]
o conn: fix connection reuse when SSL is optional [54] o conn: fix connection reuse when SSL is optional [54]
o contributors.sh: lowercase 'github' for consistency [52]
o contrithanks.sh: update docs/THANKS in place [119]
o cookie: do prefix matching case-sensitively [82]
o cookie: minor parser simplification [58] o cookie: minor parser simplification [58]
o cookie: simplify invalid_octets() [24] o cookie: simplify invalid_octets() [24]
o curl.h: change some enums to defines with L suffix [84]
o curl_msh3: remove verify bypass from DEBUGBUILDs [43] o curl_msh3: remove verify bypass from DEBUGBUILDs [43]
o curl_trc: fix build with CURL_DISABLE_VERBOSE_STRINGS [109]
o CURLMOPT_SOCKETFUNCTION.md: add advice for socket callback invocation[69]
o CURLOPT_HTTPHEADER.md: add comments to the example [90]
o CURLOPT_HTTPHEADER.md: rephrases [108]
o docs: add FD_ZERO to curl_multi_fdset example [19] o docs: add FD_ZERO to curl_multi_fdset example [19]
o docs: bump `rustls` to 0.14.1 [111]
o docs: correct argument names & URL redirection [4] o docs: correct argument names & URL redirection [4]
o eventfd: allow use on all CPUs [93]
o gnutls: fix connection state check on handshake [80]
o hash: use single linked list for entries [57] o hash: use single linked list for entries [57]
o hostip: make CURLOPT_RESOLVE support replacing IPv6 addresses [47] o hostip: make CURLOPT_RESOLVE support replacing IPv6 addresses [47]
o HTTP3.md: only speak about minimal versions [18] o HTTP3.md: only speak about minimal versions [18]
o http: convert parsers to strparse [48]
o http: fix NTLM info message typo [22] o http: fix NTLM info message typo [22]
o http: fix the auth check [88]
o http: make the RTSP version check stricter [73]
o http: negotiation and room for alt-svc/https rr to navigate [64] o http: negotiation and room for alt-svc/https rr to navigate [64]
o http: version negotiation [45] o http: version negotiation [45]
o http_aws_sigv4: use strparse more for parsing [55] o http_aws_sigv4: use strparse more for parsing [55]
o https-rr: implementation improvements [44] o https-rr: implementation improvements [44]
o httpsrr: fix port detection [51] o httpsrr: fix port detection [51]
o httpsrr: fix the HTTPS-RR threaded-resolver build combo [67] o httpsrr: fix the HTTPS-RR threaded-resolver build combo [67]
o INSTALL-CMAKE.md: CMake usage updates [101]
o INSTALL-CMAKE.md: mention `ZLIB_USE_STATIC_LIBS` [112]
o lib: better optimized casecompare() and ncasecompare() [3] o lib: better optimized casecompare() and ncasecompare() [3]
o lib: simplify more white space loops [60] o lib: simplify more white space loops [60]
o lib: strtoofft.h header cleanup [17] o lib: strtoofft.h header cleanup [17]
o lib: use Curl_str_* instead of strtok_r() [59] o lib: use Curl_str_* instead of strtok_r() [59]
o lib: use Curl_str_number() for parsing decimal numbers [13] o lib: use Curl_str_number() for parsing decimal numbers [13]
o libtest/libprereq.c: set CURLOPT_FOLLOWLOCATION with a long [89]
o managen: correct the warning for un-escaped '<' and '>' [1] o managen: correct the warning for un-escaped '<' and '>' [1]
o msvc: drop support for VS2005 and older [96]
o multi: event based rework [74]
o openssl: check return value of X509_get0_pubkey [105]
o openssl: drop support for old OpenSSL/LibreSSL versions [95]
o openssl: remove bad `goto`s into other scope [63] o openssl: remove bad `goto`s into other scope [63]
o runtests: drop recognizing 'winssl' as Schannel [102]
o runtests: drop ref to unused external function
o runtests: recognize AWS-LC as OpenSSL [103]
o runtests: support multi-target cmake, drop workarounds from CI [116]
o schannel: deduplicate Windows Vista detection [98]
o schannel: enable ALPN support under WINE 6.0+ [92]
o schannel: enable ALPN with MinGW, fix ALPN for UWP builds [71] o schannel: enable ALPN with MinGW, fix ALPN for UWP builds [71]
o schannel: guard ALPN init code to ALPN builds [91]
o scripts/managen: fix option 'single' [31] o scripts/managen: fix option 'single' [31]
o scripts/managen: fix parsing of markdown code sections [30] o scripts/managen: fix parsing of markdown code sections [30]
o setopt: remove unnecesary void pointer typecasts [76]
o ssh: consider sftp quote commands case sensitive [33] o ssh: consider sftp quote commands case sensitive [33]
o ssl session cache: add exportable flag [56] o ssl session cache: add exportable flag [56]
o strparse: make Curl_str_number() return error for no digits [14] o strparse: make Curl_str_number() return error for no digits [14]
o strparse: switch the API to work on 'const char *' [2] o strparse: switch the API to work on 'const char *' [2]
o strparse: switch to curl_off_t as base data type [7] o strparse: switch to curl_off_t as base data type [7]
o tests: fix enum/int confusion, fix autotools `CFLAGS` for `servers` [27] o tests: fix enum/int confusion (Intel C), fix autotools `CFLAGS` for `servers` [27]
o tidy-up: align MSYS2/Cygwin codepaths, follow Cygwin `MAX_PID` bump [97]
o tidy-up: delete, comment or scope C macros reported unused [16] o tidy-up: delete, comment or scope C macros reported unused [16]
o tidy-up: drop unused `CURL_INADDR_NONE` macro and `in_addr_t` type [26] o tidy-up: drop unused `CURL_INADDR_NONE` macro and `in_addr_t` type [26]
o tidy-up: use `CURL_ARRAYSIZE()` [37] o tidy-up: use `CURL_ARRAYSIZE()` [37]
o timediff: fix comment for curlx_mstotv() [25] o timediff: fix comment for curlx_mstotv() [25]
o timediff: remove unnecessary double typecast [53] o timediff: remove unnecessary double typecast [53]
o tool_getparam: clear sensitive arguments better [66] o tool_getparam: clear sensitive arguments better [66]
o tool_operate: fail SSH transfers without server auth [70]
o urlapi: simplify junkscan [23] o urlapi: simplify junkscan [23]
o variable.md: clarify 'trim' example [12] o variable.md: clarify 'trim' example [12]
o windows: drop code and curl manifest targeting W2K and older [115]
o wolfssh: retrieve the error using wolfSSH_get_error [5] o wolfssh: retrieve the error using wolfSSH_get_error [5]
o wolfssl: fix CA certificate multiple location import [34] o wolfssl: fix CA certificate multiple location import [34]
o wolfssl: warn if CA native import option is ignored [65]
o wolfssl: when using PQ KEM, use ML-KEM, not Kyber [10] o wolfssl: when using PQ KEM, use ML-KEM, not Kyber [10]
This release includes the following known bugs: This release includes the following known bugs:
@ -147,13 +98,12 @@ Planned upcoming removals include:
This release would not have looked like this without help, code, reports and This release would not have looked like this without help, code, reports and
advice from friends like these: advice from friends like these:
Anthony Hu, Dan Fandrich, Daniel Stenberg, dependabot[bot], Derek Huang, Anthony Hu, Daniel Stenberg, dependabot[bot], Dexter Gerig, Harry Sintonen,
Dexter Gerig, Harry Sintonen, Jeremy Drake, John Bampton, Joseph Chen, John Bampton, Joseph Chen, kayrus on github, kriztalz, lf- on github,
kayrus on github, kriztalz, Laurențiu Nicola, lf- on github, Marcel Raad, Marcel Raad, Mark Phillips, Ray Satiro, rmg-x on github,
Mark Phillips, qhill on github, Ray Satiro, renovate[bot], rmg-x on github, RubisetCie on Github, Sergey, Stefan Eissing, Viktor Szakats,
RubisetCie on github, Sergey, Stefan Eissing, Tianyi Song, Timo Tijhof, Zenju on github
Viktor Szakats, Yedaya Katsman, Zenju on github (19 contributors)
(28 contributors)
References to bug reports and discussions on issues: References to bug reports and discussions on issues:
@ -204,11 +154,8 @@ References to bug reports and discussions on issues:
[45] = https://curl.se/bug/?i=16100 [45] = https://curl.se/bug/?i=16100
[46] = https://curl.se/bug/?i=16375 [46] = https://curl.se/bug/?i=16375
[47] = https://curl.se/bug/?i=16357 [47] = https://curl.se/bug/?i=16357
[48] = https://curl.se/bug/?i=16436
[49] = https://curl.se/bug/?i=16352 [49] = https://curl.se/bug/?i=16352
[50] = https://curl.se/bug/?i=16167
[51] = https://curl.se/bug/?i=16409 [51] = https://curl.se/bug/?i=16409
[52] = https://curl.se/bug/?i=16443
[53] = https://curl.se/bug/?i=16367 [53] = https://curl.se/bug/?i=16367
[54] = https://curl.se/bug/?i=16384 [54] = https://curl.se/bug/?i=16384
[55] = https://curl.se/bug/?i=16366 [55] = https://curl.se/bug/?i=16366
@ -221,53 +168,8 @@ References to bug reports and discussions on issues:
[62] = https://curl.se/bug/?i=16252 [62] = https://curl.se/bug/?i=16252
[63] = https://curl.se/bug/?i=16356 [63] = https://curl.se/bug/?i=16356
[64] = https://curl.se/bug/?i=16117 [64] = https://curl.se/bug/?i=16117
[65] = https://curl.se/bug/?i=16417
[66] = https://curl.se/bug/?i=16396 [66] = https://curl.se/bug/?i=16396
[67] = https://curl.se/bug/?i=16399 [67] = https://curl.se/bug/?i=16399
[68] = https://curl.se/bug/?i=16398 [68] = https://curl.se/bug/?i=16398
[69] = https://curl.se/bug/?i=16441
[70] = https://curl.se/bug/?i=16205
[71] = https://curl.se/bug/?i=16385 [71] = https://curl.se/bug/?i=16385
[72] = https://curl.se/bug/?i=16373 [72] = https://curl.se/bug/?i=16373
[73] = https://curl.se/bug/?i=16435
[74] = https://curl.se/bug/?i=16308
[76] = https://curl.se/bug/?i=16426
[77] = https://curl.se/bug/?i=16434
[78] = https://curl.se/bug/?i=16330
[79] = https://curl.se/bug/?i=15956
[80] = https://curl.se/bug/?i=16423
[81] = https://curl.se/bug/?i=16427
[82] = https://curl.se/bug/?i=16494
[84] = https://curl.se/bug/?i=16482
[85] = https://curl.se/bug/?i=16407
[86] = https://curl.se/bug/?i=16377
[87] = https://curl.se/bug/?i=15975
[88] = https://curl.se/bug/?i=16419
[89] = https://curl.se/bug/?i=16487
[90] = https://curl.se/bug/?i=16488
[91] = https://curl.se/bug/?i=16420
[92] = https://curl.se/bug/?i=16393
[93] = https://curl.se/bug/?i=16277
[94] = https://curl.se/bug/?i=16134
[95] = https://curl.se/bug/?i=16104
[96] = https://curl.se/bug/?i=16004
[97] = https://curl.se/bug/?i=16217
[98] = https://curl.se/bug/?i=16408
[99] = https://curl.se/bug/?i=16478
[100] = https://curl.se/bug/?i=16464
[101] = https://curl.se/bug/?i=16329
[102] = https://curl.se/bug/?i=16467
[103] = https://curl.se/bug/?i=16466
[104] = https://curl.se/bug/?i=16099
[105] = https://curl.se/bug/?i=16468
[106] = https://curl.se/bug/?i=16459
[107] = https://curl.se/bug/?i=16460
[108] = https://curl.se/bug/?i=16461
[109] = https://curl.se/bug/?i=16462
[111] = https://curl.se/bug/?i=16446
[112] = https://curl.se/bug/?i=16457
[113] = https://curl.se/bug/?i=16456
[114] = https://curl.se/bug/?i=16455
[115] = https://curl.se/bug/?i=16453
[116] = https://curl.se/bug/?i=16452
[119] = https://curl.se/bug/?i=16448

View File

@ -36,8 +36,6 @@ esac
if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2022' ]; then if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2022' ]; then
openssl_root_win="C:/OpenSSL-v34${openssl_suffix}" openssl_root_win="C:/OpenSSL-v34${openssl_suffix}"
elif [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2019' ]; then elif [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2019' ]; then
openssl_root_win="C:/OpenSSL-v11${openssl_suffix}"
elif [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2013' ]; then
openssl_root_win="C:/OpenSSL${openssl_suffix}" openssl_root_win="C:/OpenSSL${openssl_suffix}"
else else
openssl_root_win="C:/OpenSSL-v111${openssl_suffix}" openssl_root_win="C:/OpenSSL-v111${openssl_suffix}"
@ -54,49 +52,35 @@ if [ "${BUILD_SYSTEM}" = 'CMake' ]; then
[ -n "${TOOLSET:-}" ] && options+=" -T ${TOOLSET}" [ -n "${TOOLSET:-}" ] && options+=" -T ${TOOLSET}"
[ "${OPENSSL}" = 'ON' ] && options+=" -DOPENSSL_ROOT_DIR=${openssl_root_win}" [ "${OPENSSL}" = 'ON' ] && options+=" -DOPENSSL_ROOT_DIR=${openssl_root_win}"
[ -n "${CURLDEBUG:-}" ] && options+=" -DENABLE_CURLDEBUG=${CURLDEBUG}" [ -n "${CURLDEBUG:-}" ] && options+=" -DENABLE_CURLDEBUG=${CURLDEBUG}"
if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2013' ]; then
mkdir "_bld${_chkprefill}"
cd "_bld${_chkprefill}"
options+=' ..'
root='..'
else
options+=" -B _bld${_chkprefill}"
options+=' -DCMAKE_VS_GLOBALS=TrackFileAccess=false'
options+=" -DCMAKE_UNITY_BUILD=${UNITY}"
root='.'
fi
# shellcheck disable=SC2086 # shellcheck disable=SC2086
time cmake -G "${PRJ_GEN}" ${TARGET} \ cmake -B "_bld${_chkprefill}" -G "${PRJ_GEN}" ${TARGET} \
-DCURL_TEST_BUNDLES=ON \ -DCMAKE_VS_GLOBALS=TrackFileAccess=false \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG= \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE= \
-DCMAKE_UNITY_BUILD="${UNITY}" -DCURL_TEST_BUNDLES=ON \
-DCURL_WERROR=ON \ -DCURL_WERROR=ON \
-DBUILD_SHARED_LIBS="${SHARED}" \ -DBUILD_SHARED_LIBS="${SHARED}" \
-DCURL_STATIC_CRT=ON \
-DENABLE_DEBUG="${DEBUG}" \ -DENABLE_DEBUG="${DEBUG}" \
-DENABLE_UNICODE="${ENABLE_UNICODE}" \ -DENABLE_UNICODE="${ENABLE_UNICODE}" \
-DHTTP_ONLY="${HTTP_ONLY}" \ -DHTTP_ONLY="${HTTP_ONLY}" \
-DCURL_USE_SCHANNEL="${SCHANNEL}" \ -DCURL_USE_SCHANNEL="${SCHANNEL}" \
-DCURL_USE_OPENSSL="${OPENSSL}" \ -DCURL_USE_OPENSSL="${OPENSSL}" \
-DCURL_USE_LIBPSL=OFF \ -DCURL_USE_LIBPSL=OFF \
${options} \ ${options}
|| { cat ${root}/_bld/CMakeFiles/CMake* 2>/dev/null; false; }
[ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2013' ] && cd ..
done done
if [ -d _bld_chkprefill ] && ! diff -u _bld/lib/curl_config.h _bld_chkprefill/lib/curl_config.h; then if [ -d _bld_chkprefill ] && ! diff -u _bld/lib/curl_config.h _bld_chkprefill/lib/curl_config.h; then
cat _bld_chkprefill/CMakeFiles/CMake* 2>/dev/null || true cat _bld_chkprefill/CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true
false false
fi fi
if false; then
cat _bld/CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true
fi
echo 'curl_config.h'; grep -F '#define' _bld/lib/curl_config.h | sort || true echo 'curl_config.h'; grep -F '#define' _bld/lib/curl_config.h | sort || true
# shellcheck disable=SC2086 # shellcheck disable=SC2086
if ! time cmake --build _bld --config "${PRJ_CFG}" --parallel 2 -- ${BUILD_OPT:-}; then cmake --build _bld --config "${PRJ_CFG}" --parallel 2 -- ${BUILD_OPT:-}
if [ "${PRJ_GEN}" = 'Visual Studio 9 2008' ]; then [ "${SHARED}" = 'ON' ] && PATH="$PWD/_bld/lib:$PATH"
find . -name BuildLog.htm -exec dos2unix '{}' + [ "${OPENSSL}" = 'ON' ] && PATH="${openssl_root}:$PATH"
find . -name BuildLog.htm -exec cat '{}' + curl='_bld/src/curl.exe'
fi
false
fi
[ "${SHARED}" = 'ON' ] && PATH="$PWD/_bld/lib/${PRJ_CFG}:$PATH"
[ "${OPENSSL}" = 'ON' ] && { PATH="${openssl_root}:$PATH"; cp "${openssl_root}"/*.dll "_bld/src/${PRJ_CFG}"; }
curl="_bld/src/${PRJ_CFG}/curl.exe"
elif [ "${BUILD_SYSTEM}" = 'VisualStudioSolution' ]; then elif [ "${BUILD_SYSTEM}" = 'VisualStudioSolution' ]; then
( (
cd projects cd projects
@ -129,7 +113,7 @@ EOF
curl="builds/libcurl-vc14.10-x64-${PATHPART}-dll-ssl-dll-ipv6-sspi/bin/curl.exe" curl="builds/libcurl-vc14.10-x64-${PATHPART}-dll-ssl-dll-ipv6-sspi/bin/curl.exe"
fi fi
find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' -o -name '*.pdb' \) -exec file '{}' \; find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' \) -exec file '{}' \;
if [ -z "${SKIP_RUN:-}" ]; then if [ -z "${SKIP_RUN:-}" ]; then
"${curl}" --disable --version "${curl}" --disable --version
else else
@ -140,14 +124,13 @@ fi
if [ "${TFLAGS}" != 'skipall' ] && \ if [ "${TFLAGS}" != 'skipall' ] && \
[ "${BUILD_SYSTEM}" = 'CMake' ]; then [ "${BUILD_SYSTEM}" = 'CMake' ]; then
time cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target testdeps cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target testdeps
fi fi
# run tests # run tests
if [ "${TFLAGS}" != 'skipall' ] && \ if [ "${TFLAGS}" != 'skipall' ] && \
[ "${TFLAGS}" != 'skiprun' ]; then [ "${TFLAGS}" != 'skiprun' ]; then
export CURL_DIRSUFFIX="${PRJ_CFG}"
if [ -x "$(cygpath "${SYSTEMROOT}/System32/curl.exe")" ]; then if [ -x "$(cygpath "${SYSTEMROOT}/System32/curl.exe")" ]; then
TFLAGS+=" -ac $(cygpath "${SYSTEMROOT}/System32/curl.exe")" TFLAGS+=" -ac $(cygpath "${SYSTEMROOT}/System32/curl.exe")"
elif [ -x "$(cygpath 'C:/msys64/usr/bin/curl.exe')" ]; then elif [ -x "$(cygpath 'C:/msys64/usr/bin/curl.exe')" ]; then
@ -155,12 +138,12 @@ if [ "${TFLAGS}" != 'skipall' ] && \
fi fi
TFLAGS+=' -j0' TFLAGS+=' -j0'
if [ "${BUILD_SYSTEM}" = 'CMake' ]; then if [ "${BUILD_SYSTEM}" = 'CMake' ]; then
time cmake --build _bld --config "${PRJ_CFG}" --target test-ci cmake --build _bld --config "${PRJ_CFG}" --target test-ci
else else
( (
TFLAGS="-a -p !flaky -r -rm ${TFLAGS}" TFLAGS="-a -p !flaky -r -rm ${TFLAGS}"
cd _bld/tests cd _bld/tests
time ./runtests.pl ./runtests.pl
) )
fi fi
fi fi
@ -169,5 +152,5 @@ fi
if [ "${EXAMPLES}" = 'ON' ] && \ if [ "${EXAMPLES}" = 'ON' ] && \
[ "${BUILD_SYSTEM}" = 'CMake' ]; then [ "${BUILD_SYSTEM}" = 'CMake' ]; then
time cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target curl-examples cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target curl-examples
fi fi

View File

@ -31,11 +31,8 @@
version: 7.50.0.{build} version: 7.50.0.{build}
environment: environment:
BUILD_SYSTEM: CMake
UNITY: 'ON' UNITY: 'ON'
OPENSSL: 'OFF' OPENSSL: 'OFF'
SCHANNEL: 'OFF'
ENABLE_UNICODE: 'OFF'
DEBUG: 'ON' DEBUG: 'ON'
SHARED: 'OFF' SHARED: 'OFF'
HTTP_ONLY: 'OFF' HTTP_ONLY: 'OFF'
@ -48,77 +45,89 @@ environment:
- job_name: 'CMake, VS2022, Release, x64, OpenSSL 3.4, Shared, Build-tests' - job_name: 'CMake, VS2022, Release, x64, OpenSSL 3.4, Shared, Build-tests'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 17 2022' PRJ_GEN: 'Visual Studio 17 2022'
TARGET: '-A x64' TARGET: '-A x64'
PRJ_CFG: Release PRJ_CFG: Release
OPENSSL: 'ON' OPENSSL: 'ON'
SCHANNEL: 'OFF'
ENABLE_UNICODE: 'OFF'
SHARED: 'ON' SHARED: 'ON'
- job_name: 'CMake, VS2022, Release, arm64, Schannel, Static, Build-tests' - job_name: 'CMake, VS2022, Release, arm64, Schannel, Static, Build-tests'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 17 2022' PRJ_GEN: 'Visual Studio 17 2022'
TARGET: '-A ARM64' TARGET: '-A ARM64'
PRJ_CFG: Release PRJ_CFG: Release
SCHANNEL: 'ON' SCHANNEL: 'ON'
ENABLE_UNICODE: 'OFF'
DEBUG: 'OFF' DEBUG: 'OFF'
CURLDEBUG: 'ON' CURLDEBUG: 'ON'
- job_name: 'CMake, VS2008, Debug, x86, OpenSSL 1.0.2 + Schannel, Shared, Build-tests & examples'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2013'
PRJ_GEN: 'Visual Studio 9 2008'
TARGET: '-A Win32'
PRJ_CFG: Debug
OPENSSL: 'ON'
SCHANNEL: 'ON'
SHARED: 'ON'
EXAMPLES: 'ON'
- job_name: 'CMake, VS2010, Debug, x64, Schannel, Shared, Build-tests & examples' - job_name: 'CMake, VS2010, Debug, x64, Schannel, Shared, Build-tests & examples'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 10 2010' PRJ_GEN: 'Visual Studio 10 2010'
TARGET: '-A x64' TARGET: '-A x64'
PRJ_CFG: Debug PRJ_CFG: Debug
SCHANNEL: 'ON' SCHANNEL: 'ON'
ENABLE_UNICODE: 'OFF'
SHARED: 'ON' SHARED: 'ON'
EXAMPLES: 'ON' EXAMPLES: 'ON'
- job_name: 'CMake, VS2012, Release, x86, OpenSSL 1.1.1 + Schannel, Shared, Build-tests' - job_name: 'CMake, VS2012, Release, x86, OpenSSL 1.1.1 + Schannel, Shared, Build-tests'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 11 2012' PRJ_GEN: 'Visual Studio 11 2012'
TARGET: '-A Win32' TARGET: '-A Win32'
PRJ_CFG: Release PRJ_CFG: Release
OPENSSL: 'ON' OPENSSL: 'ON'
SCHANNEL: 'ON' SCHANNEL: 'ON'
ENABLE_UNICODE: 'OFF'
SHARED: 'ON' SHARED: 'ON'
- job_name: 'CMake, VS2013, Debug, x64, OpenSSL 1.1.1, Shared, Build-only' - job_name: 'CMake, VS2013, Debug, x64, OpenSSL 1.1.1, Shared, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 12 2013' PRJ_GEN: 'Visual Studio 12 2013'
TARGET: '-A x64' TARGET: '-A x64'
PRJ_CFG: Debug PRJ_CFG: Debug
OPENSSL: 'ON' OPENSSL: 'ON'
SCHANNEL: 'OFF'
ENABLE_UNICODE: 'OFF'
SHARED: 'ON' SHARED: 'ON'
TFLAGS: 'skipall' TFLAGS: 'skipall'
- job_name: 'CMake, VS2015, Debug, x64, OpenSSL 1.1.1, Static, Build-only' - job_name: 'CMake, VS2015, Debug, x64, OpenSSL 1.1.1, Static, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 14 2015' PRJ_GEN: 'Visual Studio 14 2015'
TARGET: '-A x64' TARGET: '-A x64'
PRJ_CFG: Debug PRJ_CFG: Debug
OPENSSL: 'ON' OPENSSL: 'ON'
SCHANNEL: 'OFF'
ENABLE_UNICODE: 'OFF'
TFLAGS: 'skipall' TFLAGS: 'skipall'
- job_name: 'CMake, VS2017, Debug, x64, OpenSSL 1.1.1, Shared, Build-only' - job_name: 'CMake, VS2017, Debug, x64, OpenSSL 1.1.1, Shared, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 15 2017' PRJ_GEN: 'Visual Studio 15 2017'
TARGET: '-A x64' TARGET: '-A x64'
PRJ_CFG: Debug PRJ_CFG: Debug
OPENSSL: 'ON' OPENSSL: 'ON'
SCHANNEL: 'OFF'
ENABLE_UNICODE: 'OFF'
SHARED: 'ON' SHARED: 'ON'
TFLAGS: 'skipall' TFLAGS: 'skipall'
- job_name: 'CMake, VS2019, Debug, x64, OpenSSL 1.1.0 + Schannel, Shared, Build-tests' - job_name: 'CMake, VS2019, Debug, x64, OpenSSL 1.0.2 + Schannel, Shared, Build-tests'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2019' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2019'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 16 2019' PRJ_GEN: 'Visual Studio 16 2019'
TARGET: '-A x64' TARGET: '-A x64'
PRJ_CFG: Debug PRJ_CFG: Debug
OPENSSL: 'ON' OPENSSL: 'ON'
SCHANNEL: 'ON' SCHANNEL: 'ON'
ENABLE_UNICODE: 'OFF'
SHARED: 'ON' SHARED: 'ON'
- job_name: 'CMake, VS2022, Debug, x64, Schannel, Static, Unicode, Build-tests & examples, clang-cl' - job_name: 'CMake, VS2022, Debug, x64, Schannel, Static, Unicode, Build-tests & examples, clang-cl'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 17 2022' PRJ_GEN: 'Visual Studio 17 2022'
TARGET: '-A x64' TARGET: '-A x64'
PRJ_CFG: Debug PRJ_CFG: Debug
@ -128,6 +137,7 @@ environment:
TOOLSET: 'ClangCl' TOOLSET: 'ClangCl'
- job_name: 'CMake, VS2022, Debug, x64, Schannel, Static, Unicode, Build-tests' - job_name: 'CMake, VS2022, Debug, x64, Schannel, Static, Unicode, Build-tests'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 17 2022' PRJ_GEN: 'Visual Studio 17 2022'
TARGET: '-A x64' TARGET: '-A x64'
PRJ_CFG: Debug PRJ_CFG: Debug
@ -135,6 +145,7 @@ environment:
ENABLE_UNICODE: 'ON' ENABLE_UNICODE: 'ON'
- job_name: 'CMake, VS2022, Release, x64, Schannel, Shared, Unicode, DEBUGBUILD, no-CURLDEBUG, Build-tests' - job_name: 'CMake, VS2022, Release, x64, Schannel, Shared, Unicode, DEBUGBUILD, no-CURLDEBUG, Build-tests'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 17 2022' PRJ_GEN: 'Visual Studio 17 2022'
TARGET: '-A x64' TARGET: '-A x64'
PRJ_CFG: Release PRJ_CFG: Release
@ -144,14 +155,20 @@ environment:
CURLDEBUG: 'OFF' CURLDEBUG: 'OFF'
- job_name: 'CMake, VS2022, Debug, x64, no SSL, Static, Build-tests' - job_name: 'CMake, VS2022, Debug, x64, no SSL, Static, Build-tests'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 17 2022' PRJ_GEN: 'Visual Studio 17 2022'
TARGET: '-A x64' TARGET: '-A x64'
PRJ_CFG: Debug PRJ_CFG: Debug
SCHANNEL: 'OFF'
ENABLE_UNICODE: 'OFF'
- job_name: 'CMake, VS2022, Debug, x64, no SSL, Static, HTTP only, Build-tests' - job_name: 'CMake, VS2022, Debug, x64, no SSL, Static, HTTP only, Build-tests'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 17 2022' PRJ_GEN: 'Visual Studio 17 2022'
TARGET: '-A x64' TARGET: '-A x64'
PRJ_CFG: Debug PRJ_CFG: Debug
SCHANNEL: 'OFF'
ENABLE_UNICODE: 'OFF'
HTTP_ONLY: 'ON' HTTP_ONLY: 'ON'
# winbuild-based builds # winbuild-based builds
@ -237,5 +254,5 @@ skip_commits:
#artifacts: #artifacts:
# - path: '**/curl.exe' # - path: '**/curl.exe'
# name: curl # name: curl
# - path: '**/*.dll' # - path: '**/*curl*.dll'
# name: libcurl dll # name: libcurl dll

View File

@ -21,12 +21,6 @@ CMake's GUIs.
A CMake configuration of curl is similar to the autotools build of curl. A CMake configuration of curl is similar to the autotools build of curl.
It consists of the following steps after you have unpacked the source. It consists of the following steps after you have unpacked the source.
We recommend building with CMake on Windows. For instructions on migrating
from the `projects/Windows` Visual Studio solution files, see
[this section](#migrating-from-visual-studio-ide-project-files). For
instructions on migrating from the winbuild builds, see
[the following section](#migrating-from-winbuild-builds).
## Using `cmake` ## Using `cmake`
You can configure for in source tree builds or for a build tree You can configure for in source tree builds or for a build tree
@ -37,14 +31,10 @@ that is apart from the source tree.
$ cmake -B . $ cmake -B .
- Build in a separate directory (parallel to the curl source tree in this - Build in a separate directory (parallel to the curl source tree in this
example). The build directory is created for you. This is recommended over example). The build directory is created for you.
building in the source tree to separate source and build artifacts.
$ cmake -B ../curl-build $ cmake -B ../curl-build
For the full list of CMake build configuration variables see
[the corresponding section](#cmake-build-options).
### Fallback for CMake before version 3.13 ### Fallback for CMake before version 3.13
CMake before version 3.13 does not support the `-B` option. In that case, CMake before version 3.13 does not support the `-B` option. In that case,
@ -139,12 +129,6 @@ Install to default location (you have to specify the build directory).
$ cmake --install ../curl-build $ cmake --install ../curl-build
Do not use `--prefix` to change the installation prefix as the output produced
by the `curl-config` script is determined at CMake configure time. If you want
to set a custom install prefix for curl, set
[`CMAKE_INSTALL_PREFIX`](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html)
when configuring the CMake build.
### Fallback for CMake before version 3.15 ### Fallback for CMake before version 3.15
CMake before version 3.15 does not support the `--install` option. In that CMake before version 3.15 does not support the `--install` option. In that
@ -155,68 +139,6 @@ assumes that CMake generates `Makefile`:
$ cd ../curl-build $ cd ../curl-build
$ make install $ make install
# CMake usage
Just as curl can be built and installed using CMake, it can also be used from
CMake.
## Using `find_package`
To locate libcurl from CMake, one can use the standard
[`find_package`](https://cmake.org/cmake/help/latest/command/find_package.html)
command in the typical fashion:
```cmake
find_package(CURL 8.12.0 REQUIRED) # FATAL_ERROR if CURL is not found
```
This invokes the CMake-provided
[FindCURL](https://cmake.org/cmake/help/latest/module/FindCURL.html) find module,
which first performs a search using the `find_package`
[config mode](https://cmake.org/cmake/help/latest/command/find_package.html#config-mode-search-procedure).
This is supported by the `CURLConfig.cmake` CMake config script which is
available if the given CURL was built and installed using CMake.
### Detecting CURL features/protocols
Since version 8.12.0, `CURLConfig.cmake` publishes the supported CURL features
and protocols (see [release notes](https://curl.se/ch/8.12.0.html)). These can
be specified using the `find_package` keywords `COMPONENTS` and
`OPTIONAL_COMPONENTS`, with protocols in all caps, e.g. `HTTPS`, `LDAP`, while
features should be in their original sentence case, e.g. `AsynchDNS`,
`UnixSockets`. If any of the `COMPONENTS` are missing, then CURL is considered
as *not* found.
Here is an example of using `COMPONENTS` and `OPTIONAL_COMPONENTS` in
`find_package` with CURL:
```cmake
# CURL_FOUND is FALSE if no HTTPS but brotli and zstd can be missing
find_package(CURL 8.12.0 COMPONENTS HTTPS OPTIONAL_COMPONENTS brotli zstd)
```
One can also check the defined `CURL_SUPPORTS_<feature-or-protocol>` variables
if a particular feature/protocol is supported. For example:
```cmake
# check HTTPS
if(CURL_SUPPORTS_HTTPS)
message(STATUS "CURL supports HTTPS")
else()
message(STATUS "CURL does NOT support HTTPS")
endif()
```
### Linking against libcurl
To link a CMake target against libcurl one can use
[`target_link_libraries`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html)
as usual:
```cmake
target_link_libraries(my_target PRIVATE CURL::libcurl)
```
# CMake build options # CMake build options
- `BUILD_CURL_EXE`: Build curl executable. Default: `ON` - `BUILD_CURL_EXE`: Build curl executable. Default: `ON`
@ -238,7 +160,7 @@ target_link_libraries(my_target PRIVATE CURL::libcurl)
- `CURL_LIBCURL_VERSIONED_SYMBOLS`: Enable libcurl versioned symbols. Default: `OFF` - `CURL_LIBCURL_VERSIONED_SYMBOLS`: Enable libcurl versioned symbols. Default: `OFF`
- `CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX`: Override default versioned symbol prefix. Default: `<TLS-BACKEND>_` or `MULTISSL_` - `CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX`: Override default versioned symbol prefix. Default: `<TLS-BACKEND>_` or `MULTISSL_`
- `CURL_LTO`: Enable compiler Link Time Optimizations. Default: `OFF` - `CURL_LTO`: Enable compiler Link Time Optimizations. Default: `OFF`
- `CURL_STATIC_CRT`: Build libcurl with static CRT with MSVC (`/MT`) (requires static or no curl executable). Default: `OFF` - `CURL_STATIC_CRT`: Build libcurl with static CRT with MSVC (`/MT`). Default: `OFF`
- `CURL_TARGET_WINDOWS_VERSION`: Minimum target Windows version as hex string. - `CURL_TARGET_WINDOWS_VERSION`: Minimum target Windows version as hex string.
- `CURL_TEST_BUNDLES`: Bundle `libtest` and `unittest` tests into single binaries. Default: `OFF` - `CURL_TEST_BUNDLES`: Bundle `libtest` and `unittest` tests into single binaries. Default: `OFF`
- `CURL_WERROR`: Turn compiler warnings into errors. Default: `OFF` - `CURL_WERROR`: Turn compiler warnings into errors. Default: `OFF`
@ -384,7 +306,6 @@ Details via CMake
- `OPENSSL_USE_STATIC_LIBS`: Look for static OpenSSL libraries. - `OPENSSL_USE_STATIC_LIBS`: Look for static OpenSSL libraries.
- `ZLIB_INCLUDE_DIR`: The zlib include directory. - `ZLIB_INCLUDE_DIR`: The zlib include directory.
- `ZLIB_LIBRARY`: Path to `zlib` library. - `ZLIB_LIBRARY`: Path to `zlib` library.
- `ZLIB_USE_STATIC_LIBS`: Look for static ZLIB library (requires CMake v3.24).
## Dependency options ## Dependency options
@ -458,7 +379,7 @@ Details via CMake
# Migrating from Visual Studio IDE Project Files # Migrating from Visual Studio IDE Project Files
We recommend using CMake to build curl with MSVC. We recommend CMake to build curl with MSVC.
The project build files reside in project/Windows/VC\* for VS2010, VS2010 and The project build files reside in project/Windows/VC\* for VS2010, VS2010 and
VS2013 respectively. VS2013 respectively.
@ -478,8 +399,8 @@ Configuration element | Equivalent CMake options
`Win32` | `-A Win32` `Win32` | `-A Win32`
`DLL` | `BUILD_SHARED_LIBS=ON`, `BUILD_STATIC_LIBS=OFF`, (default) `DLL` | `BUILD_SHARED_LIBS=ON`, `BUILD_STATIC_LIBS=OFF`, (default)
`LIB` | `BUILD_SHARED_LIBS=OFF`, `BUILD_STATIC_LIBS=ON` `LIB` | `BUILD_SHARED_LIBS=OFF`, `BUILD_STATIC_LIBS=ON`
`Debug` | `CMAKE_BUILD_TYPE=Debug` (`-G "NMake Makefiles"` only) `Debug` | `CMAKE_BUILD_TYPE=Debug`
`Release` | `CMAKE_BUILD_TYPE=Release` (`-G "NMake Makefiles"` only) `Release` | `CMAKE_BUILD_TYPE=Release`
`DLL Windows SSPI` | `CURL_USE_SCHANNEL=ON` (with SSPI enabled by default) `DLL Windows SSPI` | `CURL_USE_SCHANNEL=ON` (with SSPI enabled by default)
`DLL OpenSSL` | `CURL_USE_OPENSSL=ON`, optional: `OPENSSL_ROOT_DIR`, `OPENSSL_USE_STATIC_LIBS=ON` `DLL OpenSSL` | `CURL_USE_OPENSSL=ON`, optional: `OPENSSL_ROOT_DIR`, `OPENSSL_USE_STATIC_LIBS=ON`
`DLL libssh2` | `CURL_USE_LIBSSH2=ON`, optional: `LIBSSH2_INCLUDE_DIR`, `LIBSSH2_LIBRARY` `DLL libssh2` | `CURL_USE_LIBSSH2=ON`, optional: `LIBSSH2_INCLUDE_DIR`, `LIBSSH2_LIBRARY`
@ -493,13 +414,7 @@ For example these commands:
translate to: translate to:
> cmake . -G "Visual Studio 12 2013" -A x64 -DCURL_USE_SCHANNEL=ON -DUSE_WIN32_IDN=ON -DCURL_USE_LIBPSL=OFF > cmake . -G "Visual Studio 12 2013" -A x64 -DCMAKE_BUILD_TYPE=Debug -DCURL_USE_SCHANNEL=ON -DUSE_WIN32_IDN=ON -DCURL_USE_LIBPSL=OFF
> cmake --build . --config Debug --parallel
We do *not* specify `-DCMAKE_BUILD_TYPE=Debug` here as we might do for the
`"NMake Makefiles"` generator because the Visual Studio generators are
[multi-config generators](https://cmake.org/cmake/help/latest/prop_gbl/GENERATOR_IS_MULTI_CONFIG.html)
and therefore ignore the value of `CMAKE_BUILD_TYPE`.
# Migrating from winbuild builds # Migrating from winbuild builds
@ -522,7 +437,7 @@ winbuild options | Equivalent CMake options
`DEBUG` | `CMAKE_BUILD_TYPE=Debug` `DEBUG` | `CMAKE_BUILD_TYPE=Debug`
`GEN_PDB` | `CMAKE_EXE_LINKER_FLAGS=/Fd<path>`, `CMAKE_SHARED_LINKER_FLAGS=/Fd<path>` `GEN_PDB` | `CMAKE_EXE_LINKER_FLAGS=/Fd<path>`, `CMAKE_SHARED_LINKER_FLAGS=/Fd<path>`
`LIB_NAME_DLL`, `LIB_NAME_STATIC` | `IMPORT_LIB_SUFFIX`, `LIBCURL_OUTPUT_NAME`, `STATIC_LIB_SUFFIX` `LIB_NAME_DLL`, `LIB_NAME_STATIC` | `IMPORT_LIB_SUFFIX`, `LIBCURL_OUTPUT_NAME`, `STATIC_LIB_SUFFIX`
`VC`: `<N>` | see the CMake [Visual Studio generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html#visual-studio-generators) `VC` | see CMake `-G` [options](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html)
`MACHINE`: `x64`, `x86` | `-A x64`, `-A Win32` `MACHINE`: `x64`, `x86` | `-A x64`, `-A Win32`
`MODE`: `dll`, `static` | `BUILD_SHARED_LIBS=ON/OFF`, `BUILD_STATIC_LIBS=ON/OFF`, `BUILD_STATIC_CURL=ON/OFF` (default: dll) `MODE`: `dll`, `static` | `BUILD_SHARED_LIBS=ON/OFF`, `BUILD_STATIC_LIBS=ON/OFF`, `BUILD_STATIC_CURL=ON/OFF` (default: dll)
`RTLIBCFG`: `static` | `CURL_STATIC_CRT=ON` `RTLIBCFG`: `static` | `CURL_STATIC_CRT=ON`
@ -552,8 +467,4 @@ For example this command-line:
translates to: translates to:
> cmake . -G "Visual Studio 17 2022" -A x64 -DBUILD_SHARED_LIBS=ON -DOPENSSL_ROOT_DIR=C:\OpenSSL -DCURL_USE_OPENSSL=ON -DENABLE_UNICODE=ON -DCURL_USE_LIBPSL=OFF > cmake . -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON -DOPENSSL_ROOT_DIR=C:\OpenSSL -DCURL_USE_OPENSSL=ON -DENABLE_UNICODE=ON -DCURL_USE_LIBPSL=OFF
> cmake --build . --config Debug
We use `--config` with `cmake --build` because the Visual Studio CMake
generators are multi-config and therefore ignore `CMAKE_BUILD_TYPE`.

View File

@ -9,7 +9,7 @@ SPDX-License-Identifier: curl
[Rustls is a TLS backend written in Rust](https://docs.rs/rustls/). curl can [Rustls is a TLS backend written in Rust](https://docs.rs/rustls/). curl can
be built to use it as an alternative to OpenSSL or other TLS backends. We use be built to use it as an alternative to OpenSSL or other TLS backends. We use
the [rustls-ffi C bindings](https://github.com/rustls/rustls-ffi/). This the [rustls-ffi C bindings](https://github.com/rustls/rustls-ffi/). This
version of curl is compatible with `rustls-ffi` v0.14.x. version of curl depends on version v0.14.0 of rustls-ffi.
# Building with Rustls # Building with Rustls
@ -17,7 +17,7 @@ First, [install Rust](https://rustup.rs/).
Next, check out, build, and install the appropriate version of rustls-ffi: Next, check out, build, and install the appropriate version of rustls-ffi:
% git clone https://github.com/rustls/rustls-ffi -b v0.14.1 % git clone https://github.com/rustls/rustls-ffi -b v0.14.0
% cd rustls-ffi % cd rustls-ffi
% make % make
% make DESTDIR=${HOME}/rustls-ffi-built/ install % make DESTDIR=${HOME}/rustls-ffi-built/ install

View File

@ -157,4 +157,3 @@ s/edmcln\z/edmcln on github/
s/andrewkirillov-ibm/Andrew Kirillov/ s/andrewkirillov-ibm/Andrew Kirillov/
s/\(.*\) via #[0-9]*// s/\(.*\) via #[0-9]*//
s/jethrogb$/jethrogb on github/ s/jethrogb$/jethrogb on github/
s/on github/on github/i

View File

@ -247,11 +247,11 @@ local system or network, the bar is raised. If a local user wrongfully has
elevated rights on your system enough to attack curl, they can probably elevated rights on your system enough to attack curl, they can probably
already do much worse harm and the problem is not really in curl. already do much worse harm and the problem is not really in curl.
## Debug & Experiments ## Experiments
Vulnerabilities in features which are off by default (in the build) and Vulnerabilities in features which are off by default (in the build) and
documented as experimental, or exist only in debug mode, are not eligible for a documented as experimental, are not eligible for a reward and we do not
reward and we do not consider them security problems. consider them security problems.
## URL inconsistencies ## URL inconsistencies

View File

@ -59,4 +59,4 @@ used.
Doing FTP over an HTTP proxy without --proxytunnel makes curl do HTTP with an Doing FTP over an HTTP proxy without --proxytunnel makes curl do HTTP with an
FTP URL over the proxy. For such transfers, common FTP specific options do not FTP URL over the proxy. For such transfers, common FTP specific options do not
work, including --ssl-reqd and --ftp-ssl-control. work, including --ftp-ssl-reqd and --ftp-ssl-control.

View File

@ -2,19 +2,16 @@
c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl SPDX-License-Identifier: curl
Long: url Long: url
Arg: <url/file> Arg: <url>
Help: URL(s) to work with Help: URL to work with
Category: curl Category: curl
Added: 7.5 Added: 7.5
Multi: append Multi: append
See-also: See-also:
- next - next
- config - config
- path-as-is
- disallow-username-in-url
Example: Example:
- --url $URL - --url $URL
- --url @file
--- ---
# `--url` # `--url`
@ -35,15 +32,3 @@ destination option unless --remote-name-all is used.
On Windows, `file://` accesses can be converted to network accesses by the On Windows, `file://` accesses can be converted to network accesses by the
operating system. operating system.
Starting in curl 8.13.0, curl can be told to download URLs provided in a text
file, one URL per line. It is done by with `--url @filename`: so instead of a
URL, you specify a filename prefixed with the `@` symbol. It can be told to
load the list of URLs from stdin by providing an argument like `@-`.
When downloading URLs given in a file, it implies using --remote-name for each
provided URL. The URLs are full, there is no globbing applied or done on
these. Features such as --skip-existing work fine in combination with this.
Lines in the URL file that start with `#` are treated as comments and are
skipped.

View File

@ -62,7 +62,7 @@ The variables available are:
## `certs` ## `certs`
Output the certificate chain with details. Supported only by the OpenSSL, Output the certificate chain with details. Supported only by the OpenSSL,
GnuTLS, Schannel, Rustls, and Secure Transport backends. (Added in 7.88.0) GnuTLS, Schannel and Secure Transport backends. (Added in 7.88.0)
## `conn_id` ## `conn_id`
The connection identifier last used by the transfer. The connection id is The connection identifier last used by the transfer. The connection id is
@ -128,7 +128,7 @@ The http method used in the most recent HTTP request. (Added in 7.72.0)
## `num_certs` ## `num_certs`
Number of server certificates received in the TLS handshake. Supported only by Number of server certificates received in the TLS handshake. Supported only by
the OpenSSL, GnuTLS, Schannel, Rustls and Secure Transport backends. the OpenSSL, GnuTLS, Schannel and Secure Transport backends.
(Added in 7.88.0) (Added in 7.88.0)
## `num_connects` ## `num_connects`

View File

@ -24,53 +24,53 @@ displays information about the curl and libcurl installation.
# OPTIONS # OPTIONS
## `--ca` ## --ca
Displays the built-in path to the CA cert bundle this libcurl uses. Displays the built-in path to the CA cert bundle this libcurl uses.
## `--cc` ## --cc
Displays the compiler used to build libcurl. Displays the compiler used to build libcurl.
## `--cflags` ## --cflags
Set of compiler options (CFLAGS) to use when compiling files that use Set of compiler options (CFLAGS) to use when compiling files that use
libcurl. Currently that is only the include path to the curl include files. libcurl. Currently that is only the include path to the curl include files.
## `--checkfor [version]` ## --checkfor [version]
Specify the oldest possible libcurl version string you want, and this script Specify the oldest possible libcurl version string you want, and this script
returns 0 if the current installation is new enough or it returns 1 and returns 0 if the current installation is new enough or it returns 1 and
outputs a text saying that the current version is not new enough. (Added in outputs a text saying that the current version is not new enough. (Added in
7.15.4) 7.15.4)
## `--configure` ## --configure
Displays the arguments given to configure when building curl. Displays the arguments given to configure when building curl.
## `--feature` ## --feature
Lists what particular main features the installed libcurl was built with. At Lists what particular main features the installed libcurl was built with. At
the time of writing, this list may include SSL, KRB4 or IPv6. Do not assume the time of writing, this list may include SSL, KRB4 or IPv6. Do not assume
any particular order. The keywords are separated by newlines. There may be any particular order. The keywords are separated by newlines. There may be
none, one, or several keywords in the list. none, one, or several keywords in the list.
## `--help` ## --help
Displays the available options. Displays the available options.
## `--libs` ## --libs
Shows the complete set of libs and other linker options you need in order to Shows the complete set of libs and other linker options you need in order to
link your application with libcurl. link your application with libcurl.
## `--prefix` ## --prefix
This is the prefix used when libcurl was installed. libcurl is then installed This is the prefix used when libcurl was installed. libcurl is then installed
in $prefix/lib and its header files are installed in $prefix/include and so in $prefix/lib and its header files are installed in $prefix/include and so
on. The prefix is set with `configure --prefix`. on. The prefix is set with "configure --prefix".
## `--protocols` ## --protocols
Lists what particular protocols the installed libcurl was built to support. At Lists what particular protocols the installed libcurl was built to support. At
the time of writing, this list may include HTTP, HTTPS, FTP, FTPS, FILE, the time of writing, this list may include HTTP, HTTPS, FTP, FTPS, FILE,
@ -78,22 +78,22 @@ TELNET, LDAP, DICT and many more. Do not assume any particular order. The
protocols are listed using uppercase and are separated by newlines. There may protocols are listed using uppercase and are separated by newlines. There may
be none, one, or several protocols in the list. (Added in 7.13.0) be none, one, or several protocols in the list. (Added in 7.13.0)
## `--ssl-backends` ## --ssl-backends
Lists the SSL backends that were enabled when libcurl was built. It might be Lists the SSL backends that were enabled when libcurl was built. It might be
no, one or several names. If more than one name, they appear comma-separated. no, one or several names. If more than one name, they appear comma-separated.
(Added in 7.58.0) (Added in 7.58.0)
## `--static-libs` ## --static-libs
Shows the complete set of libs and other linker options you need in order to Shows the complete set of libs and other linker options you need in order to
link your application with libcurl statically. (Added in 7.17.1) link your application with libcurl statically. (Added in 7.17.1)
## `--version` ## --version
Outputs version information about the installed libcurl. Outputs version information about the installed libcurl.
## `--vernum` ## --vernum
Outputs version information about the installed libcurl, in numerical mode. Outputs version information about the installed libcurl, in numerical mode.
This shows the version number, in hexadecimal, using 8 bits for each part: This shows the version number, in hexadecimal, using 8 bits for each part:
@ -104,21 +104,22 @@ omitted. (This option was broken in the 7.15.0 release.)
# EXAMPLES # EXAMPLES
What linker options do I need when I link with libcurl? What linker options do I need when I link with libcurl?
~~~
$ curl-config --libs $ curl-config --libs
~~~
What compiler options do I need when I compile using libcurl functions? What compiler options do I need when I compile using libcurl functions?
~~~
$ curl-config --cflags $ curl-config --cflags
~~~
How do I know if libcurl was built with SSL support? How do I know if libcurl was built with SSL support?
~~~
$ curl-config --feature | grep SSL $ curl-config --feature | grep SSL
~~~
What's the installed libcurl version? What's the installed libcurl version?
~~~
$ curl-config --version $ curl-config --version
~~~
How do I build a single file with a one-line command? How do I build a single file with a one-line command?
~~~
$ `curl-config --cc --cflags` -o example source.c `curl-config --libs` $ `curl-config --cc --cflags` -o example source.c `curl-config --libs`
~~~

View File

@ -298,19 +298,14 @@ int main(void)
filter = (struct connection_filter *)calloc(1, sizeof(*filter)); filter = (struct connection_filter *)calloc(1, sizeof(*filter));
if(!filter) if(!filter)
return 1; exit(1);
if(curl_global_init(CURL_GLOBAL_DEFAULT)) { if(curl_global_init(CURL_GLOBAL_DEFAULT))
free(filter); exit(1);
return 1;
}
curl = curl_easy_init(); curl = curl_easy_init();
if(!curl) { if(!curl)
curl_global_cleanup(); exit(1);
free(filter);
return 1;
}
/* Set the target URL */ /* Set the target URL */
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost"); curl_easy_setopt(curl, CURLOPT_URL, "http://localhost");

View File

@ -79,12 +79,12 @@ int main(int argc, char *argv[])
fprintf(stderr, fprintf(stderr,
"\rUsage: %s [-m=1|2|5|10|20|50|100] [-t] [-x] [url]\n", "\rUsage: %s [-m=1|2|5|10|20|50|100] [-t] [-x] [url]\n",
appname); appname);
return 1; exit(1);
case 'v': case 'v':
case 'V': case 'V':
fprintf(stderr, "\r%s %s - %s\n", fprintf(stderr, "\r%s %s - %s\n",
appname, CHKSPEED_VERSION, curl_version()); appname, CHKSPEED_VERSION, curl_version());
return 1; exit(1);
case 'a': case 'a':
case 'A': case 'A':
prtall = 1; prtall = 1;

View File

@ -34,7 +34,8 @@
#include <curl/curl.h> #include <curl/curl.h>
#include <curl/mprintf.h> #include <curl/mprintf.h>
static int print_cookies(CURL *curl) static void
print_cookies(CURL *curl)
{ {
CURLcode res; CURLcode res;
struct curl_slist *cookies; struct curl_slist *cookies;
@ -46,7 +47,7 @@ static int print_cookies(CURL *curl)
if(res != CURLE_OK) { if(res != CURLE_OK) {
fprintf(stderr, "Curl curl_easy_getinfo failed: %s\n", fprintf(stderr, "Curl curl_easy_getinfo failed: %s\n",
curl_easy_strerror(res)); curl_easy_strerror(res));
return 1; exit(1);
} }
nc = cookies; nc = cookies;
i = 1; i = 1;
@ -59,8 +60,6 @@ static int print_cookies(CURL *curl)
printf("(none)\n"); printf("(none)\n");
} }
curl_slist_free_all(cookies); curl_slist_free_all(cookies);
return 0;
} }
int int

View File

@ -418,22 +418,22 @@ static int init_fifo(GlobalInfo *g)
struct epoll_event epev; struct epoll_event epev;
fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo); fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo);
if(lstat(fifo, &st) == 0) { if(lstat (fifo, &st) == 0) {
if((st.st_mode & S_IFMT) == S_IFREG) { if((st.st_mode & S_IFMT) == S_IFREG) {
errno = EEXIST; errno = EEXIST;
perror("lstat"); perror("lstat");
return 1; exit(1);
} }
} }
unlink(fifo); unlink(fifo);
if(mkfifo(fifo, 0600) == -1) { if(mkfifo (fifo, 0600) == -1) {
perror("mkfifo"); perror("mkfifo");
return 1; exit(1);
} }
sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0); sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0);
if(sockfd == -1) { if(sockfd == -1) {
perror("open"); perror("open");
return 1; exit(1);
} }
g->fifofd = sockfd; g->fifofd = sockfd;
@ -478,13 +478,13 @@ int main(int argc, char **argv)
g.epfd = epoll_create1(EPOLL_CLOEXEC); g.epfd = epoll_create1(EPOLL_CLOEXEC);
if(g.epfd == -1) { if(g.epfd == -1) {
perror("epoll_create1 failed"); perror("epoll_create1 failed");
return 1; exit(1);
} }
g.tfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); g.tfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
if(g.tfd == -1) { if(g.tfd == -1) {
perror("timerfd_create failed"); perror("timerfd_create failed");
return 1; exit(1);
} }
memset(&its, 0, sizeof(struct itimerspec)); memset(&its, 0, sizeof(struct itimerspec));
@ -496,8 +496,7 @@ int main(int argc, char **argv)
ev.data.fd = g.tfd; ev.data.fd = g.tfd;
epoll_ctl(g.epfd, EPOLL_CTL_ADD, g.tfd, &ev); epoll_ctl(g.epfd, EPOLL_CTL_ADD, g.tfd, &ev);
if(init_fifo(&g)) init_fifo(&g);
return 1;
g.multi = curl_multi_init(); g.multi = curl_multi_init();
/* setup the generic multi interface options we want */ /* setup the generic multi interface options we want */
@ -522,7 +521,7 @@ int main(int argc, char **argv)
} }
else { else {
perror("epoll_wait"); perror("epoll_wait");
return 1; exit(1);
} }
} }

View File

@ -402,22 +402,22 @@ static int init_fifo(GlobalInfo *g)
curl_socket_t sockfd; curl_socket_t sockfd;
fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo); fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo);
if(lstat(fifo, &st) == 0) { if(lstat (fifo, &st) == 0) {
if((st.st_mode & S_IFMT) == S_IFREG) { if((st.st_mode & S_IFMT) == S_IFREG) {
errno = EEXIST; errno = EEXIST;
perror("lstat"); perror("lstat");
return 1; exit(1);
} }
} }
unlink(fifo); unlink(fifo);
if(mkfifo(fifo, 0600) == -1) { if(mkfifo (fifo, 0600) == -1) {
perror("mkfifo"); perror("mkfifo");
return 1; exit(1);
} }
sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0); sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0);
if(sockfd == -1) { if(sockfd == -1) {
perror("open"); perror("open");
return 1; exit(1);
} }
g->input = fdopen(sockfd, "r"); g->input = fdopen(sockfd, "r");
@ -436,8 +436,7 @@ int main(int argc, char **argv)
memset(&g, 0, sizeof(GlobalInfo)); memset(&g, 0, sizeof(GlobalInfo));
g.loop = ev_default_loop(0); g.loop = ev_default_loop(0);
if(init_fifo(&g)) init_fifo(&g);
return 1;
g.multi = curl_multi_init(); g.multi = curl_multi_init();
ev_timer_init(&g.timer_event, timer_cb, 0., 0.); ev_timer_init(&g.timer_event, timer_cb, 0., 0.);

View File

@ -392,21 +392,21 @@ int init_fifo(void)
if((st.st_mode & S_IFMT) == S_IFREG) { if((st.st_mode & S_IFMT) == S_IFREG) {
errno = EEXIST; errno = EEXIST;
perror("lstat"); perror("lstat");
return CURL_SOCKET_BAD; exit(1);
} }
} }
unlink(fifo); unlink(fifo);
if(mkfifo(fifo, 0600) == -1) { if(mkfifo (fifo, 0600) == -1) {
perror("mkfifo"); perror("mkfifo");
return CURL_SOCKET_BAD; exit(1);
} }
socket = open(fifo, O_RDWR | O_NONBLOCK, 0); socket = open(fifo, O_RDWR | O_NONBLOCK, 0);
if(socket == CURL_SOCKET_BAD) { if(socket == -1) {
perror("open"); perror("open");
return socket; exit(1);
} }
MSG_OUT("Now, pipe some URL's into > %s\n", fifo); MSG_OUT("Now, pipe some URL's into > %s\n", fifo);
@ -421,8 +421,6 @@ int main(void)
GIOChannel* ch; GIOChannel* ch;
fd = init_fifo(); fd = init_fifo();
if(fd == CURL_SOCKET_BAD)
return 1;
ch = g_io_channel_unix_new(fd); ch = g_io_channel_unix_new(fd);
g_io_add_watch(ch, G_IO_IN, fifo_cb, g); g_io_add_watch(ch, G_IO_IN, fifo_cb, g);
gmain = g_main_loop_new(NULL, FALSE); gmain = g_main_loop_new(NULL, FALSE);

View File

@ -399,22 +399,22 @@ static int init_fifo(GlobalInfo *g)
curl_socket_t sockfd; curl_socket_t sockfd;
fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo); fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo);
if(lstat(fifo, &st) == 0) { if(lstat (fifo, &st) == 0) {
if((st.st_mode & S_IFMT) == S_IFREG) { if((st.st_mode & S_IFMT) == S_IFREG) {
errno = EEXIST; errno = EEXIST;
perror("lstat"); perror("lstat");
return 1; exit(1);
} }
} }
unlink(fifo); unlink(fifo);
if(mkfifo (fifo, 0600) == -1) { if(mkfifo (fifo, 0600) == -1) {
perror("mkfifo"); perror("mkfifo");
return 1; exit(1);
} }
sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0); sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0);
if(sockfd == -1) { if(sockfd == -1) {
perror("open"); perror("open");
return 1; exit(1);
} }
g->input = fdopen(sockfd, "r"); g->input = fdopen(sockfd, "r");
@ -440,8 +440,7 @@ int main(int argc, char **argv)
memset(&g, 0, sizeof(GlobalInfo)); memset(&g, 0, sizeof(GlobalInfo));
g.evbase = event_base_new(); g.evbase = event_base_new();
if(init_fifo(&g)) init_fifo(&g);
return 1;
g.multi = curl_multi_init(); g.multi = curl_multi_init();
evtimer_assign(&g.timer_event, g.evbase, timer_cb, &g); evtimer_assign(&g.timer_event, g.evbase, timer_cb, &g);

View File

@ -94,7 +94,7 @@ static bool init(CURL *&conn, const char *url)
if(conn == NULL) { if(conn == NULL) {
fprintf(stderr, "Failed to create CURL connection\n"); fprintf(stderr, "Failed to create CURL connection\n");
return false; exit(EXIT_FAILURE);
} }
code = curl_easy_setopt(conn, CURLOPT_ERRORBUFFER, errorBuffer); code = curl_easy_setopt(conn, CURLOPT_ERRORBUFFER, errorBuffer);
@ -270,7 +270,7 @@ int main(int argc, char *argv[])
if(argc != 2) { if(argc != 2) {
fprintf(stderr, "Usage: %s <url>\n", argv[0]); fprintf(stderr, "Usage: %s <url>\n", argv[0]);
return EXIT_FAILURE; exit(EXIT_FAILURE);
} }
curl_global_init(CURL_GLOBAL_DEFAULT); curl_global_init(CURL_GLOBAL_DEFAULT);
@ -279,7 +279,7 @@ int main(int argc, char *argv[])
if(!init(conn, argv[1])) { if(!init(conn, argv[1])) {
fprintf(stderr, "Connection initialization failed\n"); fprintf(stderr, "Connection initialization failed\n");
return EXIT_FAILURE; exit(EXIT_FAILURE);
} }
// Retrieve content for the URL // Retrieve content for the URL
@ -289,7 +289,7 @@ int main(int argc, char *argv[])
if(code != CURLE_OK) { if(code != CURLE_OK) {
fprintf(stderr, "Failed to get '%s' [%s]\n", argv[1], errorBuffer); fprintf(stderr, "Failed to get '%s' [%s]\n", argv[1], errorBuffer);
return EXIT_FAILURE; exit(EXIT_FAILURE);
} }
// Parse the (assumed) HTML code // Parse the (assumed) HTML code

View File

@ -142,7 +142,7 @@ int my_trace(CURL *handle, curl_infotype type,
return 0; return 0;
} }
static int setup(struct transfer *t, int num) static void setup(struct transfer *t, int num)
{ {
char filename[128]; char filename[128];
CURL *hnd; CURL *hnd;
@ -155,7 +155,7 @@ static int setup(struct transfer *t, int num)
if(!t->out) { if(!t->out) {
fprintf(stderr, "error: could not open file %s for writing: %s\n", fprintf(stderr, "error: could not open file %s for writing: %s\n",
filename, strerror(errno)); filename, strerror(errno));
return 1; exit(1);
} }
/* write to this file */ /* write to this file */
@ -179,7 +179,6 @@ static int setup(struct transfer *t, int num)
/* wait for pipe connection to confirm */ /* wait for pipe connection to confirm */
curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L); curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L);
#endif #endif
return 0;
} }
/* /*
@ -205,8 +204,7 @@ int main(int argc, char **argv)
multi_handle = curl_multi_init(); multi_handle = curl_multi_init();
for(i = 0; i < num_transfers; i++) { for(i = 0; i < num_transfers; i++) {
if(setup(&trans[i], i)) setup(&trans[i], i);
return 1;
/* add the individual transfer */ /* add the individual transfer */
curl_multi_add_handle(multi_handle, trans[i].easy); curl_multi_add_handle(multi_handle, trans[i].easy);

View File

@ -200,7 +200,7 @@ static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
return retcode; return retcode;
} }
static int setup(struct input *i, int num, const char *upload) static void setup(struct input *i, int num, const char *upload)
{ {
FILE *out; FILE *out;
char url[256]; char url[256];
@ -209,15 +209,14 @@ static int setup(struct input *i, int num, const char *upload)
curl_off_t uploadsize; curl_off_t uploadsize;
CURL *hnd; CURL *hnd;
hnd = i->hnd = NULL; hnd = i->hnd = curl_easy_init();
i->num = num; i->num = num;
curl_msnprintf(filename, 128, "dl-%d", num); curl_msnprintf(filename, 128, "dl-%d", num);
out = fopen(filename, "wb"); out = fopen(filename, "wb");
if(!out) { if(!out) {
fprintf(stderr, "error: could not open file %s for writing: %s\n", upload, fprintf(stderr, "error: could not open file %s for writing: %s\n", upload,
strerror(errno)); strerror(errno));
return 1; exit(1);
} }
curl_msnprintf(url, 256, "https://localhost:8443/upload-%d", num); curl_msnprintf(url, 256, "https://localhost:8443/upload-%d", num);
@ -226,8 +225,7 @@ static int setup(struct input *i, int num, const char *upload)
if(stat(upload, &file_info)) { if(stat(upload, &file_info)) {
fprintf(stderr, "error: could not stat file %s: %s\n", upload, fprintf(stderr, "error: could not stat file %s: %s\n", upload,
strerror(errno)); strerror(errno));
fclose(out); exit(1);
return 1;
} }
uploadsize = file_info.st_size; uploadsize = file_info.st_size;
@ -236,12 +234,9 @@ static int setup(struct input *i, int num, const char *upload)
if(!i->in) { if(!i->in) {
fprintf(stderr, "error: could not open file %s for reading: %s\n", upload, fprintf(stderr, "error: could not open file %s for reading: %s\n", upload,
strerror(errno)); strerror(errno));
fclose(out); exit(1);
return 1;
} }
hnd = i->hnd = curl_easy_init();
/* write to this file */ /* write to this file */
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, out); curl_easy_setopt(hnd, CURLOPT_WRITEDATA, out);
@ -274,7 +269,6 @@ static int setup(struct input *i, int num, const char *upload)
/* wait for pipe connection to confirm */ /* wait for pipe connection to confirm */
curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L); curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L);
#endif #endif
return 0;
} }
/* /*
@ -307,8 +301,7 @@ int main(int argc, char **argv)
multi_handle = curl_multi_init(); multi_handle = curl_multi_init();
for(i = 0; i < num_transfers; i++) { for(i = 0; i < num_transfers; i++) {
if(setup(&trans[i], i, filename)) setup(&trans[i], i, filename);
return 1;
/* add the individual transfer */ /* add the individual transfer */
curl_multi_add_handle(multi_handle, trans[i].hnd); curl_multi_add_handle(multi_handle, trans[i].hnd);

View File

@ -28,10 +28,11 @@ const struct curl_easyoption *curl_easy_option_by_id(CURLoption id);
# DESCRIPTION # DESCRIPTION
Given a *CURLoption* **id**, this function returns a pointer to the Given a *CURLoption* **id**, this function returns a pointer to the
*curl_easyoption* struct, holding information about the curl_easy_setopt(3) *curl_easyoption* struct, holding information about the
option using that id. The option id is the `CURLOPT_` prefixed ones provided curl_easy_setopt(3) option using that id. The option id is the CURLOPT_
in the standard curl/curl.h header file. This function returns the non-alias prefix ones provided in the standard curl/curl.h header file. This function
version of the cases where there is an alias function as well. returns the non-alias version of the cases where there is an alias function as
well.
If libcurl has no option with the given id, this function returns NULL. If libcurl has no option with the given id, this function returns NULL.

View File

@ -27,10 +27,11 @@ const struct curl_easyoption *curl_easy_option_by_name(const char *name);
# DESCRIPTION # DESCRIPTION
Given a **name**, this function returns a pointer to the *curl_easyoption* Given a **name**, this function returns a pointer to the
struct, holding information about the curl_easy_setopt(3) option using that *curl_easyoption* struct, holding information about the
name. The name should be specified without the `CURLOPT_` prefix and the name curl_easy_setopt(3) option using that name. The name should be specified
comparison is made case insensitive. without the "CURLOPT_" prefix and the name comparison is made case
insensitive.
If libcurl has no option with the given name, this function returns NULL. If libcurl has no option with the given name, this function returns NULL.

View File

@ -316,4 +316,4 @@ filenames are now escaped before transmission.
# RETURN VALUE # RETURN VALUE
0 means everything was OK, non-zero means an error occurred corresponding to a 0 means everything was OK, non-zero means an error occurred corresponding to a
`CURL_FORMADD_*` constant defined in *\<curl/curl.h\>*. CURL_FORMADD_* constant defined in *\<curl/curl.h\>*.

View File

@ -38,9 +38,9 @@ first argument to the curl_formget_callback function.
size_t len);" size_t len);"
~~~ ~~~
The *curl_formget_callback* is invoked for each part of the HTTP POST chain. The curl_formget_callback is invoked for each part of the HTTP POST chain. The
The character buffer passed to the callback must not be freed. The callback character buffer passed to the callback must not be freed. The callback should
should return the buffer length passed to it on success. return the buffer length passed to it on success.
If the **CURLFORM_STREAM** option is used in the formpost, it prevents If the **CURLFORM_STREAM** option is used in the formpost, it prevents
curl_formget(3) from working until you have performed the actual HTTP request. curl_formget(3) from working until you have performed the actual HTTP request.

View File

@ -376,8 +376,9 @@ supports HTTP zstd content encoding using zstd library (Added in 7.72.0)
*features* mask bit: CURL_VERSION_CONV *features* mask bit: CURL_VERSION_CONV
libcurl was built with support for character conversions provided by libcurl was built with support for character conversions, as provided by the
callbacks. Always 0 since 7.82.0. (Added in 7.15.4, deprecated.) CURLOPT_CONV_* callbacks. Always 0 since 7.82.0. (Added in 7.15.4,
deprecated.)
## no name ## no name

View File

@ -23,16 +23,16 @@ These variables are intended for internal use only, subject to change and have
many effects on the behavior of libcurl. Refer to the source code to determine many effects on the behavior of libcurl. Refer to the source code to determine
how exactly they are being used. how exactly they are being used.
## `CURL_ALTSVC_HTTP` ## CURL_ALTSVC_HTTP
Bypass the AltSvc HTTPS protocol restriction if this variable exists. Bypass the AltSvc HTTPS protocol restriction if this variable exists.
## `CURL_DBG_SOCK_RBLOCK` ## CURL_DBG_SOCK_RBLOCK
The percentage of recv() calls that should be answered with a EAGAIN at random. The percentage of recv() calls that should be answered with a EAGAIN at random.
For TCP/UNIX sockets. For TCP/UNIX sockets.
## `CURL_DBG_SOCK_RMAX` ## CURL_DBG_SOCK_RMAX
The maximum data that shall be received from the network in one recv() call. The maximum data that shall be received from the network in one recv() call.
For TCP/UNIX sockets. This is applied to every recv. For TCP/UNIX sockets. This is applied to every recv.
@ -40,12 +40,12 @@ For TCP/UNIX sockets. This is applied to every recv.
Example: **CURL_DBG_SOCK_RMAX=400** means recv buffer size is limited to a Example: **CURL_DBG_SOCK_RMAX=400** means recv buffer size is limited to a
maximum of 400 bytes. maximum of 400 bytes.
## `CURL_DBG_SOCK_WBLOCK` ## CURL_DBG_SOCK_WBLOCK
The percentage of send() calls that should be answered with a EAGAIN at random. The percentage of send() calls that should be answered with a EAGAIN at random.
For TCP/UNIX sockets. For TCP/UNIX sockets.
## `CURL_DBG_SOCK_WPARTIAL` ## CURL_DBG_SOCK_WPARTIAL
The percentage of data that shall be written to the network. For TCP/UNIX The percentage of data that shall be written to the network. For TCP/UNIX
sockets. This is applied to every send. sockets. This is applied to every send.
@ -53,12 +53,12 @@ sockets. This is applied to every send.
Example: **CURL_DBG_SOCK_WPARTIAL=80** means a send with 1000 bytes would Example: **CURL_DBG_SOCK_WPARTIAL=80** means a send with 1000 bytes would
only send 800. only send 800.
## `CURL_DBG_QUIC_WBLOCK` ## CURL_DBG_QUIC_WBLOCK
The percentage of send() calls that should be answered with EAGAIN at random. The percentage of send() calls that should be answered with EAGAIN at random.
QUIC only. QUIC only.
## `CURL_DEBUG` ## CURL_DEBUG
Trace logging behavior as an alternative to calling curl_global_trace(3). Trace logging behavior as an alternative to calling curl_global_trace(3).
@ -73,39 +73,39 @@ Example: **CURL_DEBUG=tcp,-http/2 curl -vv url** means trace protocol details,
triggered by `-vv`, add tracing of TCP in addition and remove tracing of triggered by `-vv`, add tracing of TCP in addition and remove tracing of
HTTP/2. HTTP/2.
## `CURL_DEBUG_SIZE` ## CURL_DEBUG_SIZE
Fake the size returned by CURLINFO_HEADER_SIZE and CURLINFO_REQUEST_SIZE. Fake the size returned by CURLINFO_HEADER_SIZE and CURLINFO_REQUEST_SIZE.
## `CURL_GETHOSTNAME` ## CURL_GETHOSTNAME
Fake the local machine's unqualified hostname for NTLM and SMTP. Fake the local machine's unqualified hostname for NTLM and SMTP.
## `CURL_HSTS_HTTP` ## CURL_HSTS_HTTP
Bypass the HSTS HTTPS protocol restriction if this variable exists. Bypass the HSTS HTTPS protocol restriction if this variable exists.
## `CURL_FORCETIME` ## CURL_FORCETIME
A time of 0 is used for AWS signatures and NTLM if this variable exists. A time of 0 is used for AWS signatures and NTLM if this variable exists.
## `CURL_ENTROPY` ## CURL_ENTROPY
A fixed faked value to use instead of a proper random number so that functions A fixed faked value to use instead of a proper random number so that functions
in libcurl that are otherwise getting random outputs can be tested for what in libcurl that are otherwise getting random outputs can be tested for what
they generate. they generate.
## `CURL_SMALLREQSEND` ## CURL_SMALLREQSEND
An alternative size of HTTP data to be sent at a time only if smaller than the An alternative size of HTTP data to be sent at a time only if smaller than the
current. current.
## `CURL_SMALLSENDS` ## CURL_SMALLSENDS
An alternative size of socket data to be sent at a time only if smaller than An alternative size of socket data to be sent at a time only if smaller than
the current. the current.
## `CURL_TIME` ## CURL_TIME
Fake Unix timestamp to use for AltSvc, HSTS and CURLINFO variables that are Fake Unix timestamp to use for AltSvc, HSTS and CURLINFO variables that are
time related. time related.
@ -114,34 +114,34 @@ This variable can also be used to fake the data returned by some CURLINFO
variables that are not time-related (such as CURLINFO_LOCAL_PORT), and in that variables that are not time-related (such as CURLINFO_LOCAL_PORT), and in that
case the value is not a timestamp. case the value is not a timestamp.
## `CURL_TRACE` ## CURL_TRACE
LDAP tracing is enabled if this variable exists and its value is 1 or greater. LDAP tracing is enabled if this variable exists and its value is 1 or greater.
OpenLDAP tracing is separate. Refer to CURL_OPENLDAP_TRACE. OpenLDAP tracing is separate. Refer to CURL_OPENLDAP_TRACE.
## `CURL_OPENLDAP_TRACE` ## CURL_OPENLDAP_TRACE
OpenLDAP tracing is enabled if this variable exists and its value is 1 or OpenLDAP tracing is enabled if this variable exists and its value is 1 or
greater. There is a number of debug levels, refer to *openldap.c* comments. greater. There is a number of debug levels, refer to *openldap.c* comments.
## `CURL_WS_CHUNK_SIZE` ## CURL_WS_CHUNK_SIZE
Used to influence the buffer chunk size used for WebSocket encoding and Used to influence the buffer chunk size used for WebSocket encoding and
decoding. decoding.
## `CURL_WS_CHUNK_EAGAIN` ## CURL_WS_CHUNK_EAGAIN
Used to simulate blocking sends after this chunk size for WebSocket Used to simulate blocking sends after this chunk size for WebSocket
connections. connections.
## `CURL_FORBID_REUSE` ## CURL_FORBID_REUSE
Used to set the CURLOPT_FORBID_REUSE flag on each transfer initiated Used to set the CURLOPT_FORBID_REUSE flag on each transfer initiated
by the curl command line tool. The value of the environment variable by the curl command line tool. The value of the environment variable
does not matter. does not matter.
## `CURL_GRACEFUL_SHUTDOWN` ## CURL_GRACEFUL_SHUTDOWN
Make a blocking, graceful shutdown of all remaining connections when Make a blocking, graceful shutdown of all remaining connections when
a multi handle is destroyed. This implicitly triggers for easy handles a multi handle is destroyed. This implicitly triggers for easy handles

View File

@ -15,7 +15,6 @@ TLS-backend:
- GnuTLS - GnuTLS
- Schannel - Schannel
- Secure Transport - Secure Transport
- rustls
Added-in: 7.19.1 Added-in: 7.19.1
--- ---

View File

@ -32,7 +32,7 @@ CURLINFO_SCHEME(3) instead, because this option cannot return all
possible protocols. possible protocols.
Pass a pointer to a long to receive the version used in the last http Pass a pointer to a long to receive the version used in the last http
connection. The returned value is set to one of these values: connection. The returned value is set to one of the CURLPROTO_* values:
~~~c ~~~c
CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_FTP, CURLPROTO_FTPS, CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_FTP, CURLPROTO_FTPS,

View File

@ -58,11 +58,12 @@ struct curl_tlssessioninfo {
}; };
~~~ ~~~
The *backend* struct member is one of these defines: CURLSSLBACKEND_NONE (when The *backend* struct member is one of the defines in the CURLSSLBACKEND_*
built without TLS support), CURLSSLBACKEND_WOLFSSL, series: CURLSSLBACKEND_NONE (when built without TLS support),
CURLSSLBACKEND_SECURETRANSPORT, CURLSSLBACKEND_GNUTLS, CURLSSLBACKEND_MBEDTLS, CURLSSLBACKEND_WOLFSSL, CURLSSLBACKEND_SECURETRANSPORT, CURLSSLBACKEND_GNUTLS,
CURLSSLBACKEND_NSS, CURLSSLBACKEND_OPENSSL or CURLSSLBACKEND_SCHANNEL. (Note CURLSSLBACKEND_MBEDTLS, CURLSSLBACKEND_NSS, CURLSSLBACKEND_OPENSSL or
that the OpenSSL forks are all reported as just OpenSSL here.) CURLSSLBACKEND_SCHANNEL. (Note that the OpenSSL
forks are all reported as just OpenSSL here.)
The *internals* struct member points to a TLS library specific pointer for The *internals* struct member points to a TLS library specific pointer for
the active ("in use") SSL connection, with the following underlying types: the active ("in use") SSL connection, with the following underlying types:

View File

@ -47,11 +47,6 @@ libcurl then expects the application to monitor the sockets for the specific
activities and tell libcurl again when something happens on one of them. Tell activities and tell libcurl again when something happens on one of them. Tell
libcurl by calling curl_multi_socket_action(3). libcurl by calling curl_multi_socket_action(3).
This callback may get invoked at any time when interacting with libcurl.
This may even happen after all transfers are done and is *likely* to
happen *during* a call to curl_multi_cleanup(3) when cached connections
are shut down.
# CALLBACK ARGUMENTS # CALLBACK ARGUMENTS
*easy* identifies the specific transfer for which this update is related. *easy* identifies the specific transfer for which this update is related.

View File

@ -17,7 +17,6 @@ TLS-backend:
- GnuTLS - GnuTLS
- Schannel - Schannel
- Secure Transport - Secure Transport
- rustls
Added-in: 7.19.1 Added-in: 7.19.1
--- ---

View File

@ -42,24 +42,21 @@ header list establishes the document-level MIME headers to prepend to the
uploaded document described by CURLOPT_MIMEPOST(3). This does not affect raw uploaded document described by CURLOPT_MIMEPOST(3). This does not affect raw
mail uploads. mail uploads.
When used with HTTP, this option can add new headers, replace internal headers The linked list should be a fully valid list of **struct curl_slist** structs
and remove internal headers.
The linked list should be a valid list of **struct curl_slist** entries
properly filled in. Use curl_slist_append(3) to create the list and properly filled in. Use curl_slist_append(3) to create the list and
curl_slist_free_all(3) to free it again after use. curl_slist_free_all(3) to clean up an entire list. If you add a header that is
otherwise generated and used by libcurl internally, your added header is used
instead. If you add a header with no content as in 'Accept:' (no data on the
right side of the colon), the internally used header is disabled/removed. With
this option you can add new headers, replace internal headers and remove
internal headers. To add a header with no content (nothing to the right side
of the colon), use the form 'name;' (note the ending semicolon).
If you provide a header that is otherwise generated and used by libcurl The headers included in the linked list **must not** be CRLF-terminated,
internally, your header alternative is used instead. If you provide a header because libcurl adds CRLF after each header item itself. Failure to comply
without content (no data on the right side of the colon) as in `Accept:`, the with this might result in strange behavior. libcurl passes on the verbatim
internally used header is removed. To forcibly add a header without content strings you give it, without any filter or other safe guards. That includes
(nothing after the colon), use the form `name;` (using a trailing semicolon). white space and control characters.
The headers included in the linked list **must not** be CRLF-terminated, since
libcurl adds CRLF after each header item itself. Failure to comply with this
might result in strange behavior. libcurl passes on the verbatim strings you
give it, without any filter or other safe guards. That includes white space
and control characters.
The first line in an HTTP request (containing the method, usually a GET or The first line in an HTTP request (containing the method, usually a GET or
POST) is not a header and cannot be replaced using this option. Only the lines POST) is not a header and cannot be replaced using this option. Only the lines
@ -167,15 +164,9 @@ int main(void)
if(curl) { if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
/* add this header */
list = curl_slist_append(list, "Shoesize: 10"); list = curl_slist_append(list, "Shoesize: 10");
/* remove this header */
list = curl_slist_append(list, "Accept:"); list = curl_slist_append(list, "Accept:");
/* change this header */
list = curl_slist_append(list, "Host: example.net");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
curl_easy_perform(curl); curl_easy_perform(curl);

View File

@ -28,8 +28,8 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MIME_OPTIONS, long options);
# DESCRIPTION # DESCRIPTION
Pass a long that holds a bitmask of options. Each bit is a boolean flag used Pass a long that holds a bitmask of CURLMIMEOPT_* defines. Each bit is a
while encoding a MIME tree or multipart form data. Boolean flag used while encoding a MIME tree or multipart form data.
Available bits are: Available bits are:

View File

@ -31,7 +31,7 @@ This option is deprecated. We strongly recommend using
CURLOPT_PROTOCOLS_STR(3) instead because this option cannot control all CURLOPT_PROTOCOLS_STR(3) instead because this option cannot control all
available protocols. available protocols.
Pass a long that holds a bitmask of protocol bits. If used, this bitmask Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
limits what protocols libcurl may use in the transfer. This allows you to have limits what protocols libcurl may use in the transfer. This allows you to have
a libcurl built to support a wide range of protocols but still limit specific a libcurl built to support a wide range of protocols but still limit specific
transfers to only be allowed to use a subset of them. By default libcurl transfers to only be allowed to use a subset of them. By default libcurl

View File

@ -32,10 +32,10 @@ This option is deprecated. We strongly recommend using
CURLOPT_REDIR_PROTOCOLS_STR(3) instead because this option cannot CURLOPT_REDIR_PROTOCOLS_STR(3) instead because this option cannot
control all available protocols. control all available protocols.
Pass a long that holds a bitmask of protocol bits. If used, this bitmask Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
limits what protocols libcurl may use in a transfer that it follows to in a limits what protocols libcurl may use in a transfer that it follows to in a
redirect when CURLOPT_FOLLOWLOCATION(3) is enabled. This allows you to limit redirect when CURLOPT_FOLLOWLOCATION(3) is enabled. This allows you to
specific transfers to only be allowed to use a subset of protocols in limit specific transfers to only be allowed to use a subset of protocols in
redirections. redirections.
Protocols denied by CURLOPT_PROTOCOLS(3) are not overridden by this Protocols denied by CURLOPT_PROTOCOLS(3) are not overridden by this

View File

@ -89,11 +89,11 @@ could be a privacy violation and unexpected.
## CURLSSLOPT_EARLYDATA ## CURLSSLOPT_EARLYDATA
Tell libcurl to try sending application data as TLS1.3 early data. This option Tell libcurl to try sending application data as TLS1.3 early data. This option
is supported for GnuTLS and wolfSSL. This option works on a best effort basis, is only supported for GnuTLS. This option works on a best effort basis,
in cases when it wasn't possible to send early data the request is resent in cases when it wasn't possible to send early data the request is resent
normally post-handshake. normally post-handshake.
This option does not work when using QUIC. This option does not work when using QUIC.
(Added in 8.11.0 for GnuTLS and 8.13.0 for wolfSSL) (Added in 8.11.0)
# DEFAULT # DEFAULT

View File

@ -71,7 +71,7 @@ int main(void)
~~~ ~~~
If you are on Linux and somehow have a need for paths larger than 107 bytes, If you are on Linux and somehow have a need for paths larger than 107 bytes,
you can use the *proc* filesystem to bypass the limitation: you can use the proc filesystem to bypass the limitation:
~~~c ~~~c
int dirfd = open(long_directory_path_to_socket, O_DIRECTORY | O_RDONLY); int dirfd = open(long_directory_path_to_socket, O_DIRECTORY | O_RDONLY);

View File

@ -81,8 +81,9 @@ int main(void)
# HISTORY # HISTORY
This option was known as CURLOPT_FTP_SSL up to 7.16.4. Supported by LDAP since This option was known as CURLOPT_FTP_SSL up to 7.16.4, and the constants were
7.81.0. Fully supported by the OpenLDAP backend only. known as CURLFTPSSL_* Handled by LDAP since 7.81.0. Fully supported by the
OpenLDAP backend only.
# %AVAILABILITY% # %AVAILABILITY%

View File

@ -51,7 +51,7 @@ stdout
A common technique is to use the write callback to store the incoming data A common technique is to use the write callback to store the incoming data
into a dynamically growing allocated buffer, and then this into a dynamically growing allocated buffer, and then this
CURLOPT_WRITEDATA(3) is used to point to a struct or the buffer to store data CURLOPT_WRITEDATA(3) is used to point to a struct or the buffer to store data
in. Like in the *getinmemory* example: in. Like in the getinmemory example:
https://curl.se/libcurl/c/getinmemory.html https://curl.se/libcurl/c/getinmemory.html
# HISTORY # HISTORY

View File

@ -45,7 +45,6 @@ CURL_GLOBAL_DEFAULT 7.8
CURL_GLOBAL_NOTHING 7.8 CURL_GLOBAL_NOTHING 7.8
CURL_GLOBAL_SSL 7.8 CURL_GLOBAL_SSL 7.8
CURL_GLOBAL_WIN32 7.8.1 CURL_GLOBAL_WIN32 7.8.1
CURL_HAS_DECLSPEC_ATTRIBUTE 8.13.0
CURL_HET_DEFAULT 7.59.0 CURL_HET_DEFAULT 7.59.0
CURL_HTTP_VERSION_1_0 7.9.1 CURL_HTTP_VERSION_1_0 7.9.1
CURL_HTTP_VERSION_1_1 7.9.1 CURL_HTTP_VERSION_1_1 7.9.1

View File

@ -102,6 +102,11 @@
#include <sys/time.h> #include <sys/time.h>
#endif #endif
/* Compatibility for non-Clang compilers */
#ifndef __has_declspec_attribute
# define __has_declspec_attribute(x) 0
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -113,17 +118,11 @@ typedef void CURLSH;
* libcurl external API function linkage decorations. * libcurl external API function linkage decorations.
*/ */
#ifdef __has_declspec_attribute
#define CURL_HAS_DECLSPEC_ATTRIBUTE(x) __has_declspec_attribute(x)
#else
#define CURL_HAS_DECLSPEC_ATTRIBUTE(x) 0
#endif
#ifdef CURL_STATICLIB #ifdef CURL_STATICLIB
# define CURL_EXTERN # define CURL_EXTERN
#elif defined(_WIN32) || \ #elif defined(_WIN32) || \
(CURL_HAS_DECLSPEC_ATTRIBUTE(dllexport) && \ (__has_declspec_attribute(dllexport) && \
CURL_HAS_DECLSPEC_ATTRIBUTE(dllimport)) __has_declspec_attribute(dllimport))
# if defined(BUILDING_LIBCURL) # if defined(BUILDING_LIBCURL)
# define CURL_EXTERN __declspec(dllexport) # define CURL_EXTERN __declspec(dllexport)
# else # else
@ -2303,33 +2302,32 @@ enum {
/* /*
* Public API enums for RTSP requests * Public API enums for RTSP requests
*/ */
enum {
#define CURL_RTSPREQ_NONE 0L CURL_RTSPREQ_NONE, /* first in list */
#define CURL_RTSPREQ_OPTIONS 1L CURL_RTSPREQ_OPTIONS,
#define CURL_RTSPREQ_DESCRIBE 2L CURL_RTSPREQ_DESCRIBE,
#define CURL_RTSPREQ_ANNOUNCE 3L CURL_RTSPREQ_ANNOUNCE,
#define CURL_RTSPREQ_SETUP 4L CURL_RTSPREQ_SETUP,
#define CURL_RTSPREQ_PLAY 5L CURL_RTSPREQ_PLAY,
#define CURL_RTSPREQ_PAUSE 6L CURL_RTSPREQ_PAUSE,
#define CURL_RTSPREQ_TEARDOWN 7L CURL_RTSPREQ_TEARDOWN,
#define CURL_RTSPREQ_GET_PARAMETER 8L CURL_RTSPREQ_GET_PARAMETER,
#define CURL_RTSPREQ_SET_PARAMETER 9L CURL_RTSPREQ_SET_PARAMETER,
#define CURL_RTSPREQ_RECORD 10L CURL_RTSPREQ_RECORD,
#define CURL_RTSPREQ_RECEIVE 11L CURL_RTSPREQ_RECEIVE,
#define CURL_RTSPREQ_LAST 12L /* not used */ CURL_RTSPREQ_LAST /* last in list */
};
/* These enums are for use with the CURLOPT_NETRC option. */ /* These enums are for use with the CURLOPT_NETRC option. */
#define CURL_NETRC_IGNORED 0L /* The .netrc will never be read.
This is the default. */
#define CURL_NETRC_OPTIONAL 1L /* A user:password in the URL will be preferred
to one in the .netrc. */
#define CURL_NETRC_REQUIRED 2L /* A user:password in the URL will be ignored.
Unless one is set programmatically, the
.netrc will be queried. */
enum CURL_NETRC_OPTION { enum CURL_NETRC_OPTION {
/* we set a single member here, just to make sure we still provide the enum, CURL_NETRC_IGNORED, /* The .netrc will never be read.
but the values to use are defined above with L suffixes */ * This is the default. */
CURL_NETRC_LAST = 3 CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred
* to one in the .netrc. */
CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored.
* Unless one is set programmatically, the .netrc
* will be queried. */
CURL_NETRC_LAST
}; };
#define CURL_SSLVERSION_DEFAULT 0 #define CURL_SSLVERSION_DEFAULT 0
@ -2353,13 +2351,10 @@ enum CURL_NETRC_OPTION {
/* never use, keep last */ /* never use, keep last */
#define CURL_SSLVERSION_MAX_LAST (CURL_SSLVERSION_LAST << 16) #define CURL_SSLVERSION_MAX_LAST (CURL_SSLVERSION_LAST << 16)
#define CURL_TLSAUTH_NONE 0L
#define CURL_TLSAUTH_SRP 1L
enum CURL_TLSAUTH { enum CURL_TLSAUTH {
/* we set a single member here, just to make sure we still provide the enum, CURL_TLSAUTH_NONE,
but the values to use are defined above with L suffixes */ CURL_TLSAUTH_SRP,
CURL_TLSAUTH_LAST = 2 CURL_TLSAUTH_LAST /* never use, keep last */
}; };
/* symbols to use with CURLOPT_POSTREDIR. /* symbols to use with CURLOPT_POSTREDIR.
@ -2374,16 +2369,14 @@ enum CURL_TLSAUTH {
#define CURL_REDIR_POST_ALL \ #define CURL_REDIR_POST_ALL \
(CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303)
#define CURL_TIMECOND_NONE 0L
#define CURL_TIMECOND_IFMODSINCE 1L
#define CURL_TIMECOND_IFUNMODSINCE 2L
#define CURL_TIMECOND_LASTMOD 3L
typedef enum { typedef enum {
/* we set a single member here, just to make sure we still provide CURL_TIMECOND_NONE,
the enum typedef, but the values to use are defined above with L
suffixes */ CURL_TIMECOND_IFMODSINCE,
CURL_TIMECOND_LAST = 4 CURL_TIMECOND_IFUNMODSINCE,
CURL_TIMECOND_LASTMOD,
CURL_TIMECOND_LAST
} curl_TimeCond; } curl_TimeCond;
/* Special size_t value signaling a null-terminated string. */ /* Special size_t value signaling a null-terminated string. */

View File

@ -162,8 +162,7 @@ endif
TIDY := clang-tidy TIDY := clang-tidy
tidy: tidy:
(_csources=`echo ' $(CSOURCES)' | sed -e 's/ +/ /g' -e 's| | $(srcdir)/|g'`; \ $(TIDY) $(CSOURCES) $(TIDYFLAGS) $(CURL_CLANG_TIDYFLAGS) -- $(AM_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H
$(TIDY) $$_csources $(TIDYFLAGS) $(CURL_CLANG_TIDYFLAGS) -- $(AM_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H)
optiontable: optiontable:
perl optiontable.pl < $(top_srcdir)/include/curl/curl.h > easyoptions.c perl optiontable.pl < $(top_srcdir)/include/curl/curl.h > easyoptions.c

View File

@ -407,6 +407,26 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data,
return result; return result;
} }
static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen)
{
size_t len;
const char *protop;
const char *p = *ptr;
while(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 /* hostcompare() returns true if 'host' matches 'check'. The first host
* argument may have a trailing dot present that will be ignored. * argument may have a trailing dot present that will be ignored.
*/ */
@ -477,124 +497,144 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
unsigned short srcport) unsigned short srcport)
{ {
const char *p = value; const char *p = value;
char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
struct altsvc *as; struct altsvc *as;
unsigned short dstport = srcport; /* the same by default */ unsigned short dstport = srcport; /* the same by default */
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
size_t entries = 0; size_t entries = 0;
struct Curl_str alpn; size_t alpnlen = strlen(alpnbuf);
const char *sp; size_t srchostlen = strlen(srchost);
time_t maxage = 24 * 3600; /* default is 24 hours */
bool persist = FALSE;
#ifdef CURL_DISABLE_VERBOSE_STRINGS #ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data; (void)data;
#endif #endif
if(result) {
infof(data, "Excessive alt-svc header, ignoring.");
return CURLE_OK;
}
DEBUGASSERT(asi); DEBUGASSERT(asi);
/* initial check for "clear" */
if(!Curl_str_until(&p, &alpn, MAX_ALTSVC_LINE, ';') &&
!Curl_str_single(&p, ';')) {
Curl_str_trimblanks(&alpn);
/* "clear" is a magic keyword */ /* "clear" is a magic keyword */
if(Curl_str_casecompare(&alpn, "clear")) { if(strcasecompare(alpnbuf, "clear")) {
/* Flush cached alternatives for this source origin */ /* Flush cached alternatives for this source origin */
altsvc_flush(asi, srcalpnid, srchost, srcport); altsvc_flush(asi, srcalpnid, srchost, srcport);
return CURLE_OK; return CURLE_OK;
} }
}
p = value;
if(Curl_str_until(&p, &alpn, MAX_ALTSVC_LINE, '='))
return CURLE_OK; /* strange line */
Curl_str_trimblanks(&alpn);
/* Handle the optional 'ma' and 'persist' flags once first, as they need to
be known for each alternative service. Unknown flags are skipped. */
sp = strchr(p, ';');
if(sp) {
sp++; /* pass the semicolon */
for(;;) {
struct Curl_str name;
struct Curl_str val;
const char *vp;
curl_off_t num;
bool quoted;
/* allow some extra whitespaces around name and value */
if(Curl_str_until(&sp, &name, 20, '=') ||
Curl_str_single(&sp, '=') ||
Curl_str_until(&sp, &val, 80, ';'))
break;
Curl_str_trimblanks(&name);
Curl_str_trimblanks(&val);
/* the value might be quoted */
vp = Curl_str(&val);
quoted = (*vp == '\"');
if(quoted)
vp++;
if(!Curl_str_number(&vp, &num, TIME_T_MAX)) {
if(Curl_str_casecompare(&name, "ma"))
maxage = (time_t)num;
else if(Curl_str_casecompare(&name, "persist") && (num == 1))
persist = TRUE;
}
if(quoted && Curl_str_single(&sp, '\"'))
break;
if(Curl_str_single(&sp, ';'))
break;
}
}
do { do {
if(!Curl_str_single(&p, '=')) { if(*p == '=') {
/* [protocol]="[host][:port], [protocol]="[host][:port]" */ /* [protocol]="[host][:port]" */
enum alpnid dstalpnid = enum alpnid dstalpnid = Curl_alpn2alpnid(alpnbuf, alpnlen);
Curl_alpn2alpnid(Curl_str(&alpn), Curl_strlen(&alpn)); p++;
if(!Curl_str_single(&p, '\"')) { if(*p == '\"') {
struct Curl_str dsthost; const char *dsthost = "";
curl_off_t port = 0; size_t dstlen = 0; /* destination hostname length */
if(Curl_str_single(&p, ':')) { const char *value_ptr;
char option[32];
curl_off_t num;
bool quoted = FALSE;
time_t maxage = 24 * 3600; /* default is 24 hours */
bool persist = FALSE;
bool valid = TRUE;
p++;
if(*p != ':') {
/* hostname starts here */ /* hostname starts here */
if(Curl_str_single(&p, '[')) { const char *hostp = p;
if(Curl_str_until(&p, &dsthost, MAX_ALTSVC_HOSTLEN, ':')) { if(*p == '[') {
infof(data, "Bad alt-svc hostname, ignoring."); /* pass all valid IPv6 letters - does not handle zone id */
dstlen = strspn(++p, "0123456789abcdefABCDEF:.");
if(p[dstlen] != ']')
/* invalid host syntax, bail out */
break; break;
/* we store the IPv6 numerical address *with* brackets */
dstlen += 2;
p = &p[dstlen-1];
}
else {
while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
p++;
dstlen = p - hostp;
}
if(!dstlen || (dstlen >= MAX_ALTSVC_HOSTLEN)) {
infof(data, "Excessive alt-svc hostname, ignoring.");
valid = FALSE;
}
else {
dsthost = hostp;
} }
} }
else { else {
/* IPv6 host name */ /* no destination name, use source host */
if(Curl_str_until(&p, &dsthost, MAX_IPADR_LEN, ']') || dsthost = srchost;
Curl_str_single(&p, ']')) { dstlen = strlen(srchost);
infof(data, "Bad alt-svc IPv6 hostname, ignoring.");
break;
} }
} if(*p == ':') {
if(Curl_str_single(&p, ':')) curl_off_t port = 0;
break; p++;
if(Curl_str_number(&p, &port, 0xffff) || (*p != '\"')) {
infof(data, "Unknown alt-svc port number, ignoring.");
valid = FALSE;
} }
else else
/* no destination name, use source host */
Curl_str_assign(&dsthost, srchost, strlen(srchost));
if(Curl_str_number(&p, &port, 0xffff)) {
infof(data, "Unknown alt-svc port number, ignoring.");
break;
}
dstport = (unsigned short)port; dstport = (unsigned short)port;
}
if(Curl_str_single(&p, '\"')) if(*p++ != '\"')
break; break;
/* Handle the optional 'ma' and 'persist' flags. Unknown flags
if(dstalpnid) { 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(ISBLANK(*p))
p++;
if(*p != '=')
return CURLE_OK;
p++;
while(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++;
}
if(!Curl_str_number(&value_ptr, &num, TIME_T_MAX)) {
if(strcasecompare("ma", option))
maxage = (time_t)num;
else if(strcasecompare("persist", option) && (num == 1))
persist = TRUE;
}
}
if(dstalpnid && valid) {
if(!entries++) if(!entries++)
/* Flush cached alternatives for this source origin, if any - when /* Flush cached alternatives for this source origin, if any - when
this is the first entry of the line. */ this is the first entry of the line. */
altsvc_flush(asi, srcalpnid, srchost, srcport); altsvc_flush(asi, srcalpnid, srchost, srcport);
as = altsvc_createid(srchost, strlen(srchost), as = altsvc_createid(srchost, srchostlen,
Curl_str(&dsthost), dsthost, dstlen,
Curl_strlen(&dsthost),
srcalpnid, dstalpnid, srcalpnid, dstalpnid,
srcport, dstport); srcport, dstport);
if(as) { if(as) {
@ -607,28 +647,26 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
as->expires = maxage + secs; as->expires = maxage + secs;
as->persist = persist; as->persist = persist;
Curl_llist_append(&asi->list, as, &as->node); Curl_llist_append(&asi->list, as, &as->node);
infof(data, "Added alt-svc: %.*s:%d over %s", infof(data, "Added alt-svc: %s:%d over %s", dsthost, dstport,
(int)Curl_strlen(&dsthost), Curl_str(&dsthost), Curl_alpnid2str(dstalpnid));
dstport, Curl_alpnid2str(dstalpnid));
} }
} }
} }
else else
break; break;
/* after the double quote there can be a comma if there is another /* after the double quote there can be a comma if there is another
string or a semicolon if no more */ string or a semicolon if no more */
if(Curl_str_single(&p, ',')) if(*p == ',') {
/* comma means another alternative is presented */
p++;
result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
if(result)
break; break;
}
/* comma means another alternative is present */
if(Curl_str_until(&p, &alpn, MAX_ALTSVC_LINE, '='))
break;
Curl_str_trimblanks(&alpn);
} }
else else
break; break;
} while(1); } while(*p && (*p != ';') && (*p != '\n') && (*p != '\r'));
return CURLE_OK; return CURLE_OK;
} }

View File

@ -592,7 +592,7 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
res->num_pending--; res->num_pending--;
if(CURL_ASYNC_SUCCESS == status) { if(CURL_ASYNC_SUCCESS == status) {
struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->conn->remote_port); struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port);
if(ai) { if(ai) {
compound_results(res, ai); compound_results(res, ai);
} }
@ -774,6 +774,8 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
if(!res->hostname) if(!res->hostname)
return NULL; return NULL;
data->state.async.hostname = res->hostname;
data->state.async.port = port;
data->state.async.done = FALSE; /* not done */ data->state.async.done = FALSE; /* not done */
data->state.async.dns = NULL; /* clear */ data->state.async.dns = NULL; /* clear */
@ -809,7 +811,6 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
service, &hints, addrinfo_cb, data); service, &hints, addrinfo_cb, data);
} }
#else #else
(void)port;
#ifdef HAVE_CARES_IPV6 #ifdef HAVE_CARES_IPV6
if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) { if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {

View File

@ -400,7 +400,7 @@ static void destroy_async_data(struct Curl_easy *data)
td->init = FALSE; td->init = FALSE;
} }
Curl_safefree(async->hostname);
} }
#ifdef USE_HTTPSRR_ARES #ifdef USE_HTTPSRR_ARES
@ -414,7 +414,7 @@ static CURLcode resolve_httpsrr(struct Curl_easy *data,
memset(&async->thdata.hinfo, 0, sizeof(struct Curl_https_rrinfo)); memset(&async->thdata.hinfo, 0, sizeof(struct Curl_https_rrinfo));
async->thdata.hinfo.port = -1; async->thdata.hinfo.port = -1;
ares_query_dnsrec(async->thdata.channel, ares_query_dnsrec(async->thdata.channel,
data->conn->host.name, ARES_CLASS_IN, async->hostname, ARES_CLASS_IN,
ARES_REC_TYPE_HTTPS, ARES_REC_TYPE_HTTPS,
Curl_dnsrec_done_cb, data, NULL); Curl_dnsrec_done_cb, data, NULL);
@ -436,6 +436,7 @@ static bool init_resolve_thread(struct Curl_easy *data,
int err = ENOMEM; int err = ENOMEM;
struct Curl_async *async = &data->state.async; struct Curl_async *async = &data->state.async;
async->port = port;
async->done = FALSE; async->done = FALSE;
async->dns = NULL; async->dns = NULL;
td->thread_hnd = curl_thread_t_null; td->thread_hnd = curl_thread_t_null;
@ -446,6 +447,11 @@ static bool init_resolve_thread(struct Curl_easy *data,
goto errno_exit; goto errno_exit;
} }
free(async->hostname);
async->hostname = strdup(hostname);
if(!async->hostname)
goto err_exit;
/* The thread will set this TRUE when complete. */ /* The thread will set this TRUE when complete. */
td->tsd.done = FALSE; td->tsd.done = FALSE;

View File

@ -536,9 +536,9 @@ parse_cookie_header(struct Curl_easy *data,
* "the rest". Prefixes must start with '__' and end with a '-', so * "the rest". Prefixes must start with '__' and end with a '-', so
* only test for names where that can possibly be true. * only test for names where that can possibly be true.
*/ */
if(!strncmp("__Secure-", Curl_str(&name), 9)) if(strncasecompare("__Secure-", Curl_str(&name), 9))
co->prefix_secure = TRUE; co->prefix_secure = TRUE;
else if(!strncmp("__Host-", Curl_str(&name), 7)) else if(strncasecompare("__Host-", Curl_str(&name), 7))
co->prefix_host = TRUE; co->prefix_host = TRUE;
/* /*

View File

@ -34,9 +34,15 @@
#endif #endif
#else /* HAVE_MEMRCHR */ #else /* HAVE_MEMRCHR */
#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)) || \
defined(USE_OPENSSL) || \
defined(USE_SCHANNEL)
void *Curl_memrchr(const void *s, int c, size_t n); void *Curl_memrchr(const void *s, int c, size_t n);
#define memrchr(x,y,z) Curl_memrchr((x),(y),(z)) #define memrchr(x,y,z) Curl_memrchr((x),(y),(z))
#endif
#endif /* HAVE_MEMRCHR */ #endif /* HAVE_MEMRCHR */
#endif /* HEADER_CURL_MEMRCHR_H */ #endif /* HEADER_CURL_MEMRCHR_H */

View File

@ -120,14 +120,6 @@
# endif # endif
#endif #endif
/* Avoid bogus format check warnings with mingw32ce gcc 4.4.0 in
C99 (-std=gnu99) mode */
#if defined(__MINGW32CE__) && !defined(CURL_NO_FMT_CHECKS) && \
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) && \
(defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 4))
#define CURL_NO_FMT_CHECKS
#endif
/* Compatibility */ /* Compatibility */
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
#define USE_IPV6 1 #define USE_IPV6 1

View File

@ -85,6 +85,7 @@ void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
void Curl_trc_multi(struct Curl_easy *data, void Curl_trc_multi(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3); const char *fmt, ...) CURL_PRINTF(2, 3);
const char *Curl_trc_mstate_name(int state); const char *Curl_trc_mstate_name(int state);
#define CURL_MSTATE_NAME(s) Curl_trc_mstate_name((int)(s))
void Curl_trc_write(struct Curl_easy *data, void Curl_trc_write(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3); const char *fmt, ...) CURL_PRINTF(2, 3);
void Curl_trc_read(struct Curl_easy *data, void Curl_trc_read(struct Curl_easy *data,
@ -178,14 +179,13 @@ void Curl_trc_ws(struct Curl_easy *data,
#endif /* !CURL_HAVE_C99 */ #endif /* !CURL_HAVE_C99 */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
/* informational messages enabled */
struct curl_trc_feat { struct curl_trc_feat {
const char *name; const char *name;
int log_level; int log_level;
}; };
#ifndef CURL_DISABLE_VERBOSE_STRINGS
/* informational messages enabled */
extern struct curl_trc_feat Curl_trc_feat_multi; extern struct curl_trc_feat Curl_trc_feat_multi;
extern struct curl_trc_feat Curl_trc_feat_read; extern struct curl_trc_feat Curl_trc_feat_read;
extern struct curl_trc_feat Curl_trc_feat_write; extern struct curl_trc_feat Curl_trc_feat_write;
@ -201,7 +201,6 @@ extern struct curl_trc_feat Curl_trc_feat_dns;
#define Curl_trc_ft_is_verbose(data, ft) \ #define Curl_trc_ft_is_verbose(data, ft) \
(Curl_trc_is_verbose(data) && \ (Curl_trc_is_verbose(data) && \
(ft)->log_level >= CURL_LOG_LVL_INFO) (ft)->log_level >= CURL_LOG_LVL_INFO)
#define CURL_MSTATE_NAME(s) Curl_trc_mstate_name((int)(s))
#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */ #else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
/* All informational messages are not compiled in for size savings */ /* All informational messages are not compiled in for size savings */

View File

@ -1181,7 +1181,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
if(dohp->probe[DOH_SLOT_IPV4].easy_mid < 0 && if(dohp->probe[DOH_SLOT_IPV4].easy_mid < 0 &&
dohp->probe[DOH_SLOT_IPV6].easy_mid < 0) { dohp->probe[DOH_SLOT_IPV6].easy_mid < 0) {
failf(data, "Could not DoH-resolve: %s", dohp->host); failf(data, "Could not DoH-resolve: %s", data->state.async.hostname);
return CONN_IS_PROXIED(data->conn) ? CURLE_COULDNT_RESOLVE_PROXY : return CONN_IS_PROXIED(data->conn) ? CURLE_COULDNT_RESOLVE_PROXY :
CURLE_COULDNT_RESOLVE_HOST; CURLE_COULDNT_RESOLVE_HOST;
} }

View File

@ -76,8 +76,8 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = Curl_cache_addr(data, ai, dns = Curl_cache_addr(data, ai,
data->conn->host.dispname, 0, data->state.async.hostname, 0,
data->conn->localport, FALSE); data->state.async.port, FALSE);
if(data->share) if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS); Curl_share_unlock(data, CURL_LOCK_DATA_DNS);

View File

@ -1480,7 +1480,7 @@ CURLcode Curl_resolver_error(struct Curl_easy *data)
} }
failf(data, "Could not resolve %s: %s", host_or_proxy, failf(data, "Could not resolve %s: %s", host_or_proxy,
data->conn->host.dispname); data->state.async.hostname);
return result; return result;
} }

View File

@ -273,28 +273,46 @@ char *Curl_checkProxyheaders(struct Curl_easy *data,
#endif #endif
/* /*
* Strip off leading and trailing whitespace from the value in the given HTTP * Strip off leading and trailing whitespace from the value in the
* header line and return a strdup()ed copy. Returns NULL in case of * given HTTP header line and return a strdupped copy. Returns NULL in
* allocation failure or bad input. Returns an empty string if the header * case of allocation failure. Returns an empty string if the header value
* value consists entirely of whitespace. * consists entirely of whitespace.
*
* If the header is provided as "name;", ending with a semicolon, it must
* return a blank string.
*/ */
char *Curl_copy_header_value(const char *header) char *Curl_copy_header_value(const char *header)
{ {
struct Curl_str out; const char *start;
const char *end;
size_t len;
/* find the end of the header name */ /* Find the end of the header name */
if(!Curl_str_cspn(&header, &out, ";:") && while(*header && (*header != ':'))
(!Curl_str_single(&header, ':') || !Curl_str_single(&header, ';'))) { ++header;
Curl_str_untilnl(&header, &out, MAX_HTTP_RESP_HEADER_SIZE);
Curl_str_trimblanks(&out);
return Curl_memdup0(Curl_str(&out), Curl_strlen(&out)); if(*header)
} /* Skip over colon */
/* bad input */ ++header;
/* Find the first non-space letter */
start = header;
while(ISSPACE(*start))
start++;
end = strchr(start, '\r');
if(!end)
end = strchr(start, '\n');
if(!end)
end = strchr(start, '\0');
if(!end)
return NULL; return NULL;
/* skip all trailing space letters */
while((end > start) && ISSPACE(*end))
end--;
/* get length of the type */
len = end - start + 1;
return Curl_memdup0(start, len);
} }
#ifndef CURL_DISABLE_HTTP_AUTH #ifndef CURL_DISABLE_HTTP_AUTH
@ -1450,8 +1468,9 @@ Curl_compareheader(const char *headerline, /* line to check */
* The field value MAY be preceded by any amount of LWS, though a single SP * The field value MAY be preceded by any amount of LWS, though a single SP
* is preferred." */ * is preferred." */
const char *p; size_t len;
struct Curl_str val; const char *start;
const char *end;
DEBUGASSERT(hlen); DEBUGASSERT(hlen);
DEBUGASSERT(clen); DEBUGASSERT(clen);
DEBUGASSERT(header); DEBUGASSERT(header);
@ -1461,21 +1480,31 @@ Curl_compareheader(const char *headerline, /* line to check */
return FALSE; /* does not start with header */ return FALSE; /* does not start with header */
/* pass the header */ /* pass the header */
p = &headerline[hlen]; start = &headerline[hlen];
if(Curl_str_untilnl(&p, &val, MAX_HTTP_RESP_HEADER_SIZE)) /* pass all whitespace */
return FALSE; while(ISSPACE(*start))
Curl_str_trimblanks(&val); start++;
/* find the end of the header line */
end = strchr(start, '\r'); /* lines end with CRLF */
if(!end) {
/* in case there is a non-standard compliant line here */
end = strchr(start, '\n');
if(!end)
/* hm, there is no line ending here, use the zero byte! */
end = strchr(start, '\0');
}
len = end-start; /* length of the content part of the input line */
/* find the content string in the rest of the line */ /* find the content string in the rest of the line */
if(Curl_strlen(&val) >= clen) { for(; len >= clen; len--, start++) {
size_t len; if(strncasecompare(start, content, clen))
p = Curl_str(&val);
for(len = Curl_strlen(&val); len >= Curl_strlen(&val); len--, p++) {
if(strncasecompare(p, content, clen))
return TRUE; /* match! */ return TRUE; /* match! */
} }
}
return FALSE; /* no match */ return FALSE; /* no match */
} }
@ -1594,6 +1623,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
bool is_connect, int httpversion, bool is_connect, int httpversion,
struct dynbuf *req) struct dynbuf *req)
{ {
char *ptr;
struct curl_slist *h[2]; struct curl_slist *h[2];
struct curl_slist *headers; struct curl_slist *headers;
int numlists = 1; /* by default */ int numlists = 1; /* by default */
@ -1633,83 +1663,100 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
/* loop through one or two lists */ /* loop through one or two lists */
for(i = 0; i < numlists; i++) { for(i = 0; i < numlists; i++) {
for(headers = h[i]; headers; headers = headers->next) { headers = h[i];
CURLcode result = CURLE_OK;
bool blankheader = FALSE;
struct Curl_str name;
const char *p = headers->data;
const char *origp = p;
/* explicitly asked to send header without content is done by a header while(headers) {
that ends with a semicolon, but there must be no colon present in the char *semicolonp = NULL;
name */ ptr = strchr(headers->data, ':');
if(!Curl_str_until(&p, &name, MAX_HTTP_RESP_HEADER_SIZE, ';') && if(!ptr) {
!Curl_str_single(&p, ';') && char *optr;
!Curl_str_single(&p, '\0') && /* no colon, semicolon? */
!memchr(Curl_str(&name), ':', Curl_strlen(&name))) ptr = strchr(headers->data, ';');
blankheader = TRUE; if(ptr) {
optr = ptr;
ptr++; /* pass the semicolon */
while(ISSPACE(*ptr))
ptr++;
if(*ptr) {
/* this may be used for something else in the future */
optr = NULL;
}
else { else {
p = origp; if(*(--ptr) == ';') {
if(!Curl_str_until(&p, &name, MAX_HTTP_RESP_HEADER_SIZE, ':') && /* copy the source */
!Curl_str_single(&p, ':')) { semicolonp = strdup(headers->data);
struct Curl_str val; if(!semicolonp) {
Curl_str_untilnl(&p, &val, MAX_HTTP_RESP_HEADER_SIZE); Curl_dyn_free(req);
Curl_str_trimblanks(&val); return CURLE_OUT_OF_MEMORY;
if(!Curl_strlen(&val))
/* no content, don't send this */
continue;
} }
else /* put a colon where the semicolon is */
/* no colon */ semicolonp[ptr - headers->data] = ':';
continue; /* point at the colon */
optr = &semicolonp [ptr - headers->data];
} }
}
ptr = optr;
}
}
if(ptr && (ptr != headers->data)) {
/* we require a colon for this to be a true header */
ptr++; /* pass the colon */
while(ISSPACE(*ptr))
ptr++;
if(*ptr || semicolonp) {
/* only send this if the contents was non-blank or done special */ /* only send this if the contents was non-blank or done special */
CURLcode result = CURLE_OK;
char *compare = semicolonp ? semicolonp : headers->data;
if(data->state.aptr.host && if(data->state.aptr.host &&
/* a Host: header was sent already, do not pass on any custom /* a Host: header was sent already, do not pass on any custom
Host: header as that will produce *two* in the same Host: header as that will produce *two* in the same
request! */ request! */
Curl_str_casecompare(&name, "Host")) checkprefix("Host:", compare))
; ;
else if(data->state.httpreq == HTTPREQ_POST_FORM && else if(data->state.httpreq == HTTPREQ_POST_FORM &&
/* this header (extended by formdata.c) is sent later */ /* this header (extended by formdata.c) is sent later */
Curl_str_casecompare(&name, "Content-Type")) checkprefix("Content-Type:", compare))
; ;
else if(data->state.httpreq == HTTPREQ_POST_MIME && else if(data->state.httpreq == HTTPREQ_POST_MIME &&
/* this header is sent later */ /* this header is sent later */
Curl_str_casecompare(&name, "Content-Type")) checkprefix("Content-Type:", compare))
; ;
else if(data->req.authneg && else if(data->req.authneg &&
/* while doing auth neg, do not allow the custom length since /* while doing auth neg, do not allow the custom length since
we will force length zero then */ we will force length zero then */
Curl_str_casecompare(&name, "Content-Length")) checkprefix("Content-Length:", compare))
; ;
else if(data->state.aptr.te && else if(data->state.aptr.te &&
/* when asking for Transfer-Encoding, do not pass on a custom /* when asking for Transfer-Encoding, do not pass on a custom
Connection: */ Connection: */
Curl_str_casecompare(&name, "Connection")) checkprefix("Connection:", compare))
; ;
else if((httpversion >= 20) && else if((httpversion >= 20) &&
Curl_str_casecompare(&name, "Transfer-Encoding")) checkprefix("Transfer-Encoding:", compare))
/* HTTP/2 does not support chunked requests */ /* HTTP/2 does not support chunked requests */
; ;
else if((Curl_str_casecompare(&name, "Authorization") || else if((checkprefix("Authorization:", compare) ||
Curl_str_casecompare(&name, "Cookie")) && checkprefix("Cookie:", compare)) &&
/* be careful of sending this potentially sensitive header to /* be careful of sending this potentially sensitive header to
other hosts */ other hosts */
!Curl_auth_allowed_to_host(data)) !Curl_auth_allowed_to_host(data))
; ;
else if(blankheader) else {
result = Curl_dyn_addf(req, "%.*s:\r\n", (int)Curl_strlen(&name), result = Curl_dyn_addf(req, "%s\r\n", compare);
Curl_str(&name)); }
else if(semicolonp)
result = Curl_dyn_addf(req, "%s\r\n", origp); free(semicolonp);
if(result) if(result)
return result; return result;
} }
} }
headers = headers->next;
}
}
return CURLE_OK; return CURLE_OK;
} }

View File

@ -438,7 +438,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
*/ */
if((arg < CURL_TIMECOND_NONE) || (arg >= CURL_TIMECOND_LAST)) if((arg < CURL_TIMECOND_NONE) || (arg >= CURL_TIMECOND_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.timecondition = (unsigned char)arg; data->set.timecondition = (unsigned char)(curl_TimeCond)arg;
break; break;
case CURLOPT_TIMEVALUE: case CURLOPT_TIMEVALUE:
/* /*

View File

@ -93,6 +93,12 @@
* newer symbols. * newer symbols.
*/ */
#ifndef _WIN32_WINNT_NT4
#define _WIN32_WINNT_NT4 0x0400 /* Windows NT 4.0 */
#endif
#ifndef _WIN32_WINNT_WIN2K
#define _WIN32_WINNT_WIN2K 0x0500 /* Windows 2000 */
#endif
#ifndef _WIN32_WINNT_WINXP #ifndef _WIN32_WINNT_WINXP
#define _WIN32_WINNT_WINXP 0x0501 /* Windows XP */ #define _WIN32_WINNT_WINXP 0x0501 /* Windows XP */
#endif #endif

View File

@ -114,10 +114,7 @@ void *Curl_memdup0(const char *src, size_t length)
char *buf = malloc(length + 1); char *buf = malloc(length + 1);
if(!buf) if(!buf)
return NULL; return NULL;
if(length) {
DEBUGASSERT(src); /* must never be NULL */
memcpy(buf, src, length); memcpy(buf, src, length);
}
buf[length] = 0; buf[length] = 0;
return buf; return buf;
} }

View File

@ -31,12 +31,6 @@ void Curl_str_init(struct Curl_str *out)
out->len = 0; out->len = 0;
} }
void Curl_str_assign(struct Curl_str *out, const char *str, size_t len)
{
out->str = str;
out->len = len;
}
/* Get a word until the first DELIM or end of string. At least one byte long. /* Get a word until the first DELIM or end of string. At least one byte long.
return non-zero on error */ return non-zero on error */
int Curl_str_until(const char **linep, struct Curl_str *out, int Curl_str_until(const char **linep, struct Curl_str *out,
@ -69,29 +63,6 @@ int Curl_str_word(const char **linep, struct Curl_str *out,
return Curl_str_until(linep, out, max, ' '); return Curl_str_until(linep, out, max, ' ');
} }
/* Get a word until a newline byte or end of string. At least one byte long.
return non-zero on error */
int Curl_str_untilnl(const char **linep, struct Curl_str *out,
const size_t max)
{
const char *s = *linep;
size_t len = 0;
DEBUGASSERT(linep && *linep && out && max);
Curl_str_init(out);
while(*s && !ISNEWLINE(*s)) {
s++;
if(++len > max)
return STRE_BIG;
}
if(!len)
return STRE_SHORT;
out->str = *linep;
out->len = len;
*linep = s; /* point to the first byte after the word */
return STRE_OK;
}
/* Get a "quoted" word. No escaping possible. /* Get a "quoted" word. No escaping possible.
return non-zero on error */ return non-zero on error */

View File

@ -43,7 +43,6 @@ struct Curl_str {
}; };
void Curl_str_init(struct Curl_str *out); void Curl_str_init(struct Curl_str *out);
void Curl_str_assign(struct Curl_str *out, const char *str, size_t len);
#define Curl_str(x) ((x)->str) #define Curl_str(x) ((x)->str)
#define Curl_strlen(x) ((x)->len) #define Curl_strlen(x) ((x)->len)
@ -57,11 +56,6 @@ int Curl_str_word(const char **linep, struct Curl_str *out, const size_t max);
int Curl_str_until(const char **linep, struct Curl_str *out, const size_t max, int Curl_str_until(const char **linep, struct Curl_str *out, const size_t max,
char delim); char delim);
/* Get a word until a newline byte or end of string. At least one byte long.
return non-zero on error */
int Curl_str_untilnl(const char **linep, struct Curl_str *out,
const size_t max);
/* Get a "quoted" word. No escaping possible. /* Get a "quoted" word. No escaping possible.
return non-zero on error */ return non-zero on error */
int Curl_str_quotedword(const char **linep, struct Curl_str *out, int Curl_str_quotedword(const char **linep, struct Curl_str *out,

View File

@ -35,7 +35,6 @@
#include "strdup.h" #include "strdup.h"
#include "idn.h" #include "idn.h"
#include "strparse.h" #include "strparse.h"
#include "curl_memrchr.h"
/* The last 3 #include files should be in this order */ /* The last 3 #include files should be in this order */
#include "curl_printf.h" #include "curl_printf.h"
@ -111,18 +110,26 @@ static void free_urlhandle(struct Curl_URL *u)
*/ */
static const char *find_host_sep(const char *url) static const char *find_host_sep(const char *url)
{ {
const char *sep;
const char *query;
/* Find the start of the hostname */ /* Find the start of the hostname */
const char *sep = strstr(url, "//"); sep = strstr(url, "//");
if(!sep) if(!sep)
sep = url; sep = url;
else else
sep += 2; sep += 2;
/* Find first / or ? */ query = strchr(sep, '?');
while(*sep && *sep != '/' && *sep != '?') sep = strchr(sep, '/');
sep++;
return sep; if(!sep)
sep = url + strlen(url);
if(!query)
query = url + strlen(url);
return sep < query ? sep : query;
} }
/* convert CURLcode to CURLUcode */ /* convert CURLcode to CURLUcode */
@ -148,40 +155,46 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
bool left = !query; bool left = !query;
const unsigned char *iptr; const unsigned char *iptr;
const unsigned char *host_sep = (const unsigned char *) url; const unsigned char *host_sep = (const unsigned char *) url;
CURLcode result = CURLE_OK; CURLcode result;
if(!relative) { if(!relative)
size_t n;
host_sep = (const unsigned char *) find_host_sep(url); host_sep = (const unsigned char *) find_host_sep(url);
/* output the first piece as-is */ for(iptr = (unsigned char *)url; /* read from here */
n = (const char *)host_sep - url; len; iptr++, len--) {
result = Curl_dyn_addn(o, url, n);
len -= n; if(iptr < host_sep) {
result = Curl_dyn_addn(o, iptr, 1);
if(result)
return cc2cu(result);
continue;
} }
for(iptr = host_sep; len && !result; iptr++, len--) {
if(*iptr == ' ') { if(*iptr == ' ') {
if(left) if(left)
result = Curl_dyn_addn(o, "%20", 3); result = Curl_dyn_addn(o, "%20", 3);
else else
result = Curl_dyn_addn(o, "+", 1); result = Curl_dyn_addn(o, "+", 1);
if(result)
return cc2cu(result);
continue;
} }
else if(urlchar_needs_escaping(*iptr)) {
if(*iptr == '?')
left = FALSE;
if(urlchar_needs_escaping(*iptr)) {
char out[3]={'%'}; char out[3]={'%'};
out[1] = hexdigits[*iptr >> 4]; out[1] = hexdigits[*iptr >> 4];
out[2] = hexdigits[*iptr & 0xf]; out[2] = hexdigits[*iptr & 0xf];
result = Curl_dyn_addn(o, out, 3); result = Curl_dyn_addn(o, out, 3);
} }
else { else
result = Curl_dyn_addn(o, iptr, 1); result = Curl_dyn_addn(o, iptr, 1);
if(*iptr == '?')
left = FALSE;
}
}
if(result) if(result)
return cc2cu(result); return cc2cu(result);
}
return CURLUE_OK; return CURLUE_OK;
} }
@ -234,76 +247,87 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
} }
/* /*
* Concatenate a relative URL onto a base URL making it absolute. * Concatenate a relative URL to a base URL making it absolute.
*
* Note that this function destroys the 'base' string.
*/ */
static CURLUcode redirect_url(const char *base, const char *relurl, static CURLUcode redirect_url(char *base, const char *relurl,
CURLU *u, unsigned int flags) CURLU *u, unsigned int flags)
{ {
struct dynbuf urlbuf; struct dynbuf urlbuf;
bool host_changed = FALSE; bool host_changed = FALSE;
const char *useurl = relurl; const char *useurl = relurl;
const char *cutoff = NULL; CURLcode result = CURLE_OK;
size_t prelen;
CURLUcode uc; CURLUcode uc;
/* protsep points to the start of the hostname */
char *protsep = strstr(base, "//");
DEBUGASSERT(protsep);
if(!protsep)
protsep = base;
else
protsep += 2; /* pass the slashes */
/* protsep points to the start of the hostname, after [scheme]:// */ if(('/' != relurl[0]) && ('#' != relurl[0])) {
const char *protsep = base + strlen(u->scheme) + 3; /* First we need to find out if there is a ?-letter in the original URL,
DEBUGASSERT(base && relurl && u); /* all set here */ and cut it and the right-side of that off */
if(!base) char *pathsep = strchr(protsep, '?');
return CURLUE_MALFORMED_INPUT; /* should never happen */ if(pathsep)
*pathsep = 0;
else {
/* if not, cut off the potential fragment */
pathsep = strchr(protsep, '#');
if(pathsep)
*pathsep = 0;
}
/* if the redirect-to piece is not just a query, cut the path after the
last slash */
if(useurl[0] != '?') {
pathsep = strrchr(protsep, '/');
if(pathsep)
pathsep[1] = 0; /* leave the slash */
}
}
else if('/' == relurl[0]) {
/* We got a new absolute path for this server */
/* handle different relative URL types */
switch(relurl[0]) {
case '/':
if(relurl[1] == '/') { if(relurl[1] == '/') {
/* protocol-relative URL: //example.com/path */ /* the new URL starts with //, just keep the protocol part from the
cutoff = protsep; original one */
useurl = &relurl[2]; *protsep = 0;
useurl = &relurl[2]; /* we keep the slashes from the original, so we
skip the new ones */
host_changed = TRUE; host_changed = TRUE;
} }
else else {
/* absolute /path */ /* cut the original URL at first slash */
cutoff = strchr(protsep, '/'); char *pathsep = strchr(protsep, '/');
break; if(pathsep)
*pathsep = 0;
case '#':
/* fragment-only change */
if(u->fragment)
cutoff = strchr(protsep, '#');
break;
default:
/* path or query-only change */
if(u->query && u->query[0])
/* remove existing query */
cutoff = strchr(protsep, '?');
else if(u->fragment && u->fragment[0])
/* Remove existing fragment */
cutoff = strchr(protsep, '#');
if(relurl[0] != '?') {
/* append a relative path after the last slash */
cutoff = memrchr(protsep, '/',
cutoff ? (size_t)(cutoff - protsep) : strlen(protsep));
if(cutoff)
cutoff++; /* truncate after last slash */
} }
break; }
else {
/* the relative piece starts with '#' */
/* If there is a fragment in the original URL, cut it off */
char *pathsep = strchr(protsep, '#');
if(pathsep)
*pathsep = 0;
} }
prelen = cutoff ? (size_t)(cutoff - base) : strlen(base);
/* build new URL */
Curl_dyn_init(&urlbuf, CURL_MAX_INPUT_LENGTH); Curl_dyn_init(&urlbuf, CURL_MAX_INPUT_LENGTH);
if(!Curl_dyn_addn(&urlbuf, base, prelen) && /* copy over the root URL part */
!urlencode_str(&urlbuf, useurl, strlen(useurl), !host_changed, FALSE)) { result = Curl_dyn_add(&urlbuf, base);
uc = parseurl_and_replace(Curl_dyn_ptr(&urlbuf), u, if(result)
flags & ~CURLU_PATH_AS_IS); return cc2cu(result);
}
else
uc = CURLUE_OUT_OF_MEMORY;
/* then append the new piece on the right side */
uc = urlencode_str(&urlbuf, useurl, strlen(useurl), !host_changed,
FALSE);
if(!uc)
uc = parseurl_and_replace(Curl_dyn_ptr(&urlbuf), u,
flags&~CURLU_PATH_AS_IS);
Curl_dyn_free(&urlbuf); Curl_dyn_free(&urlbuf);
return uc; return uc;
} }
@ -1416,10 +1440,8 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
punycode = (flags & CURLU_PUNYCODE) ? 1 : 0; punycode = (flags & CURLU_PUNYCODE) ? 1 : 0;
depunyfy = (flags & CURLU_PUNY2IDN) ? 1 : 0; depunyfy = (flags & CURLU_PUNY2IDN) ? 1 : 0;
if(u->scheme && strcasecompare("file", u->scheme)) { if(u->scheme && strcasecompare("file", u->scheme)) {
url = aprintf("file://%s%s%s%s%s", url = aprintf("file://%s%s%s",
u->path, u->path,
show_query ? "?": "",
u->query ? u->query : "",
show_fragment ? "#": "", show_fragment ? "#": "",
u->fragment ? u->fragment : ""); u->fragment ? u->fragment : "");
} }
@ -1773,7 +1795,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
|| curl_url_get(u, CURLUPART_URL, &oldurl, flags)) { || curl_url_get(u, CURLUPART_URL, &oldurl, flags)) {
return parseurl_and_replace(part, u, flags); return parseurl_and_replace(part, u, flags);
} }
DEBUGASSERT(oldurl); /* it is set here */
/* apply the relative part to create a new URL */ /* apply the relative part to create a new URL */
uc = redirect_url(oldurl, part, u, flags); uc = redirect_url(oldurl, part, u, flags);
free(oldurl); free(oldurl);

View File

@ -565,12 +565,14 @@ struct hostname {
#if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH) #if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH)
#define USE_CURL_ASYNC #define USE_CURL_ASYNC
struct Curl_async { struct Curl_async {
char *hostname;
struct Curl_dns_entry *dns; struct Curl_dns_entry *dns;
#ifdef CURLRES_ASYNCH #ifdef CURLRES_ASYNCH
struct thread_data thdata; struct thread_data thdata;
#endif #endif
void *resolver; /* resolver state, if it is used in the URL state - void *resolver; /* resolver state, if it is used in the URL state -
ares_channel e.g. */ ares_channel e.g. */
int port;
BIT(done); /* set TRUE when the lookup is complete */ BIT(done); /* set TRUE when the lookup is complete */
}; };
@ -1688,9 +1690,6 @@ struct UserDefined {
struct curl_slist *mail_rcpt; /* linked list of mail recipients */ struct curl_slist *mail_rcpt; /* linked list of mail recipients */
#endif #endif
unsigned int maxconnects; /* Max idle connections in the connection cache */ unsigned int maxconnects; /* Max idle connections in the connection cache */
#ifdef USE_ECH
int tls_ech; /* TLS ECH configuration */
#endif
unsigned short use_port; /* which port to use (when not using default) */ unsigned short use_port; /* which port to use (when not using default) */
#ifndef CURL_DISABLE_BINDLOCAL #ifndef CURL_DISABLE_BINDLOCAL
unsigned short localport; /* local port number to bind to */ unsigned short localport; /* local port number to bind to */
@ -1828,6 +1827,9 @@ struct UserDefined {
#ifndef CURL_DISABLE_WEBSOCKETS #ifndef CURL_DISABLE_WEBSOCKETS
BIT(ws_raw_mode); BIT(ws_raw_mode);
#endif #endif
#ifdef USE_ECH
int tls_ech; /* TLS ECH configuration */
#endif
}; };
#ifndef CURL_DISABLE_MIME #ifndef CURL_DISABLE_MIME

View File

@ -113,12 +113,88 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
/* we are always running on PLATFORM_WINNT */ /* we are always running on PLATFORM_WINNT */
matched = FALSE; matched = FALSE;
} }
#elif defined(UNDER_CE) #elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
(void)majorVersion; (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
(void)minorVersion; OSVERSIONINFO osver;
(void)buildVersion;
(void)platform; memset(&osver, 0, sizeof(osver));
(void)condition; osver.dwOSVersionInfoSize = sizeof(osver);
/* Find out Windows version */
if(GetVersionEx(&osver)) {
/* Verify the Operating System version number */
switch(condition) {
case VERSION_LESS_THAN:
if(osver.dwMajorVersion < majorVersion ||
(osver.dwMajorVersion == majorVersion &&
osver.dwMinorVersion < minorVersion) ||
(buildVersion != 0 &&
(osver.dwMajorVersion == majorVersion &&
osver.dwMinorVersion == minorVersion &&
osver.dwBuildNumber < buildVersion)))
matched = TRUE;
break;
case VERSION_LESS_THAN_EQUAL:
if(osver.dwMajorVersion < majorVersion ||
(osver.dwMajorVersion == majorVersion &&
osver.dwMinorVersion < minorVersion) ||
(osver.dwMajorVersion == majorVersion &&
osver.dwMinorVersion == minorVersion &&
(buildVersion == 0 ||
osver.dwBuildNumber <= buildVersion)))
matched = TRUE;
break;
case VERSION_EQUAL:
if(osver.dwMajorVersion == majorVersion &&
osver.dwMinorVersion == minorVersion &&
(buildVersion == 0 ||
osver.dwBuildNumber == buildVersion))
matched = TRUE;
break;
case VERSION_GREATER_THAN_EQUAL:
if(osver.dwMajorVersion > majorVersion ||
(osver.dwMajorVersion == majorVersion &&
osver.dwMinorVersion > minorVersion) ||
(osver.dwMajorVersion == majorVersion &&
osver.dwMinorVersion == minorVersion &&
(buildVersion == 0 ||
osver.dwBuildNumber >= buildVersion)))
matched = TRUE;
break;
case VERSION_GREATER_THAN:
if(osver.dwMajorVersion > majorVersion ||
(osver.dwMajorVersion == majorVersion &&
osver.dwMinorVersion > minorVersion) ||
(buildVersion != 0 &&
(osver.dwMajorVersion == majorVersion &&
osver.dwMinorVersion == minorVersion &&
osver.dwBuildNumber > buildVersion)))
matched = TRUE;
break;
}
/* Verify the platform identifier (if necessary) */
if(matched) {
switch(platform) {
case PLATFORM_WINDOWS:
if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
matched = FALSE;
break;
case PLATFORM_WINNT:
if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
matched = FALSE;
break;
default: /* like platform == PLATFORM_DONT_CARE */
break;
}
}
}
#else #else
ULONGLONG cm = 0; ULONGLONG cm = 0;
struct OUR_OSVERSIONINFOEXW osver; struct OUR_OSVERSIONINFOEXW osver;

View File

@ -481,27 +481,17 @@ static int cf_ngtcp2_handshake_completed(ngtcp2_conn *tconn, void *user_data)
* the handshake time when we really did connect */ * the handshake time when we really did connect */
if(ctx->use_earlydata) if(ctx->use_earlydata)
Curl_pgrsTimeWas(data, TIMER_APPCONNECT, ctx->handshake_at); Curl_pgrsTimeWas(data, TIMER_APPCONNECT, ctx->handshake_at);
if(ctx->use_earlydata) {
#ifdef USE_GNUTLS #ifdef USE_GNUTLS
if(ctx->use_earlydata) {
int flags = gnutls_session_get_flags(ctx->tls.gtls.session); int flags = gnutls_session_get_flags(ctx->tls.gtls.session);
ctx->earlydata_accepted = !!(flags & GNUTLS_SFLAGS_EARLY_DATA); ctx->earlydata_accepted = !!(flags & GNUTLS_SFLAGS_EARLY_DATA);
#endif
#ifdef USE_WOLFSSL
#ifdef WOLFSSL_EARLY_DATA
ctx->earlydata_accepted =
(wolfSSL_get_early_data_status(ctx->tls.wssl.ssl) !=
WOLFSSL_EARLY_DATA_REJECTED);
#else
DEBUGASSERT(0); /* should not come here if ED is disabled. */
ctx->earlydata_accepted = FALSE;
#endif /* WOLFSSL_EARLY_DATA */
#endif
CURL_TRC_CF(data, cf, "server did%s accept %zu bytes of early data", CURL_TRC_CF(data, cf, "server did%s accept %zu bytes of early data",
ctx->earlydata_accepted ? "" : " not", ctx->earlydata_skip); ctx->earlydata_accepted ? "" : " not", ctx->earlydata_skip);
Curl_pgrsEarlyData(data, ctx->earlydata_accepted ? Curl_pgrsEarlyData(data, ctx->earlydata_accepted ?
(curl_off_t)ctx->earlydata_skip : (curl_off_t)ctx->earlydata_skip :
-(curl_off_t)ctx->earlydata_skip); -(curl_off_t)ctx->earlydata_skip);
} }
#endif
return 0; return 0;
} }
@ -2267,23 +2257,8 @@ static int wssl_quic_new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session)
struct Curl_easy *data = CF_DATA_CURRENT(cf); struct Curl_easy *data = CF_DATA_CURRENT(cf);
DEBUGASSERT(data); DEBUGASSERT(data);
if(data && ctx) { if(data && ctx) {
ngtcp2_ssize tplen;
uint8_t tpbuf[256];
unsigned char *quic_tp = NULL;
size_t quic_tp_len = 0;
tplen = ngtcp2_conn_encode_0rtt_transport_params(ctx->qconn, tpbuf,
sizeof(tpbuf));
if(tplen < 0)
CURL_TRC_CF(data, cf, "error encoding 0RTT transport data: %s",
ngtcp2_strerror((int)tplen));
else {
quic_tp = (unsigned char *)tpbuf;
quic_tp_len = (size_t)tplen;
}
(void)Curl_wssl_cache_session(cf, data, ctx->peer.scache_key, (void)Curl_wssl_cache_session(cf, data, ctx->peer.scache_key,
session, wolfSSL_version(ssl), session, wolfSSL_version(ssl), "h3");
"h3", quic_tp, quic_tp_len);
} }
} }
return 0; return 0;
@ -2333,13 +2308,13 @@ static CURLcode cf_ngtcp2_tls_ctx_setup(struct Curl_cfilter *cf,
} }
#elif defined(USE_WOLFSSL) #elif defined(USE_WOLFSSL)
if(ngtcp2_crypto_wolfssl_configure_client_context(ctx->wssl.ssl_ctx) != 0) { if(ngtcp2_crypto_wolfssl_configure_client_context(ctx->wssl.ctx) != 0) {
failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed"); failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed");
return CURLE_FAILED_INIT; return CURLE_FAILED_INIT;
} }
if(ssl_config->primary.cache_session) { if(ssl_config->primary.cache_session) {
/* Register to get notified when a new session is received */ /* Register to get notified when a new session is received */
wolfSSL_CTX_sess_set_new_cb(ctx->wssl.ssl_ctx, wssl_quic_new_session_cb); wolfSSL_CTX_sess_set_new_cb(ctx->wssl.ctx, wssl_quic_new_session_cb);
} }
#endif #endif
return CURLE_OK; return CURLE_OK;
@ -2347,7 +2322,6 @@ static CURLcode cf_ngtcp2_tls_ctx_setup(struct Curl_cfilter *cf,
static CURLcode cf_ngtcp2_on_session_reuse(struct Curl_cfilter *cf, static CURLcode cf_ngtcp2_on_session_reuse(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
struct alpn_spec *alpns,
struct Curl_ssl_session *scs, struct Curl_ssl_session *scs,
bool *do_early_data) bool *do_early_data)
{ {
@ -2358,19 +2332,10 @@ static CURLcode cf_ngtcp2_on_session_reuse(struct Curl_cfilter *cf,
#ifdef USE_GNUTLS #ifdef USE_GNUTLS
ctx->earlydata_max = ctx->earlydata_max =
gnutls_record_get_max_early_data_size(ctx->tls.gtls.session); gnutls_record_get_max_early_data_size(ctx->tls.gtls.session);
#endif
#ifdef USE_WOLFSSL
#ifdef WOLFSSL_EARLY_DATA
ctx->earlydata_max = scs->earlydata_max;
#else
ctx->earlydata_max = 0;
#endif /* WOLFSSL_EARLY_DATA */
#endif
#if defined(USE_GNUTLS) || defined(USE_WOLFSSL)
if((!ctx->earlydata_max)) { if((!ctx->earlydata_max)) {
CURL_TRC_CF(data, cf, "SSL session does not allow earlydata"); CURL_TRC_CF(data, cf, "SSL session does not allow earlydata");
} }
else if(!Curl_alpn_contains_proto(alpns, scs->alpn)) { else if(strcmp("h3", scs->alpn)) {
CURL_TRC_CF(data, cf, "SSL session from different ALPN, no early data"); CURL_TRC_CF(data, cf, "SSL session from different ALPN, no early data");
} }
else if(!scs->quic_tp || !scs->quic_tp_len) { else if(!scs->quic_tp || !scs->quic_tp_len) {
@ -2398,7 +2363,6 @@ static CURLcode cf_ngtcp2_on_session_reuse(struct Curl_cfilter *cf,
(void)data; (void)data;
(void)ctx; (void)ctx;
(void)scs; (void)scs;
(void)alpns;
#endif #endif
return result; return result;
} }
@ -2416,9 +2380,6 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
CURLcode result; CURLcode result;
const struct Curl_sockaddr_ex *sockaddr = NULL; const struct Curl_sockaddr_ex *sockaddr = NULL;
int qfd; int qfd;
static const struct alpn_spec ALPN_SPEC_H3 = {
{ "h3", "h3-29" }, 2
};
DEBUGASSERT(ctx->initialized); DEBUGASSERT(ctx->initialized);
ctx->dcid.datalen = NGTCP2_MAX_CIDLEN; ctx->dcid.datalen = NGTCP2_MAX_CIDLEN;
@ -2462,7 +2423,9 @@ static const struct alpn_spec ALPN_SPEC_H3 = {
if(rc) if(rc)
return CURLE_QUIC_CONNECT_ERROR; return CURLE_QUIC_CONNECT_ERROR;
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer, &ALPN_SPEC_H3, #define H3_ALPN "\x2h3\x5h3-29"
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
H3_ALPN, sizeof(H3_ALPN) - 1,
cf_ngtcp2_tls_ctx_setup, &ctx->tls, cf_ngtcp2_tls_ctx_setup, &ctx->tls,
&ctx->conn_ref, &ctx->conn_ref,
cf_ngtcp2_on_session_reuse); cf_ngtcp2_on_session_reuse);
@ -2475,7 +2438,7 @@ static const struct alpn_spec ALPN_SPEC_H3 = {
#elif defined(USE_GNUTLS) #elif defined(USE_GNUTLS)
ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.gtls.session); ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.gtls.session);
#elif defined(USE_WOLFSSL) #elif defined(USE_WOLFSSL)
ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.wssl.ssl); ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.wssl.handle);
#else #else
#error "ngtcp2 TLS backend not defined" #error "ngtcp2 TLS backend not defined"
#endif #endif

View File

@ -1163,15 +1163,13 @@ static CURLcode cf_osslq_ctx_start(struct Curl_cfilter *cf,
const struct Curl_sockaddr_ex *peer_addr = NULL; const struct Curl_sockaddr_ex *peer_addr = NULL;
BIO *bio = NULL; BIO *bio = NULL;
BIO_ADDR *baddr = NULL; BIO_ADDR *baddr = NULL;
static const struct alpn_spec ALPN_SPEC_H3 = {
{ "h3" }, 1
};
DEBUGASSERT(ctx->initialized); DEBUGASSERT(ctx->initialized);
#define H3_ALPN "\x2h3" #define H3_ALPN "\x2h3"
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer, result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
&ALPN_SPEC_H3, NULL, NULL, NULL, NULL); H3_ALPN, sizeof(H3_ALPN) - 1,
NULL, NULL, NULL, NULL);
if(result) if(result)
goto out; goto out;

View File

@ -1267,9 +1267,6 @@ static CURLcode cf_quiche_ctx_open(struct Curl_cfilter *cf,
int rv; int rv;
CURLcode result; CURLcode result;
const struct Curl_sockaddr_ex *sockaddr; const struct Curl_sockaddr_ex *sockaddr;
static const struct alpn_spec ALPN_SPEC_H3 = {
{ "h3" }, 1
};
DEBUGASSERT(ctx->q.sockfd != CURL_SOCKET_BAD); DEBUGASSERT(ctx->q.sockfd != CURL_SOCKET_BAD);
DEBUGASSERT(ctx->initialized); DEBUGASSERT(ctx->initialized);
@ -1307,7 +1304,9 @@ static const struct alpn_spec ALPN_SPEC_H3 = {
- 1); - 1);
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer, result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
&ALPN_SPEC_H3, NULL, NULL, cf, NULL); QUICHE_H3_APPLICATION_PROTOCOL,
sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1,
NULL, NULL, cf, NULL);
if(result) if(result)
return result; return result;

View File

@ -58,11 +58,178 @@
#include "curl_memory.h" #include "curl_memory.h"
#include "memdebug.h" #include "memdebug.h"
#if defined(USE_WOLFSSL)
#define QUIC_CIPHERS \
"TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
"POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
#define QUIC_GROUPS "P-256:P-384:P-521"
#if defined(HAVE_SECRET_CALLBACK)
static void keylog_callback(const WOLFSSL *ssl, const char *line)
{
(void)ssl;
Curl_tls_keylog_write_line(line);
}
#endif
static CURLcode wssl_init_ctx(struct curl_tls_ctx *ctx,
struct Curl_cfilter *cf,
struct Curl_easy *data,
Curl_vquic_tls_ctx_setup *cb_setup,
void *cb_user_data)
{
struct ssl_primary_config *conn_config;
CURLcode result = CURLE_FAILED_INIT;
conn_config = Curl_ssl_cf_get_primary_config(cf);
if(!conn_config) {
result = CURLE_FAILED_INIT;
goto out;
}
ctx->wssl.ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
if(!ctx->wssl.ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
if(cb_setup) {
result = cb_setup(cf, data, cb_user_data);
if(result)
goto out;
}
wolfSSL_CTX_set_default_verify_paths(ctx->wssl.ctx);
if(wolfSSL_CTX_set_cipher_list(ctx->wssl.ctx, conn_config->cipher_list13 ?
conn_config->cipher_list13 :
QUIC_CIPHERS) != 1) {
char error_buffer[256];
ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
failf(data, "wolfSSL failed to set ciphers: %s", error_buffer);
result = CURLE_BAD_FUNCTION_ARGUMENT;
goto out;
}
if(wolfSSL_CTX_set1_groups_list(ctx->wssl.ctx, conn_config->curves ?
conn_config->curves :
(char *)QUIC_GROUPS) != 1) {
failf(data, "wolfSSL failed to set curves");
result = CURLE_BAD_FUNCTION_ARGUMENT;
goto out;
}
/* Open the file if a TLS or QUIC backend has not done this before. */
Curl_tls_keylog_open();
if(Curl_tls_keylog_enabled()) {
#if defined(HAVE_SECRET_CALLBACK)
wolfSSL_CTX_set_keylog_callback(ctx->wssl.ctx, keylog_callback);
#else
failf(data, "wolfSSL was built without keylog callback");
result = CURLE_NOT_BUILT_IN;
goto out;
#endif
}
if(conn_config->verifypeer) {
const char * const ssl_cafile = conn_config->CAfile;
const char * const ssl_capath = conn_config->CApath;
wolfSSL_CTX_set_verify(ctx->wssl.ctx, SSL_VERIFY_PEER, NULL);
if(ssl_cafile || ssl_capath) {
/* tell wolfSSL where to find CA certificates that are used to verify
the server's certificate. */
int rc =
wolfSSL_CTX_load_verify_locations_ex(ctx->wssl.ctx, ssl_cafile,
ssl_capath,
WOLFSSL_LOAD_FLAG_IGNORE_ERR);
if(SSL_SUCCESS != rc) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate verify locations:"
" CAfile: %s CApath: %s",
ssl_cafile ? ssl_cafile : "none",
ssl_capath ? ssl_capath : "none");
result = CURLE_SSL_CACERT_BADFILE;
goto out;
}
infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
}
#ifdef CURL_CA_FALLBACK
else {
/* verifying the peer without any CA certificates will not work so
use wolfSSL's built-in default as fallback */
wolfSSL_CTX_set_default_verify_paths(ctx->wssl.ctx);
}
#endif
}
else {
wolfSSL_CTX_set_verify(ctx->wssl.ctx, SSL_VERIFY_NONE, NULL);
}
/* give application a chance to interfere with SSL set up. */
if(data->set.ssl.fsslctx) {
Curl_set_in_callback(data, TRUE);
result = (*data->set.ssl.fsslctx)(data, ctx->wssl.ctx,
data->set.ssl.fsslctxp);
Curl_set_in_callback(data, FALSE);
if(result) {
failf(data, "error signaled by ssl ctx callback");
goto out;
}
}
result = CURLE_OK;
out:
if(result && ctx->wssl.ctx) {
SSL_CTX_free(ctx->wssl.ctx);
ctx->wssl.ctx = NULL;
}
return result;
}
/** SSL callbacks ***/
static CURLcode wssl_init_ssl(struct curl_tls_ctx *ctx,
struct Curl_cfilter *cf,
struct Curl_easy *data,
struct ssl_peer *peer,
const char *alpn, size_t alpn_len,
void *user_data)
{
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
DEBUGASSERT(!ctx->wssl.handle);
DEBUGASSERT(ctx->wssl.ctx);
ctx->wssl.handle = wolfSSL_new(ctx->wssl.ctx);
wolfSSL_set_app_data(ctx->wssl.handle, user_data);
wolfSSL_set_connect_state(ctx->wssl.handle);
wolfSSL_set_quic_use_legacy_codepoint(ctx->wssl.handle, 0);
if(alpn)
wolfSSL_set_alpn_protos(ctx->wssl.handle, (const unsigned char *)alpn,
(unsigned int)alpn_len);
if(peer->sni) {
wolfSSL_UseSNI(ctx->wssl.handle, WOLFSSL_SNI_HOST_NAME,
peer->sni, (unsigned short)strlen(peer->sni));
}
if(ssl_config->primary.cache_session) {
(void)Curl_wssl_setup_session(cf, data, &ctx->wssl, peer->scache_key);
}
return CURLE_OK;
}
#endif /* defined(USE_WOLFSSL) */
CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx, CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx,
struct Curl_cfilter *cf, struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
struct ssl_peer *peer, struct ssl_peer *peer,
const struct alpn_spec *alpns, const char *alpn, size_t alpn_len,
Curl_vquic_tls_ctx_setup *cb_setup, Curl_vquic_tls_ctx_setup *cb_setup,
void *cb_user_data, void *ssl_user_data, void *cb_user_data, void *ssl_user_data,
Curl_vquic_session_reuse_cb *session_reuse_cb) Curl_vquic_session_reuse_cb *session_reuse_cb)
@ -87,16 +254,21 @@ CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx,
#ifdef USE_OPENSSL #ifdef USE_OPENSSL
(void)result; (void)result;
return Curl_ossl_ctx_init(&ctx->ossl, cf, data, peer, alpns, return Curl_ossl_ctx_init(&ctx->ossl, cf, data, peer,
(const unsigned char *)alpn, alpn_len,
cb_setup, cb_user_data, NULL, ssl_user_data); cb_setup, cb_user_data, NULL, ssl_user_data);
#elif defined(USE_GNUTLS) #elif defined(USE_GNUTLS)
return Curl_gtls_ctx_init(&ctx->gtls, cf, data, peer, alpns, return Curl_gtls_ctx_init(&ctx->gtls, cf, data, peer,
(const unsigned char *)alpn, alpn_len,
cb_setup, cb_user_data, ssl_user_data, cb_setup, cb_user_data, ssl_user_data,
session_reuse_cb); session_reuse_cb);
#elif defined(USE_WOLFSSL) #elif defined(USE_WOLFSSL)
return Curl_wssl_ctx_init(&ctx->wssl, cf, data, peer, alpns, result = wssl_init_ctx(ctx, cf, data, cb_setup, cb_user_data);
cb_setup, cb_user_data, if(result)
ssl_user_data, session_reuse_cb); return result;
(void)session_reuse_cb;
return wssl_init_ssl(ctx, cf, data, peer, alpn, alpn_len, ssl_user_data);
#else #else
#error "no TLS lib in used, should not happen" #error "no TLS lib in used, should not happen"
return CURLE_FAILED_INIT; return CURLE_FAILED_INIT;
@ -115,10 +287,10 @@ void Curl_vquic_tls_cleanup(struct curl_tls_ctx *ctx)
gnutls_deinit(ctx->gtls.session); gnutls_deinit(ctx->gtls.session);
Curl_gtls_shared_creds_free(&ctx->gtls.shared_creds); Curl_gtls_shared_creds_free(&ctx->gtls.shared_creds);
#elif defined(USE_WOLFSSL) #elif defined(USE_WOLFSSL)
if(ctx->wssl.ssl) if(ctx->wssl.handle)
wolfSSL_free(ctx->wssl.ssl); wolfSSL_free(ctx->wssl.handle);
if(ctx->wssl.ssl_ctx) if(ctx->wssl.ctx)
wolfSSL_CTX_free(ctx->wssl.ssl_ctx); wolfSSL_CTX_free(ctx->wssl.ctx);
#endif #endif
memset(ctx, 0, sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx));
} }
@ -179,7 +351,7 @@ CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx,
(void)data; (void)data;
if(conn_config->verifyhost) { if(conn_config->verifyhost) {
if(peer->sni) { if(peer->sni) {
WOLFSSL_X509* cert = wolfSSL_get_peer_certificate(ctx->wssl.ssl); WOLFSSL_X509* cert = wolfSSL_get_peer_certificate(ctx->wssl.handle);
if(wolfSSL_X509_check_host(cert, peer->sni, strlen(peer->sni), 0, NULL) if(wolfSSL_X509_check_host(cert, peer->sni, strlen(peer->sni), 0, NULL)
== WOLFSSL_FAILURE) { == WOLFSSL_FAILURE) {
result = CURLE_PEER_FAILED_VERIFICATION; result = CURLE_PEER_FAILED_VERIFICATION;

View File

@ -27,7 +27,6 @@
#include "curl_setup.h" #include "curl_setup.h"
#include "bufq.h" #include "bufq.h"
#include "vtls/vtls.h" #include "vtls/vtls.h"
#include "vtls/vtls_int.h"
#include "vtls/openssl.h" #include "vtls/openssl.h"
#if defined(USE_HTTP3) && \ #if defined(USE_HTTP3) && \
@ -44,7 +43,7 @@ struct curl_tls_ctx {
#elif defined(USE_GNUTLS) #elif defined(USE_GNUTLS)
struct gtls_ctx gtls; struct gtls_ctx gtls;
#elif defined(USE_WOLFSSL) #elif defined(USE_WOLFSSL)
struct wssl_ctx wssl; struct wolfssl_ctx wssl;
#endif #endif
}; };
@ -61,7 +60,6 @@ typedef CURLcode Curl_vquic_tls_ctx_setup(struct Curl_cfilter *cf,
typedef CURLcode Curl_vquic_session_reuse_cb(struct Curl_cfilter *cf, typedef CURLcode Curl_vquic_session_reuse_cb(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
struct alpn_spec *alpns,
struct Curl_ssl_session *scs, struct Curl_ssl_session *scs,
bool *do_early_data); bool *do_early_data);
@ -72,7 +70,9 @@ typedef CURLcode Curl_vquic_session_reuse_cb(struct Curl_cfilter *cf,
* @param cf the connection filter involved * @param cf the connection filter involved
* @param data the transfer involved * @param data the transfer involved
* @param peer the peer that will be connected to * @param peer the peer that will be connected to
* @param alpns the ALPN specifications to negotiate, may be NULL * @param alpn the ALPN string in protocol format ((len+bytes+)+),
* may be NULL
* @param alpn_len the overall number of bytes in `alpn`
* @param cb_setup optional callback for early TLS config * @param cb_setup optional callback for early TLS config
* @param cb_user_data user_data param for callback * @param cb_user_data user_data param for callback
* @param ssl_user_data optional pointer to set in TLS application context * @param ssl_user_data optional pointer to set in TLS application context
@ -82,7 +82,7 @@ CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx,
struct Curl_cfilter *cf, struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
struct ssl_peer *peer, struct ssl_peer *peer,
const struct alpn_spec *alpns, const char *alpn, size_t alpn_len,
Curl_vquic_tls_ctx_setup *cb_setup, Curl_vquic_tls_ctx_setup *cb_setup,
void *cb_user_data, void *cb_user_data,
void *ssl_user_data, void *ssl_user_data,

View File

@ -959,7 +959,7 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf,
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
} }
else { else if(ssl_config->key_passwd) {
const unsigned int supported_key_encryption_algorithms = const unsigned int supported_key_encryption_algorithms =
GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR | GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES | GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
@ -974,12 +974,22 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf,
supported_key_encryption_algorithms); supported_key_encryption_algorithms);
if(rc != GNUTLS_E_SUCCESS) { if(rc != GNUTLS_E_SUCCESS) {
failf(data, failf(data,
"error reading X.509 %skey file: %s", "error reading X.509 potentially-encrypted key file: %s",
ssl_config->key_passwd ? "potentially-encrypted " : "",
gnutls_strerror(rc)); gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
} }
else {
if(gnutls_certificate_set_x509_key_file(
gtls->shared_creds->creds,
config->clientcert,
ssl_config->key ? ssl_config->key : config->clientcert,
gnutls_do_file_type(ssl_config->cert_type) ) !=
GNUTLS_E_SUCCESS) {
failf(data, "error reading X.509 key or certificate file");
return CURLE_SSL_CONNECT_ERROR;
}
}
} }
#ifdef USE_GNUTLS_SRP #ifdef USE_GNUTLS_SRP
@ -1032,7 +1042,6 @@ static int keylog_callback(gnutls_session_t session, const char *label,
static CURLcode gtls_on_session_reuse(struct Curl_cfilter *cf, static CURLcode gtls_on_session_reuse(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
struct alpn_spec *alpns,
struct Curl_ssl_session *scs, struct Curl_ssl_session *scs,
bool *do_early_data) bool *do_early_data)
{ {
@ -1048,13 +1057,13 @@ static CURLcode gtls_on_session_reuse(struct Curl_cfilter *cf,
/* Seems to be GnuTLS way to signal no EarlyData in session */ /* Seems to be GnuTLS way to signal no EarlyData in session */
CURL_TRC_CF(data, cf, "SSL session does not allow earlydata"); CURL_TRC_CF(data, cf, "SSL session does not allow earlydata");
} }
else if(!Curl_alpn_contains_proto(alpns, scs->alpn)) { else if(!Curl_alpn_contains_proto(connssl->alpn, scs->alpn)) {
CURL_TRC_CF(data, cf, "SSL session has different ALPN, no early data"); CURL_TRC_CF(data, cf, "SSL session has different ALPN, no early data");
} }
else { else {
infof(data, "SSL session allows %zu bytes of early data, " infof(data, "SSL session allows %zu bytes of early data, "
"reusing ALPN '%s'", connssl->earlydata_max, scs->alpn); "reusing ALPN '%s'", connssl->earlydata_max, scs->alpn);
connssl->earlydata_state = ssl_earlydata_await; connssl->earlydata_state = ssl_earlydata_use;
connssl->state = ssl_connection_deferred; connssl->state = ssl_connection_deferred;
result = Curl_alpn_set_negotiated(cf, data, connssl, result = Curl_alpn_set_negotiated(cf, data, connssl,
(const unsigned char *)scs->alpn, (const unsigned char *)scs->alpn,
@ -1068,7 +1077,7 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
struct Curl_cfilter *cf, struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
struct ssl_peer *peer, struct ssl_peer *peer,
const struct alpn_spec *alpns_requested, const unsigned char *alpn, size_t alpn_len,
Curl_gtls_ctx_setup_cb *cb_setup, Curl_gtls_ctx_setup_cb *cb_setup,
void *cb_user_data, void *cb_user_data,
void *ssl_user_data, void *ssl_user_data,
@ -1077,16 +1086,13 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
struct Curl_ssl_session *scs = NULL; struct Curl_ssl_session *scs = NULL;
gnutls_datum_t gtls_alpns[ALPN_ENTRIES_MAX]; gnutls_datum_t gtls_alpns[5];
size_t gtls_alpns_count = 0; size_t gtls_alpns_count = 0;
bool gtls_session_setup = FALSE; bool gtls_session_setup = FALSE;
struct alpn_spec alpns;
CURLcode result; CURLcode result;
int rc; int rc;
DEBUGASSERT(gctx); DEBUGASSERT(gctx);
Curl_alpn_copy(&alpns, alpns_requested);
/* This might be a reconnect, so we check for a session ID in the cache /* This might be a reconnect, so we check for a session ID in the cache
to speed up things. We need to do this before constructing the gnutls to speed up things. We need to do this before constructing the gnutls
session since we need to set flags depending on the kind of reuse. */ session since we need to set flags depending on the kind of reuse. */
@ -1095,8 +1101,7 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
if(result) if(result)
goto out; goto out;
if(scs && scs->sdata && scs->sdata_len && if(scs && scs->sdata && scs->sdata_len) {
(!scs->alpn || Curl_alpn_contains_proto(&alpns, scs->alpn))) {
/* we got a cached session, use it! */ /* we got a cached session, use it! */
result = gtls_client_init(cf, data, peer, scs->earlydata_max, gctx); result = gtls_client_init(cf, data, peer, scs->earlydata_max, gctx);
@ -1110,19 +1115,30 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
else { else {
infof(data, "SSL reusing session with ALPN '%s'", infof(data, "SSL reusing session with ALPN '%s'",
scs->alpn ? scs->alpn : "-"); scs->alpn ? scs->alpn : "-");
if(ssl_config->earlydata && scs->alpn && if(ssl_config->earlydata &&
!cf->conn->connect_only && !cf->conn->connect_only &&
(gnutls_protocol_get_version(gctx->session) == GNUTLS_TLS1_3)) { (gnutls_protocol_get_version(gctx->session) == GNUTLS_TLS1_3)) {
bool do_early_data = FALSE; bool do_early_data = FALSE;
if(sess_reuse_cb) { if(sess_reuse_cb) {
result = sess_reuse_cb(cf, data, &alpns, scs, &do_early_data); result = sess_reuse_cb(cf, data, scs, &do_early_data);
if(result) if(result)
goto out; goto out;
} }
if(do_early_data) { if(do_early_data) {
/* We only try the ALPN protocol the session used before, /* We only try the ALPN protocol the session used before,
* otherwise we might send early data for the wrong protocol */ * otherwise we might send early data for the wrong protocol */
Curl_alpn_restrict_to(&alpns, scs->alpn); gtls_alpns[0].data = (unsigned char *)scs->alpn;
gtls_alpns[0].size = (unsigned)strlen(scs->alpn);
if(gnutls_alpn_set_protocols(gctx->session,
gtls_alpns, 1,
GNUTLS_ALPN_MANDATORY)) {
failf(data, "failed setting ALPN");
result = CURLE_SSL_CONNECT_ERROR;
goto out;
}
/* don't set again below */
gtls_alpns_count = 0;
alpn = NULL;
} }
} }
} }
@ -1152,14 +1168,24 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
/* convert the ALPN string from our arguments to a list of strings that /* convert the ALPN string from our arguments to a list of strings that
* gnutls wants and will convert internally back to this string for sending * gnutls wants and will convert internally back to this string for sending
* to the server. nice. */ * to the server. nice. */
if(!gtls_alpns_count && alpns.count) { if(!gtls_alpns_count && alpn && alpn_len) {
size_t i; size_t i, alen = alpn_len;
DEBUGASSERT(CURL_ARRAYSIZE(gtls_alpns) >= alpns.count); unsigned char *salpn = (unsigned char *)alpn;
for(i = 0; i < alpns.count; ++i) { unsigned char slen;
gtls_alpns[i].data = (unsigned char *)alpns.entries[i]; for(i = 0; (i < CURL_ARRAYSIZE(gtls_alpns)) && alen; ++i) {
gtls_alpns[i].size = (unsigned int)strlen(alpns.entries[i]); slen = salpn[0];
if(slen >= alen)
return CURLE_FAILED_INIT;
gtls_alpns[i].data = salpn + 1;
gtls_alpns[i].size = slen;
salpn += slen + 1;
alen -= (size_t)slen + 1;
} }
gtls_alpns_count = alpns.count; if(alen) { /* not all alpn chars used, wrong format or too many */
result = CURLE_FAILED_INIT;
goto out;
}
gtls_alpns_count = i;
} }
if(gtls_alpns_count && if(gtls_alpns_count &&
@ -1181,6 +1207,7 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
struct gtls_ssl_backend_data *backend = struct gtls_ssl_backend_data *backend =
(struct gtls_ssl_backend_data *)connssl->backend; (struct gtls_ssl_backend_data *)connssl->backend;
struct alpn_proto_buf proto;
CURLcode result; CURLcode result;
DEBUGASSERT(backend); DEBUGASSERT(backend);
@ -1190,15 +1217,22 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
same connection */ same connection */
return CURLE_OK; return CURLE_OK;
memset(&proto, 0, sizeof(proto));
if(connssl->alpn) {
result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
if(result) {
failf(data, "Error determining ALPN");
return CURLE_SSL_CONNECT_ERROR;
}
}
result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer, result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer,
connssl->alpn, NULL, NULL, cf, proto.data, proto.len,
gtls_on_session_reuse); NULL, NULL, cf, gtls_on_session_reuse);
if(result) if(result)
return result; return result;
if(connssl->alpn && (connssl->state != ssl_connection_deferred)) { if(connssl->alpn && (connssl->state != ssl_connection_deferred)) {
struct alpn_proto_buf proto;
memset(&proto, 0, sizeof(proto));
Curl_alpn_to_proto_str(&proto, connssl->alpn); Curl_alpn_to_proto_str(&proto, connssl->alpn);
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data); infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
} }
@ -1746,6 +1780,30 @@ out:
return result; return result;
} }
static CURLcode gtls_set_earlydata(struct Curl_cfilter *cf,
struct Curl_easy *data,
const void *buf, size_t blen)
{
struct ssl_connect_data *connssl = cf->ctx;
ssize_t nwritten = 0;
CURLcode result = CURLE_OK;
DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_use);
DEBUGASSERT(Curl_bufq_is_empty(&connssl->earlydata));
if(blen) {
if(blen > connssl->earlydata_max)
blen = connssl->earlydata_max;
nwritten = Curl_bufq_write(&connssl->earlydata, buf, blen, &result);
CURL_TRC_CF(data, cf, "gtls_set_earlydata(len=%zu) -> %zd",
blen, nwritten);
if(nwritten < 0)
return result;
}
connssl->earlydata_state = ssl_earlydata_sending;
connssl->earlydata_skip = Curl_bufq_len(&connssl->earlydata);
return CURLE_OK;
}
static CURLcode gtls_send_earlydata(struct Curl_cfilter *cf, static CURLcode gtls_send_earlydata(struct Curl_cfilter *cf,
struct Curl_easy *data) struct Curl_easy *data)
{ {
@ -1821,7 +1879,7 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
} }
if(connssl->connecting_state == ssl_connect_2) { if(connssl->connecting_state == ssl_connect_2) {
if(connssl->earlydata_state == ssl_earlydata_await) { if(connssl->earlydata_state == ssl_earlydata_use) {
goto out; goto out;
} }
else if(connssl->earlydata_state == ssl_earlydata_sending) { else if(connssl->earlydata_state == ssl_earlydata_sending) {
@ -1829,6 +1887,8 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
if(result) if(result)
goto out; goto out;
connssl->earlydata_state = ssl_earlydata_sent; connssl->earlydata_state = ssl_earlydata_sent;
if(!Curl_ssl_cf_is_proxy(cf))
Curl_pgrsEarlyData(data, (curl_off_t)connssl->earlydata_skip);
} }
DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) || DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) ||
(connssl->earlydata_state == ssl_earlydata_sent)); (connssl->earlydata_state == ssl_earlydata_sent));
@ -1860,19 +1920,31 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
if(result) if(result)
goto out; goto out;
if(connssl->earlydata_state > ssl_earlydata_none) { if(connssl->earlydata_state == ssl_earlydata_sent) {
/* We should be in this state by now */ /* report the true time the handshake was done */
DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sent); connssl->handshake_done = Curl_now();
connssl->earlydata_state = Curl_pgrsTimeWas(data, TIMER_APPCONNECT, connssl->handshake_done);
(gnutls_session_get_flags(backend->gtls.session) & if(gnutls_session_get_flags(backend->gtls.session) &
GNUTLS_SFLAGS_EARLY_DATA) ? GNUTLS_SFLAGS_EARLY_DATA) {
ssl_earlydata_accepted : ssl_earlydata_rejected; connssl->earlydata_state = ssl_earlydata_accepted;
infof(data, "Server accepted %zu bytes of TLS early data.",
connssl->earlydata_skip);
}
else {
connssl->earlydata_state = ssl_earlydata_rejected;
if(!Curl_ssl_cf_is_proxy(cf))
Curl_pgrsEarlyData(data, -(curl_off_t)connssl->earlydata_skip);
infof(data, "Server rejected TLS early data.");
connssl->earlydata_skip = 0;
}
} }
connssl->connecting_state = ssl_connect_done; connssl->connecting_state = ssl_connect_done;
} }
if(connssl->connecting_state == ssl_connect_done) if(ssl_connect_done == connssl->connecting_state) {
DEBUGASSERT(connssl->state == ssl_connection_complete); connssl->state = ssl_connection_complete;
*done = TRUE;
}
out: out:
if(result == CURLE_AGAIN) { if(result == CURLE_AGAIN) {
@ -1890,8 +1962,7 @@ static CURLcode gtls_connect(struct Curl_cfilter *cf,
bool *done) bool *done)
{ {
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
if((connssl->state == ssl_connection_deferred) && if(connssl->state == ssl_connection_deferred) {
(connssl->earlydata_state == ssl_earlydata_await)) {
/* We refuse to be pushed, we are waiting for someone to send/recv. */ /* We refuse to be pushed, we are waiting for someone to send/recv. */
*done = TRUE; *done = TRUE;
return CURLE_OK; return CURLE_OK;
@ -1899,6 +1970,26 @@ static CURLcode gtls_connect(struct Curl_cfilter *cf,
return gtls_connect_common(cf, data, done); return gtls_connect_common(cf, data, done);
} }
static CURLcode gtls_connect_deferred(struct Curl_cfilter *cf,
struct Curl_easy *data,
const void *buf,
size_t blen,
bool *done)
{
struct ssl_connect_data *connssl = cf->ctx;
CURLcode result = CURLE_OK;
DEBUGASSERT(connssl->state == ssl_connection_deferred);
*done = FALSE;
if(connssl->earlydata_state == ssl_earlydata_use) {
result = gtls_set_earlydata(cf, data, buf, blen);
if(result)
return result;
}
return gtls_connect_common(cf, data, done);
}
static bool gtls_data_pending(struct Curl_cfilter *cf, static bool gtls_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data) const struct Curl_easy *data)
{ {
@ -1926,9 +2017,38 @@ static ssize_t gtls_send(struct Curl_cfilter *cf,
ssize_t rc; ssize_t rc;
size_t nwritten, total_written = 0; size_t nwritten, total_written = 0;
(void)data;
DEBUGASSERT(backend); DEBUGASSERT(backend);
if(connssl->state == ssl_connection_deferred) {
bool done = FALSE;
*curlcode = gtls_connect_deferred(cf, data, buf, blen, &done);
if(*curlcode) {
rc = -1;
goto out;
}
else if(!done) {
*curlcode = CURLE_AGAIN;
rc = -1;
goto out;
}
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
if(connssl->earlydata_skip) {
if(connssl->earlydata_skip >= blen) {
connssl->earlydata_skip -= blen;
*curlcode = CURLE_OK;
rc = (ssize_t)blen;
goto out;
}
else {
total_written += connssl->earlydata_skip;
buf = ((const char *)buf) + connssl->earlydata_skip;
blen -= connssl->earlydata_skip;
connssl->earlydata_skip = 0;
}
}
while(blen) { while(blen) {
backend->gtls.io_result = CURLE_OK; backend->gtls.io_result = CURLE_OK;
rc = gnutls_record_send(backend->gtls.session, buf, blen); rc = gnutls_record_send(backend->gtls.session, buf, blen);
@ -2075,6 +2195,21 @@ static ssize_t gtls_recv(struct Curl_cfilter *cf,
(void)data; (void)data;
DEBUGASSERT(backend); DEBUGASSERT(backend);
if(connssl->state == ssl_connection_deferred) {
bool done = FALSE;
*curlcode = gtls_connect_deferred(cf, data, NULL, 0, &done);
if(*curlcode) {
ret = -1;
goto out;
}
else if(!done) {
*curlcode = CURLE_AGAIN;
ret = -1;
goto out;
}
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
ret = gnutls_record_recv(backend->gtls.session, buf, buffersize); ret = gnutls_record_recv(backend->gtls.session, buf, buffersize);
if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) { if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
*curlcode = CURLE_AGAIN; *curlcode = CURLE_AGAIN;

View File

@ -42,7 +42,6 @@
struct Curl_easy; struct Curl_easy;
struct Curl_cfilter; struct Curl_cfilter;
struct alpn_spec;
struct ssl_primary_config; struct ssl_primary_config;
struct ssl_config_data; struct ssl_config_data;
struct ssl_peer; struct ssl_peer;
@ -82,7 +81,6 @@ typedef CURLcode Curl_gtls_ctx_setup_cb(struct Curl_cfilter *cf,
typedef CURLcode Curl_gtls_init_session_reuse_cb(struct Curl_cfilter *cf, typedef CURLcode Curl_gtls_init_session_reuse_cb(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
struct alpn_spec *alpns,
struct Curl_ssl_session *scs, struct Curl_ssl_session *scs,
bool *do_early_data); bool *do_early_data);
@ -90,7 +88,7 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
struct Curl_cfilter *cf, struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
struct ssl_peer *peer, struct ssl_peer *peer,
const struct alpn_spec *alpns, const unsigned char *alpn, size_t alpn_len,
Curl_gtls_ctx_setup_cb *cb_setup, Curl_gtls_ctx_setup_cb *cb_setup,
void *cb_user_data, void *cb_user_data,
void *ssl_user_data, void *ssl_user_data,

View File

@ -3527,7 +3527,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
struct Curl_cfilter *cf, struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
struct ssl_peer *peer, struct ssl_peer *peer,
const struct alpn_spec *alpns, const unsigned char *alpn, size_t alpn_len,
Curl_ossl_ctx_setup_cb *cb_setup, Curl_ossl_ctx_setup_cb *cb_setup,
void *cb_user_data, void *cb_user_data,
Curl_ossl_new_session_cb *cb_new_session, Curl_ossl_new_session_cb *cb_new_session,
@ -3722,21 +3722,14 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
SSL_CTX_set_mode(octx->ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); SSL_CTX_set_mode(octx->ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
#endif #endif
if(alpn && alpn_len) {
#ifdef HAS_ALPN_OPENSSL #ifdef HAS_ALPN_OPENSSL
if(alpns && alpns->count) { if(SSL_CTX_set_alpn_protos(octx->ssl_ctx, alpn, (int)alpn_len)) {
struct alpn_proto_buf proto;
memset(&proto, 0, sizeof(proto));
result = Curl_alpn_to_proto_buf(&proto, alpns);
if(result) {
failf(data, "Error determining ALPN");
return CURLE_SSL_CONNECT_ERROR;
}
if(SSL_CTX_set_alpn_protos(octx->ssl_ctx, proto.data, (int)proto.len)) {
failf(data, "Error setting ALPN"); failf(data, "Error setting ALPN");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
}
#endif #endif
}
if(ssl_cert || ssl_cert_blob || ssl_cert_type) { if(ssl_cert || ssl_cert_blob || ssl_cert_type) {
if(!result && if(!result &&
@ -4060,14 +4053,25 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
{ {
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend; struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
struct alpn_proto_buf proto;
BIO *bio; BIO *bio;
CURLcode result; CURLcode result;
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
DEBUGASSERT(octx); DEBUGASSERT(octx);
memset(&proto, 0, sizeof(proto));
#ifdef HAS_ALPN_OPENSSL
if(connssl->alpn) {
result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
if(result) {
failf(data, "Error determining ALPN");
return CURLE_SSL_CONNECT_ERROR;
}
}
#endif
result = Curl_ossl_ctx_init(octx, cf, data, &connssl->peer, result = Curl_ossl_ctx_init(octx, cf, data, &connssl->peer,
connssl->alpn, NULL, NULL, proto.data, proto.len, NULL, NULL,
ossl_new_session_cb, cf); ossl_new_session_cb, cf);
if(result) if(result)
return result; return result;
@ -4095,8 +4099,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
#ifdef HAS_ALPN_OPENSSL #ifdef HAS_ALPN_OPENSSL
if(connssl->alpn) { if(connssl->alpn) {
struct alpn_proto_buf proto;
memset(&proto, 0, sizeof(proto));
Curl_alpn_to_proto_str(&proto, connssl->alpn); Curl_alpn_to_proto_str(&proto, connssl->alpn);
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data); infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
} }
@ -4532,7 +4534,7 @@ static void infof_certstack(struct Curl_easy *data, const SSL *ssl)
sizeof(group_name), NULL); sizeof(group_name), NULL);
msnprintf(group_name_final, sizeof(group_name_final), "/%s", group_name); msnprintf(group_name_final, sizeof(group_name_final), "/%s", group_name);
} }
type_name = current_pkey ? EVP_PKEY_get0_type_name(current_pkey) : NULL; type_name = EVP_PKEY_get0_type_name(current_pkey);
#else #else
get_group_name = 0; get_group_name = 0;
type_name = NULL; type_name = NULL;

View File

@ -49,7 +49,6 @@
#define HAVE_KEYLOG_CALLBACK #define HAVE_KEYLOG_CALLBACK
#endif #endif
struct alpn_spec;
struct ssl_peer; struct ssl_peer;
/* Struct to hold a curl OpenSSL instance */ /* Struct to hold a curl OpenSSL instance */
@ -81,7 +80,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
struct Curl_cfilter *cf, struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
struct ssl_peer *peer, struct ssl_peer *peer,
const struct alpn_spec *alpns, const unsigned char *alpn, size_t alpn_len,
Curl_ossl_ctx_setup_cb *cb_setup, Curl_ossl_ctx_setup_cb *cb_setup,
void *cb_user_data, void *cb_user_data,
Curl_ossl_new_session_cb *cb_new_session, Curl_ossl_new_session_cb *cb_new_session,

View File

@ -43,7 +43,6 @@
#include "connect.h" /* for the connect timeout */ #include "connect.h" /* for the connect timeout */
#include "cipher_suite.h" #include "cipher_suite.h"
#include "rand.h" #include "rand.h"
#include "x509asn1.h"
struct rustls_ssl_backend_data struct rustls_ssl_backend_data
{ {
@ -846,43 +845,6 @@ cr_connect(struct Curl_cfilter *cf,
infof(data, "rustls: handshake complete, %s, cipher: %s", infof(data, "rustls: handshake complete, %s, cipher: %s",
ver, buf); ver, buf);
} }
if(data->set.ssl.certinfo) {
size_t num_certs = 0;
while(rustls_connection_get_peer_certificate(rconn, (int)num_certs)) {
num_certs++;
}
result = Curl_ssl_init_certinfo(data, (int)num_certs);
if(result)
return result;
for(size_t i = 0; i < num_certs; i++) {
const rustls_certificate *cert;
const unsigned char *der_data;
size_t der_len;
rustls_result rresult = RUSTLS_RESULT_OK;
cert = rustls_connection_get_peer_certificate(rconn, i);
DEBUGASSERT(cert); /* Should exist since we counted already */
rresult = rustls_certificate_get_der(cert, &der_data, &der_len);
if(rresult != RUSTLS_RESULT_OK) {
char errorbuf[255];
size_t errorlen;
rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
failf(data,
"Failed getting DER of server certificate #%ld: %.*s", i,
(int)errorlen, errorbuf);
return map_error(rresult);
}
{
const char *beg;
const char *end;
beg = (const char *)der_data;
end = (const char *)(der_data + der_len);
result = Curl_extract_certinfo(data, (int)i, beg, end);
if(result)
return result;
}
}
}
connssl->state = ssl_connection_complete; connssl->state = ssl_connection_complete;
*done = TRUE; *done = TRUE;
return CURLE_OK; return CURLE_OK;
@ -1049,8 +1011,7 @@ const struct Curl_ssl Curl_ssl_rustls = {
SSLSUPP_CAINFO_BLOB | /* supports */ SSLSUPP_CAINFO_BLOB | /* supports */
SSLSUPP_HTTPS_PROXY | SSLSUPP_HTTPS_PROXY |
SSLSUPP_CIPHER_LIST | SSLSUPP_CIPHER_LIST |
SSLSUPP_TLS13_CIPHERSUITES | SSLSUPP_TLS13_CIPHERSUITES,
SSLSUPP_CERTINFO,
sizeof(struct rustls_ssl_backend_data), sizeof(struct rustls_ssl_backend_data),
NULL, /* init */ NULL, /* init */

View File

@ -898,6 +898,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
unsigned char alpn_buffer[128]; unsigned char alpn_buffer[128];
#endif #endif
SECURITY_STATUS sspi_status = SEC_E_OK; SECURITY_STATUS sspi_status = SEC_E_OK;
struct Curl_schannel_cred *old_cred = NULL;
CURLcode result; CURLcode result;
DEBUGASSERT(backend); DEBUGASSERT(backend);
@ -954,10 +955,9 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
/* check for an existing reusable credential handle */ /* check for an existing reusable credential handle */
if(ssl_config->primary.cache_session) { if(ssl_config->primary.cache_session) {
struct Curl_schannel_cred *old_cred;
Curl_ssl_scache_lock(data); Curl_ssl_scache_lock(data);
old_cred = Curl_ssl_scache_get_obj(cf, data, connssl->peer.scache_key); if(Curl_ssl_scache_get_obj(cf, data, connssl->peer.scache_key,
if(old_cred) { (void **)&old_cred)) {
backend->cred = old_cred; backend->cred = old_cred;
DEBUGF(infof(data, "schannel: reusing existing credential handle")); DEBUGF(infof(data, "schannel: reusing existing credential handle"));

View File

@ -1333,9 +1333,8 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
size_t ssl_sessionid_len; size_t ssl_sessionid_len;
Curl_ssl_scache_lock(data); Curl_ssl_scache_lock(data);
ssl_sessionid = Curl_ssl_scache_get_obj(cf, data, if(Curl_ssl_scache_get_obj(cf, data, connssl->peer.scache_key,
connssl->peer.scache_key); (void **)&ssl_sessionid)) {
if(ssl_sessionid) {
/* we got a session id, use it! */ /* we got a session id, use it! */
err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid,
strlen(ssl_sessionid)); strlen(ssl_sessionid));

View File

@ -485,6 +485,18 @@ static void cf_ctx_free(struct ssl_connect_data *ctx)
} }
} }
static CURLcode
ssl_connect(struct Curl_cfilter *cf, struct Curl_easy *data, bool *done)
{
struct ssl_connect_data *connssl = cf->ctx;
if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
/* mark this is being ssl requested from here on. */
return connssl->ssl_impl->do_connect(cf, data, done);
}
CURLcode Curl_ssl_get_channel_binding(struct Curl_easy *data, int sockindex, CURLcode Curl_ssl_get_channel_binding(struct Curl_easy *data, int sockindex,
struct dynbuf *binding) struct dynbuf *binding)
{ {
@ -1306,7 +1318,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
struct cf_call_data save; struct cf_call_data save;
CURLcode result; CURLcode result;
if(cf->connected && (connssl->state != ssl_connection_deferred)) { if(cf->connected) {
*done = TRUE; *done = TRUE;
return CURLE_OK; return CURLE_OK;
} }
@ -1324,6 +1336,8 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
CF_DATA_SAVE(save, cf, data); CF_DATA_SAVE(save, cf, data);
CURL_TRC_CF(data, cf, "cf_connect()"); CURL_TRC_CF(data, cf, "cf_connect()");
DEBUGASSERT(data->conn);
DEBUGASSERT(data->conn == cf->conn);
DEBUGASSERT(connssl); DEBUGASSERT(connssl);
*done = FALSE; *done = FALSE;
@ -1335,13 +1349,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
goto out; goto out;
} }
if(!connssl->prefs_checked) { result = ssl_connect(cf, data, done);
if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
connssl->prefs_checked = TRUE;
}
result = connssl->ssl_impl->do_connect(cf, data, done);
if(!result && *done) { if(!result && *done) {
cf->connected = TRUE; cf->connected = TRUE;
@ -1350,8 +1358,6 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
/* Connection can be deferred when sending early data */ /* Connection can be deferred when sending early data */
DEBUGASSERT(connssl->state == ssl_connection_complete || DEBUGASSERT(connssl->state == ssl_connection_complete ||
connssl->state == ssl_connection_deferred); connssl->state == ssl_connection_deferred);
DEBUGASSERT(connssl->state != ssl_connection_deferred ||
connssl->earlydata_state > ssl_earlydata_none);
} }
out: out:
CURL_TRC_CF(data, cf, "cf_connect() -> %d, done=%d", result, *done); CURL_TRC_CF(data, cf, "cf_connect() -> %d, done=%d", result, *done);
@ -1359,77 +1365,6 @@ out:
return result; return result;
} }
static CURLcode ssl_cf_set_earlydata(struct Curl_cfilter *cf,
struct Curl_easy *data,
const void *buf, size_t blen)
{
struct ssl_connect_data *connssl = cf->ctx;
ssize_t nwritten = 0;
CURLcode result = CURLE_OK;
DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_await);
DEBUGASSERT(Curl_bufq_is_empty(&connssl->earlydata));
if(blen) {
if(blen > connssl->earlydata_max)
blen = connssl->earlydata_max;
nwritten = Curl_bufq_write(&connssl->earlydata, buf, blen, &result);
CURL_TRC_CF(data, cf, "ssl_cf_set_earlydata(len=%zu) -> %zd",
blen, nwritten);
if(nwritten < 0)
return result;
}
return CURLE_OK;
}
static CURLcode ssl_cf_connect_deferred(struct Curl_cfilter *cf,
struct Curl_easy *data,
const void *buf, size_t blen,
bool *done)
{
struct ssl_connect_data *connssl = cf->ctx;
CURLcode result = CURLE_OK;
DEBUGASSERT(connssl->state == ssl_connection_deferred);
*done = FALSE;
if(connssl->earlydata_state == ssl_earlydata_await) {
result = ssl_cf_set_earlydata(cf, data, buf, blen);
if(result)
return result;
/* we buffered any early data we'd like to send. Actually
* do the connect now which sends it and performs the handshake. */
connssl->earlydata_state = ssl_earlydata_sending;
connssl->earlydata_skip = Curl_bufq_len(&connssl->earlydata);
}
result = ssl_cf_connect(cf, data, done);
if(!result && *done) {
Curl_pgrsTimeWas(data, TIMER_APPCONNECT, connssl->handshake_done);
switch(connssl->earlydata_state) {
case ssl_earlydata_none:
break;
case ssl_earlydata_accepted:
if(!Curl_ssl_cf_is_proxy(cf))
Curl_pgrsEarlyData(data, (curl_off_t)connssl->earlydata_skip);
infof(data, "Server accepted %zu bytes of TLS early data.",
connssl->earlydata_skip);
break;
case ssl_earlydata_rejected:
if(!Curl_ssl_cf_is_proxy(cf))
Curl_pgrsEarlyData(data, -(curl_off_t)connssl->earlydata_skip);
infof(data, "Server rejected TLS early data.");
connssl->earlydata_skip = 0;
break;
default:
/* This should not happen. Either we do not use early data or we
* should know if it was accepted or not. */
DEBUGASSERT(NULL);
break;
}
}
return result;
}
static bool ssl_cf_data_pending(struct Curl_cfilter *cf, static bool ssl_cf_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data) const struct Curl_easy *data)
{ {
@ -1448,57 +1383,21 @@ static bool ssl_cf_data_pending(struct Curl_cfilter *cf,
} }
static ssize_t ssl_cf_send(struct Curl_cfilter *cf, static ssize_t ssl_cf_send(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data, const void *buf, size_t len,
const void *buf, size_t blen,
bool eos, CURLcode *err) bool eos, CURLcode *err)
{ {
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
struct cf_call_data save; struct cf_call_data save;
ssize_t nwritten = 0, early_written = 0; ssize_t nwritten = 0;
(void)eos; (void)eos;
*err = CURLE_OK;
CF_DATA_SAVE(save, cf, data);
if(connssl->state == ssl_connection_deferred) {
bool done = FALSE;
*err = ssl_cf_connect_deferred(cf, data, buf, blen, &done);
if(*err) {
nwritten = -1;
goto out;
}
else if(!done) {
*err = CURLE_AGAIN;
nwritten = -1;
goto out;
}
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
if(connssl->earlydata_skip) {
if(connssl->earlydata_skip >= blen) {
connssl->earlydata_skip -= blen;
*err = CURLE_OK;
nwritten = (ssize_t)blen;
goto out;
}
else {
early_written = connssl->earlydata_skip;
buf = ((const char *)buf) + connssl->earlydata_skip;
blen -= connssl->earlydata_skip;
connssl->earlydata_skip = 0;
}
}
/* OpenSSL and maybe other TLS libs do not like 0-length writes. Skip. */ /* OpenSSL and maybe other TLS libs do not like 0-length writes. Skip. */
if(blen > 0) *err = CURLE_OK;
nwritten = connssl->ssl_impl->send_plain(cf, data, buf, blen, err); if(len > 0) {
CF_DATA_SAVE(save, cf, data);
if(nwritten >= 0) nwritten = connssl->ssl_impl->send_plain(cf, data, buf, len, err);
nwritten += early_written;
out:
CF_DATA_RESTORE(cf, save); CF_DATA_RESTORE(cf, save);
}
return nwritten; return nwritten;
} }
@ -1512,21 +1411,6 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
CF_DATA_SAVE(save, cf, data); CF_DATA_SAVE(save, cf, data);
*err = CURLE_OK; *err = CURLE_OK;
if(connssl->state == ssl_connection_deferred) {
bool done = FALSE;
*err = ssl_cf_connect_deferred(cf, data, NULL, 0, &done);
if(*err) {
nread = -1;
goto out;
}
else if(!done) {
*err = CURLE_AGAIN;
nread = -1;
goto out;
}
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
nread = connssl->ssl_impl->recv_plain(cf, data, buf, len, err); nread = connssl->ssl_impl->recv_plain(cf, data, buf, len, err);
if(nread > 0) { if(nread > 0) {
DEBUGASSERT((size_t)nread <= len); DEBUGASSERT((size_t)nread <= len);
@ -1535,8 +1419,6 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
/* eof */ /* eof */
*err = CURLE_OK; *err = CURLE_OK;
} }
out:
CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len, CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len,
nread, *err); nread, *err);
CF_DATA_RESTORE(cf, save); CF_DATA_RESTORE(cf, save);
@ -1551,9 +1433,7 @@ static CURLcode ssl_cf_shutdown(struct Curl_cfilter *cf,
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
*done = TRUE; *done = TRUE;
/* If we have done the SSL handshake, shut down the connection cleanly */ if(!cf->shutdown && Curl_ssl->shut_down) {
if(cf->connected && (connssl->state == ssl_connection_complete) &&
!cf->shutdown && Curl_ssl->shut_down) {
struct cf_call_data save; struct cf_call_data save;
CF_DATA_SAVE(save, cf, data); CF_DATA_SAVE(save, cf, data);
@ -1951,24 +1831,6 @@ bool Curl_alpn_contains_proto(const struct alpn_spec *spec,
return FALSE; return FALSE;
} }
void Curl_alpn_restrict_to(struct alpn_spec *spec, const char *proto)
{
size_t plen = strlen(proto);
DEBUGASSERT(plen < sizeof(spec->entries[0]));
if(plen < sizeof(spec->entries[0])) {
memcpy(spec->entries[0], proto, plen + 1);
spec->count = 1;
}
}
void Curl_alpn_copy(struct alpn_spec *dest, const struct alpn_spec *src)
{
if(src)
memcpy(dest, src, sizeof(*dest));
else
memset(dest, 0, sizeof(*dest));
}
CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf, CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
struct ssl_connect_data *connssl, struct ssl_connect_data *connssl,

View File

@ -49,7 +49,7 @@ struct ssl_connect_data;
#define ALPN_PROTO_BUF_MAX (ALPN_ENTRIES_MAX * (ALPN_NAME_MAX + 1)) #define ALPN_PROTO_BUF_MAX (ALPN_ENTRIES_MAX * (ALPN_NAME_MAX + 1))
struct alpn_spec { struct alpn_spec {
char entries[ALPN_ENTRIES_MAX][ALPN_NAME_MAX]; const char entries[ALPN_ENTRIES_MAX][ALPN_NAME_MAX];
size_t count; /* number of entries */ size_t count; /* number of entries */
}; };
@ -62,8 +62,6 @@ CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf,
const struct alpn_spec *spec); const struct alpn_spec *spec);
CURLcode Curl_alpn_to_proto_str(struct alpn_proto_buf *buf, CURLcode Curl_alpn_to_proto_str(struct alpn_proto_buf *buf,
const struct alpn_spec *spec); const struct alpn_spec *spec);
void Curl_alpn_restrict_to(struct alpn_spec *spec, const char *proto);
void Curl_alpn_copy(struct alpn_spec *dest, const struct alpn_spec *src);
CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf, CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
@ -91,7 +89,7 @@ typedef enum {
typedef enum { typedef enum {
ssl_earlydata_none, ssl_earlydata_none,
ssl_earlydata_await, ssl_earlydata_use,
ssl_earlydata_sending, ssl_earlydata_sending,
ssl_earlydata_sent, ssl_earlydata_sent,
ssl_earlydata_accepted, ssl_earlydata_accepted,
@ -126,7 +124,6 @@ struct ssl_connect_data {
int io_need; /* TLS signals special SEND/RECV needs */ int io_need; /* TLS signals special SEND/RECV needs */
BIT(use_alpn); /* if ALPN shall be used in handshake */ BIT(use_alpn); /* if ALPN shall be used in handshake */
BIT(peer_closed); /* peer has closed connection */ BIT(peer_closed); /* peer has closed connection */
BIT(prefs_checked); /* SSL preferences have been checked */
}; };

View File

@ -962,29 +962,31 @@ out:
return result; return result;
} }
void *Curl_ssl_scache_get_obj(struct Curl_cfilter *cf, bool Curl_ssl_scache_get_obj(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
const char *ssl_peer_key) const char *ssl_peer_key,
void **sobj)
{ {
struct Curl_ssl_scache *scache = cf_ssl_scache_get(data); struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct Curl_ssl_scache_peer *peer = NULL; struct Curl_ssl_scache_peer *peer = NULL;
CURLcode result; CURLcode result;
void *sobj;
*sobj = NULL;
if(!scache) if(!scache)
return NULL; return FALSE;
result = cf_ssl_find_peer_by_key(data, scache, ssl_peer_key, conn_config, result = cf_ssl_find_peer_by_key(data, scache, ssl_peer_key, conn_config,
&peer); &peer);
if(result) if(result)
return NULL; return FALSE;
sobj = peer ? peer->sobj : NULL; if(peer)
*sobj = peer->sobj;
CURL_TRC_SSLS(data, "%s cached session for '%s'", CURL_TRC_SSLS(data, "%s cached session for '%s'",
sobj ? "Found" : "No", ssl_peer_key); *sobj ? "Found" : "No", ssl_peer_key);
return sobj; return !!*sobj;
} }
void Curl_ssl_scache_remove_all(struct Curl_cfilter *cf, void Curl_ssl_scache_remove_all(struct Curl_cfilter *cf,

View File

@ -85,11 +85,12 @@ void Curl_ssl_scache_unlock(struct Curl_easy *data);
* @param cf the connection filter wanting to use it * @param cf the connection filter wanting to use it
* @param data the transfer involved * @param data the transfer involved
* @param ssl_peer_key the key for lookup * @param ssl_peer_key the key for lookup
* @retval sobj the object for the peer key or NULL * @param sobj on return, the object for the peer key or NULL
*/ */
void *Curl_ssl_scache_get_obj(struct Curl_cfilter *cf, bool Curl_ssl_scache_get_obj(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
const char *ssl_peer_key); const char *ssl_peer_key,
void **sobj);
typedef void Curl_ssl_scache_obj_dtor(void *sobj); typedef void Curl_ssl_scache_obj_dtor(void *sobj);

File diff suppressed because it is too large Load Diff

View File

@ -29,21 +29,19 @@
#include "urldata.h" #include "urldata.h"
struct alpn_spec;
struct ssl_peer;
struct Curl_ssl_session;
struct WOLFSSL; struct WOLFSSL;
typedef struct WOLFSSL WOLFSSL;
struct WOLFSSL_CTX; struct WOLFSSL_CTX;
typedef struct WOLFSSL_CTX WOLFSSL_CTX;
struct WOLFSSL_SESSION; struct WOLFSSL_SESSION;
typedef struct WOLFSSL_SESSION WOLFSSL_SESSION;
extern const struct Curl_ssl Curl_ssl_wolfssl; extern const struct Curl_ssl Curl_ssl_wolfssl;
struct wssl_ctx { struct wolfssl_ctx {
struct WOLFSSL_CTX *ssl_ctx; WOLFSSL_CTX *ctx;
struct WOLFSSL *ssl; WOLFSSL *handle;
CURLcode io_result; /* result of last BIO cfilter operation */ CURLcode io_result; /* result of last BIO cfilter operation */
CURLcode hs_result; /* result of handshake */
int io_send_blocked_len; /* length of last BIO write that EAGAINed */ int io_send_blocked_len; /* length of last BIO write that EAGAINed */
BIT(x509_store_setup); /* x509 store has been set up */ BIT(x509_store_setup); /* x509 store has been set up */
BIT(shutting_down); /* TLS is being shut down */ BIT(shutting_down); /* TLS is being shut down */
@ -51,43 +49,21 @@ struct wssl_ctx {
size_t Curl_wssl_version(char *buffer, size_t size); size_t Curl_wssl_version(char *buffer, size_t size);
typedef CURLcode Curl_wssl_ctx_setup_cb(struct Curl_cfilter *cf,
struct Curl_easy *data,
void *user_data);
typedef CURLcode Curl_wssl_init_session_reuse_cb(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct alpn_spec *alpns,
struct Curl_ssl_session *scs,
bool *do_early_data);
CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx,
struct Curl_cfilter *cf,
struct Curl_easy *data,
struct ssl_peer *peer,
const struct alpn_spec *alpns,
Curl_wssl_ctx_setup_cb *cb_setup,
void *cb_user_data,
void *ssl_user_data,
Curl_wssl_init_session_reuse_cb *sess_reuse_cb);
CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
struct wssl_ctx *wssl); struct wolfssl_ctx *wssl);
CURLcode Curl_wssl_setup_session(struct Curl_cfilter *cf, CURLcode Curl_wssl_setup_session(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
struct wssl_ctx *wss, struct wolfssl_ctx *wss,
const char *ssl_peer_key); const char *ssl_peer_key);
CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf, CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
const char *ssl_peer_key, const char *ssl_peer_key,
struct WOLFSSL_SESSION *session, WOLFSSL_SESSION *session,
int ietf_tls_id, int ietf_tls_id,
const char *alpn, const char *alpn);
unsigned char *quic_tp,
size_t quic_tp_len);
#endif /* USE_WOLFSSL */ #endif /* USE_WOLFSSL */

View File

@ -26,15 +26,15 @@
#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \ #if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \ defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS) || defined(USE_RUSTLS) defined(USE_MBEDTLS)
#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \ #if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS) || defined(USE_WOLFSSL) || defined(USE_RUSTLS) defined(USE_MBEDTLS) || defined(USE_WOLFSSL)
#define WANT_PARSEX509 /* uses Curl_parseX509() */ #define WANT_PARSEX509 /* uses Curl_parseX509() */
#endif #endif
#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \ #if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS) || defined(USE_RUSTLS) defined(USE_MBEDTLS)
#define WANT_EXTRACT_CERTINFO /* uses Curl_extract_certinfo() */ #define WANT_EXTRACT_CERTINFO /* uses Curl_extract_certinfo() */
#endif #endif
@ -1277,5 +1277,4 @@ done:
#endif /* WANT_EXTRACT_CERTINFO */ #endif /* WANT_EXTRACT_CERTINFO */
#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP #endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP */
or USE_MBEDTLS or USE_RUSTLS */

View File

@ -29,7 +29,7 @@
#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \ #if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \ defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS) || defined(USE_RUSTLS) defined(USE_MBEDTLS)
#include "cfilters.h" #include "cfilters.h"
#include "urldata.h" #include "urldata.h"
@ -80,7 +80,7 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf, struct Curl_easy *data,
#ifdef UNITTESTS #ifdef UNITTESTS
#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \ #if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS) || defined(USE_RUSTLS) defined(USE_MBEDTLS)
/* used by unit1656.c */ /* used by unit1656.c */
CURLcode Curl_x509_GTime2str(struct dynbuf *store, CURLcode Curl_x509_GTime2str(struct dynbuf *store,
@ -91,6 +91,5 @@ CURLcode Curl_x509_getASN1Element(struct Curl_asn1Element *elem,
#endif #endif
#endif #endif
#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP #endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP */
or USE_MBEDTLS or USE_RUSTLS */
#endif /* HEADER_CURL_X509ASN1_H */ #endif /* HEADER_CURL_X509ASN1_H */

View File

@ -482,7 +482,7 @@ AC_DEFUN([CURL_COMPILER_WORKS_IFELSE], [
#endif #endif
]],[[ ]],[[
int i = 0; int i = 0;
return i; exit(i);
]]) ]])
],[ ],[
tmp_compiler_works="yes" tmp_compiler_works="yes"

View File

@ -1270,12 +1270,11 @@ AC_DEFUN([CURL_CHECK_FUNC_GETADDRINFO], [
struct addrinfo hints; struct addrinfo hints;
struct addrinfo *ai = 0; struct addrinfo *ai = 0;
int error; int error;
int exitcode;
#ifdef _WIN32 #ifdef _WIN32
WSADATA wsa; WSADATA wsa;
if(WSAStartup(MAKEWORD(2, 2), &wsa)) if(WSAStartup(MAKEWORD(2, 2), &wsa))
return 2; exit(2);
#endif #endif
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
@ -1284,15 +1283,9 @@ AC_DEFUN([CURL_CHECK_FUNC_GETADDRINFO], [
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo("127.0.0.1", 0, &hints, &ai); error = getaddrinfo("127.0.0.1", 0, &hints, &ai);
if(error || !ai) if(error || !ai)
exitcode = 1; /* fail */ exit(1); /* fail */
else { else
freeaddrinfo(ai); exit(0);
exitcode = 0;
}
#ifdef _WIN32
WSACleanup();
#endif
return exitcode;
]]) ]])
],[ ],[
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
@ -1890,11 +1883,9 @@ AC_DEFUN([CURL_CHECK_FUNC_GETIFADDRS], [
error = getifaddrs(&ifa); error = getifaddrs(&ifa);
if(error || !ifa) if(error || !ifa)
return 1; /* fail */ exit(1); /* fail */
else { else
freeifaddrs(ifa); exit(0);
return 0;
}
]]) ]])
],[ ],[
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
@ -2012,9 +2003,9 @@ AC_DEFUN([CURL_CHECK_FUNC_GMTIME_R], [
gmt = gmtime_r(&local, &result); gmt = gmtime_r(&local, &result);
(void)result; (void)result;
if(gmt) if(gmt)
return 0; exit(0);
else else
return 1; exit(1);
]]) ]])
],[ ],[
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
@ -2143,13 +2134,13 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_NTOP], [
/* - */ /* - */
ipv4ptr = inet_ntop(AF_INET, ipv4a, ipv4res, sizeof(ipv4res)); ipv4ptr = inet_ntop(AF_INET, ipv4a, ipv4res, sizeof(ipv4res));
if(!ipv4ptr) if(!ipv4ptr)
return 1; /* fail */ exit(1); /* fail */
if(ipv4ptr != ipv4res) if(ipv4ptr != ipv4res)
return 1; /* fail */ exit(1); /* fail */
if(!ipv4ptr[0]) if(!ipv4ptr[0])
return 1; /* fail */ exit(1); /* fail */
if(memcmp(ipv4res, "192.168.100.1", 13) != 0) if(memcmp(ipv4res, "192.168.100.1", 13) != 0)
return 1; /* fail */ exit(1); /* fail */
/* - */ /* - */
ipv6res[0] = '\0'; ipv6res[0] = '\0';
memset(ipv6a, 0, sizeof(ipv6a)); memset(ipv6a, 0, sizeof(ipv6a));
@ -2167,15 +2158,15 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_NTOP], [
/* - */ /* - */
ipv6ptr = inet_ntop(AF_INET6, ipv6a, ipv6res, sizeof(ipv6res)); ipv6ptr = inet_ntop(AF_INET6, ipv6a, ipv6res, sizeof(ipv6res));
if(!ipv6ptr) if(!ipv6ptr)
return 1; /* fail */ exit(1); /* fail */
if(ipv6ptr != ipv6res) if(ipv6ptr != ipv6res)
return 1; /* fail */ exit(1); /* fail */
if(!ipv6ptr[0]) if(!ipv6ptr[0])
return 1; /* fail */ exit(1); /* fail */
if(memcmp(ipv6res, "fe80::214:4fff:fe0b:76c8", 24) != 0) if(memcmp(ipv6res, "fe80::214:4fff:fe0b:76c8", 24) != 0)
return 1; /* fail */ exit(1); /* fail */
/* - */ /* - */
return 0; exit(0);
]]) ]])
],[ ],[
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
@ -2295,18 +2286,18 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_PTON], [
/* - */ /* - */
memset(ipv4a, 1, sizeof(ipv4a)); memset(ipv4a, 1, sizeof(ipv4a));
if(1 != inet_pton(AF_INET, ipv4src, ipv4a)) if(1 != inet_pton(AF_INET, ipv4src, ipv4a))
return 1; /* fail */ exit(1); /* fail */
/* - */ /* - */
if( (ipv4a[0] != 0xc0) || if( (ipv4a[0] != 0xc0) ||
(ipv4a[1] != 0xa8) || (ipv4a[1] != 0xa8) ||
(ipv4a[2] != 0x64) || (ipv4a[2] != 0x64) ||
(ipv4a[3] != 0x01) || (ipv4a[3] != 0x01) ||
(ipv4a[4] != 0x01) ) (ipv4a[4] != 0x01) )
return 1; /* fail */ exit(1); /* fail */
/* - */ /* - */
memset(ipv6a, 1, sizeof(ipv6a)); memset(ipv6a, 1, sizeof(ipv6a));
if(1 != inet_pton(AF_INET6, ipv6src, ipv6a)) if(1 != inet_pton(AF_INET6, ipv6src, ipv6a))
return 1; /* fail */ exit(1); /* fail */
/* - */ /* - */
if( (ipv6a[0] != 0xfe) || if( (ipv6a[0] != 0xfe) ||
(ipv6a[1] != 0x80) || (ipv6a[1] != 0x80) ||
@ -2319,7 +2310,7 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_PTON], [
(ipv6a[14] != 0x76) || (ipv6a[14] != 0x76) ||
(ipv6a[15] != 0xc8) || (ipv6a[15] != 0xc8) ||
(ipv6a[16] != 0x01) ) (ipv6a[16] != 0x01) )
return 1; /* fail */ exit(1); /* fail */
/* - */ /* - */
if( (ipv6a[2] != 0x0) || if( (ipv6a[2] != 0x0) ||
(ipv6a[3] != 0x0) || (ipv6a[3] != 0x0) ||
@ -2327,9 +2318,9 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_PTON], [
(ipv6a[5] != 0x0) || (ipv6a[5] != 0x0) ||
(ipv6a[6] != 0x0) || (ipv6a[6] != 0x0) ||
(ipv6a[7] != 0x0) ) (ipv6a[7] != 0x0) )
return 1; /* fail */ exit(1); /* fail */
/* - */ /* - */
return 0; exit(0);
]]) ]])
],[ ],[
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
@ -3818,11 +3809,11 @@ AC_DEFUN([CURL_CHECK_FUNC_STRERROR_R], [
buffer[0] = '\0'; buffer[0] = '\0';
string = strerror_r(EACCES, buffer, sizeof(buffer)); string = strerror_r(EACCES, buffer, sizeof(buffer));
if(!string) if(!string)
return 1; /* fail */ exit(1); /* fail */
if(!string[0]) if(!string[0])
return 1; /* fail */ exit(1); /* fail */
else else
return 0; exit(0);
]]) ]])
],[ ],[
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
@ -3881,11 +3872,11 @@ AC_DEFUN([CURL_CHECK_FUNC_STRERROR_R], [
buffer[0] = '\0'; buffer[0] = '\0';
error = strerror_r(EACCES, buffer, sizeof(buffer)); error = strerror_r(EACCES, buffer, sizeof(buffer));
if(error) if(error)
return 1; /* fail */ exit(1); /* fail */
if(buffer[0] == '\0') if(buffer[0] == '\0')
return 1; /* fail */ exit(1); /* fail */
else else
return 0; exit(0);
]]) ]])
],[ ],[
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])

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