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;
}
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,125 +2660,20 @@ 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)
auth_err = check_auth (u, user, passwd, resp, req,
&ntlm_seen, &retry,
&basic_auth_finished,
&auth_finished);
if (auth_err == RETROK && retry)
{
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);
resp_free (resp);
xfree (message);
xfree (head);
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);
xfree (message);