mirror of
https://github.com/mirror/wget.git
synced 2025-01-23 18:50:11 +08: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>
|
2005-04-21 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
* gen_sslfunc.c (ssl_init): Fix warning message text; mark the
|
* 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;
|
int size;
|
||||||
char *buffer = (char *) alloca (strlen (header));
|
char *buffer = (char *) alloca (strlen (header));
|
||||||
|
|
||||||
|
DEBUGP (("Received a type-2 NTLM message.\n"));
|
||||||
|
|
||||||
size = base64_decode (header, buffer);
|
size = base64_decode (header, buffer);
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
return 0; /* malformed base64 from server */
|
return 0; /* malformed base64 from server */
|
||||||
@ -162,8 +164,12 @@ int ntlm_input (struct ntlmdata *ntlm, const char *header)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ntlm->state >= NTLMSTATE_TYPE1)
|
if (ntlm->state >= NTLMSTATE_TYPE1)
|
||||||
return 0; /* this is an error */
|
{
|
||||||
|
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 */
|
ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,6 +332,8 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
|
|||||||
default: /* for the weird cases we (re)start here */
|
default: /* for the weird cases we (re)start here */
|
||||||
hostoff = 32;
|
hostoff = 32;
|
||||||
domoff = hostoff + hostlen;
|
domoff = hostoff + hostlen;
|
||||||
|
|
||||||
|
DEBUGP (("Creating a type-1 NTLM message.\n"));
|
||||||
|
|
||||||
/* Create and send a type-1 message:
|
/* Create and send a type-1 message:
|
||||||
|
|
||||||
@ -412,6 +420,8 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
|
|||||||
const char *usr;
|
const char *usr;
|
||||||
int userlen;
|
int userlen;
|
||||||
|
|
||||||
|
DEBUGP (("Creating a type-3 NTLM message.\n"));
|
||||||
|
|
||||||
usr = strchr(user, '\\');
|
usr = strchr(user, '\\');
|
||||||
if(!usr)
|
if(!usr)
|
||||||
usr = strchr(user, '/');
|
usr = strchr(user, '/');
|
||||||
|
104
src/http.c
104
src/http.c
@ -1071,9 +1071,9 @@ free_hstat (struct http_stat *hs)
|
|||||||
|
|
||||||
static char *create_authorization_line PARAMS ((const char *, const char *,
|
static char *create_authorization_line PARAMS ((const char *, const char *,
|
||||||
const char *, const char *,
|
const char *, const char *,
|
||||||
const char *));
|
const char *, int *));
|
||||||
static char *basic_authentication_encode PARAMS ((const char *, const char *));
|
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 *));
|
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 sock = -1;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
/* Whether authorization has been already tried. */
|
/* Set to 1 when the authorization has failed permanently and should
|
||||||
int auth_tried_already;
|
not be tried again. */
|
||||||
|
int auth_finished = 0;
|
||||||
|
|
||||||
/* Whether our connection to the remote host is through SSL. */
|
/* Whether our connection to the remote host is through SSL. */
|
||||||
int using_ssl = 0;
|
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. */
|
know the local filename so we can save to it. */
|
||||||
assert (*hs->local_file != NULL);
|
assert (*hs->local_file != NULL);
|
||||||
|
|
||||||
auth_tried_already = 0;
|
|
||||||
|
|
||||||
/* Initialize certain elements of struct http_stat. */
|
/* Initialize certain elements of struct http_stat. */
|
||||||
hs->len = 0;
|
hs->len = 0;
|
||||||
hs->contlen = -1;
|
hs->contlen = -1;
|
||||||
@ -1588,7 +1587,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
|
|||||||
CLOSE_FINISH (sock);
|
CLOSE_FINISH (sock);
|
||||||
else
|
else
|
||||||
CLOSE_INVALIDATE (sock);
|
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
|
/* If we have tried it already, then there is not point
|
||||||
retrying it. */
|
retrying it. */
|
||||||
@ -1596,13 +1595,26 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *www_authenticate = resp_header_strdup (resp,
|
/* IIS sometimes sends two instances of WWW-Authenticate
|
||||||
"WWW-Authenticate");
|
header, one with the keyword "negotiate", and other with
|
||||||
/* If the authentication scheme is unknown or if it's the
|
useful data. Loop over all occurrences of this header
|
||||||
"Basic" authentication (which we try by default), there's
|
and use the one we recognize. */
|
||||||
no sense in retrying. */
|
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
|
if (!www_authenticate
|
||||||
|| !known_authentication_scheme_p (www_authenticate)
|
|
||||||
|| BEGINS_WITH (www_authenticate, "Basic"))
|
|| BEGINS_WITH (www_authenticate, "Basic"))
|
||||||
{
|
{
|
||||||
xfree_null (www_authenticate);
|
xfree_null (www_authenticate);
|
||||||
@ -1611,13 +1623,13 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *pth;
|
char *pth;
|
||||||
auth_tried_already = 1;
|
|
||||||
pth = url_full_path (u);
|
pth = url_full_path (u);
|
||||||
request_set_header (req, "Authorization",
|
request_set_header (req, "Authorization",
|
||||||
create_authorization_line (www_authenticate,
|
create_authorization_line (www_authenticate,
|
||||||
user, passwd,
|
user, passwd,
|
||||||
request_method (req),
|
request_method (req),
|
||||||
pth),
|
pth,
|
||||||
|
&auth_finished),
|
||||||
rel_value);
|
rel_value);
|
||||||
xfree (pth);
|
xfree (pth);
|
||||||
xfree (www_authenticate);
|
xfree (www_authenticate);
|
||||||
@ -2833,26 +2845,33 @@ username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"",
|
|||||||
}
|
}
|
||||||
#endif /* ENABLE_DIGEST */
|
#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) \
|
/* Whether chars in [b, e) begin with the literal string provided as
|
||||||
(!strncasecmp (line, string_constant, sizeof (string_constant) - 1) \
|
first argument and are followed by whitespace or terminating \0.
|
||||||
&& (ISSPACE (line[sizeof (string_constant) - 1]) \
|
The comparison is case-insensitive. */
|
||||||
|| !line[sizeof (string_constant) - 1]))
|
#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
|
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
|
#ifdef ENABLE_DIGEST
|
||||||
|| BEGINS_WITH (au, "Digest")
|
|| STARTS ("Digest", hdrbeg, hdrend)
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_NTLM
|
#ifdef ENABLE_NTLM
|
||||||
|| BEGINS_WITH (au, "NTLM")
|
|| STARTS ("NTLM", hdrbeg, hdrend)
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef BEGINS_WITH
|
#undef STARTS
|
||||||
|
|
||||||
/* Create the HTTP authorization request header. When the
|
/* Create the HTTP authorization request header. When the
|
||||||
`WWW-Authenticate' response header is seen, according to the
|
`WWW-Authenticate' response header is seen, according to the
|
||||||
@ -2862,25 +2881,34 @@ known_authentication_scheme_p (const char *au)
|
|||||||
static char *
|
static char *
|
||||||
create_authorization_line (const char *au, const char *user,
|
create_authorization_line (const char *au, const char *user,
|
||||||
const char *passwd, const char *method,
|
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
|
||||||
return basic_authentication_encode (user, passwd);
|
first letter. */
|
||||||
|
switch (TOUPPER (*au))
|
||||||
|
{
|
||||||
|
case 'B': /* Basic */
|
||||||
|
*finished = 1;
|
||||||
|
return basic_authentication_encode (user, passwd);
|
||||||
#ifdef ENABLE_DIGEST
|
#ifdef ENABLE_DIGEST
|
||||||
if (0 == strncasecmp (au, "Digest", 6))
|
case 'D': /* Digest */
|
||||||
return digest_authentication_encode (au, user, passwd, method, path);
|
*finished = 1;
|
||||||
|
return digest_authentication_encode (au, user, passwd, method, path);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_NTLM
|
#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;
|
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
|
#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
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user