mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Fix bugs in NTML handling.
This commit is contained in:
parent
e09eb765f4
commit
add6c24a19
@ -1,3 +1,13 @@
|
||||
2005-04-22 Hrvoje Niksic <hniksic@xemacs.org>
|
||||
|
||||
* http.c (gethttp): Handle multiple WWW-Authentication headers,
|
||||
only one of which is recognized. Those are sent by IIS with NTLM
|
||||
authorization.
|
||||
(create_authorization_line): Propagate information whether
|
||||
authorization is finished.
|
||||
(gethttp): Only stop authorization when it's really finished, not
|
||||
after fixed two steps.
|
||||
|
||||
2005-04-21 Hrvoje Niksic <hniksic@xemacs.org>
|
||||
|
||||
* gen_sslfunc.c (ssl_init): Fix warning message text; mark the
|
||||
|
@ -147,6 +147,8 @@ int ntlm_input (struct ntlmdata *ntlm, const char *header)
|
||||
int size;
|
||||
char *buffer = (char *) alloca (strlen (header));
|
||||
|
||||
DEBUGP (("Received a type-2 NTLM message.\n"));
|
||||
|
||||
size = base64_decode (header, buffer);
|
||||
if (size < 0)
|
||||
return 0; /* malformed base64 from server */
|
||||
@ -162,8 +164,12 @@ int ntlm_input (struct ntlmdata *ntlm, const char *header)
|
||||
else
|
||||
{
|
||||
if (ntlm->state >= NTLMSTATE_TYPE1)
|
||||
{
|
||||
DEBUGP (("Unexpected empty NTLM message.\n"));
|
||||
return 0; /* this is an error */
|
||||
}
|
||||
|
||||
DEBUGP (("Empty NTLM message, starting transaction.\n"));
|
||||
ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
|
||||
}
|
||||
|
||||
@ -327,6 +333,8 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
|
||||
hostoff = 32;
|
||||
domoff = hostoff + hostlen;
|
||||
|
||||
DEBUGP (("Creating a type-1 NTLM message.\n"));
|
||||
|
||||
/* Create and send a type-1 message:
|
||||
|
||||
Index Description Content
|
||||
@ -412,6 +420,8 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
|
||||
const char *usr;
|
||||
int userlen;
|
||||
|
||||
DEBUGP (("Creating a type-3 NTLM message.\n"));
|
||||
|
||||
usr = strchr(user, '\\');
|
||||
if(!usr)
|
||||
usr = strchr(user, '/');
|
||||
|
94
src/http.c
94
src/http.c
@ -1071,9 +1071,9 @@ free_hstat (struct http_stat *hs)
|
||||
|
||||
static char *create_authorization_line PARAMS ((const char *, const char *,
|
||||
const char *, const char *,
|
||||
const char *));
|
||||
const char *, int *));
|
||||
static char *basic_authentication_encode PARAMS ((const char *, const char *));
|
||||
static int known_authentication_scheme_p PARAMS ((const char *));
|
||||
static int known_authentication_scheme_p PARAMS ((const char *, const char *));
|
||||
|
||||
time_t http_atotm PARAMS ((const char *));
|
||||
|
||||
@ -1109,8 +1109,9 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
|
||||
int sock = -1;
|
||||
int flags;
|
||||
|
||||
/* Whether authorization has been already tried. */
|
||||
int auth_tried_already;
|
||||
/* Set to 1 when the authorization has failed permanently and should
|
||||
not be tried again. */
|
||||
int auth_finished = 0;
|
||||
|
||||
/* Whether our connection to the remote host is through SSL. */
|
||||
int using_ssl = 0;
|
||||
@ -1176,8 +1177,6 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
|
||||
know the local filename so we can save to it. */
|
||||
assert (*hs->local_file != NULL);
|
||||
|
||||
auth_tried_already = 0;
|
||||
|
||||
/* Initialize certain elements of struct http_stat. */
|
||||
hs->len = 0;
|
||||
hs->contlen = -1;
|
||||
@ -1588,7 +1587,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
|
||||
CLOSE_FINISH (sock);
|
||||
else
|
||||
CLOSE_INVALIDATE (sock);
|
||||
if (auth_tried_already || !(user && passwd))
|
||||
if (auth_finished || !(user && passwd))
|
||||
{
|
||||
/* If we have tried it already, then there is not point
|
||||
retrying it. */
|
||||
@ -1596,13 +1595,26 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
|
||||
}
|
||||
else
|
||||
{
|
||||
char *www_authenticate = resp_header_strdup (resp,
|
||||
"WWW-Authenticate");
|
||||
/* If the authentication scheme is unknown or if it's the
|
||||
"Basic" authentication (which we try by default), there's
|
||||
no sense in retrying. */
|
||||
/* IIS sometimes sends two instances of WWW-Authenticate
|
||||
header, one with the keyword "negotiate", and other with
|
||||
useful data. Loop over all occurrences of this header
|
||||
and use the one we recognize. */
|
||||
int wapos;
|
||||
const char *wabeg, *waend;
|
||||
char *www_authenticate = NULL;
|
||||
for (wapos = 0;
|
||||
(wapos = resp_header_locate (resp, "WWW-Authenticate", wapos,
|
||||
&wabeg, &waend)) != -1;
|
||||
++wapos)
|
||||
if (known_authentication_scheme_p (wabeg, waend))
|
||||
{
|
||||
www_authenticate = strdupdelim (wabeg, waend);
|
||||
break;
|
||||
}
|
||||
/* If the authentication header is missing or recognized, or
|
||||
if the authentication scheme is "Basic" (which we send by
|
||||
default), there's no sense in retrying. */
|
||||
if (!www_authenticate
|
||||
|| !known_authentication_scheme_p (www_authenticate)
|
||||
|| BEGINS_WITH (www_authenticate, "Basic"))
|
||||
{
|
||||
xfree_null (www_authenticate);
|
||||
@ -1611,13 +1623,13 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
|
||||
else
|
||||
{
|
||||
char *pth;
|
||||
auth_tried_already = 1;
|
||||
pth = url_full_path (u);
|
||||
request_set_header (req, "Authorization",
|
||||
create_authorization_line (www_authenticate,
|
||||
user, passwd,
|
||||
request_method (req),
|
||||
pth),
|
||||
pth,
|
||||
&auth_finished),
|
||||
rel_value);
|
||||
xfree (pth);
|
||||
xfree (www_authenticate);
|
||||
@ -2833,26 +2845,33 @@ username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"",
|
||||
}
|
||||
#endif /* ENABLE_DIGEST */
|
||||
|
||||
/* Computing the size of a string literal must take into account that
|
||||
value returned by sizeof includes the terminating \0. */
|
||||
#define STRSIZE(literal) (sizeof (literal) - 1)
|
||||
|
||||
#define BEGINS_WITH(line, string_constant) \
|
||||
(!strncasecmp (line, string_constant, sizeof (string_constant) - 1) \
|
||||
&& (ISSPACE (line[sizeof (string_constant) - 1]) \
|
||||
|| !line[sizeof (string_constant) - 1]))
|
||||
/* Whether chars in [b, e) begin with the literal string provided as
|
||||
first argument and are followed by whitespace or terminating \0.
|
||||
The comparison is case-insensitive. */
|
||||
#define STARTS(literal, b, e) \
|
||||
((e) - (b) >= STRSIZE (literal) \
|
||||
&& 0 == strncasecmp (b, literal, STRSIZE (literal)) \
|
||||
&& ((e) - (b) == STRSIZE (literal) \
|
||||
|| ISSPACE (b[STRSIZE (literal)])))
|
||||
|
||||
static int
|
||||
known_authentication_scheme_p (const char *au)
|
||||
known_authentication_scheme_p (const char *hdrbeg, const char *hdrend)
|
||||
{
|
||||
return BEGINS_WITH (au, "Basic")
|
||||
return STARTS ("Basic", hdrbeg, hdrend)
|
||||
#ifdef ENABLE_DIGEST
|
||||
|| BEGINS_WITH (au, "Digest")
|
||||
|| STARTS ("Digest", hdrbeg, hdrend)
|
||||
#endif
|
||||
#ifdef ENABLE_NTLM
|
||||
|| BEGINS_WITH (au, "NTLM")
|
||||
|| STARTS ("NTLM", hdrbeg, hdrend)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
#undef BEGINS_WITH
|
||||
#undef STARTS
|
||||
|
||||
/* Create the HTTP authorization request header. When the
|
||||
`WWW-Authenticate' response header is seen, according to the
|
||||
@ -2862,25 +2881,34 @@ known_authentication_scheme_p (const char *au)
|
||||
static char *
|
||||
create_authorization_line (const char *au, const char *user,
|
||||
const char *passwd, const char *method,
|
||||
const char *path)
|
||||
const char *path, int *finished)
|
||||
{
|
||||
if (0 == strncasecmp (au, "Basic", 5))
|
||||
/* We are called only with known schemes, so we can dispatch on the
|
||||
first letter. */
|
||||
switch (TOUPPER (*au))
|
||||
{
|
||||
case 'B': /* Basic */
|
||||
*finished = 1;
|
||||
return basic_authentication_encode (user, passwd);
|
||||
#ifdef ENABLE_DIGEST
|
||||
if (0 == strncasecmp (au, "Digest", 6))
|
||||
case 'D': /* Digest */
|
||||
*finished = 1;
|
||||
return digest_authentication_encode (au, user, passwd, method, path);
|
||||
#endif
|
||||
#ifdef ENABLE_NTLM
|
||||
if (0 == strncasecmp (au, "NTLM", 4))
|
||||
case 'N': /* NTLM */
|
||||
if (!ntlm_input (&pconn.ntlm, au))
|
||||
{
|
||||
int ok = ntlm_input (&pconn.ntlm, au);
|
||||
if (!ok)
|
||||
*finished = 1;
|
||||
return NULL;
|
||||
/* #### we shouldn't ignore the OK that ntlm_output returns. */
|
||||
return ntlm_output (&pconn.ntlm, user, passwd, &ok);
|
||||
}
|
||||
return ntlm_output (&pconn.ntlm, user, passwd, finished);
|
||||
#endif
|
||||
return NULL;
|
||||
default:
|
||||
/* We shouldn't get here -- this function should be only called
|
||||
with values approved by known_authentication_scheme_p. */
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user