1
0
mirror of https://github.com/moparisthebest/wget synced 2024-07-03 16:38:41 -04:00

Fix erroneous error codes when HTTP Digest Authentication fails.

This commit is contained in:
Darshit Shah 2013-07-22 19:35:53 +05:30 committed by Giuseppe Scrivano
parent c19d76c024
commit 92035dbabd
4 changed files with 91 additions and 37 deletions

View File

@ -1,3 +1,22 @@
2013-07-16 Darshit Shah <darnir@gmail.com>
* wget.h (err_t): Added new errors, ATTRMISSING and UNKNOWNATTR to
handle missing attributes and Unknown attribute values respectively in
HTTP Headers.
* exits.c (get_status_for_err): ATTRMISSING is a Protocol Error while
UNKNOWNATTR is a general error, presumably because of a feature that
is not yet implemented.
* http.c (gethttp): Call create_authorization_line () separately. In
case the auth_err flag has been set with an error, handle it and exit.
* http.c (create_authorization_line): Pass a pointer, auth_err to set
the flag for different kinds of errors encountered.
* http.c (http_loop): Handle the errors raised by the authentication
handlers.
* http.c (digest_authentication_encode): Pass pointer auth_err to set
the error flags.
Set qop to NULL in case the value of the qop / algorithm attribute is
unknown to Wget. Set an appropriate error too.
2013-07-13 Tim Ruehsen <tim.ruehsen@gmx.de> 2013-07-13 Tim Ruehsen <tim.ruehsen@gmx.de>
* http.c (digest_authentication_encode): Fix a crash when the algorithm * http.c (digest_authentication_encode): Fix a crash when the algorithm

View File

@ -68,7 +68,7 @@ get_status_for_err (uerr_t err)
return WGET_EXIT_SSL_AUTH_FAIL; return WGET_EXIT_SSL_AUTH_FAIL;
case FTPLOGINC: case FTPLOGREFUSED: case AUTHFAILED: case FTPLOGINC: case FTPLOGREFUSED: case AUTHFAILED:
return WGET_EXIT_SERVER_AUTH_FAIL; return WGET_EXIT_SERVER_AUTH_FAIL;
case HEOF: case HERR: case HEOF: case HERR: case ATTRMISSING:
return WGET_EXIT_PROTOCOL_ERROR; return WGET_EXIT_PROTOCOL_ERROR;
case WRONGCODE: case FTPPORTERR: case FTPSYSERR: case WRONGCODE: case FTPPORTERR: case FTPSYSERR:
case FTPNSFOD: case FTPUNKNOWNTYPE: case FTPSRVERR: case FTPNSFOD: case FTPUNKNOWNTYPE: case FTPSRVERR:
@ -76,7 +76,7 @@ get_status_for_err (uerr_t err)
case CONTNOTSUPPORTED: case RANGEERR: case RETRBADPATTERN: case CONTNOTSUPPORTED: case RANGEERR: case RETRBADPATTERN:
case PROXERR: case PROXERR:
return WGET_EXIT_SERVER_ERROR; return WGET_EXIT_SERVER_ERROR;
case URLERROR: case QUOTEXC: case SSLINITFAILED: case URLERROR: case QUOTEXC: case SSLINITFAILED: case UNKNOWNATTR:
default: default:
return WGET_EXIT_UNKNOWN; return WGET_EXIT_UNKNOWN;
} }

View File

@ -74,7 +74,7 @@ extern char *version_string;
struct http_stat; struct http_stat;
static char *create_authorization_line (const char *, const char *, static char *create_authorization_line (const char *, const char *,
const char *, const char *, const char *, const char *,
const char *, bool *); const char *, bool *, uerr_t *);
static char *basic_authentication_encode (const char *, const char *); static char *basic_authentication_encode (const char *, const char *);
static bool known_authentication_scheme_p (const char *, const char *); static bool known_authentication_scheme_p (const char *, const char *);
static void ensure_extension (struct http_stat *, const char *, int *); static void ensure_extension (struct http_stat *, const char *, int *);
@ -2350,6 +2350,7 @@ read_header:
} }
pconn.authorized = false; pconn.authorized = false;
uerr_t auth_err = RETROK;
if (!auth_finished && (user && passwd)) if (!auth_finished && (user && passwd))
{ {
/* IIS sends multiple copies of WWW-Authenticate, one with /* IIS sends multiple copies of WWW-Authenticate, one with
@ -2377,28 +2378,44 @@ read_header:
else if (!basic_auth_finished else if (!basic_auth_finished
|| !BEGINS_WITH (www_authenticate, "Basic")) || !BEGINS_WITH (www_authenticate, "Basic"))
{ {
char *pth; char *pth = url_full_path (u);
pth = url_full_path (u); const char *value;
request_set_header (req, "Authorization", uerr_t *auth_stat;
create_authorization_line (www_authenticate, auth_stat = xmalloc (sizeof (uerr_t));
user, passwd, *auth_stat = RETROK;
request_method (req),
pth, value = create_authorization_line (www_authenticate,
&auth_finished), user, passwd,
rel_value); request_method (req),
if (BEGINS_WITH (www_authenticate, "NTLM")) pth,
ntlm_seen = true; &auth_finished,
else if (!u->user && BEGINS_WITH (www_authenticate, "Basic")) auth_stat);
auth_err = *auth_stat;
if (auth_err == RETROK)
{ {
/* Need to register this host as using basic auth, request_set_header (req, "Authorization", value, rel_value);
* so we automatically send creds next time. */
register_basic_auth_host (u->host); 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_null (message);
resp_free (resp);
xfree (head);
xfree (auth_stat);
goto retry_with_auth;
}
else
{
/* Creating the Authorization header went wrong */
} }
xfree (pth);
xfree_null (message);
resp_free (resp);
xfree (head);
goto retry_with_auth;
} }
else else
{ {
@ -2406,12 +2423,14 @@ read_header:
* give up. */ * give up. */
} }
} }
logputs (LOG_NOTQUIET, _("Authorization failed.\n"));
request_free (req); request_free (req);
xfree_null (message); xfree_null (message);
resp_free (resp); resp_free (resp);
xfree (head); xfree (head);
return AUTHFAILED; if (auth_err == RETROK)
return AUTHFAILED;
else
return auth_err;
} }
else /* statcode != HTTP_STATUS_UNAUTHORIZED */ else /* statcode != HTTP_STATUS_UNAUTHORIZED */
{ {
@ -3133,12 +3152,23 @@ Spider mode enabled. Check if remote file exists.\n"));
logputs (LOG_VERBOSE, "\n"); logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET, _("Cannot write to %s (%s).\n"), logprintf (LOG_NOTQUIET, _("Cannot write to %s (%s).\n"),
quote (hstat.local_file), strerror (errno)); quote (hstat.local_file), strerror (errno));
case HOSTERR: case CONIMPOSSIBLE: case PROXERR: case AUTHFAILED: case HOSTERR: case CONIMPOSSIBLE: case PROXERR: case SSLINITFAILED:
case SSLINITFAILED: case CONTNOTSUPPORTED: case VERIFCERTERR: case CONTNOTSUPPORTED: case VERIFCERTERR: case FILEBADFILE:
case FILEBADFILE: case UNKNOWNATTR:
/* Fatal errors just return from the function. */ /* Fatal errors just return from the function. */
ret = err; ret = err;
goto exit; goto exit;
case ATTRMISSING:
/* A missing attribute in a Header is a fatal Protocol error. */
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET, _("Required attribute missing from Header received.\n"));
ret = err;
goto exit;
case AUTHFAILED:
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET, _("Username/Password Authentication Failed.\n"));
ret = err;
goto exit;
case WARC_ERR: case WARC_ERR:
/* A fatal WARC error. */ /* A fatal WARC error. */
logputs (LOG_VERBOSE, "\n"); logputs (LOG_VERBOSE, "\n");
@ -3677,7 +3707,7 @@ dump_hash (char *buf, const unsigned char *hash)
static char * static char *
digest_authentication_encode (const char *au, const char *user, digest_authentication_encode (const char *au, const char *user,
const char *passwd, const char *method, const char *passwd, const char *method,
const char *path) const char *path, uerr_t *auth_err)
{ {
static char *realm, *opaque, *nonce, *qop, *algorithm; static char *realm, *opaque, *nonce, *qop, *algorithm;
static struct { static struct {
@ -3717,22 +3747,27 @@ digest_authentication_encode (const char *au, const char *user,
if (qop != NULL && strcmp(qop,"auth")) if (qop != NULL && strcmp(qop,"auth"))
{ {
logprintf (LOG_NOTQUIET, _("Unsupported quality of protection '%s'.\n"), qop); logprintf (LOG_NOTQUIET, _("Unsupported quality of protection '%s'.\n"), qop);
user = NULL; /* force freeing mem and return */ xfree_null (qop); /* force freeing mem and return */
qop = NULL;
} }
else if (algorithm != NULL && strcmp (algorithm,"MD5") && strcmp (algorithm,"MD5-sess"))
if (algorithm != NULL && strcmp (algorithm,"MD5") && strcmp (algorithm,"MD5-sess"))
{ {
logprintf (LOG_NOTQUIET, _("Unsupported algorithm '%s'.\n"), algorithm); logprintf (LOG_NOTQUIET, _("Unsupported algorithm '%s'.\n"), algorithm);
user = NULL; /* force freeing mem and return */ xfree_null (qop); /* force freeing mem and return */
qop = NULL;
} }
if (!realm || !nonce || !user || !passwd || !path || !method) if (!realm || !nonce || !user || !passwd || !path || !method || !qop)
{ {
xfree_null (realm); xfree_null (realm);
xfree_null (opaque); xfree_null (opaque);
xfree_null (nonce); xfree_null (nonce);
xfree_null (qop); xfree_null (qop);
xfree_null (algorithm); xfree_null (algorithm);
if (!qop)
*auth_err = UNKNOWNATTR;
else
*auth_err = ATTRMISSING;
return NULL; return NULL;
} }
@ -3902,7 +3937,7 @@ known_authentication_scheme_p (const char *hdrbeg, const char *hdrend)
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, bool *finished) const char *path, bool *finished, uerr_t *auth_err)
{ {
/* We are called only with known schemes, so we can dispatch on the /* We are called only with known schemes, so we can dispatch on the
first letter. */ first letter. */
@ -3914,7 +3949,7 @@ create_authorization_line (const char *au, const char *user,
#ifdef ENABLE_DIGEST #ifdef ENABLE_DIGEST
case 'D': /* Digest */ case 'D': /* Digest */
*finished = true; *finished = true;
return digest_authentication_encode (au, user, passwd, method, path); return digest_authentication_encode (au, user, passwd, method, path, auth_err);
#endif #endif
#ifdef ENABLE_NTLM #ifdef ENABLE_NTLM
case 'N': /* NTLM */ case 'N': /* NTLM */

View File

@ -357,7 +357,7 @@ typedef enum
PROXERR, PROXERR,
/* 50 */ /* 50 */
AUTHFAILED, QUOTEXC, WRITEFAILED, SSLINITFAILED, VERIFCERTERR, AUTHFAILED, QUOTEXC, WRITEFAILED, SSLINITFAILED, VERIFCERTERR,
UNLINKERR, NEWLOCATION_KEEP_POST, CLOSEFAILED, UNLINKERR, NEWLOCATION_KEEP_POST, CLOSEFAILED, ATTRMISSING, UNKNOWNATTR,
WARC_ERR, WARC_TMP_FOPENERR, WARC_TMP_FWRITEERR WARC_ERR, WARC_TMP_FOPENERR, WARC_TMP_FWRITEERR
} uerr_t; } uerr_t;