Compare commits

..

69 Commits

Author SHA1 Message Date
Viktor Szakats
b4834a7d6d
examples: prefer return over exit() (cont.)
Some of these calls were not in callbacks. These examples may leak
handles.

Also fix some whitespace.

Follow-up to 08c7c937dc #16507
Closes #16524
2025-03-01 02:09:02 +01:00
Viktor Szakats
5693342ec2
winbuild: reduce command-line length by dropping whitespace
Keep the `@for %%i in [...]` lines within limits by stripping whitespace
from the input `.c` source lists read from `Makefile.inc`. To avoid this
error after adding a new `.c` source:
```
configuration name: libcurl-vc14-x64-release-dll-ssl-dll-ipv6-sspi
NMAKE : fatal error U1095: expanded command line 'for %i in (altsvc.obj            amigaos.obj
           asyn-ares.obj         asyn-thread.obj       base64.obj            bufq.obj
              bufref.obj            cf-h1-proxy.obj       cf-h2-proxy.obj       cf-haproxy.obj [...]
  vssh/wolfssh.obj) do @echo ..\builds\libcurl-vc14-x64-release-dll-ssl-dll-ipv6-sspi-obj-lib/%i \
                   ' too long
Stop.
Command exited with code 2
```
Ref: https://ci.appveyor.com/project/curlorg/curl/builds/51605338/job/dqg6qtebtscb279g#L44

Reported-by: Stefan Eissing
Bug: https://github.com/curl/curl/pull/16508#issuecomment-2690443409
Fixes #16521
Closes #16528
2025-03-01 02:04:42 +01:00
Dan Fandrich
c693cc02b0 docs: vulnerabilities in debug code are not eligible for a bounty
This is code that is off by default and is therefore treated as a
regular bug.

Ref: #16526
Closes #16527
2025-02-28 14:21:46 -08:00
Viktor Szakats
e7751571eb
GHA/macos: use quictls in some jobs, other small improvements
- enable quictls in autotools and cmake jobs. autotools requires
  a workaround due to wrong libpath in the quictls pkg-config.
  nghttp3 is offered by Homebrew, but not ngtcp2, to enable H3.

- install `libnghttp2` rather than `nghttp2`.
  `libnghttp2` is preinstalled and smaller. It also avoids detecting
  `nghttpx`, which confuses `pytest`.

- limit `brew unlink openssl` to libressl/quictls jobs.

Closes #16517
2025-02-28 16:58:12 +01:00
Zhaoming Luo
7211576442
tests: fix comment in lib533
Closes #16523
2025-02-28 16:12:20 +01:00
Stefan Eissing
794dfe7fc4
gnutls: fix use of pkcs11 urls for keys/certs
Fixes #16249
Forwarded-to-us-by: Carlos Henrique Lima Melara

Always use `gnutls_certificate_set_x509_key_file2()` for loading keys
and certificates, even without a password, since this function support
pkcs11 urls.

Thanks to @tatsuhiro-t for finding this out.
Help-by: Tatsuhiro Tsujikawa

Closes #16472
2025-02-28 16:08:10 +01:00
Viktor Szakats
049352dd80
cmake: allow CURL_STATIC_CRT with shared libcurl and no curl exe
Follow-up to edfa537100 #16456

Closes #16516
2025-02-28 13:11:41 +01:00
Viktor Szakats
08c7c937dc
tidy-up: prefer return over exit(), fix fallouts
To avoid breaking the control flow and align to majority of code
already using `return`.

`exit()` has the side-effect of suppressing leak detection in cases.
Fix fallouts detected after switching to `return`.

- configure:
  - fix `getaddrinfo` run test to call `freeaddrinfo()` to pacify ASAN,
    and call `WSACleanup()` to deinit winsock2.
  - fix `getifaddrs` run test to call `freeifaddrs()` to pacify ASAN.
- tests/server:
  - setup `atexit(win32_cleanup)` via `win32_init()`.
  - return 2 instead of 1 on winsock2 init failures.
  - sws: goto cleanup instead of `exit()` in `http_connect()`.
    Follow-up to 02dfe71937 #7235
- tests/client/http:
  - cleanup memory to pacify ASAN in `h2-upgrade-extreme`,
    `tls-session-reuse`.
- examples:
  - block_ip: fix memory leak reported by CI.
  - http2-upload: avoid handle leaks.

Untouched `exit()` calls, made from callbacks:
- docs/examples: ephiperfifo.c, ghiper.c, hiperfifo.c
- tests/libtest: lib582.c, lib655.c, lib670.c
- tests/server: tftpd.c

Closes #16507
2025-02-28 13:11:41 +01:00
Stefan Eissing
2e585f5640
test488: set --output-dir
Otherwise the downloaded files land in the `tests` directory and
show up in git status.

Closes #16519
2025-02-28 12:47:31 +01:00
Viktor Szakats
399cb7130a
cmake: drop HAVE_C_FLAG_Wno_long_double logic for ancient Apple gcc
The initial curl CMake commit introduced it in 2009-04-02 via
4c5307b456. Suppressing a stray
`-Wlong-double` warning in `mprintf.c`. This was before Apple switched
to clang, and likely affected the Apple distributed GCC, version 4.2.1
at the time. It applied the workaround to CMake builds only, though
the issue seems build-tool agnostic. Yet, it was not suppressed or
reported for autotools builds.

For these reasons this logic seems obsolete and this patch drops it with
no replacement. It saves a feature detection for GCC builds for macOS.

In PR sub-commits I added (and reverted) in-source suppression. In case
it becomes necessary, that should fix it for all build tools.

Closes #16513
2025-02-28 03:40:40 +01:00
Viktor Szakats
5a021aba41
cmake: improve httpd detection for pytest
Look for `httpd` in addition to `apache2`, like `./configure` does.
It fixes detection with macOS Homebrew for example.

Closes #16515
2025-02-28 03:40:40 +01:00
Viktor Szakats
6913c9b6ab
GHA/linux: improve 'test configs' step, don't set TFLAGS for pytest
- omit comments from th config dump, show filenames for each line.
- `TFLAGS` is not used by pytest, don't set it.

Closes #16514
2025-02-28 03:40:40 +01:00
Daniel Stenberg
953cd694dc
asyn-ares: use the correct port number
Only triggers with old c-ares versions.

Follow-up to 8ded8e5f3f

Closes #16511
2025-02-27 22:18:43 +01:00
Viktor Szakats
af6172c8f2
GHA/linux: merge two package install steps
Merge pytest prereq package install step into the main package install
step, to save install time.

Closes #16509
2025-02-27 20:32:50 +01:00
Daniel Stenberg
8ded8e5f3f
urldata: remove 'hostname' from struct Curl_async
It is unnecessary duplicated information, as the host name being
resolved is already present in conn->host.

Closes #16451
2025-02-27 17:18:43 +01:00
Daniel Stenberg
7007f59caa
GHA: spellcheck curl symbols better
This now makes sure to trim off exact matches for curl symbols and long
curl commanad line options instead of using pattern matching as before.
This should catch typoed names (that still follow the pattern) better.

The cleanspell.pl script is no longer used. cleancmd.pl is used for all
markdown files.

Closes #16504
2025-02-27 13:15:21 +01:00
Daniel Stenberg
a8ad9a5758
docs: minor edits to please the new spellchecker regime 2025-02-27 13:15:21 +01:00
Viktor Szakats
cba83bfb10
runtests: accept CURL_DIRSUFFIX without ending slash
Follow-up to 3585796049 #16452
Closes #16506
2025-02-27 12:11:23 +01:00
Viktor Szakats
59f4727480
appveyor: run VS2008 job with old CMake 3.12.2
Switch VS2008 job the oldest runner machine. It adds the oldest CMake to
the Windows mix, from 2018-11-30. Not a beauty, missing support for `-B`
and Unity, but it's a version curl supports. It's newer than Old Linux.
The previous oldest was 3.16.2. It remains used with VS2010-VS2017.

Also:
- fix VS2008 job to actually build examples.
- switch VS2019 job to OpenSSL 1.1.0 that wasn't tested before.
  Migrate OpenSSL 1.0.2 to the VS2008 job.
- measure run time of individual build steps.

Follow-up to 01c25e3b00 #16458
Closes #16505
2025-02-27 12:11:08 +01:00
Viktor Szakats
08a29e7f18
GHA: tidy up parallel options, improve performance for some jobs
- replace `--parallel <n>` and `-j<n>` for individual commands with
  `MAKEFLAGS`, for jobs not yet doing it.
  This enables parallel builds in distcheck / maketgz-and-verify-in-tree,
  where `-j` option was missing.
- add `--parallel` for iOS Xcode job for improved performance.
- drop redundant `-j5` for Android jobs.
- drop stray `cmake --config` options from single-target jobs (cygwin,
  msys/mingw, dl-mingw, non-native). Drop redundant
  `CMAKE_RUNTIME_OUTPUT_DIRECTORY_*` settings too.
- GHA/windows: add timeout for package install steps where missing.
- GHA/non-native: specify target type explicitly for iOS cmake jobs.
  Xcode default was already Debug, single-target default was generic,
  now it's Release, with unity batch to keep it fast.

`MAKEFLAGS` is necessary for autotools jobs and CMake jobs using
the default (GNU Make) generator. It's ignored by Ninja and other tools.
`cmake --parallel` is still necessary for jobs with Visual Studio or
Xcode generators. Parallelism is 5 for GHA Linux and Windows runners,
4 for macOS, 3 for VMs, 2 for AppVeyor.

Closes #16502
2025-02-27 12:11:07 +01:00
Daniel Stenberg
bc24c60512
urlapi: fix redirect from file:// with query, and simplify
- fix redirect from file:// URL with query part
- find_host_sep() simplify
- urlencode_str() simplify
- redirect_url() simplify
- made more const char *
- add more redirect URL test cases to test 1560

Closes #16498
2025-02-27 11:51:19 +01:00
Viktor Szakats
c028a243f2
build: set -O3 and tune WinCE in CI, fix getpart, vtls_scache fallouts
- GHA/windows/WinCE:
  - set `-O3 -DNDEBUG` C flags manually for the CMake mingw32ce build.
    CMake doesn't recognize the platform and fails to add them. To match
    autotools (using `-O2`), and hit similar compiler warnings.
  - enable parallel builds for cmake.
  - tune parallelism for cmake using unity batches.
  - tune parallelism for autotools.

  Follow-up to 2a292c3984 #15975

- tests: fix potentially uninitialized value in `readline()` in
  `getpart.c`. Detected by gcc 4.4.0 `-O2` (Windows CE) jobs:
  ```
  tests/server/getpart.c: In function 'getpart':
  tests/server/getpart.c:298: error: 'datalen' may be used uninitialized in this function
  ```
  Ref: https://github.com/curl/curl/actions/runs/13522595237/job/37785147505?pr=16476#step:11:25
  Follow-up to 592880a3ca

- vtls_scache: rework returning pointer to avoid compiler warning seen
  with `-O3` gcc 4.4.0 builds (Windows CE/schannel):
  ```
  lib/vtls/schannel.c: In function 'schannel_connect_step1':
  lib/vtls/vtls_scache.c:975: error: dereferencing pointer 'old_cred.4474' does break strict-aliasing rules
  lib/vtls/vtls_scache.c:985: error: dereferencing pointer 'old_cred.4474' does break strict-aliasing rules
  lib/vtls/schannel.c:959: note: initialized from here
  ```
  Ref: https://github.com/curl/curl/actions/runs/13523868335/job/37789610845#step:9:25
  Follow-up to fa0ccd9f1f #15774

Closes #16476
2025-02-26 21:23:11 +01:00
Viktor Szakats
4f98f354b1
GHA/windows: move UWP vcpkg job up top
To bring it closer to WinCE and make the vcpkg jobs with tests form
a continuous group.

Closes #16499
2025-02-26 16:21:01 +01:00
Stefan Eissing
4ed9db9eef
vtls: move common early data code into vtls.c
With now 2 backends implementing early data, it makes sense to have the
common handling in a single place.

Closes #16450
2025-02-26 16:00:37 +01:00
Viktor Szakats
a1d00da81e
test1167: catch #defines with extra whitespace
Before this patch, it missed this in `curl/curl.h`:
```c
#  define __has_declspec_attribute(x) 0
```
After this patch:
```
test 1167...[Verify curl prefix of public symbols in header files]
/usr/bin/perl -I. -I.  returned 1, when expecting 0
 1167: exit FAILED
== Contents of files in the log/14/ dir after test 1167
=== Start of file server.cmd
 Testnum 1167
=== End of file server.cmd
=== Start of file stdout1167
 Bad symbols in public header files:
   __has_declspec_attribute(x)
=== End of file stdout1167
FAIL 1167: 'Verify curl prefix of public symbols in header files' source analysis
TESTFAIL: These test cases failed: 1167
```

Ref: #16491
Closes #16496
2025-02-26 14:01:40 +01:00
Daniel Stenberg
f5527e57f8
tests: make sure gdb gets the right path for -x
Regression from #16452

Closes #16495
2025-02-26 13:12:04 +01:00
Viktor Szakats
dbbbf717f3
curl.h: stop defining non-curl __has_declspec_attribute
Public curl headers are best not to define 3rd-party or system macros.
Introduce `CURL_HAS_DECLSPEC_ATTRIBUTE` to cover this system macro and
use it.

Detected by test1167 after dropping the indentation:
```
test 1167...[Verify curl prefix of public symbols in header files]

/usr/bin/perl -I. -I.  returned 1, when expecting 0
 1167: exit FAILED
== Contents of files in the log/10/ dir after test 1167
=== Start of file server.cmd
 Testnum 1167
=== End of file server.cmd
=== Start of file stdout1167
 Bad symbols in public header files:
   __has_declspec_attribute(x)
=== End of file stdout1167
```
Ref: https://github.com/curl/curl/actions/runs/13533200900/job/37819784405?pr=16490#step:42:2087

Ref: https://clang.llvm.org/docs/LanguageExtensions.html#has-declspec-attribute
Follow-up to 50482b8c0a #3616
Ref: #16496 (fixing test1167)
Closes #16491
2025-02-26 13:10:31 +01:00
Viktor Szakats
3efc53f5e9
build: silence mingw32ce C99 format warnings, simplify CI
`./configure` mingw32ce builds enable C99 mode automatically, that
triggers compiler warnings in gcc 4.4.0. We initially worked it around
in CI by suppressing the detection of C99 with `ac_cv_prog_cc_c99=no`.

Replace it with automatically silencing the bogus warnings in C99 mode,
for all build systems:
```
lib/ftp.c: In function 'Curl_GetFTPResponse':
lib/ftp.c:726: error: format '%zd' expects type 'signed size_t', but argument 4 has type 'ssize_t'
lib/ws.c: In function 'ws_dec_pass_payload':
lib/ws.c:304: error: format '%zd' expects type 'signed size_t', but argument 3 has type 'ssize_t'
lib/ws.c: In function 'ws_enc_write_head':
lib/ws.c:581: error: format '%zd' expects type 'signed size_t', but argument 3 has type 'long int'
lib/vtls/schannel.c: In function 'schannel_connect_step1':
lib/vtls/schannel.c:1122: error: format '%zd' expects type 'signed size_t', but argument 3 has type 'ssize_t'
lib/vtls/schannel.c: In function 'schannel_connect_step2':
lib/vtls/schannel.c:1311: error: format '%zd' expects type 'signed size_t', but argument 3 has type 'ssize_t'
lib/vtls/schannel.c: In function 'schannel_send':
lib/vtls/schannel.c:1793: error: format '%zd' expects type 'signed size_t', but argument 3 has type 'ssize_t'
lib/vtls/schannel.c:1810: error: format '%zd' expects type 'signed size_t', but argument 3 has type 'ssize_t'
lib/vtls/schannel.c: In function 'schannel_shutdown':
lib/vtls/schannel.c:2286: error: format '%zd' expects type 'signed size_t', but argument 4 has type 'ssize_t'
lib/vtls/vtls.c: In function 'ssl_cf_recv':
lib/vtls/vtls.c:1422: error: format '%zd' expects type 'signed size_t', but argument 5 has type 'ssize_t'
```
Ref: https://github.com/curl/curl/actions/runs/13533841306/job/37821720902?pr=16492#step:9:20

Also: simplify Windows CE job configuration in GHA/windows.

Follow-up to 2a292c3984 #15975
Closes #16492
2025-02-26 12:35:03 +01:00
Viktor Szakats
518543dec8
cmake: warn for OpenSSL versions missing TLS 1.3 support (revert)
We decided not to show warnings for this issue.

Also this:
```
CMake Warning at CMakeLists.txt:783 (message):
  OpenSSL does not support TLS 1.3.
```
as seen in #16483 with CMake 3.12.4, `OPENSSL_VERSION` is empty.
Perhaps detection isn't reliable? I haven't seen this so far with
mainline OpenSSL. An `if(OPENSSL_VERSION AND ...)` can fix it, if we
opt for this warning in the future.

Follow-up to #16122
This reverts commit 34c1c653fc #16120
Closes #16485
2025-02-26 12:35:03 +01:00
Viktor Szakats
bc42010f66
GHA/http3-linux: build out-of-tree, make test2502 support it
To sync with the rest of core workflows.

Also fixup test2502 failing for out-of-tree builds due to:
```
== Info: error reading ca cert file ./certs/EdelCurlRoot-ca.cacert (Error while reading file.)
```
Ref: https://github.com/curl/curl/actions/runs/13525575035/job/37795171282?pr=16480#step:23:3608

Cherry-picked from #16480
Closes #16481
2025-02-26 12:35:03 +01:00
Viktor Szakats
37523c91bc
GHA/linux: build out-of-tree, make autotools tidy target support it
To sync with the rest of core workflows.

Also fix the `tidy` (clang-tidy) target in autotools to support
out-of-tree builds:
```
clang-tidy slist_wc.c terminal.c tool_bname.c [...] var.c tool_hugehelp.c tool_ca_embed.c
  -quiet --warnings-as-errors=* -checks=-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-analyzer-valist.Uninitialized --
  -I../../include -I../lib -I../src -I../../lib -I../../src
  -DBUILDING_CURL -DUSE_MANUAL -D_GNU_SOURCE -DHAVE_CONFIG_H
[1/45] Processing file /home/runner/work/curl/curl/bld/src/slist_wc.c.
Error while processing /home/runner/work/curl/curl/bld/src/slist_wc.c.
[2/45] Processing file /home/runner/work/curl/curl/bld/src/terminal.c.
Error while processing /home/runner/work/curl/curl/bld/src/terminal.c.
[3/45] Processing file /home/runner/work/curl/curl/bld/src/tool_bname.c.
Error while processing /home/runner/work/curl/curl/bld/src/tool_bname.c.
[...]
```
Ref: https://github.com/curl/curl/actions/runs/13525337357/job/37794388404?pr=16480#step:36:561

Closes #16480
2025-02-26 12:35:03 +01:00
Daniel Stenberg
200993fccd
RELEASE-NOTES: synced 2025-02-26 10:31:16 +01:00
Jay Satiro
2fce176bf6 wolfssl: warn if CA native import option is ignored
- Show verbose message if the CA native import option is set but
  the wolfSSL build does not support it.

wolfSSL has to be built with WOLFSSL_SYS_CA_CERTS to import native
CA certificates and that may not be common.

Closes https://github.com/curl/curl/pull/16417
2025-02-26 03:05:36 -05:00
Daniel Stenberg
d485177151
altsvc: rewrite parser using strparse
Extend test 1654.

Closes #16454
2025-02-26 08:36:08 +01:00
Daniel Stenberg
5b5e2f7318
cookie: do prefix matching case-sensitively
According to section 4.1.3.1 and 4.1.3.2 of
draft-ietf-httpbis-rfc6265bis-19

Ref: https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-19#section-4.1.3.1

Closes #16494
2025-02-26 08:33:49 +01:00
Daniel Stenberg
ac4a65f8d2
urldata: move the ech struct field to the "right place"
We keep the struct field ordered in a rough size order, big to small.

Closes #16489
2025-02-26 08:18:35 +01:00
Daniel Stenberg
71f190cbbc
GHA: enable the RTSP tests on macOS gcc-12 2025-02-26 07:58:54 +01:00
Daniel Stenberg
2ec00372a1
curl.h: change some enums to defines with L suffix
To help applications do the right thing easier, change some enum values
into defines with L suffixes so that they get the corect type (long)
easier when used with curl_easy_setopt(). This also fixes a few of our
own libtests.

To reduce the risk that this change breaks the compile for any existing
users, the previously provided enums are still provided, but the values
to use are not defined by the enums.

This change "magically" fixes a few RTSP test failures we have had on
64-bit platforms because those options were not see using longs
properly.

Closes #16482
2025-02-26 07:58:15 +01:00
Daniel Stenberg
7826927d9b
libtest/libprereq.c: set CURLOPT_FOLLOWLOCATION with a long
Previously this used '1', which as an int. The option needs a long.

Closes #16487
2025-02-26 00:06:24 +01:00
Daniel Stenberg
6c81f2a35c
CURLOPT_HTTPHEADER.md: add comments to the example
Ref: https://mastodon.social/@jpmens/114065709635360064
Closes #16488
2025-02-25 23:56:05 +01:00
Viktor Szakats
baa9c647d3
cmake: sync cutoff version with autotools for picky option -ftree-vrp
Sync cutoff version for `-ftree-vrp` with autotools, which enables it
for gcc 4.3+ (cmake builds enabled it for 5.0+, before this patch).

Cherry-picked from #16476
Closes #16478
2025-02-25 16:57:45 +01:00
Viktor Szakats
29978df61f
cmake: pre-fill known type sizes for Windows OSes
To save configuration time.

After this patch, for mingw-w64 and MSVC curl's CMake builds pre-fill
almost all type sizes without auto-detection. In most cases this leaves
3 type size auto-detections. Those depend on 64/32-bitness, and `time_t`
also depends on CRT and custom options. Old mingw-w64 versions require
some extra detections. We recommend v3.0 or newer to avoid them.

For Windows CE, this patch pre-fills all type sizes.

If this is causing any issue, please report it and disable pre-filling
with `-D_CURL_PREFILL=OFF` in the meantime.

Cherry-picked from #16394
Closes #16464
2025-02-25 16:57:13 +01:00
Derek Huang
af0100fc17
INSTALL-CMAKE.md: CMake usage updates
This PR updates the CMake build/install docs in `docs/INSTALL-CMAKE.md`,
in particular focusing on the use of libcurl from CMake using
`find_package` as well as the newly added features/protocols support via
using `COMPONENTS` or `OPTIONAL_COMPONENTS` with `find_package`.
See #15854 for initial discussion and the corresponding PR #15858 that
was merged.

Some additional best-practices notes are added, for example:

* Encouraging building out-of-source
* Using `--config` with `cmake --build` for multi-config CMake
  generators, not `CMAKE_BUILD_TYPE`

We also add a CURL CMake-specific tip on using `CMAKE_INSTALL_PREFIX`
during configure time to set the install prefix, not using `--prefix`
when running `cmake --install` so `curl-config` output is consistent.

Closes #16329
2025-02-25 13:02:51 +01:00
Viktor Szakats
84332d49fb
runtests: drop recognizing 'winssl' as Schannel
Follow-up to 180501cb02 #3504
Closes #16467
2025-02-25 12:59:10 +01:00
Viktor Szakats
31fd77fb3b
runtests: recognize AWS-LC as OpenSSL
Fixes (GHA/linux, AWS-LC jobs):
```
test 0307 SKIPPED: curl lacks OpenSSL support
test 0308 SKIPPED: curl lacks OpenSSL support
[...]
```
Ref: https://github.com/curl/curl/actions/runs/13511134270/job/37751473424#step:42:104

Follow-up to 34ef4fab22 #10320
Closes #16466
2025-02-25 12:59:09 +01:00
Daniel Stenberg
6306476fc3
tool_getparam: make --url support a file with URLs
It implies -O used for each URL.

Mention in the --url documentation.

Test 488 and 489 verify.

Closes #16099
2025-02-25 09:16:54 +01:00
Tianyi Song
5addb3e1cc
openssl: check return value of X509_get0_pubkey
Fixes #16468
Closes #16469
2025-02-25 08:10:18 +01:00
Yedaya Katsman
a55b5b7c62
rustls: add support for CERTINFO
This allows you to use the `certs` and `num_certs` writeout variables in
the curl tool, and getting information about the server certificates
using CURLINFO_CERTINFO.

Closes #16459
2025-02-25 07:59:39 +01:00
Viktor Szakats
3175984ab2
build: drop unused getpart tool
Drop the `getpart` test tool from standard builds. This tool was not
used by tests.

Also:
- make it easier to build it standalone for testing `getpart.c` on
  the command-line.
- reduce local var scopes in source.

Closes #16460
2025-02-25 01:52:13 +01:00
Daniel Stenberg
b930142d12
CURLOPT_HTTPHEADER.md: rephrases
An attempt to use better language

Closes #16461
2025-02-24 23:15:26 +01:00
Daniel Stenberg
413b2a44a8
curl_trc: fix build with CURL_DISABLE_VERBOSE_STRINGS
Fixes #16462
Closes #16463
2025-02-24 23:14:54 +01:00
Viktor Szakats
a7bcf25c83
runtests: drop ref to unused external function [ci skip]
Follow-up to 3585796049 #16452
2025-02-24 23:07:51 +01:00
Viktor Szakats
01c25e3b00
CI: misc improvements, restore VS2008 job
- appveyor: restore VS2008 job, after fixing its issues.
  Enable OpenSSL in it. It takes 1 minute.
  Follow-up to 9b0467b169 #16453
  Follow-up to edfa537100 #16456
- appveyor: make a copy of OpenSSL DLLs to have them picked up as an
  artifact (disabled by default) to aid local tests.
- appveyor: dump CMake configuration logs on failure.
- appveyor: tidy up job parameter defaults.
- GHA/windows: add pre-fill check option for dl-mingw jobs.
- GHA/windows: fix pre-fill check option for MSYS jobs by installing
  `diffutils`.
  Follow-up to e7adf3e837 #15841
- GHA/windows: de-duplicate to `PATH` commands for Cygwin.
- GHA/windows: drop `$SYSTEMROOT/System32` from `PATH` for Cygwin
  configure. It's not needed.
  Follow-up to 36fd2dd6ee #13599
- list `.pdb` files in curl version step for MSVC.
  Ref: #16439

Cherry-picked from #16394
Closes #16458
2025-02-24 22:47:37 +01:00
Laurențiu Nicola
46f17ef010
docs: bump rustls to 0.14.1
Closes #16446
2025-02-24 22:41:30 +01:00
Viktor Szakats
5070b6ac45
INSTALL-CMAKE.md: mention ZLIB_USE_STATIC_LIBS
Cherry-picked from #16394
Closes #16457
2025-02-24 21:00:31 +01:00
Viktor Szakats
edfa537100
cmake: restrict static CRT builds to static curl exe, test in CI
Static CRT crashes MSVCR* MSVC builds (in VS2008, VS2010, VS2012,
VS2013) according to CI and local tests. The reproducible crash happens
in `curl_mfprintf() -> fputc(s, stderr)` when trying to display the
warning message in `curl -V`. `stderr` is non-NULL and resolves to `2`.
This reproducer needs a debug-enabled build, but it's unrelated to debug
features or curl's memory tracker. It happens regardless of unity build,
CPU architecture or `DllMain()` use. Example from VS2013:

```
+ _bld/src/Debug/curl.exe --disable --version
./appveyor.sh: line 124:   203 Segmentation fault      "${curl}" --disable --version
```
Ref: https://ci.appveyor.com/project/curlorg/curl/builds/51570451/job/ojpdqrsm1hmpmq6a#L210

Another crash happened in an UCRT build (VS2017) with a couple of
`printf()`s added to curl's `main()` function:

```
Microsoft Visual C++ Runtime Library
Debug Assertion Failed!
Program: C:/projects/curl/bld/src/Debug/curl.exe
File: minkernel/crts/ucrt/src/appcrt/heap/debug_heap.cpp
Line: 996
Expression: _act_first_block == header
```
(it hangs the job in CI due to the GUI popup)
Ref: https://github.com/curl/curl/pull/16394#issuecomment-2677181716

To avoid actual and potential issues, this patch issues a warning on
the shared-libcurl + static-CRT combination and falls back to the
default, shared CRT. IOW a static CRT build now requires a static curl
exe when using the `CURL_STATIC_CRT=ON` option.

Follow-up to 4fc6ebe18a #1621
Cherry-picked from #16394 (with more details there)

Closes #16456
2025-02-24 21:00:31 +01:00
Viktor Szakats
7b8b9b9c2b
cmake: hide empty MINGW64_VERSION output for mingw32ce
Follow-up to e49797abc2 #16022
Follow-up to 2a292c3984 #15975
Cherry-picked from #16394

Closes #16455
2025-02-24 21:00:31 +01:00
Viktor Szakats
9b0467b169
windows: drop code and curl manifest targeting W2K and older
curl requires Windows XP since 2023. Drop version detection code using
`GetVersionEx()` aimed to support earlier Windows versions. With that
call deleted, the embedded manifest in `curl.rc` becomes unnecessary.
Delete it too, along with the enabler logic in build systems.

This allows to stop forcing `/MANIFEST:NO` for MSVC builds. Dropping it
fixes VS2008 shared builds, that require an auto-generated SxS
(side-by-side assembly) manifest to find their CRT DLLs. This was the
issue that prevented VS2008 `curl.exe` launching on AppVeyor CI:
```
src/curl.exe: error while loading shared libraries: ?: cannot open shared object file: No such file or directory
```
Ref: https://ci.appveyor.com/project/curlorg/curl/builds/51577006/job/eitypvwlb1rxr11d#L261

FWIW the `curl.rc` embedded manifest wasn't ever enabled for VS2008 CI
builds either, because CMake did not pass our custom macro via
`CMAKE_RC_FLAGS` to `rc.exe`. For reasons I could not figure out.

After this patch the curl build no longer inject its own manifest, and
lets the default be applied by linkers and toolchains. It fixes VS2008
shared builds. curl continues to detect the real Windows version via
`RtlVerifyVersionInfo()` from `ntdll`.

Follow-up to 960d601481 #12225
Follow-up to 5044909ca2 #7810
Follow-up to ebd213270a #1221
Ref: #15972
Cherry-picked from #16394

Closes #16453
2025-02-24 21:00:31 +01:00
Viktor Szakats
3585796049
runtests: support multi-target cmake, drop workarounds from CI
Support multi-target cmake builds via `CURL_DIRSUFFIX` env. For example:
`export CURL_DIRSUFFIX=Debug/`.

Multi-target generators place their output to `src/<subdir>/`,
`lib/<subdir>/`, `tests/server/<subdir>`, `tests/libtest/<subdir>` and
`tests/unit/<subdir>/` by default. Before this patch, `runtests.pl`
couldn't run on such builds because it expected the binaries under the
their `<subdir>`-less directories. This patch allows to set such subdir
and make `runtests.pl` find the binaries. In CI we use multi-target
builds with tests for MSVC. It also helps Xcode-generator builds, though
in CI we don't have such job running tests.

There may be better solutions to configure this, but passing a custom
value to `runtests.pl` including its subprocesses is somewhat tricky.
The reason the configuration value expects the slash at the end is
because MSYS is automagically expanding the env to a (wrong) absolute
path if the slash is in the front.

Also:
- drop the `-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_*=` workaround from CI.
- replace `resolve` references in tests with a new `%RESOLVE` variable.
  It didn't use a filename extension before. After this patch it uses
  `exe_ext('TOOL')`. I'm not sure if this is the correct choice vs.
  `exe_ext('SRV')`.
- fix `-c` option format in manual.
- fix some whitespace.

Note, in CI we still tweak `CMAKE_RUNTIME_OUTPUT_DIRECTORY_*` in jobs
which share steps between `./configure` and cmake. It's easier that way.

Ref: #15000
Cherry-picked from #16394

Closes #16452
2025-02-24 21:00:30 +01:00
Daniel Stenberg
db2fd7c3de
delta: get contributors without changing THANKS
Give contrithanks.sh the option to send the list of names to stdout so
that delta can use it appropriately for counting.

Closes #16449
2025-02-24 13:26:48 +01:00
Laurențiu Nicola
dfdd380844
ci: use stable rust toolchain for rustls and skip installing the docs
Closes #16447
2025-02-24 13:08:27 +01:00
Daniel Stenberg
8f79b3e696
contrithanks.sh: update docs/THANKS in place
Now using 'sort' for sorting the names. This has the small side-effect
that it sorts slightly different than the previously used sort function
(emacs).

I think this is a better sort and over all it makes it more convenient
to use the script as it removes a manual step.

Closes #16448
2025-02-24 13:04:11 +01:00
Daniel Stenberg
7694fc8256
RELEASE-NOTES: synced 2025-02-24 10:13:06 +01:00
Daniel Stenberg
04289c62de
http: convert parsers to strparse
Closes #16436
2025-02-24 10:02:40 +01:00
Stefan Eissing
edd573d980
wolfssl: tls early data support
Enable TLS Early Data for wolfSSL:

- merge WOLFSSL_CTX and WOLFSSL setup from ngtcp2 with the general
  implemenation in wolfssl.c
- enable for QUIC via ngtcp2
- give Curl_vquic_tls_init() a `struct alpn_spec` like used for the TCP
  case. Adapt gnutls and other users.
- enable pytest test cases for early data with wolfSSL

and while this messes up wolfssl.c anyway, do

- rename all struct/functions with prefix 'wolfssl_' to 'wssl_' to not
  pollute that name prefix
- rename `ctx/handle` to `ssl_ctx/ssl`, as used in openssl case

Closes #16167
2025-02-24 10:01:51 +01:00
Daniel Stenberg
efec626ebb
contributors.sh: lowercase 'github' for consistency
also fix contrithanks and THANKS-filter

Ref: #16438
Closes #16443
2025-02-24 08:05:06 +01:00
Timo Tijhof
9391fc151f
RELEASE-NOTES: fix github casing
Follows-up b22f9066a5, which added a new contributor with a different
casing for "github" than the others.

Closes #16438
2025-02-24 00:10:18 +01:00
Stefan Eissing
51f8aa79a9
CURLMOPT_SOCKETFUNCTION.md: add advice for socket callback invocation times
Explain when a registered socket callback may get invoked to make user
better aware on how to handle it.

Closes #16441
2025-02-24 00:05:56 +01:00
Daniel Stenberg
e1b3d46944
tool_operate: fail SSH transfers without server auth
This now insists on using a server auth option unless --insecure is
provided. As an added bonus, it now also only checks for the knownhosts
file once (if found).

Ref: #16197
Closes #16205
2025-02-23 17:54:21 +01:00
166 changed files with 3270 additions and 2564 deletions

View File

@ -3,55 +3,117 @@
#
# SPDX-License-Identifier: curl
#
# Input: a cmdline docs markdown, it gets modified *in place*
# Input: cmdline docs markdown files, they get 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.
my $header = 1;
while(1) {
# set this if the markdown has no meta-data header to skip
if($ARGV[0] eq "--no-header") {
shift @ARGV;
$header = 0;
}
else {
last;
open(S, "<./docs/libcurl/symbols-in-versions")
|| die "can't find symbols-in-versions";
while(<S>) {
if(/^([^ ]*) /) {
push @asyms, $1;
}
}
close(S);
my $f = $ARGV[0];
# init the opts table with "special" options not easy to figure out
my @aopts = (
'--ftp-ssl-reqd', # old alias
);
open(F, "<$f") or die;
my $ignore = $header;
my $sepcount = 0;
my @out;
while(<F>) {
if(/^---/ && $header) {
if(++$sepcount == 2) {
$ignore = 0;
open(O, "<./docs/options-in-versions")
|| 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")
|| die "can't find spellcheck.curl";
while(<C>) {
if(/^\#/) {
next;
}
next if($ignore);
# strip out backticked words
$_ =~ s/`[^`]+`//g;
# strip out all long command line options
$_ =~ s/--[a-z0-9-]+//g;
# strip out https URLs, we don't want them spellchecked
$_ =~ s!https://[a-z0-9\#_/.-]+!!gi;
push @out, $_;
chomp;
if(/^([^ ]+)/) {
push @asyms, $1;
}
}
close(F);
close(C);
if(!$ignore) {
open(O, ">$f") or die;
print O @out;
close(O);
# 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;
next;
}
next if($ignore);
my $l = $_;
# strip out backticked words
$l =~ s/`[^`]+`//g;
# **bold**
$l =~ s/\*\*(\S.*?)\*\*//g;
# *italics*
$l =~ s/\*(\S.*?)\*//g;
# strip out https URLs, we don't want them spellchecked
$l =~ s!https://[a-z0-9\#_/.-]+!!gi;
$out .= $l;
}
close(F);
# cut out all known curl cmdline options
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;
print O $out;
close(O);
}
}
for my $f (@ARGV) {
process($f);
}

View File

@ -1,86 +0,0 @@
#!/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);

151
.github/scripts/spellcheck.curl vendored Normal file
View File

@ -0,0 +1,151 @@
# 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,8 +121,6 @@ CMakeLists
CNA
CNAME
CNAMEs
CodeQL
codeql
CODESET
codeset
CodeSonar
@ -253,6 +251,7 @@ Feltzing
ffi
filesize
filesystem
FindCURL
FLOSS
fnmatch
footguns
@ -952,7 +951,6 @@ winbuild
WinIDN
WinLDAP
winsock
winssl
Wireshark
wolfSSH
wolfSSL

View File

@ -107,20 +107,8 @@ jobs:
persist-credentials: false
name: checkout
- name: trim all man page *.md files
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: trim all *.md files in docs/
run: .github/scripts/cleancmd.pl $(find docs -name "*.md")
- name: setup the custom wordlist
run: grep -v '^#' .github/scripts/spellcheck.words > wordlist.txt

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -87,3 +87,10 @@ macro(curl_required_libpaths _libpaths_arg)
list(APPEND CMAKE_REQUIRED_LINK_DIRECTORIES "${_libpaths_arg}")
endif()
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,6 +182,7 @@ if(PICKY_COMPILER)
-Wold-style-declaration # gcc 4.3
-Wpragmas # clang 3.5 gcc 4.1 appleclang 6.0
-Wstrict-aliasing=3 # gcc 4.0
-ftree-vrp # gcc 4.3 (required for -Warray-bounds, included in -Wall)
)
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5)
@ -204,7 +205,7 @@ if(PICKY_COMPILER)
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0)
list(APPEND _picky_enable
-Warray-bounds=2 -ftree-vrp # clang 3.0 gcc 5.0 (clang default: -Warray-bounds)
-Warray-bounds=2 # clang 3.0 gcc 5.0 (clang default: -Warray-bounds)
)
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.0)

View File

@ -44,10 +44,6 @@ if(MINGW)
set(HAVE_UTIME_H 1) # wrapper to sys/utime.h
set(HAVE_DIRENT_H 1)
set(HAVE_OPENDIR 1)
if(MINGW32CE)
set(HAVE_STRTOK_R 0)
set(HAVE_FILE_OFFSET_BITS 0)
endif()
else()
set(HAVE_LIBGEN_H 0)
set(HAVE_FTRUNCATE 0)
@ -78,7 +74,6 @@ else()
set(HAVE_SNPRINTF 0)
endif()
set(HAVE_BASENAME 0)
set(HAVE_FILE_OFFSET_BITS 0)
endif()
endif()
@ -196,6 +191,37 @@ set(STDC_HEADERS 1)
set(HAVE_SIZEOF_SUSECONDS_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
set(HAVE_LOCALE_H 0)
set(HAVE_GETADDRINFO 0)
@ -204,7 +230,15 @@ if(WINCE) # Windows CE exceptions
set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 0)
set(HAVE_SIGNAL 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)
set(HAVE_STRTOK_R 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()

View File

@ -217,13 +217,6 @@ option(ENABLE_ARES "Enable c-ares support" OFF)
option(CURL_DISABLE_INSTALL "Disable installation targets" OFF)
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)
if(WINDOWS_STORE OR WINCE)
set(ENABLE_UNICODE ON)
@ -264,7 +257,9 @@ if(WIN32)
if(MINGW64_VERSION)
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}")
message(STATUS "Found MINGW64_VERSION=${MINGW64_VERSION}")
if(MINGW64_VERSION)
message(STATUS "Found MINGW64_VERSION=${MINGW64_VERSION}")
endif()
endif()
unset(MINGW64_VERSION CACHE) # Avoid storing in CMake cache
endif()
@ -354,6 +349,19 @@ else()
set(LIB_SELECTED ${LIB_STATIC})
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.
if((UNIX AND NOT ANDROID AND (NOT APPLE OR CMAKE_SYSTEM_NAME MATCHES "Darwin")) OR
VCPKG_TOOLCHAIN OR
@ -819,9 +827,6 @@ if(CURL_USE_OPENSSL)
set(_openssl "AmiSSL")
else()
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()
@ -1948,22 +1953,6 @@ endif()
# 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)
set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_cmake_try_compile_target_type_save})
unset(_cmake_try_compile_target_type_save)
@ -1983,9 +1972,6 @@ if(WIN32)
set(USE_WIN32_LARGE_FILES ON)
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
if(NOT WINDOWS_STORE)
set(USE_WIN32_CRYPTO ON)
@ -2001,9 +1987,6 @@ if(WIN32)
endif()
if(MSVC)
# Disable default manifest added by CMake
string(APPEND CMAKE_EXE_LINKER_FLAGS " -MANIFEST:NO")
string(APPEND CMAKE_C_FLAGS " -MP") # Parallel compilation
endif()

View File

@ -4,10 +4,15 @@ curl and libcurl 8.13.0
Command line options: 267
curl_easy_setopt() options: 306
Public functions in libcurl: 96
Contributors: 3349
Contributors: 3354
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:
@ -16,67 +21,111 @@ This release includes the following bugfixes:
o asyn-thread: avoid the separate curl_mutex_t alloc [6]
o asyn-thread: do not allocate thread_data separately [21]
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: fix compiler warnings in feature detections [39]
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 c-ares: error out for unsupported versions, drop unused macros [85]
o ca-native.md: sync with CURLSSLOPT_NATIVE_CA [72]
o cf-socket: deduplicate Windows Vista detection [11]
o client writer: handle pause before deocding [61]
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: allow empty custom `IMPORT_LIB_SUFFIX`, add suffix collision detection [41]
o cmake: allow empty `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 two stray TLS feature checks for wolfSSL [9]
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: hide empty `MINGW64_VERSION` output for mingw32ce [114]
o cmake: mention 'insecure' in the debug build warning [15]
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 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 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: 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_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: bump `rustls` to 0.14.1 [111]
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 hostip: make CURLOPT_RESOLVE support replacing IPv6 addresses [47]
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 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: version negotiation [45]
o http_aws_sigv4: use strparse more for parsing [55]
o https-rr: implementation improvements [44]
o httpsrr: fix port detection [51]
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: simplify more white space loops [60]
o lib: strtoofft.h header cleanup [17]
o lib: use Curl_str_* instead of strtok_r() [59]
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 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 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: guard ALPN init code to ALPN builds [91]
o scripts/managen: fix option 'single' [31]
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 ssl session cache: add exportable flag [56]
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 to curl_off_t as base data type [7]
o tests: fix enum/int confusion (Intel C), fix autotools `CFLAGS` for `servers` [27]
o tests: fix enum/int confusion, 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: drop unused `CURL_INADDR_NONE` macro and `in_addr_t` type [26]
o tidy-up: use `CURL_ARRAYSIZE()` [37]
o timediff: fix comment for curlx_mstotv() [25]
o timediff: remove unnecessary double typecast [53]
o tool_getparam: clear sensitive arguments better [66]
o tool_operate: fail SSH transfers without server auth [70]
o urlapi: simplify junkscan [23]
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 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]
This release includes the following known bugs:
@ -98,12 +147,13 @@ Planned upcoming removals include:
This release would not have looked like this without help, code, reports and
advice from friends like these:
Anthony Hu, Daniel Stenberg, dependabot[bot], Dexter Gerig, Harry Sintonen,
John Bampton, Joseph Chen, kayrus on github, kriztalz, lf- on github,
Marcel Raad, Mark Phillips, Ray Satiro, rmg-x on github,
RubisetCie on Github, Sergey, Stefan Eissing, Viktor Szakats,
Zenju on github
(19 contributors)
Anthony Hu, Dan Fandrich, Daniel Stenberg, dependabot[bot], Derek Huang,
Dexter Gerig, Harry Sintonen, Jeremy Drake, John Bampton, Joseph Chen,
kayrus on github, kriztalz, Laurențiu Nicola, lf- on github, Marcel Raad,
Mark Phillips, qhill on github, Ray Satiro, renovate[bot], rmg-x on github,
RubisetCie on github, Sergey, Stefan Eissing, Tianyi Song, Timo Tijhof,
Viktor Szakats, Yedaya Katsman, Zenju on github
(28 contributors)
References to bug reports and discussions on issues:
@ -154,8 +204,11 @@ References to bug reports and discussions on issues:
[45] = https://curl.se/bug/?i=16100
[46] = https://curl.se/bug/?i=16375
[47] = https://curl.se/bug/?i=16357
[48] = https://curl.se/bug/?i=16436
[49] = https://curl.se/bug/?i=16352
[50] = https://curl.se/bug/?i=16167
[51] = https://curl.se/bug/?i=16409
[52] = https://curl.se/bug/?i=16443
[53] = https://curl.se/bug/?i=16367
[54] = https://curl.se/bug/?i=16384
[55] = https://curl.se/bug/?i=16366
@ -168,8 +221,53 @@ References to bug reports and discussions on issues:
[62] = https://curl.se/bug/?i=16252
[63] = https://curl.se/bug/?i=16356
[64] = https://curl.se/bug/?i=16117
[65] = https://curl.se/bug/?i=16417
[66] = https://curl.se/bug/?i=16396
[67] = https://curl.se/bug/?i=16399
[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
[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,6 +36,8 @@ esac
if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2022' ]; then
openssl_root_win="C:/OpenSSL-v34${openssl_suffix}"
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}"
else
openssl_root_win="C:/OpenSSL-v111${openssl_suffix}"
@ -52,35 +54,49 @@ if [ "${BUILD_SYSTEM}" = 'CMake' ]; then
[ -n "${TOOLSET:-}" ] && options+=" -T ${TOOLSET}"
[ "${OPENSSL}" = 'ON' ] && options+=" -DOPENSSL_ROOT_DIR=${openssl_root_win}"
[ -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
cmake -B "_bld${_chkprefill}" -G "${PRJ_GEN}" ${TARGET} \
-DCMAKE_VS_GLOBALS=TrackFileAccess=false \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG= \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE= \
-DCMAKE_UNITY_BUILD="${UNITY}" -DCURL_TEST_BUNDLES=ON \
time cmake -G "${PRJ_GEN}" ${TARGET} \
-DCURL_TEST_BUNDLES=ON \
-DCURL_WERROR=ON \
-DBUILD_SHARED_LIBS="${SHARED}" \
-DCURL_STATIC_CRT=ON \
-DENABLE_DEBUG="${DEBUG}" \
-DENABLE_UNICODE="${ENABLE_UNICODE}" \
-DHTTP_ONLY="${HTTP_ONLY}" \
-DCURL_USE_SCHANNEL="${SCHANNEL}" \
-DCURL_USE_OPENSSL="${OPENSSL}" \
-DCURL_USE_LIBPSL=OFF \
${options}
${options} \
|| { cat ${root}/_bld/CMakeFiles/CMake* 2>/dev/null; false; }
[ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2013' ] && cd ..
done
if [ -d _bld_chkprefill ] && ! diff -u _bld/lib/curl_config.h _bld_chkprefill/lib/curl_config.h; then
cat _bld_chkprefill/CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true
cat _bld_chkprefill/CMakeFiles/CMake* 2>/dev/null || true
false
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
# shellcheck disable=SC2086
cmake --build _bld --config "${PRJ_CFG}" --parallel 2 -- ${BUILD_OPT:-}
[ "${SHARED}" = 'ON' ] && PATH="$PWD/_bld/lib:$PATH"
[ "${OPENSSL}" = 'ON' ] && PATH="${openssl_root}:$PATH"
curl='_bld/src/curl.exe'
if ! time cmake --build _bld --config "${PRJ_CFG}" --parallel 2 -- ${BUILD_OPT:-}; then
if [ "${PRJ_GEN}" = 'Visual Studio 9 2008' ]; then
find . -name BuildLog.htm -exec dos2unix '{}' +
find . -name BuildLog.htm -exec cat '{}' +
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
(
cd projects
@ -113,7 +129,7 @@ EOF
curl="builds/libcurl-vc14.10-x64-${PATHPART}-dll-ssl-dll-ipv6-sspi/bin/curl.exe"
fi
find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' \) -exec file '{}' \;
find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' -o -name '*.pdb' \) -exec file '{}' \;
if [ -z "${SKIP_RUN:-}" ]; then
"${curl}" --disable --version
else
@ -124,13 +140,14 @@ fi
if [ "${TFLAGS}" != 'skipall' ] && \
[ "${BUILD_SYSTEM}" = 'CMake' ]; then
cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target testdeps
time cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target testdeps
fi
# run tests
if [ "${TFLAGS}" != 'skipall' ] && \
[ "${TFLAGS}" != 'skiprun' ]; then
export CURL_DIRSUFFIX="${PRJ_CFG}"
if [ -x "$(cygpath "${SYSTEMROOT}/System32/curl.exe")" ]; then
TFLAGS+=" -ac $(cygpath "${SYSTEMROOT}/System32/curl.exe")"
elif [ -x "$(cygpath 'C:/msys64/usr/bin/curl.exe')" ]; then
@ -138,12 +155,12 @@ if [ "${TFLAGS}" != 'skipall' ] && \
fi
TFLAGS+=' -j0'
if [ "${BUILD_SYSTEM}" = 'CMake' ]; then
cmake --build _bld --config "${PRJ_CFG}" --target test-ci
time cmake --build _bld --config "${PRJ_CFG}" --target test-ci
else
(
TFLAGS="-a -p !flaky -r -rm ${TFLAGS}"
cd _bld/tests
./runtests.pl
time ./runtests.pl
)
fi
fi
@ -152,5 +169,5 @@ fi
if [ "${EXAMPLES}" = 'ON' ] && \
[ "${BUILD_SYSTEM}" = 'CMake' ]; then
cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target curl-examples
time cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target curl-examples
fi

View File

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

View File

@ -21,6 +21,12 @@ CMake's GUIs.
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.
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`
You can configure for in source tree builds or for a build tree
@ -31,10 +37,14 @@ that is apart from the source tree.
$ cmake -B .
- Build in a separate directory (parallel to the curl source tree in this
example). The build directory is created for you.
example). The build directory is created for you. This is recommended over
building in the source tree to separate source and build artifacts.
$ 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
CMake before version 3.13 does not support the `-B` option. In that case,
@ -129,6 +139,12 @@ Install to default location (you have to specify the build directory).
$ 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
CMake before version 3.15 does not support the `--install` option. In that
@ -139,6 +155,68 @@ assumes that CMake generates `Makefile`:
$ cd ../curl-build
$ 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
- `BUILD_CURL_EXE`: Build curl executable. Default: `ON`
@ -160,7 +238,7 @@ assumes that CMake generates `Makefile`:
- `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_LTO`: Enable compiler Link Time Optimizations. Default: `OFF`
- `CURL_STATIC_CRT`: Build libcurl with static CRT with MSVC (`/MT`). Default: `OFF`
- `CURL_STATIC_CRT`: Build libcurl with static CRT with MSVC (`/MT`) (requires static or no curl executable). Default: `OFF`
- `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_WERROR`: Turn compiler warnings into errors. Default: `OFF`
@ -306,6 +384,7 @@ Details via CMake
- `OPENSSL_USE_STATIC_LIBS`: Look for static OpenSSL libraries.
- `ZLIB_INCLUDE_DIR`: The zlib include directory.
- `ZLIB_LIBRARY`: Path to `zlib` library.
- `ZLIB_USE_STATIC_LIBS`: Look for static ZLIB library (requires CMake v3.24).
## Dependency options
@ -379,7 +458,7 @@ Details via CMake
# Migrating from Visual Studio IDE Project Files
We recommend CMake to build curl with MSVC.
We recommend using CMake to build curl with MSVC.
The project build files reside in project/Windows/VC\* for VS2010, VS2010 and
VS2013 respectively.
@ -399,8 +478,8 @@ Configuration element | Equivalent CMake options
`Win32` | `-A Win32`
`DLL` | `BUILD_SHARED_LIBS=ON`, `BUILD_STATIC_LIBS=OFF`, (default)
`LIB` | `BUILD_SHARED_LIBS=OFF`, `BUILD_STATIC_LIBS=ON`
`Debug` | `CMAKE_BUILD_TYPE=Debug`
`Release` | `CMAKE_BUILD_TYPE=Release`
`Debug` | `CMAKE_BUILD_TYPE=Debug` (`-G "NMake Makefiles"` only)
`Release` | `CMAKE_BUILD_TYPE=Release` (`-G "NMake Makefiles"` only)
`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 libssh2` | `CURL_USE_LIBSSH2=ON`, optional: `LIBSSH2_INCLUDE_DIR`, `LIBSSH2_LIBRARY`
@ -414,7 +493,13 @@ For example these commands:
translate to:
> 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 . -G "Visual Studio 12 2013" -A x64 -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
@ -437,7 +522,7 @@ winbuild options | Equivalent CMake options
`DEBUG` | `CMAKE_BUILD_TYPE=Debug`
`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`
`VC` | see CMake `-G` [options](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html)
`VC`: `<N>` | see the CMake [Visual Studio generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html#visual-studio-generators)
`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)
`RTLIBCFG`: `static` | `CURL_STATIC_CRT=ON`
@ -467,4 +552,8 @@ For example this command-line:
translates to:
> 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 . -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 --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
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
version of curl depends on version v0.14.0 of rustls-ffi.
version of curl is compatible with `rustls-ffi` v0.14.x.
# 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:
% git clone https://github.com/rustls/rustls-ffi -b v0.14.0
% git clone https://github.com/rustls/rustls-ffi -b v0.14.1
% cd rustls-ffi
% make
% make DESTDIR=${HOME}/rustls-ffi-built/ install

View File

@ -157,3 +157,4 @@ s/edmcln\z/edmcln on github/
s/andrewkirillov-ibm/Andrew Kirillov/
s/\(.*\) via #[0-9]*//
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
already do much worse harm and the problem is not really in curl.
## Experiments
## Debug & Experiments
Vulnerabilities in features which are off by default (in the build) and
documented as experimental, are not eligible for a reward and we do not
consider them security problems.
documented as experimental, or exist only in debug mode, are not eligible for a
reward and we do not consider them security problems.
## URL inconsistencies

View File

@ -59,4 +59,4 @@ used.
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
work, including --ftp-ssl-reqd and --ftp-ssl-control.
work, including --ssl-reqd and --ftp-ssl-control.

View File

@ -2,16 +2,19 @@
c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
Long: url
Arg: <url>
Help: URL to work with
Arg: <url/file>
Help: URL(s) to work with
Category: curl
Added: 7.5
Multi: append
See-also:
- next
- config
- path-as-is
- disallow-username-in-url
Example:
- --url $URL
- --url @file
---
# `--url`
@ -32,3 +35,15 @@ destination option unless --remote-name-all is used.
On Windows, `file://` accesses can be converted to network accesses by the
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`
Output the certificate chain with details. Supported only by the OpenSSL,
GnuTLS, Schannel and Secure Transport backends. (Added in 7.88.0)
GnuTLS, Schannel, Rustls, and Secure Transport backends. (Added in 7.88.0)
## `conn_id`
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`
Number of server certificates received in the TLS handshake. Supported only by
the OpenSSL, GnuTLS, Schannel and Secure Transport backends.
the OpenSSL, GnuTLS, Schannel, Rustls and Secure Transport backends.
(Added in 7.88.0)
## `num_connects`

View File

@ -24,53 +24,53 @@ displays information about the curl and libcurl installation.
# OPTIONS
## --ca
## `--ca`
Displays the built-in path to the CA cert bundle this libcurl uses.
## --cc
## `--cc`
Displays the compiler used to build libcurl.
## --cflags
## `--cflags`
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.
## --checkfor [version]
## `--checkfor [version]`
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
outputs a text saying that the current version is not new enough. (Added in
7.15.4)
## --configure
## `--configure`
Displays the arguments given to configure when building curl.
## --feature
## `--feature`
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
any particular order. The keywords are separated by newlines. There may be
none, one, or several keywords in the list.
## --help
## `--help`
Displays the available options.
## --libs
## `--libs`
Shows the complete set of libs and other linker options you need in order to
link your application with libcurl.
## --prefix
## `--prefix`
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
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
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
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
no, one or several names. If more than one name, they appear comma-separated.
(Added in 7.58.0)
## --static-libs
## `--static-libs`
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)
## --version
## `--version`
Outputs version information about the installed libcurl.
## --vernum
## `--vernum`
Outputs version information about the installed libcurl, in numerical mode.
This shows the version number, in hexadecimal, using 8 bits for each part:
@ -104,22 +104,21 @@ omitted. (This option was broken in the 7.15.0 release.)
# EXAMPLES
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?
~~~
$ curl-config --cflags
~~~
$ curl-config --cflags
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?
~~~
$ curl-config --version
~~~
$ curl-config --version
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,14 +298,19 @@ int main(void)
filter = (struct connection_filter *)calloc(1, sizeof(*filter));
if(!filter)
exit(1);
return 1;
if(curl_global_init(CURL_GLOBAL_DEFAULT))
exit(1);
if(curl_global_init(CURL_GLOBAL_DEFAULT)) {
free(filter);
return 1;
}
curl = curl_easy_init();
if(!curl)
exit(1);
if(!curl) {
curl_global_cleanup();
free(filter);
return 1;
}
/* Set the target URL */
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost");

View File

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

View File

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

View File

@ -418,22 +418,22 @@ static int init_fifo(GlobalInfo *g)
struct epoll_event epev;
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) {
errno = EEXIST;
perror("lstat");
exit(1);
return 1;
}
}
unlink(fifo);
if(mkfifo (fifo, 0600) == -1) {
if(mkfifo(fifo, 0600) == -1) {
perror("mkfifo");
exit(1);
return 1;
}
sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0);
if(sockfd == -1) {
perror("open");
exit(1);
return 1;
}
g->fifofd = sockfd;
@ -449,9 +449,9 @@ static int init_fifo(GlobalInfo *g)
static void clean_fifo(GlobalInfo *g)
{
epoll_ctl(g->epfd, EPOLL_CTL_DEL, g->fifofd, NULL);
fclose(g->input);
unlink(fifo);
epoll_ctl(g->epfd, EPOLL_CTL_DEL, g->fifofd, NULL);
fclose(g->input);
unlink(fifo);
}
@ -478,13 +478,13 @@ int main(int argc, char **argv)
g.epfd = epoll_create1(EPOLL_CLOEXEC);
if(g.epfd == -1) {
perror("epoll_create1 failed");
exit(1);
return 1;
}
g.tfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
if(g.tfd == -1) {
perror("timerfd_create failed");
exit(1);
return 1;
}
memset(&its, 0, sizeof(struct itimerspec));
@ -496,7 +496,8 @@ int main(int argc, char **argv)
ev.data.fd = g.tfd;
epoll_ctl(g.epfd, EPOLL_CTL_ADD, g.tfd, &ev);
init_fifo(&g);
if(init_fifo(&g))
return 1;
g.multi = curl_multi_init();
/* setup the generic multi interface options we want */
@ -521,7 +522,7 @@ int main(int argc, char **argv)
}
else {
perror("epoll_wait");
exit(1);
return 1;
}
}

View File

@ -402,22 +402,22 @@ static int init_fifo(GlobalInfo *g)
curl_socket_t sockfd;
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) {
errno = EEXIST;
perror("lstat");
exit(1);
return 1;
}
}
unlink(fifo);
if(mkfifo (fifo, 0600) == -1) {
if(mkfifo(fifo, 0600) == -1) {
perror("mkfifo");
exit(1);
return 1;
}
sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0);
if(sockfd == -1) {
perror("open");
exit(1);
return 1;
}
g->input = fdopen(sockfd, "r");
@ -436,7 +436,8 @@ int main(int argc, char **argv)
memset(&g, 0, sizeof(GlobalInfo));
g.loop = ev_default_loop(0);
init_fifo(&g);
if(init_fifo(&g))
return 1;
g.multi = curl_multi_init();
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) {
errno = EEXIST;
perror("lstat");
exit(1);
return CURL_SOCKET_BAD;
}
}
unlink(fifo);
if(mkfifo (fifo, 0600) == -1) {
if(mkfifo(fifo, 0600) == -1) {
perror("mkfifo");
exit(1);
return CURL_SOCKET_BAD;
}
socket = open(fifo, O_RDWR | O_NONBLOCK, 0);
if(socket == -1) {
if(socket == CURL_SOCKET_BAD) {
perror("open");
exit(1);
return socket;
}
MSG_OUT("Now, pipe some URL's into > %s\n", fifo);
@ -421,6 +421,8 @@ int main(void)
GIOChannel* ch;
fd = init_fifo();
if(fd == CURL_SOCKET_BAD)
return 1;
ch = g_io_channel_unix_new(fd);
g_io_add_watch(ch, G_IO_IN, fifo_cb, g);
gmain = g_main_loop_new(NULL, FALSE);

View File

@ -399,22 +399,22 @@ static int init_fifo(GlobalInfo *g)
curl_socket_t sockfd;
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) {
errno = EEXIST;
perror("lstat");
exit(1);
return 1;
}
}
unlink(fifo);
if(mkfifo (fifo, 0600) == -1) {
perror("mkfifo");
exit(1);
return 1;
}
sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0);
if(sockfd == -1) {
perror("open");
exit(1);
return 1;
}
g->input = fdopen(sockfd, "r");
@ -440,7 +440,8 @@ int main(int argc, char **argv)
memset(&g, 0, sizeof(GlobalInfo));
g.evbase = event_base_new();
init_fifo(&g);
if(init_fifo(&g))
return 1;
g.multi = curl_multi_init();
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) {
fprintf(stderr, "Failed to create CURL connection\n");
exit(EXIT_FAILURE);
return false;
}
code = curl_easy_setopt(conn, CURLOPT_ERRORBUFFER, errorBuffer);
@ -270,7 +270,7 @@ int main(int argc, char *argv[])
if(argc != 2) {
fprintf(stderr, "Usage: %s <url>\n", argv[0]);
exit(EXIT_FAILURE);
return EXIT_FAILURE;
}
curl_global_init(CURL_GLOBAL_DEFAULT);
@ -279,7 +279,7 @@ int main(int argc, char *argv[])
if(!init(conn, argv[1])) {
fprintf(stderr, "Connection initialization failed\n");
exit(EXIT_FAILURE);
return EXIT_FAILURE;
}
// Retrieve content for the URL
@ -289,7 +289,7 @@ int main(int argc, char *argv[])
if(code != CURLE_OK) {
fprintf(stderr, "Failed to get '%s' [%s]\n", argv[1], errorBuffer);
exit(EXIT_FAILURE);
return EXIT_FAILURE;
}
// Parse the (assumed) HTML code

View File

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

View File

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

View File

@ -27,11 +27,10 @@ const struct curl_easyoption *curl_easy_option_by_name(const char *name);
# DESCRIPTION
Given a **name**, this function returns a pointer to the
*curl_easyoption* struct, holding information about the
curl_easy_setopt(3) option using that name. The name should be specified
without the "CURLOPT_" prefix and the name comparison is made case
insensitive.
Given a **name**, this function returns a pointer to the *curl_easyoption*
struct, holding information about the curl_easy_setopt(3) option using that
name. The name should be specified 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.

View File

@ -316,4 +316,4 @@ filenames are now escaped before transmission.
# RETURN VALUE
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);"
~~~
The curl_formget_callback is invoked for each part of the HTTP POST chain. The
character buffer passed to the callback must not be freed. The callback should
return the buffer length passed to it on success.
The *curl_formget_callback* is invoked for each part of the HTTP POST chain.
The character buffer passed to the callback must not be freed. The callback
should return the buffer length passed to it on success.
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.

View File

@ -376,9 +376,8 @@ supports HTTP zstd content encoding using zstd library (Added in 7.72.0)
*features* mask bit: CURL_VERSION_CONV
libcurl was built with support for character conversions, as provided by the
CURLOPT_CONV_* callbacks. Always 0 since 7.82.0. (Added in 7.15.4,
deprecated.)
libcurl was built with support for character conversions provided by
callbacks. Always 0 since 7.82.0. (Added in 7.15.4, deprecated.)
## 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
how exactly they are being used.
## CURL_ALTSVC_HTTP
## `CURL_ALTSVC_HTTP`
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.
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.
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
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.
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
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
only send 800.
## CURL_DBG_QUIC_WBLOCK
## `CURL_DBG_QUIC_WBLOCK`
The percentage of send() calls that should be answered with EAGAIN at random.
QUIC only.
## CURL_DEBUG
## `CURL_DEBUG`
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
HTTP/2.
## CURL_DEBUG_SIZE
## `CURL_DEBUG_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.
## CURL_HSTS_HTTP
## `CURL_HSTS_HTTP`
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.
## CURL_ENTROPY
## `CURL_ENTROPY`
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
they generate.
## CURL_SMALLREQSEND
## `CURL_SMALLREQSEND`
An alternative size of HTTP data to be sent at a time only if smaller than the
current.
## CURL_SMALLSENDS
## `CURL_SMALLSENDS`
An alternative size of socket data to be sent at a time only if smaller than
the current.
## CURL_TIME
## `CURL_TIME`
Fake Unix timestamp to use for AltSvc, HSTS and CURLINFO variables that are
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
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.
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
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
decoding.
## CURL_WS_CHUNK_EAGAIN
## `CURL_WS_CHUNK_EAGAIN`
Used to simulate blocking sends after this chunk size for WebSocket
connections.
## CURL_FORBID_REUSE
## `CURL_FORBID_REUSE`
Used to set the CURLOPT_FORBID_REUSE flag on each transfer initiated
by the curl command line tool. The value of the environment variable
does not matter.
## CURL_GRACEFUL_SHUTDOWN
## `CURL_GRACEFUL_SHUTDOWN`
Make a blocking, graceful shutdown of all remaining connections when
a multi handle is destroyed. This implicitly triggers for easy handles

View File

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

View File

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

View File

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

View File

@ -47,6 +47,11 @@ 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
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
*easy* identifies the specific transfer for which this update is related.

View File

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

View File

@ -42,21 +42,24 @@ header list establishes the document-level MIME headers to prepend to the
uploaded document described by CURLOPT_MIMEPOST(3). This does not affect raw
mail uploads.
The linked list should be a fully valid list of **struct curl_slist** structs
properly filled in. Use curl_slist_append(3) to create the list and
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).
When used with HTTP, this option can add new headers, replace internal headers
and remove internal headers.
The headers included in the linked list **must not** be CRLF-terminated,
because 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 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
curl_slist_free_all(3) to free it again after use.
If you provide a header that is otherwise generated and used by libcurl
internally, your header alternative is used instead. If you provide a header
without content (no data on the right side of the colon) as in `Accept:`, the
internally used header is removed. To forcibly add a header without content
(nothing after the colon), use the form `name;` (using a trailing semicolon).
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
POST) is not a header and cannot be replaced using this option. Only the lines
@ -164,9 +167,15 @@ int main(void)
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
/* add this header */
list = curl_slist_append(list, "Shoesize: 10");
/* remove this header */
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_perform(curl);

View File

@ -28,8 +28,8 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MIME_OPTIONS, long options);
# DESCRIPTION
Pass a long that holds a bitmask of CURLMIMEOPT_* defines. Each bit is a
Boolean flag used while encoding a MIME tree or multipart form data.
Pass a long that holds a bitmask of options. Each bit is a boolean flag used
while encoding a MIME tree or multipart form data.
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
available protocols.
Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
Pass a long that holds a bitmask of protocol bits. If used, this bitmask
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
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
control all available protocols.
Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
Pass a long that holds a bitmask of protocol bits. If used, this bitmask
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 specific transfers to only be allowed to use a subset of protocols in
redirect when CURLOPT_FOLLOWLOCATION(3) is enabled. This allows you to limit
specific transfers to only be allowed to use a subset of protocols in
redirections.
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
Tell libcurl to try sending application data as TLS1.3 early data. This option
is only supported for GnuTLS. This option works on a best effort basis,
is supported for GnuTLS and wolfSSL. This option works on a best effort basis,
in cases when it wasn't possible to send early data the request is resent
normally post-handshake.
This option does not work when using QUIC.
(Added in 8.11.0)
(Added in 8.11.0 for GnuTLS and 8.13.0 for wolfSSL)
# 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,
you can use the proc filesystem to bypass the limitation:
you can use the *proc* filesystem to bypass the limitation:
~~~c
int dirfd = open(long_directory_path_to_socket, O_DIRECTORY | O_RDONLY);

View File

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

View File

@ -51,7 +51,7 @@ stdout
A common technique is to use the write callback to store the incoming data
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
in. Like in the getinmemory example:
in. Like in the *getinmemory* example:
https://curl.se/libcurl/c/getinmemory.html
# HISTORY

View File

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

View File

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

View File

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

View File

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

View File

@ -592,7 +592,7 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
res->num_pending--;
if(CURL_ASYNC_SUCCESS == status) {
struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port);
struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->conn->remote_port);
if(ai) {
compound_results(res, ai);
}
@ -774,8 +774,6 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
if(!res->hostname)
return NULL;
data->state.async.hostname = res->hostname;
data->state.async.port = port;
data->state.async.done = FALSE; /* not done */
data->state.async.dns = NULL; /* clear */
@ -811,6 +809,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
service, &hints, addrinfo_cb, data);
}
#else
(void)port;
#ifdef HAVE_CARES_IPV6
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;
}
Curl_safefree(async->hostname);
}
#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));
async->thdata.hinfo.port = -1;
ares_query_dnsrec(async->thdata.channel,
async->hostname, ARES_CLASS_IN,
data->conn->host.name, ARES_CLASS_IN,
ARES_REC_TYPE_HTTPS,
Curl_dnsrec_done_cb, data, NULL);
@ -436,7 +436,6 @@ static bool init_resolve_thread(struct Curl_easy *data,
int err = ENOMEM;
struct Curl_async *async = &data->state.async;
async->port = port;
async->done = FALSE;
async->dns = NULL;
td->thread_hnd = curl_thread_t_null;
@ -447,11 +446,6 @@ static bool init_resolve_thread(struct Curl_easy *data,
goto errno_exit;
}
free(async->hostname);
async->hostname = strdup(hostname);
if(!async->hostname)
goto err_exit;
/* The thread will set this TRUE when complete. */
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
* only test for names where that can possibly be true.
*/
if(strncasecompare("__Secure-", Curl_str(&name), 9))
if(!strncmp("__Secure-", Curl_str(&name), 9))
co->prefix_secure = TRUE;
else if(strncasecompare("__Host-", Curl_str(&name), 7))
else if(!strncmp("__Host-", Curl_str(&name), 7))
co->prefix_host = TRUE;
/*

View File

@ -34,15 +34,9 @@
#endif
#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);
#define memrchr(x,y,z) Curl_memrchr((x),(y),(z))
#endif
#endif /* HAVE_MEMRCHR */
#endif /* HEADER_CURL_MEMRCHR_H */

View File

@ -120,6 +120,14 @@
# 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 */
#ifdef ENABLE_IPV6
#define USE_IPV6 1

View File

@ -85,7 +85,6 @@ void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
void Curl_trc_multi(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
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,
const char *fmt, ...) CURL_PRINTF(2, 3);
void Curl_trc_read(struct Curl_easy *data,
@ -179,13 +178,14 @@ void Curl_trc_ws(struct Curl_easy *data,
#endif /* !CURL_HAVE_C99 */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
/* informational messages enabled */
struct curl_trc_feat {
const char *name;
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_read;
extern struct curl_trc_feat Curl_trc_feat_write;
@ -201,6 +201,7 @@ extern struct curl_trc_feat Curl_trc_feat_dns;
#define Curl_trc_ft_is_verbose(data, ft) \
(Curl_trc_is_verbose(data) && \
(ft)->log_level >= CURL_LOG_LVL_INFO)
#define CURL_MSTATE_NAME(s) Curl_trc_mstate_name((int)(s))
#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
/* 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 &&
dohp->probe[DOH_SLOT_IPV6].easy_mid < 0) {
failf(data, "Could not DoH-resolve: %s", data->state.async.hostname);
failf(data, "Could not DoH-resolve: %s", dohp->host);
return CONN_IS_PROXIED(data->conn) ? CURLE_COULDNT_RESOLVE_PROXY :
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);
dns = Curl_cache_addr(data, ai,
data->state.async.hostname, 0,
data->state.async.port, FALSE);
data->conn->host.dispname, 0,
data->conn->localport, FALSE);
if(data->share)
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,
data->state.async.hostname);
data->conn->host.dispname);
return result;
}

View File

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

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))
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.timecondition = (unsigned char)(curl_TimeCond)arg;
data->set.timecondition = (unsigned char)arg;
break;
case CURLOPT_TIMEVALUE:
/*

View File

@ -93,12 +93,6 @@
* 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
#define _WIN32_WINNT_WINXP 0x0501 /* Windows XP */
#endif

View File

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

View File

@ -31,6 +31,12 @@ void Curl_str_init(struct Curl_str *out)
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.
return non-zero on error */
int Curl_str_until(const char **linep, struct Curl_str *out,
@ -63,6 +69,29 @@ int Curl_str_word(const char **linep, struct Curl_str *out,
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.
return non-zero on error */

View File

@ -43,6 +43,7 @@ struct Curl_str {
};
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_strlen(x) ((x)->len)
@ -56,6 +57,11 @@ 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,
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.
return non-zero on error */
int Curl_str_quotedword(const char **linep, struct Curl_str *out,

View File

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

View File

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

View File

@ -113,88 +113,12 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
/* we are always running on PLATFORM_WINNT */
matched = FALSE;
}
#elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
(_WIN32_WINNT < _WIN32_WINNT_WIN2K)
OSVERSIONINFO osver;
memset(&osver, 0, sizeof(osver));
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;
}
}
}
#elif defined(UNDER_CE)
(void)majorVersion;
(void)minorVersion;
(void)buildVersion;
(void)platform;
(void)condition;
#else
ULONGLONG cm = 0;
struct OUR_OSVERSIONINFOEXW osver;

View File

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

View File

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

View File

@ -1267,6 +1267,9 @@ static CURLcode cf_quiche_ctx_open(struct Curl_cfilter *cf,
int rv;
CURLcode result;
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->initialized);
@ -1304,9 +1307,7 @@ static CURLcode cf_quiche_ctx_open(struct Curl_cfilter *cf,
- 1);
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
QUICHE_H3_APPLICATION_PROTOCOL,
sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1,
NULL, NULL, cf, NULL);
&ALPN_SPEC_H3, NULL, NULL, cf, NULL);
if(result)
return result;

View File

@ -58,178 +58,11 @@
#include "curl_memory.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,
struct Curl_cfilter *cf,
struct Curl_easy *data,
struct ssl_peer *peer,
const char *alpn, size_t alpn_len,
const struct alpn_spec *alpns,
Curl_vquic_tls_ctx_setup *cb_setup,
void *cb_user_data, void *ssl_user_data,
Curl_vquic_session_reuse_cb *session_reuse_cb)
@ -254,21 +87,16 @@ CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx,
#ifdef USE_OPENSSL
(void)result;
return Curl_ossl_ctx_init(&ctx->ossl, cf, data, peer,
(const unsigned char *)alpn, alpn_len,
return Curl_ossl_ctx_init(&ctx->ossl, cf, data, peer, alpns,
cb_setup, cb_user_data, NULL, ssl_user_data);
#elif defined(USE_GNUTLS)
return Curl_gtls_ctx_init(&ctx->gtls, cf, data, peer,
(const unsigned char *)alpn, alpn_len,
return Curl_gtls_ctx_init(&ctx->gtls, cf, data, peer, alpns,
cb_setup, cb_user_data, ssl_user_data,
session_reuse_cb);
#elif defined(USE_WOLFSSL)
result = wssl_init_ctx(ctx, cf, data, cb_setup, cb_user_data);
if(result)
return result;
(void)session_reuse_cb;
return wssl_init_ssl(ctx, cf, data, peer, alpn, alpn_len, ssl_user_data);
return Curl_wssl_ctx_init(&ctx->wssl, cf, data, peer, alpns,
cb_setup, cb_user_data,
ssl_user_data, session_reuse_cb);
#else
#error "no TLS lib in used, should not happen"
return CURLE_FAILED_INIT;
@ -287,10 +115,10 @@ void Curl_vquic_tls_cleanup(struct curl_tls_ctx *ctx)
gnutls_deinit(ctx->gtls.session);
Curl_gtls_shared_creds_free(&ctx->gtls.shared_creds);
#elif defined(USE_WOLFSSL)
if(ctx->wssl.handle)
wolfSSL_free(ctx->wssl.handle);
if(ctx->wssl.ctx)
wolfSSL_CTX_free(ctx->wssl.ctx);
if(ctx->wssl.ssl)
wolfSSL_free(ctx->wssl.ssl);
if(ctx->wssl.ssl_ctx)
wolfSSL_CTX_free(ctx->wssl.ssl_ctx);
#endif
memset(ctx, 0, sizeof(*ctx));
}
@ -351,7 +179,7 @@ CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx,
(void)data;
if(conn_config->verifyhost) {
if(peer->sni) {
WOLFSSL_X509* cert = wolfSSL_get_peer_certificate(ctx->wssl.handle);
WOLFSSL_X509* cert = wolfSSL_get_peer_certificate(ctx->wssl.ssl);
if(wolfSSL_X509_check_host(cert, peer->sni, strlen(peer->sni), 0, NULL)
== WOLFSSL_FAILURE) {
result = CURLE_PEER_FAILED_VERIFICATION;

View File

@ -27,6 +27,7 @@
#include "curl_setup.h"
#include "bufq.h"
#include "vtls/vtls.h"
#include "vtls/vtls_int.h"
#include "vtls/openssl.h"
#if defined(USE_HTTP3) && \
@ -43,7 +44,7 @@ struct curl_tls_ctx {
#elif defined(USE_GNUTLS)
struct gtls_ctx gtls;
#elif defined(USE_WOLFSSL)
struct wolfssl_ctx wssl;
struct wssl_ctx wssl;
#endif
};
@ -60,6 +61,7 @@ typedef CURLcode Curl_vquic_tls_ctx_setup(struct Curl_cfilter *cf,
typedef CURLcode Curl_vquic_session_reuse_cb(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct alpn_spec *alpns,
struct Curl_ssl_session *scs,
bool *do_early_data);
@ -70,9 +72,7 @@ typedef CURLcode Curl_vquic_session_reuse_cb(struct Curl_cfilter *cf,
* @param cf the connection filter involved
* @param data the transfer involved
* @param peer the peer that will be connected to
* @param alpn the ALPN string in protocol format ((len+bytes+)+),
* may be NULL
* @param alpn_len the overall number of bytes in `alpn`
* @param alpns the ALPN specifications to negotiate, may be NULL
* @param cb_setup optional callback for early TLS config
* @param cb_user_data user_data param for callback
* @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_easy *data,
struct ssl_peer *peer,
const char *alpn, size_t alpn_len,
const struct alpn_spec *alpns,
Curl_vquic_tls_ctx_setup *cb_setup,
void *cb_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;
}
}
else if(ssl_config->key_passwd) {
else {
const unsigned int supported_key_encryption_algorithms =
GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
@ -974,22 +974,12 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf,
supported_key_encryption_algorithms);
if(rc != GNUTLS_E_SUCCESS) {
failf(data,
"error reading X.509 potentially-encrypted key file: %s",
"error reading X.509 %skey file: %s",
ssl_config->key_passwd ? "potentially-encrypted " : "",
gnutls_strerror(rc));
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
@ -1042,6 +1032,7 @@ static int keylog_callback(gnutls_session_t session, const char *label,
static CURLcode gtls_on_session_reuse(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct alpn_spec *alpns,
struct Curl_ssl_session *scs,
bool *do_early_data)
{
@ -1057,13 +1048,13 @@ static CURLcode gtls_on_session_reuse(struct Curl_cfilter *cf,
/* Seems to be GnuTLS way to signal no EarlyData in session */
CURL_TRC_CF(data, cf, "SSL session does not allow earlydata");
}
else if(!Curl_alpn_contains_proto(connssl->alpn, scs->alpn)) {
else if(!Curl_alpn_contains_proto(alpns, scs->alpn)) {
CURL_TRC_CF(data, cf, "SSL session has different ALPN, no early data");
}
else {
infof(data, "SSL session allows %zu bytes of early data, "
"reusing ALPN '%s'", connssl->earlydata_max, scs->alpn);
connssl->earlydata_state = ssl_earlydata_use;
connssl->earlydata_state = ssl_earlydata_await;
connssl->state = ssl_connection_deferred;
result = Curl_alpn_set_negotiated(cf, data, connssl,
(const unsigned char *)scs->alpn,
@ -1077,7 +1068,7 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
struct Curl_cfilter *cf,
struct Curl_easy *data,
struct ssl_peer *peer,
const unsigned char *alpn, size_t alpn_len,
const struct alpn_spec *alpns_requested,
Curl_gtls_ctx_setup_cb *cb_setup,
void *cb_user_data,
void *ssl_user_data,
@ -1086,13 +1077,16 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
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 Curl_ssl_session *scs = NULL;
gnutls_datum_t gtls_alpns[5];
gnutls_datum_t gtls_alpns[ALPN_ENTRIES_MAX];
size_t gtls_alpns_count = 0;
bool gtls_session_setup = FALSE;
struct alpn_spec alpns;
CURLcode result;
int rc;
DEBUGASSERT(gctx);
Curl_alpn_copy(&alpns, alpns_requested);
/* 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
session since we need to set flags depending on the kind of reuse. */
@ -1101,7 +1095,8 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
if(result)
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! */
result = gtls_client_init(cf, data, peer, scs->earlydata_max, gctx);
@ -1115,30 +1110,19 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
else {
infof(data, "SSL reusing session with ALPN '%s'",
scs->alpn ? scs->alpn : "-");
if(ssl_config->earlydata &&
if(ssl_config->earlydata && scs->alpn &&
!cf->conn->connect_only &&
(gnutls_protocol_get_version(gctx->session) == GNUTLS_TLS1_3)) {
bool do_early_data = FALSE;
if(sess_reuse_cb) {
result = sess_reuse_cb(cf, data, scs, &do_early_data);
result = sess_reuse_cb(cf, data, &alpns, scs, &do_early_data);
if(result)
goto out;
}
if(do_early_data) {
/* We only try the ALPN protocol the session used before,
* otherwise we might send early data for the wrong protocol */
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;
Curl_alpn_restrict_to(&alpns, scs->alpn);
}
}
}
@ -1168,24 +1152,14 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
/* 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
* to the server. nice. */
if(!gtls_alpns_count && alpn && alpn_len) {
size_t i, alen = alpn_len;
unsigned char *salpn = (unsigned char *)alpn;
unsigned char slen;
for(i = 0; (i < CURL_ARRAYSIZE(gtls_alpns)) && alen; ++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;
if(!gtls_alpns_count && alpns.count) {
size_t i;
DEBUGASSERT(CURL_ARRAYSIZE(gtls_alpns) >= alpns.count);
for(i = 0; i < alpns.count; ++i) {
gtls_alpns[i].data = (unsigned char *)alpns.entries[i];
gtls_alpns[i].size = (unsigned int)strlen(alpns.entries[i]);
}
if(alen) { /* not all alpn chars used, wrong format or too many */
result = CURLE_FAILED_INIT;
goto out;
}
gtls_alpns_count = i;
gtls_alpns_count = alpns.count;
}
if(gtls_alpns_count &&
@ -1207,7 +1181,6 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
struct ssl_connect_data *connssl = cf->ctx;
struct gtls_ssl_backend_data *backend =
(struct gtls_ssl_backend_data *)connssl->backend;
struct alpn_proto_buf proto;
CURLcode result;
DEBUGASSERT(backend);
@ -1217,22 +1190,15 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
same connection */
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,
proto.data, proto.len,
NULL, NULL, cf, gtls_on_session_reuse);
connssl->alpn, NULL, NULL, cf,
gtls_on_session_reuse);
if(result)
return result;
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);
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
@ -1780,30 +1746,6 @@ out:
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,
struct Curl_easy *data)
{
@ -1879,7 +1821,7 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
}
if(connssl->connecting_state == ssl_connect_2) {
if(connssl->earlydata_state == ssl_earlydata_use) {
if(connssl->earlydata_state == ssl_earlydata_await) {
goto out;
}
else if(connssl->earlydata_state == ssl_earlydata_sending) {
@ -1887,8 +1829,6 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
if(result)
goto out;
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) ||
(connssl->earlydata_state == ssl_earlydata_sent));
@ -1920,31 +1860,19 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
if(result)
goto out;
if(connssl->earlydata_state == ssl_earlydata_sent) {
/* report the true time the handshake was done */
connssl->handshake_done = Curl_now();
Curl_pgrsTimeWas(data, TIMER_APPCONNECT, connssl->handshake_done);
if(gnutls_session_get_flags(backend->gtls.session) &
GNUTLS_SFLAGS_EARLY_DATA) {
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;
}
if(connssl->earlydata_state > ssl_earlydata_none) {
/* We should be in this state by now */
DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sent);
connssl->earlydata_state =
(gnutls_session_get_flags(backend->gtls.session) &
GNUTLS_SFLAGS_EARLY_DATA) ?
ssl_earlydata_accepted : ssl_earlydata_rejected;
}
connssl->connecting_state = ssl_connect_done;
}
if(ssl_connect_done == connssl->connecting_state) {
connssl->state = ssl_connection_complete;
*done = TRUE;
}
if(connssl->connecting_state == ssl_connect_done)
DEBUGASSERT(connssl->state == ssl_connection_complete);
out:
if(result == CURLE_AGAIN) {
@ -1962,7 +1890,8 @@ static CURLcode gtls_connect(struct Curl_cfilter *cf,
bool *done)
{
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. */
*done = TRUE;
return CURLE_OK;
@ -1970,26 +1899,6 @@ static CURLcode gtls_connect(struct Curl_cfilter *cf,
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,
const struct Curl_easy *data)
{
@ -2017,38 +1926,9 @@ static ssize_t gtls_send(struct Curl_cfilter *cf,
ssize_t rc;
size_t nwritten, total_written = 0;
(void)data;
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) {
backend->gtls.io_result = CURLE_OK;
rc = gnutls_record_send(backend->gtls.session, buf, blen);
@ -2195,21 +2075,6 @@ static ssize_t gtls_recv(struct Curl_cfilter *cf,
(void)data;
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);
if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
*curlcode = CURLE_AGAIN;

View File

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

View File

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

View File

@ -43,6 +43,7 @@
#include "connect.h" /* for the connect timeout */
#include "cipher_suite.h"
#include "rand.h"
#include "x509asn1.h"
struct rustls_ssl_backend_data
{
@ -845,6 +846,43 @@ cr_connect(struct Curl_cfilter *cf,
infof(data, "rustls: handshake complete, %s, cipher: %s",
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;
*done = TRUE;
return CURLE_OK;
@ -1011,7 +1049,8 @@ const struct Curl_ssl Curl_ssl_rustls = {
SSLSUPP_CAINFO_BLOB | /* supports */
SSLSUPP_HTTPS_PROXY |
SSLSUPP_CIPHER_LIST |
SSLSUPP_TLS13_CIPHERSUITES,
SSLSUPP_TLS13_CIPHERSUITES |
SSLSUPP_CERTINFO,
sizeof(struct rustls_ssl_backend_data),
NULL, /* init */

View File

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

View File

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

View File

@ -485,18 +485,6 @@ 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,
struct dynbuf *binding)
{
@ -1318,7 +1306,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
struct cf_call_data save;
CURLcode result;
if(cf->connected) {
if(cf->connected && (connssl->state != ssl_connection_deferred)) {
*done = TRUE;
return CURLE_OK;
}
@ -1336,8 +1324,6 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
CF_DATA_SAVE(save, cf, data);
CURL_TRC_CF(data, cf, "cf_connect()");
DEBUGASSERT(data->conn);
DEBUGASSERT(data->conn == cf->conn);
DEBUGASSERT(connssl);
*done = FALSE;
@ -1349,7 +1335,13 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
goto out;
}
result = ssl_connect(cf, data, done);
if(!connssl->prefs_checked) {
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) {
cf->connected = TRUE;
@ -1358,6 +1350,8 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
/* Connection can be deferred when sending early data */
DEBUGASSERT(connssl->state == ssl_connection_complete ||
connssl->state == ssl_connection_deferred);
DEBUGASSERT(connssl->state != ssl_connection_deferred ||
connssl->earlydata_state > ssl_earlydata_none);
}
out:
CURL_TRC_CF(data, cf, "cf_connect() -> %d, done=%d", result, *done);
@ -1365,6 +1359,77 @@ out:
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,
const struct Curl_easy *data)
{
@ -1383,21 +1448,57 @@ static bool ssl_cf_data_pending(struct Curl_cfilter *cf,
}
static ssize_t ssl_cf_send(struct Curl_cfilter *cf,
struct Curl_easy *data, const void *buf, size_t len,
struct Curl_easy *data,
const void *buf, size_t blen,
bool eos, CURLcode *err)
{
struct ssl_connect_data *connssl = cf->ctx;
struct cf_call_data save;
ssize_t nwritten = 0;
ssize_t nwritten = 0, early_written = 0;
(void)eos;
/* OpenSSL and maybe other TLS libs do not like 0-length writes. Skip. */
*err = CURLE_OK;
if(len > 0) {
CF_DATA_SAVE(save, cf, data);
nwritten = connssl->ssl_impl->send_plain(cf, data, buf, len, err);
CF_DATA_RESTORE(cf, save);
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. */
if(blen > 0)
nwritten = connssl->ssl_impl->send_plain(cf, data, buf, blen, err);
if(nwritten >= 0)
nwritten += early_written;
out:
CF_DATA_RESTORE(cf, save);
return nwritten;
}
@ -1411,6 +1512,21 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
CF_DATA_SAVE(save, cf, data);
*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);
if(nread > 0) {
DEBUGASSERT((size_t)nread <= len);
@ -1419,6 +1535,8 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
/* eof */
*err = CURLE_OK;
}
out:
CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len,
nread, *err);
CF_DATA_RESTORE(cf, save);
@ -1433,7 +1551,9 @@ static CURLcode ssl_cf_shutdown(struct Curl_cfilter *cf,
CURLcode result = CURLE_OK;
*done = TRUE;
if(!cf->shutdown && Curl_ssl->shut_down) {
/* If we have done the SSL handshake, shut down the connection cleanly */
if(cf->connected && (connssl->state == ssl_connection_complete) &&
!cf->shutdown && Curl_ssl->shut_down) {
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
@ -1831,6 +1951,24 @@ bool Curl_alpn_contains_proto(const struct alpn_spec *spec,
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,
struct Curl_easy *data,
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))
struct alpn_spec {
const char entries[ALPN_ENTRIES_MAX][ALPN_NAME_MAX];
char entries[ALPN_ENTRIES_MAX][ALPN_NAME_MAX];
size_t count; /* number of entries */
};
@ -62,6 +62,8 @@ CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf,
const struct alpn_spec *spec);
CURLcode Curl_alpn_to_proto_str(struct alpn_proto_buf *buf,
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,
struct Curl_easy *data,
@ -89,7 +91,7 @@ typedef enum {
typedef enum {
ssl_earlydata_none,
ssl_earlydata_use,
ssl_earlydata_await,
ssl_earlydata_sending,
ssl_earlydata_sent,
ssl_earlydata_accepted,
@ -124,6 +126,7 @@ struct ssl_connect_data {
int io_need; /* TLS signals special SEND/RECV needs */
BIT(use_alpn); /* if ALPN shall be used in handshake */
BIT(peer_closed); /* peer has closed connection */
BIT(prefs_checked); /* SSL preferences have been checked */
};

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -29,19 +29,21 @@
#include "urldata.h"
struct alpn_spec;
struct ssl_peer;
struct Curl_ssl_session;
struct WOLFSSL;
typedef struct WOLFSSL WOLFSSL;
struct WOLFSSL_CTX;
typedef struct WOLFSSL_CTX WOLFSSL_CTX;
struct WOLFSSL_SESSION;
typedef struct WOLFSSL_SESSION WOLFSSL_SESSION;
extern const struct Curl_ssl Curl_ssl_wolfssl;
struct wolfssl_ctx {
WOLFSSL_CTX *ctx;
WOLFSSL *handle;
struct wssl_ctx {
struct WOLFSSL_CTX *ssl_ctx;
struct WOLFSSL *ssl;
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 */
BIT(x509_store_setup); /* x509 store has been set up */
BIT(shutting_down); /* TLS is being shut down */
@ -49,21 +51,43 @@ struct wolfssl_ctx {
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,
struct Curl_easy *data,
struct wolfssl_ctx *wssl);
struct wssl_ctx *wssl);
CURLcode Curl_wssl_setup_session(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct wolfssl_ctx *wss,
struct wssl_ctx *wss,
const char *ssl_peer_key);
CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf,
struct Curl_easy *data,
const char *ssl_peer_key,
WOLFSSL_SESSION *session,
struct WOLFSSL_SESSION *session,
int ietf_tls_id,
const char *alpn);
const char *alpn,
unsigned char *quic_tp,
size_t quic_tp_len);
#endif /* USE_WOLFSSL */

View File

@ -26,15 +26,15 @@
#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS)
defined(USE_MBEDTLS) || defined(USE_RUSTLS)
#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS) || defined(USE_WOLFSSL)
defined(USE_MBEDTLS) || defined(USE_WOLFSSL) || defined(USE_RUSTLS)
#define WANT_PARSEX509 /* uses Curl_parseX509() */
#endif
#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS)
defined(USE_MBEDTLS) || defined(USE_RUSTLS)
#define WANT_EXTRACT_CERTINFO /* uses Curl_extract_certinfo() */
#endif
@ -1277,4 +1277,5 @@ done:
#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) || \
defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS)
defined(USE_MBEDTLS) || defined(USE_RUSTLS)
#include "cfilters.h"
#include "urldata.h"
@ -80,7 +80,7 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf, struct Curl_easy *data,
#ifdef UNITTESTS
#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS)
defined(USE_MBEDTLS) || defined(USE_RUSTLS)
/* used by unit1656.c */
CURLcode Curl_x509_GTime2str(struct dynbuf *store,
@ -91,5 +91,6 @@ CURLcode Curl_x509_getASN1Element(struct Curl_asn1Element *elem,
#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 */

View File

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

View File

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

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