From 47f1d2f8834f8944dcf9e6e83a9b25653776e926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim Rühsen?= Date: Mon, 17 Nov 2014 17:16:54 +0100 Subject: [PATCH] Fix authentication problem with turkish locale --- ChangeLog | 4 ++++ bootstrap.conf | 1 + src/ChangeLog | 5 ++++ src/http.c | 5 ++-- testenv/ChangeLog | 5 ++++ testenv/server/http/http_server.py | 47 ++++++++++++++++++++------------------ 6 files changed, 43 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 767221d..15580c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2014-11-17 Tim Ruehsen + + * bootstrap.conf (gnulib_modules): Add module c-strcase + 2014-11-16 Darshit Shah * po/stamp-po: Remove autogenerated file from checked out sources diff --git a/bootstrap.conf b/bootstrap.conf index 11f5f92..71aa913 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -31,6 +31,7 @@ announce-gen base32 bind c-ctype +c-strcase clock-time close connect diff --git a/src/ChangeLog b/src/ChangeLog index 0fe61fa..87b1feb 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,10 @@ 2014-11-17 Tim Ruehsen + * http.c: use c_strncasecmp() in BEGINS_WITH macro + and in STARTS macro + +2014-11-17 Tim Ruehsen + * main.c: code cleanup for redirect_output_signal() 2014-11-17 Tim Ruehsen diff --git a/src/http.c b/src/http.c index de96e32..da40e98 100644 --- a/src/http.c +++ b/src/http.c @@ -59,6 +59,7 @@ as that of the covered work. */ #include "convert.h" #include "spider.h" #include "warc.h" +#include "c-strcase.h" #ifdef TESTING #include "test.h" @@ -1631,7 +1632,7 @@ read_response_body (struct http_stat *hs, int sock, FILE *fp, wgint contlen, } #define BEGINS_WITH(line, string_constant) \ - (!strncasecmp (line, string_constant, sizeof (string_constant) - 1) \ + (!c_strncasecmp (line, string_constant, sizeof (string_constant) - 1) \ && (c_isspace (line[sizeof (string_constant) - 1]) \ || !line[sizeof (string_constant) - 1])) @@ -3958,7 +3959,7 @@ digest_authentication_encode (const char *au, const char *user, #define STARTS(literal, b, e) \ ((e > b) \ && ((size_t) ((e) - (b))) >= STRSIZE (literal) \ - && 0 == strncasecmp (b, literal, STRSIZE (literal)) \ + && 0 == c_strncasecmp (b, literal, STRSIZE (literal)) \ && ((size_t) ((e) - (b)) == STRSIZE (literal) \ || c_isspace (b[STRSIZE (literal)]))) diff --git a/testenv/ChangeLog b/testenv/ChangeLog index 5ac01ac..f230ac6 100644 --- a/testenv/ChangeLog +++ b/testenv/ChangeLog @@ -1,3 +1,8 @@ +2014-11-17 Tim Ruehsen + + * server/http/http_server.py: allow case-insensitive auth-type, + send BasIc and DIgest to provoke Wget failures with turkish locales + 2014-11-15 Darshit Shah * certs/README: Remove trailing whitespaces diff --git a/testenv/server/http/http_server.py b/testenv/server/http/http_server.py index 1b67bfc..e28759a 100644 --- a/testenv/server/http/http_server.py +++ b/testenv/server/http/http_server.py @@ -205,34 +205,37 @@ class _Handler (BaseHTTPRequestHandler): return string.decode ('utf-8') def send_challenge (self, auth_type): - if auth_type == "Both": - self.send_challenge ("Digest") - self.send_challenge ("Basic") + auth_type = auth_type.lower() + if auth_type == "both": + self.send_challenge ("digest") + self.send_challenge ("basic") return - if auth_type == "Basic": - challenge_str = 'Basic realm="Wget-Test"' - elif auth_type == "Digest" or auth_type == "Both_inline": + if auth_type == "basic": + challenge_str = 'BasIc realm="Wget-Test"' + elif auth_type == "digest" or auth_type == "both_inline": self.nonce = md5 (str (random ()).encode ('utf-8')).hexdigest() self.opaque = md5 (str (random ()).encode ('utf-8')).hexdigest() - challenge_str = 'Digest realm="Test", nonce="%s", opaque="%s"' % ( + # 'DIgest' to provoke a Wget failure with turkish locales + challenge_str = 'DIgest realm="Test", nonce="%s", opaque="%s"' % ( self.nonce, self.opaque) challenge_str += ', qop="auth"' - if auth_type == "Both_inline": - challenge_str = 'Basic realm="Wget-Test", ' + challenge_str + if auth_type == "both_inline": + # 'BasIc' to provoke a Wget failure with turkish locales + challenge_str = 'BasIc realm="Wget-Test", ' + challenge_str self.send_header ("WWW-Authenticate", challenge_str) - def authorize_Basic (self, auth_header, auth_rule): - if auth_header is None or auth_header.split(' ')[0] != 'Basic': + def authorize_basic (self, auth_header, auth_rule): + if auth_header is None or auth_header.split(' ')[0].lower() != 'basic': return False else: self.user = auth_rule.auth_user self.passw = auth_rule.auth_pass - auth_str = "Basic " + self.base64 (self.user + ":" + self.passw) - return True if auth_str == auth_header else False + auth_str = "basic " + self.base64 (self.user + ":" + self.passw) + return True if auth_str.lower() == auth_header.lower() else False def parse_auth_header (self, auth_header): - n = len("Digest ") + n = len("digest ") auth_header = auth_header[n:].strip() items = auth_header.split(", ") keyvals = [i.split("=", 1) for i in items] @@ -264,8 +267,8 @@ class _Handler (BaseHTTPRequestHandler): return True if resp == params['response'] else False - def authorize_Digest (self, auth_header, auth_rule): - if auth_header is None or auth_header.split(' ')[0] != 'Digest': + def authorize_digest (self, auth_header, auth_rule): + if auth_header is None or auth_header.split(' ')[0].lower() != 'digest': return False else: self.user = auth_rule.auth_user @@ -284,10 +287,10 @@ class _Handler (BaseHTTPRequestHandler): pass_auth = False return pass_auth - def authorize_Both (self, auth_header, auth_rule): + def authorize_both (self, auth_header, auth_rule): return False - def authorize_Both_inline (self, auth_header, auth_rule): + def authorize_both_inline (self, auth_header, auth_rule): return False def Authentication (self, auth_rule): @@ -302,16 +305,16 @@ class _Handler (BaseHTTPRequestHandler): def handle_auth (self, auth_rule): is_auth = True auth_header = self.headers.get ("Authorization") - required_auth = auth_rule.auth_type - if required_auth == "Both" or required_auth == "Both_inline": - auth_type = auth_header.split(' ')[0] if auth_header else required_auth + required_auth = auth_rule.auth_type.lower() + if required_auth == "both" or required_auth == "both_inline": + auth_type = auth_header.split(' ')[0].lower() if auth_header else required_auth else: auth_type = required_auth try: assert hasattr (self, "authorize_" + auth_type) is_auth = getattr (self, "authorize_" + auth_type) (auth_header, auth_rule) except AssertionError: - raise ServerError ("Authentication Mechanism " + auth_rule + " not supported") + raise ServerError ("Authentication Mechanism " + auth_type + " not supported") except AttributeError as ae: raise ServerError (ae.__str__()) if is_auth is False: -- 2.1.3