curl/docs/internals/CREDENTIALS.md
Stefan Eissing 73daec6620
lib: transfer origin and proxy handling
Add `data->state.origin` as the origin the transfer is sending the
current request to/gets the response from. Use it for request specific
properties like authentication, hsts and cookie handling, etc.

Unless talking to a forwarding HTTP proxy (e.g. not tunneling),
`data->state.origin` and `conn->origin` are the same.

With a forwarding HTTP proxy in play, `conn->origin` is set to
`conn->http_proxy.peer` and `conn->bits.origin_is_proxy` (a new bit) is
set.

Remove the connection bits, now replaced with:

* `conn->bits.socksproxy` -> `conn->socks_proy.peer`
* `conn->bits.httpproxy` -> `conn->http_proy.peer`
* `conn->bits.proxy` -> `(conn->socks_proy.peer || conn->http_proy.peer`)
* `conn->bits.tunnel_proxy` -> (`conn->http_proy.peer && !conn->bits.origin_is_proxy`)
* `(conn->bits.httpproxy && !conn->bits.tunnel_proxy)` -> `conn->bits.origin_is_proxy`

Rename `noproxy.[ch]` to `proxy.[ch]`. Move the connection proxy setup
code from `url.c` to `proxy.c`.

Remove `data->info.conn_remote_port` as no one uses it.

Add test_40_02b for a SOCKS connection to a forwarding HTTPS proxy.

Update internal documentation about peers and creds.

Closes #21967
2026-06-12 23:52:00 +02:00

76 lines
3 KiB
Markdown

<!--
Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
SPDX-License-Identifier: curl
-->
# curl `creds`
Authorization credentials are kept in `struct Curl_creds`. This contains:
* `user`: the username, maybe the empty string
* `passwd`: the password, maybe the empty string
* `sasl_authzid`: the SASL `authz` value, maybe the empty string
* `oauth_bearer`: the OAUTH bearer token, maybe the empty string
* `source`: where the credentials from
* `refcount`: a reference counter to link/unlink `creds`
A `creds` with all values empty is equivalent to NULL, e.g. no `creds`
instance. With reference counting, `creds` can be linked in several places.
Two `creds` are the same if all values are equal apart from `source`
and `refcount`. The comparison of strings is done via `Curl_timestrcmp()`
to prevent side channel attacks.
## `creds` locations
Credentials are kept in three places:
* `data->state.creds`: the credentials to use for the transfer in talking
to the `origin` (see PEERS)
* `conn->creds`: the credentials tied to a connection (more below)
* `conn->*_proxy.creds`: credentials used to talk to the `conn->*_proxy.peer`
### `data->state.creds`
This `creds` instance is created when the transfer starts looking for a
suitable connection. For an `easy_perform()` this may happen several times
if, for example, http redirects are followed.
When an `easy_perform()` starts, the transfer's `data->state.initial_origin`
peer is cleared. When creating the connection, `data->state.origin` is
calculated (e.g. who the request talks to). If `data->state.initial_origin`
is not set, the first `data->state.origin` is linked there.
Now `libcurl` knows where
the transfer initially talked to on all possible subsequent requests.
Credential information from `CURLOPT_*` settings is only applicable for the
initial origin. Any followup request going to another origin must not
use it. Therefore `data->state.creds` is *only* created from `CURLOPT_*`
when current origin and initial origin match.
Without credentials from `CURLOPT_*`, the URL is inspected for user and
password and `netrc` is consulted as well (when built in).
### `conn->creds`
Once `data->state.creds` is known, the connection credentials are
determined. For protocols that tie authorization to everything send
on a connection (protocols without flag `PROTOPT_CREDSPERREQUEST`),
`conn->creds` is linked to `data->state.creds`. Only connections
carrying the same credentials may be reused.
Protocol with flag `PROTOPT_CREDSPERREQUEST` leave `conn->creds` empty,
as connections for such protocols may be reused with different
credentials.
That being said, there are authentication schemes like `NTLM` and
`NEGOTIATE` that tie credentials to a connection. Those do set `conn->creds`
once they start to operate, preventing connection reuse from then on
for transfers with different credentials.
### `conn->*_proxy.creds`
Those are set during connection setup from the `CURLOPT_*` values. They
do not require any "initial origin" handling as the origin of a proxy
does not change for a transfer.