1
0
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:
Giuseppe Scrivano 2015-03-16 01:41:20 +01:00
parent 8aa63e482e
commit 14bbc18512

View File

@ -2114,6 +2114,141 @@ check_file_output (struct url *u, struct http_stat *hs,
return RETROK; 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 /* Retrieve a document through HTTP protocol. It recognizes status
code, and correctly handles redirections. It closes the network code, and correctly handles redirections. It closes the network
socket. If it receives an error from the functions below it, it socket. If it receives an error from the functions below it, it
@ -2488,7 +2623,7 @@ read_header:
{ {
/* Authorization is required. */ /* Authorization is required. */
uerr_t auth_err = RETROK; uerr_t auth_err = RETROK;
bool retry;
/* Normally we are not interested in the response body. /* Normally we are not interested in the response body.
But if we are writing a WARC file we are: we like to keep everyting. */ But if we are writing a WARC file we are: we like to keep everyting. */
if (warc_enabled) if (warc_enabled)
@ -2525,126 +2660,21 @@ read_header:
} }
pconn.authorized = false; 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; auth_err = check_auth (u, user, passwd, resp, req,
&ntlm_seen, &retry,
for (;!ntlm;) &basic_auth_finished,
{ &auth_finished);
/* extract the auth-scheme */ if (auth_err == RETROK && retry)
while (c_isspace (*www_authenticate)) www_authenticate++; {
name.e = name.b = www_authenticate; xfree (hs->message);
while (*name.e && !c_isspace (*name.e)) name.e++; resp_free (resp);
xfree (message);
if (name.b == name.e) xfree (head);
break; goto retry_with_auth;
}
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. */
}
}
request_free (req); request_free (req);
xfree (message); xfree (message);
resp_free (resp); resp_free (resp);