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