From: Darshit Shah Date: Mon, 22 Jul 2013 14:05:53 +0000 (+0530) Subject: Fix erroneous error codes when HTTP Digest Authentication fails. X-Git-Tag: v1.15~32 X-Git-Url: http://sjero.net/git/?p=wget;a=commitdiff_plain;h=92035dbabd8bb7fc3d10535c97adad2088c9129b Fix erroneous error codes when HTTP Digest Authentication fails. --- diff --git a/src/ChangeLog b/src/ChangeLog index a3721caf..fe7ce5f4 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,22 @@ +2013-07-16 Darshit Shah + + * 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 * http.c (digest_authentication_encode): Fix a crash when the algorithm diff --git a/src/exits.c b/src/exits.c index cea38d5c..b8230f8f 100644 --- a/src/exits.c +++ b/src/exits.c @@ -68,7 +68,7 @@ get_status_for_err (uerr_t err) return WGET_EXIT_SSL_AUTH_FAIL; case FTPLOGINC: case FTPLOGREFUSED: case AUTHFAILED: return WGET_EXIT_SERVER_AUTH_FAIL; - case HEOF: case HERR: + case HEOF: case HERR: case ATTRMISSING: return WGET_EXIT_PROTOCOL_ERROR; case WRONGCODE: case FTPPORTERR: case FTPSYSERR: case FTPNSFOD: case FTPUNKNOWNTYPE: case FTPSRVERR: @@ -76,7 +76,7 @@ get_status_for_err (uerr_t err) case CONTNOTSUPPORTED: case RANGEERR: case RETRBADPATTERN: case PROXERR: return WGET_EXIT_SERVER_ERROR; - case URLERROR: case QUOTEXC: case SSLINITFAILED: + case URLERROR: case QUOTEXC: case SSLINITFAILED: case UNKNOWNATTR: default: return WGET_EXIT_UNKNOWN; } diff --git a/src/http.c b/src/http.c index b2a03c87..6b042a7e 100644 --- a/src/http.c +++ b/src/http.c @@ -74,7 +74,7 @@ extern char *version_string; struct http_stat; static char *create_authorization_line (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 bool known_authentication_scheme_p (const char *, const char *); static void ensure_extension (struct http_stat *, const char *, int *); @@ -2350,6 +2350,7 @@ read_header: } pconn.authorized = false; + uerr_t auth_err = RETROK; if (!auth_finished && (user && passwd)) { /* IIS sends multiple copies of WWW-Authenticate, one with @@ -2377,28 +2378,44 @@ read_header: else if (!basic_auth_finished || !BEGINS_WITH (www_authenticate, "Basic")) { - char *pth; - pth = url_full_path (u); - request_set_header (req, "Authorization", - create_authorization_line (www_authenticate, - user, passwd, - request_method (req), - pth, - &auth_finished), - rel_value); - if (BEGINS_WITH (www_authenticate, "NTLM")) - ntlm_seen = true; - else if (!u->user && BEGINS_WITH (www_authenticate, "Basic")) + char *pth = url_full_path (u); + const char *value; + uerr_t *auth_stat; + auth_stat = xmalloc (sizeof (uerr_t)); + *auth_stat = RETROK; + + value = create_authorization_line (www_authenticate, + user, passwd, + request_method (req), + pth, + &auth_finished, + auth_stat); + + auth_err = *auth_stat; + if (auth_err == RETROK) { - /* Need to register this host as using basic auth, - * so we automatically send creds next time. */ - register_basic_auth_host (u->host); + 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_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 { @@ -2406,12 +2423,14 @@ read_header: * give up. */ } } - logputs (LOG_NOTQUIET, _("Authorization failed.\n")); request_free (req); xfree_null (message); resp_free (resp); xfree (head); - return AUTHFAILED; + if (auth_err == RETROK) + return AUTHFAILED; + else + return auth_err; } else /* statcode != HTTP_STATUS_UNAUTHORIZED */ { @@ -3133,12 +3152,23 @@ Spider mode enabled. Check if remote file exists.\n")); logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, _("Cannot write to %s (%s).\n"), quote (hstat.local_file), strerror (errno)); - case HOSTERR: case CONIMPOSSIBLE: case PROXERR: case AUTHFAILED: - case SSLINITFAILED: case CONTNOTSUPPORTED: case VERIFCERTERR: - case FILEBADFILE: + case HOSTERR: case CONIMPOSSIBLE: case PROXERR: case SSLINITFAILED: + case CONTNOTSUPPORTED: case VERIFCERTERR: case FILEBADFILE: + case UNKNOWNATTR: /* Fatal errors just return from the function. */ ret = err; 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: /* A fatal WARC error. */ logputs (LOG_VERBOSE, "\n"); @@ -3677,7 +3707,7 @@ dump_hash (char *buf, const unsigned char *hash) static char * digest_authentication_encode (const char *au, const char *user, const char *passwd, const char *method, - const char *path) + const char *path, uerr_t *auth_err) { static char *realm, *opaque, *nonce, *qop, *algorithm; static struct { @@ -3717,22 +3747,27 @@ digest_authentication_encode (const char *au, const char *user, if (qop != NULL && strcmp(qop,"auth")) { 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; } - - if (algorithm != NULL && strcmp (algorithm,"MD5") && strcmp (algorithm,"MD5-sess")) + else if (algorithm != NULL && strcmp (algorithm,"MD5") && strcmp (algorithm,"MD5-sess")) { 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 (opaque); xfree_null (nonce); xfree_null (qop); xfree_null (algorithm); + if (!qop) + *auth_err = UNKNOWNATTR; + else + *auth_err = ATTRMISSING; return NULL; } @@ -3902,7 +3937,7 @@ known_authentication_scheme_p (const char *hdrbeg, const char *hdrend) static char * create_authorization_line (const char *au, const char *user, 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 first letter. */ @@ -3914,7 +3949,7 @@ create_authorization_line (const char *au, const char *user, #ifdef ENABLE_DIGEST case 'D': /* Digest */ *finished = true; - return digest_authentication_encode (au, user, passwd, method, path); + return digest_authentication_encode (au, user, passwd, method, path, auth_err); #endif #ifdef ENABLE_NTLM case 'N': /* NTLM */ diff --git a/src/wget.h b/src/wget.h index 14a1965e..3c739472 100644 --- a/src/wget.h +++ b/src/wget.h @@ -357,7 +357,7 @@ typedef enum PROXERR, /* 50 */ 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 } uerr_t;