mirror of
https://github.com/curl/curl.git
synced 2026-08-26 02:43:31 +03:00
creds: hold credentials
Authorizdation 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 from * `refcount`: a reference counter to link/unkink creds A `creds` with all values empty is equivalent to NULL, e.g. no `creds` instance. With reference counting, `creds` can be linked/unlinked in several places. See docs/internals/CREDENTIALS.md for use. Closes #21548
This commit is contained in:
parent
a32a2b0b77
commit
8f71d0fde5
47 changed files with 1138 additions and 962 deletions
118
lib/http.c
118
lib/http.c
|
|
@ -250,14 +250,14 @@ char *Curl_copy_header_value(const char *header)
|
|||
*
|
||||
* Returns CURLcode.
|
||||
*/
|
||||
static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
|
||||
static CURLcode http_output_basic(struct Curl_easy *data,
|
||||
struct connectdata *conn, bool proxy)
|
||||
{
|
||||
size_t size = 0;
|
||||
char *authorization = NULL;
|
||||
char **p_hd;
|
||||
const char *user;
|
||||
const char *pwd;
|
||||
CURLcode result;
|
||||
struct Curl_creds *creds = NULL;
|
||||
char *out;
|
||||
|
||||
/* credentials are unique per transfer for HTTP, do not use the ones for the
|
||||
|
|
@ -265,19 +265,23 @@ static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
|
|||
if(proxy) {
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
p_hd = &data->req.hd_proxy_auth;
|
||||
user = data->state.aptr.proxyuser;
|
||||
pwd = data->state.aptr.proxypasswd;
|
||||
creds = conn->http_proxy.creds;
|
||||
#else
|
||||
(void)conn;
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
p_hd = &data->req.hd_auth;
|
||||
user = data->state.aptr.user;
|
||||
pwd = data->state.aptr.passwd;
|
||||
creds = data->state.creds;
|
||||
}
|
||||
|
||||
out = curl_maprintf("%s:%s", user ? user : "", pwd ? pwd : "");
|
||||
if(!creds) {
|
||||
DEBUGASSERT(0);
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
out = curl_maprintf("%s:%s", creds->user, creds->passwd);
|
||||
if(!out)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
|
|
@ -320,10 +324,11 @@ static CURLcode http_output_bearer(struct Curl_easy *data)
|
|||
char **userp;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
DEBUGASSERT(Curl_creds_has_oauth_bearer(data->state.creds));
|
||||
userp = &data->req.hd_auth;
|
||||
curlx_free(*userp);
|
||||
*userp = curl_maprintf("Authorization: Bearer %s\r\n",
|
||||
data->set.str[STRING_BEARER]);
|
||||
Curl_creds_oauth_bearer(data->state.creds));
|
||||
|
||||
if(!*userp) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
|
|
@ -527,10 +532,10 @@ static bool http_should_fail(struct Curl_easy *data, int httpcode)
|
|||
* Either we are not authenticating, or we are supposed to be authenticating
|
||||
* something else. This is an error.
|
||||
*/
|
||||
if((httpcode == 401) && !data->state.aptr.user)
|
||||
if((httpcode == 401) && !data->state.creds)
|
||||
return TRUE;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if((httpcode == 407) && !data->conn->bits.proxy_user_passwd)
|
||||
if((httpcode == 407) && !data->conn->http_proxy.creds)
|
||||
return TRUE;
|
||||
#endif
|
||||
|
||||
|
|
@ -551,7 +556,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
|
|||
CURLcode result = CURLE_OK;
|
||||
unsigned long authmask = ~0UL;
|
||||
|
||||
if(!data->set.str[STRING_BEARER])
|
||||
if(!Curl_creds_has_oauth_bearer(data->state.creds))
|
||||
authmask &= (unsigned long)~CURLAUTH_BEARER;
|
||||
|
||||
if(100 <= data->req.httpcode && data->req.httpcode <= 199)
|
||||
|
|
@ -561,7 +566,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
|
|||
if(data->state.authproblem)
|
||||
return data->set.http_fail_on_error ? CURLE_HTTP_RETURNED_ERROR : CURLE_OK;
|
||||
|
||||
if((data->state.aptr.user || data->set.str[STRING_BEARER]) &&
|
||||
if(data->state.creds &&
|
||||
((data->req.httpcode == 401) ||
|
||||
(data->req.authneg && data->req.httpcode < 300))) {
|
||||
pickhost = pickoneauth(&data->state.authhost, authmask);
|
||||
|
|
@ -578,7 +583,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
|
|||
}
|
||||
}
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(conn->bits.proxy_user_passwd &&
|
||||
if(conn->http_proxy.creds &&
|
||||
((data->req.httpcode == 407) ||
|
||||
(data->req.authneg && data->req.httpcode < 300))) {
|
||||
pickproxy = pickoneauth(&data->state.authproxy,
|
||||
|
|
@ -694,14 +699,14 @@ static CURLcode output_auth_headers(struct Curl_easy *data,
|
|||
/* Basic */
|
||||
if(
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
(proxy && conn->bits.proxy_user_passwd &&
|
||||
(proxy && conn->http_proxy.creds &&
|
||||
!Curl_checkProxyheaders(data, conn,
|
||||
STRCONST("Proxy-authorization"))) ||
|
||||
#endif
|
||||
(!proxy && data->state.aptr.user &&
|
||||
(!proxy && data->state.creds &&
|
||||
!Curl_checkheaders(data, STRCONST("Authorization")))) {
|
||||
auth = "Basic";
|
||||
result = http_output_basic(data, proxy);
|
||||
result = http_output_basic(data, conn, proxy);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
|
@ -714,8 +719,7 @@ static CURLcode output_auth_headers(struct Curl_easy *data,
|
|||
#ifndef CURL_DISABLE_BEARER_AUTH
|
||||
if(authstatus->picked == CURLAUTH_BEARER) {
|
||||
/* Bearer */
|
||||
if(!proxy && data->set.str[STRING_BEARER] &&
|
||||
Curl_auth_allowed_to_host(data) &&
|
||||
if(!proxy && Curl_creds_has_oauth_bearer(data->state.creds) &&
|
||||
!Curl_checkheaders(data, STRCONST("Authorization"))) {
|
||||
auth = "Bearer";
|
||||
result = http_output_bearer(data);
|
||||
|
|
@ -737,15 +741,15 @@ static CURLcode output_auth_headers(struct Curl_easy *data,
|
|||
data->info.httpauthpicked = authstatus->picked;
|
||||
infof(data, "%s auth using %s with user '%s'",
|
||||
proxy ? "Proxy" : "Server", auth,
|
||||
proxy ? (data->state.aptr.proxyuser ?
|
||||
data->state.aptr.proxyuser : "") :
|
||||
(data->state.aptr.user ?
|
||||
data->state.aptr.user : ""));
|
||||
proxy ? (conn->http_proxy.creds ?
|
||||
conn->http_proxy.creds->user : "") :
|
||||
(data->state.creds ?
|
||||
data->state.creds->user : ""));
|
||||
#else
|
||||
(void)proxy;
|
||||
infof(data, "Server auth using %s with user '%s'",
|
||||
auth, data->state.aptr.user ?
|
||||
data->state.aptr.user : "");
|
||||
auth, data->state.creds ?
|
||||
data->state.creds->user : "");
|
||||
#endif
|
||||
authstatus->multipass = !authstatus->done;
|
||||
}
|
||||
|
|
@ -780,14 +784,13 @@ CURLcode Curl_http_output_auth(struct Curl_easy *data,
|
|||
|
||||
if(
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
(!conn->bits.httpproxy || !conn->bits.proxy_user_passwd) &&
|
||||
(!conn->bits.httpproxy || !conn->http_proxy.creds) &&
|
||||
#endif
|
||||
!data->state.aptr.user &&
|
||||
#ifdef USE_SPNEGO
|
||||
!(authhost->want & CURLAUTH_NEGOTIATE) &&
|
||||
!(authproxy->want & CURLAUTH_NEGOTIATE) &&
|
||||
#endif
|
||||
!data->set.str[STRING_BEARER]) {
|
||||
!data->state.creds) {
|
||||
/* no authentication with no user or password */
|
||||
authhost->done = TRUE;
|
||||
authproxy->done = TRUE;
|
||||
|
|
@ -832,13 +835,9 @@ CURLcode Curl_http_output_auth(struct Curl_easy *data,
|
|||
with it */
|
||||
authproxy->done = TRUE;
|
||||
|
||||
/* To prevent the user+password to get sent to other than the original host
|
||||
due to a location-follow */
|
||||
if(Curl_auth_allowed_to_host(data)
|
||||
#ifndef CURL_DISABLE_NETRC
|
||||
|| conn->bits.netrc
|
||||
#endif
|
||||
)
|
||||
/* Either we have credentials for the origin we talk to or
|
||||
performing authentication is allowed here */
|
||||
if(data->state.creds || Curl_auth_allowed_to_host(data))
|
||||
result = output_auth_headers(data, conn, authhost, request,
|
||||
path_and_query, FALSE);
|
||||
else
|
||||
|
|
@ -1227,8 +1226,6 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
|
|||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
bool same_origin;
|
||||
CURLcode result;
|
||||
CURLU *u = curl_url();
|
||||
if(!u)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
|
@ -1242,29 +1239,16 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
|
|||
return Curl_uc_to_curlcode(uc);
|
||||
}
|
||||
|
||||
same_origin = Curl_url_same_origin(u, data->state.uh);
|
||||
curl_url_cleanup(u);
|
||||
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
if(!same_origin)
|
||||
Curl_auth_digest_cleanup(&data->state.digest);
|
||||
{
|
||||
bool same_origin = Curl_url_same_origin(u, data->state.uh);
|
||||
curl_url_cleanup(u);
|
||||
if(!same_origin)
|
||||
Curl_auth_digest_cleanup(&data->state.digest);
|
||||
}
|
||||
#else
|
||||
curl_url_cleanup(u);
|
||||
#endif
|
||||
|
||||
if((!same_origin && !data->set.allow_auth_to_other_hosts) ||
|
||||
!data->set.str[STRING_USERNAME]) {
|
||||
result = Curl_reset_userpwd(data);
|
||||
if(result) {
|
||||
curlx_free(follow_url);
|
||||
return result;
|
||||
}
|
||||
curlx_safefree(data->state.aptr.user);
|
||||
curlx_safefree(data->state.aptr.passwd);
|
||||
}
|
||||
result = Curl_reset_proxypwd(data);
|
||||
if(result) {
|
||||
curlx_free(follow_url);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
DEBUGASSERT(follow_url);
|
||||
|
||||
|
|
@ -2005,9 +1989,6 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data)
|
|||
struct dynamically_allocated_data *aptr = &data->state.aptr;
|
||||
const char *ptr;
|
||||
|
||||
if(!data->state.this_is_a_follow)
|
||||
Curl_peer_link(&data->state.first_origin, conn->origin);
|
||||
|
||||
curlx_safefree(aptr->host);
|
||||
#ifndef CURL_DISABLE_COOKIES
|
||||
curlx_safefree(data->req.cookiehost);
|
||||
|
|
@ -2015,7 +1996,7 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data)
|
|||
|
||||
ptr = Curl_checkheaders(data, STRCONST("Host"));
|
||||
if(ptr && (!data->state.this_is_a_follow ||
|
||||
Curl_peer_equal(data->state.first_origin, conn->origin))) {
|
||||
Curl_peer_equal(data->state.initial_origin, conn->origin))) {
|
||||
#ifndef CURL_DISABLE_COOKIES
|
||||
/* If we have a given custom Host: header, we extract the hostname in
|
||||
order to possibly use it for cookie reasons later on. We only allow the
|
||||
|
|
@ -2138,6 +2119,19 @@ static CURLcode http_target(struct Curl_easy *data,
|
|||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
else if(data->state.creds && (data->state.creds->source != CREDS_URL)) {
|
||||
/* credentials not from the URL need to be set */
|
||||
uc = curl_url_set(h, CURLUPART_USER,
|
||||
data->state.creds->user, CURLU_URLENCODE);
|
||||
if(!uc)
|
||||
uc = curl_url_set(h, CURLUPART_PASSWORD,
|
||||
data->state.creds->passwd, CURLU_URLENCODE);
|
||||
if(uc) {
|
||||
curl_url_cleanup(h);
|
||||
return Curl_uc_to_curlcode(uc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract the URL to use in the request. */
|
||||
uc = curl_url_get(h, CURLUPART_URL, &url, CURLU_NO_DEFAULT_PORT);
|
||||
if(uc) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue