mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
Factor out some auth gethttp code
* src/http.c (gethttp): Move some code in... (check_auth): ... a new function.
This commit is contained in:
parent
8aa63e482e
commit
14bbc18512
270
src/http.c
270
src/http.c
@ -2114,6 +2114,141 @@ check_file_output (struct url *u, struct http_stat *hs,
|
||||
return RETROK;
|
||||
}
|
||||
|
||||
static uerr_t
|
||||
check_auth (struct url *u, char *user, char *passwd, struct response *resp,
|
||||
struct request *req, bool *ntlm_seen_ref, bool *retry,
|
||||
bool *basic_auth_finished_ref, bool *auth_finished_ref)
|
||||
{
|
||||
uerr_t auth_err = RETROK;
|
||||
bool basic_auth_finished = *basic_auth_finished_ref;
|
||||
bool auth_finished = *auth_finished_ref;
|
||||
bool ntlm_seen = *ntlm_seen_ref;
|
||||
*retry = false;
|
||||
if (!auth_finished && (user && passwd))
|
||||
{
|
||||
/* IIS sends multiple copies of WWW-Authenticate, one with
|
||||
the value "negotiate", and other(s) with data. Loop over
|
||||
all the occurrences and pick the one we recognize. */
|
||||
int wapos;
|
||||
char *buf;
|
||||
const char *www_authenticate = NULL;
|
||||
const char *wabeg, *waend;
|
||||
const char *digest = NULL, *basic = NULL, *ntlm = NULL;
|
||||
for (wapos = 0; !ntlm
|
||||
&& (wapos = resp_header_locate (resp, "WWW-Authenticate", wapos,
|
||||
&wabeg, &waend)) != -1;
|
||||
++wapos)
|
||||
{
|
||||
param_token name, value;
|
||||
|
||||
BOUNDED_TO_ALLOCA (wabeg, waend, buf);
|
||||
www_authenticate = buf;
|
||||
|
||||
for (;!ntlm;)
|
||||
{
|
||||
/* extract the auth-scheme */
|
||||
while (c_isspace (*www_authenticate)) www_authenticate++;
|
||||
name.e = name.b = www_authenticate;
|
||||
while (*name.e && !c_isspace (*name.e)) name.e++;
|
||||
|
||||
if (name.b == name.e)
|
||||
break;
|
||||
|
||||
DEBUGP (("Auth scheme found '%.*s'\n", (int) (name.e - name.b), name.b));
|
||||
|
||||
if (known_authentication_scheme_p (name.b, name.e))
|
||||
{
|
||||
if (BEGINS_WITH (name.b, "NTLM"))
|
||||
{
|
||||
ntlm = name.b;
|
||||
break; /* this is the most secure challenge, stop here */
|
||||
}
|
||||
else if (!digest && BEGINS_WITH (name.b, "Digest"))
|
||||
digest = name.b;
|
||||
else if (!basic && BEGINS_WITH (name.b, "Basic"))
|
||||
basic = name.b;
|
||||
}
|
||||
|
||||
/* now advance over the auth-params */
|
||||
www_authenticate = name.e;
|
||||
DEBUGP (("Auth param list '%s'\n", www_authenticate));
|
||||
while (extract_param (&www_authenticate, &name, &value, ',', NULL) && name.b && value.b)
|
||||
{
|
||||
DEBUGP (("Auth param %.*s=%.*s\n",
|
||||
(int) (name.e - name.b), name.b, (int) (value.e - value.b), value.b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!basic && !digest && !ntlm)
|
||||
{
|
||||
/* If the authentication header is missing or
|
||||
unrecognized, there's no sense in retrying. */
|
||||
logputs (LOG_NOTQUIET, _("Unknown authentication scheme.\n"));
|
||||
}
|
||||
else if (!basic_auth_finished
|
||||
|| !basic)
|
||||
{
|
||||
char *pth = url_full_path (u);
|
||||
const char *value;
|
||||
uerr_t *auth_stat;
|
||||
auth_stat = xmalloc (sizeof (uerr_t));
|
||||
*auth_stat = RETROK;
|
||||
|
||||
if (ntlm)
|
||||
www_authenticate = ntlm;
|
||||
else if (digest)
|
||||
www_authenticate = digest;
|
||||
else
|
||||
www_authenticate = basic;
|
||||
|
||||
logprintf (LOG_NOTQUIET, _("Authentication selected: %s\n"), www_authenticate);
|
||||
|
||||
value = create_authorization_line (www_authenticate,
|
||||
user, passwd,
|
||||
request_method (req),
|
||||
pth,
|
||||
&auth_finished,
|
||||
auth_stat);
|
||||
|
||||
auth_err = *auth_stat;
|
||||
if (auth_err == RETROK)
|
||||
{
|
||||
request_set_header (req, "Authorization", value, rel_value);
|
||||
|
||||
if (BEGINS_WITH (www_authenticate, "NTLM"))
|
||||
ntlm_seen = true;
|
||||
else if (!u->user && BEGINS_WITH (www_authenticate, "Basic"))
|
||||
{
|
||||
/* Need to register this host as using basic auth,
|
||||
* so we automatically send creds next time. */
|
||||
register_basic_auth_host (u->host);
|
||||
}
|
||||
|
||||
xfree (pth);
|
||||
xfree (auth_stat);
|
||||
*retry = true;
|
||||
goto cleanup;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Creating the Authorization header went wrong */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We already did Basic auth, and it failed. Gotta
|
||||
* give up. */
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
*ntlm_seen_ref = ntlm_seen;
|
||||
*basic_auth_finished_ref = basic_auth_finished;
|
||||
*auth_finished_ref = auth_finished;
|
||||
return auth_err;
|
||||
}
|
||||
|
||||
/* Retrieve a document through HTTP protocol. It recognizes status
|
||||
code, and correctly handles redirections. It closes the network
|
||||
socket. If it receives an error from the functions below it, it
|
||||
@ -2488,7 +2623,7 @@ read_header:
|
||||
{
|
||||
/* Authorization is required. */
|
||||
uerr_t auth_err = RETROK;
|
||||
|
||||
bool retry;
|
||||
/* Normally we are not interested in the response body.
|
||||
But if we are writing a WARC file we are: we like to keep everyting. */
|
||||
if (warc_enabled)
|
||||
@ -2525,126 +2660,21 @@ read_header:
|
||||
}
|
||||
|
||||
pconn.authorized = false;
|
||||
if (!auth_finished && (user && passwd))
|
||||
{
|
||||
/* IIS sends multiple copies of WWW-Authenticate, one with
|
||||
the value "negotiate", and other(s) with data. Loop over
|
||||
all the occurrences and pick the one we recognize. */
|
||||
int wapos;
|
||||
char *buf;
|
||||
const char *www_authenticate = NULL;
|
||||
const char *wabeg, *waend;
|
||||
const char *digest = NULL, *basic = NULL, *ntlm = NULL;
|
||||
for (wapos = 0; !ntlm
|
||||
&& (wapos = resp_header_locate (resp, "WWW-Authenticate", wapos,
|
||||
&wabeg, &waend)) != -1;
|
||||
++wapos)
|
||||
{
|
||||
param_token name, value;
|
||||
|
||||
BOUNDED_TO_ALLOCA (wabeg, waend, buf);
|
||||
www_authenticate = buf;
|
||||
|
||||
for (;!ntlm;)
|
||||
{
|
||||
/* extract the auth-scheme */
|
||||
while (c_isspace (*www_authenticate)) www_authenticate++;
|
||||
name.e = name.b = www_authenticate;
|
||||
while (*name.e && !c_isspace (*name.e)) name.e++;
|
||||
|
||||
if (name.b == name.e)
|
||||
break;
|
||||
|
||||
DEBUGP (("Auth scheme found '%.*s'\n", (int) (name.e - name.b), name.b));
|
||||
|
||||
if (known_authentication_scheme_p (name.b, name.e))
|
||||
{
|
||||
if (BEGINS_WITH (name.b, "NTLM"))
|
||||
{
|
||||
ntlm = name.b;
|
||||
break; /* this is the most secure challenge, stop here */
|
||||
}
|
||||
else if (!digest && BEGINS_WITH (name.b, "Digest"))
|
||||
digest = name.b;
|
||||
else if (!basic && BEGINS_WITH (name.b, "Basic"))
|
||||
basic = name.b;
|
||||
}
|
||||
|
||||
/* now advance over the auth-params */
|
||||
www_authenticate = name.e;
|
||||
DEBUGP (("Auth param list '%s'\n", www_authenticate));
|
||||
while (extract_param (&www_authenticate, &name, &value, ',', NULL) && name.b && value.b)
|
||||
{
|
||||
DEBUGP (("Auth param %.*s=%.*s\n",
|
||||
(int) (name.e - name.b), name.b, (int) (value.e - value.b), value.b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!basic && !digest && !ntlm)
|
||||
{
|
||||
/* If the authentication header is missing or
|
||||
unrecognized, there's no sense in retrying. */
|
||||
logputs (LOG_NOTQUIET, _("Unknown authentication scheme.\n"));
|
||||
}
|
||||
else if (!basic_auth_finished
|
||||
|| !basic)
|
||||
{
|
||||
char *pth = url_full_path (u);
|
||||
const char *value;
|
||||
uerr_t *auth_stat;
|
||||
auth_stat = xmalloc (sizeof (uerr_t));
|
||||
*auth_stat = RETROK;
|
||||
|
||||
if (ntlm)
|
||||
www_authenticate = ntlm;
|
||||
else if (digest)
|
||||
www_authenticate = digest;
|
||||
else
|
||||
www_authenticate = basic;
|
||||
|
||||
logprintf (LOG_NOTQUIET, _("Authentication selected: %s\n"), www_authenticate);
|
||||
|
||||
value = create_authorization_line (www_authenticate,
|
||||
user, passwd,
|
||||
request_method (req),
|
||||
pth,
|
||||
&auth_finished,
|
||||
auth_stat);
|
||||
|
||||
auth_err = *auth_stat;
|
||||
if (auth_err == RETROK)
|
||||
{
|
||||
request_set_header (req, "Authorization", value, rel_value);
|
||||
|
||||
if (BEGINS_WITH (www_authenticate, "NTLM"))
|
||||
ntlm_seen = true;
|
||||
else if (!u->user && BEGINS_WITH (www_authenticate, "Basic"))
|
||||
{
|
||||
/* Need to register this host as using basic auth,
|
||||
* so we automatically send creds next time. */
|
||||
register_basic_auth_host (u->host);
|
||||
}
|
||||
|
||||
xfree (pth);
|
||||
xfree (message);
|
||||
resp_free (resp);
|
||||
xfree (head);
|
||||
xfree (auth_stat);
|
||||
xfree (hs->message);
|
||||
goto retry_with_auth;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Creating the Authorization header went wrong */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We already did Basic auth, and it failed. Gotta
|
||||
* give up. */
|
||||
}
|
||||
}
|
||||
{
|
||||
auth_err = check_auth (u, user, passwd, resp, req,
|
||||
&ntlm_seen, &retry,
|
||||
&basic_auth_finished,
|
||||
&auth_finished);
|
||||
if (auth_err == RETROK && retry)
|
||||
{
|
||||
xfree (hs->message);
|
||||
resp_free (resp);
|
||||
xfree (message);
|
||||
xfree (head);
|
||||
goto retry_with_auth;
|
||||
}
|
||||
}
|
||||
request_free (req);
|
||||
xfree (message);
|
||||
resp_free (resp);
|
||||
|
Loading…
Reference in New Issue
Block a user