Fix possible authentication problem with turkish locale

The test server now treats authentication schemes case-independent.
This commit is contained in:
Tim Rühsen 2014-11-17 17:16:54 +01:00
parent db621341a4
commit 94b8458af1
6 changed files with 43 additions and 24 deletions

View File

@ -1,3 +1,7 @@
2014-11-17 Tim Ruehsen <tim.ruehsen@gmx.de>
* bootstrap.conf (gnulib_modules): Add module c-strcase
2014-11-16 Darshit Shah <darnir@gmail.com>
* po/stamp-po: Remove autogenerated file from checked out sources

View File

@ -31,6 +31,7 @@ announce-gen
base32
bind
c-ctype
c-strcase
clock-time
close
connect

View File

@ -1,3 +1,8 @@
2014-11-17 Tim Ruehsen <tim.ruehsen@gmx.de>
* http.c: use c_strncasecmp() in BEGINS_WITH macro
and in STARTS macro
2014-11-17 Tim Ruehsen <tim.ruehsen@gmx.de>
* main.c: code cleanup for redirect_output_signal()

View File

@ -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)])))

View File

@ -1,3 +1,8 @@
2014-11-17 Tim Ruehsen <tim.ruehsen@gmx.de>
* 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 <darnir@gmail.com>
* certs/README: Remove trailing whitespaces

View File

@ -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: