Am Samstag, 22. November 2014, 16:24:18 schrieb Darshit Shah: > Another reason why I never got around to implementing this feature is that > it is required by almost no one. The issue at hand is that when a Server > responds with two possible authentication methods, the client is expected > to choose the strongest one it knows. Instead Wget chooses the first one it > knows. This violates the RFC and hence I marked it up as a bug. I'll > probably add all this information into the test file in a while and push > it.
Hi Darshit, I just made up a patch to 1. Parse multiple challenges from WWW-Authenticate 2. Select the strongest auth scheme Please have a look at it. Tim
From a4c9939376cd8327e55111af3b190dd2e91f5746 Mon Sep 17 00:00:00 2001 From: Tim Ruehsen <tim.rueh...@gmx.de> Date: Sat, 22 Nov 2014 22:00:28 +0100 Subject: [PATCH] Select most secure auth challenge --- src/http.c | 67 ++++++++++++++++++++++++++++++++------ testenv/server/http/http_server.py | 2 +- 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/http.c b/src/http.c index 87ceffd..832707d 100644 --- a/src/http.c +++ b/src/http.c @@ -2380,26 +2380,64 @@ read_header: 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; - char *www_authenticate = NULL; - for (wapos = 0; - (wapos = resp_header_locate (resp, "WWW-Authenticate", wapos, + const char *digest = NULL, *basic = NULL, *ntlm = NULL; + for (wapos = 0; !ntlm + && (wapos = resp_header_locate (resp, "WWW-Authenticate", wapos, &wabeg, &waend)) != -1; ++wapos) - if (known_authentication_scheme_p (wabeg, waend)) - { - BOUNDED_TO_ALLOCA (wabeg, waend, www_authenticate); - break; - } + { + 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; // most secure + } + 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 (!www_authenticate) + 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 - || !BEGINS_WITH (www_authenticate, "Basic")) + || !basic) { char *pth = url_full_path (u); const char *value; @@ -2407,6 +2445,15 @@ read_header: 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), diff --git a/testenv/server/http/http_server.py b/testenv/server/http/http_server.py index 52c4913..9128b3e 100644 --- a/testenv/server/http/http_server.py +++ b/testenv/server/http/http_server.py @@ -207,8 +207,8 @@ class _Handler (BaseHTTPRequestHandler): def send_challenge (self, auth_type): auth_type = auth_type.lower() if auth_type == "both": - self.send_challenge ("digest") self.send_challenge ("basic") + self.send_challenge ("digest") return if auth_type == "basic": challenge_str = 'BasIc realm="Wget-Test"' -- 2.1.3
signature.asc
Description: This is a digitally signed message part.