diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2015-04-21 15:57:41 +0200 |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2015-04-21 15:57:41 +0200 |
commit | b4187e5d61acb98ffb86767c82a60280db7833f3 (patch) | |
tree | 6ee1e8ba1d6834f343d960aaa3b3868b594d1d29 /paste/auth | |
parent | f3fd444b0bc18e95d08c88567d9d8ed17346027d (diff) | |
download | paste-b4187e5d61acb98ffb86767c82a60280db7833f3.tar.gz |
Port paste.auth to Python 3
* md5() and hmac expects bytes: on Python 3, encode text to utf-8
* Don't compare None with int
* HTTP body must be bytes
Diffstat (limited to 'paste/auth')
-rw-r--r-- | paste/auth/cookie.py | 17 | ||||
-rw-r--r-- | paste/auth/digest.py | 29 |
2 files changed, 35 insertions, 11 deletions
diff --git a/paste/auth/cookie.py b/paste/auth/cookie.py index 14b1fd8..8f11d1b 100644 --- a/paste/auth/cookie.py +++ b/paste/auth/cookie.py @@ -74,7 +74,10 @@ class CookieTooLarge(RuntimeError): _all_chars = ''.join([chr(x) for x in range(0, 255)]) def new_secret(): """ returns a 64 byte secret """ - return ''.join(random.sample(_all_chars, 64)) + secret = ''.join(random.sample(_all_chars, 64)) + if six.PY3: + secret = secret.encode('utf8') + return secret class AuthCookieSigner(object): """ @@ -137,12 +140,16 @@ class AuthCookieSigner(object): need to be escaped and quoted). The expiration of this cookie is handled server-side in the auth() function. """ + timestamp = make_time(time.time() + 60*self.timeout) + if six.PY3: + content = content.encode('utf8') + timestamp = timestamp.encode('utf8') cookie = base64.encodestring( hmac.new(self.secret, content, sha1).digest() + - make_time(time.time() + 60*self.timeout) + + timestamp + content) - cookie = cookie.replace("/", "_").replace("=", "~") - cookie = cookie.replace('\n', '').replace('\r', '') + cookie = cookie.replace(b"/", b"_").replace(b"=", b"~") + cookie = cookie.replace(b'\n', b'').replace(b'\r', b'') if len(cookie) > self.maxlen: raise CookieTooLarge(content, cookie) return cookie @@ -298,6 +305,8 @@ class AuthCookieHandler(object): if content: content = ";".join(content) content = self.signer.sign(content) + if six.PY3: + content = content.decode('utf8') cookie = '%s=%s; Path=/;' % (self.cookie_name, content) if 'https' == environ['wsgi.url_scheme']: cookie += ' secure;' diff --git a/paste/auth/digest.py b/paste/auth/digest.py index 798f447..85e0362 100644 --- a/paste/auth/digest.py +++ b/paste/auth/digest.py @@ -37,6 +37,7 @@ except ImportError: from md5 import md5 import time, random from six.moves.urllib.parse import quote as url_quote +import six def _split_auth_string(auth_string): """ split a digest auth string into individual key=value strings """ @@ -68,7 +69,10 @@ def _auth_to_kv_pairs(auth_string): def digest_password(realm, username, password): """ construct the appropriate hashcode needed for HTTP digest """ - return md5("%s:%s:%s" % (username, realm, password)).hexdigest() + content = "%s:%s:%s" % (username, realm, password) + if six.PY3: + content = content.encode('utf8') + return md5(content).hexdigest() class AuthDigestAuthenticator(object): """ implementation of RFC 2617 - HTTP Digest Authentication """ @@ -79,10 +83,16 @@ class AuthDigestAuthenticator(object): def build_authentication(self, stale = ''): """ builds the authentication error """ - nonce = md5( - "%s:%s" % (time.time(), random.random())).hexdigest() - opaque = md5( - "%s:%s" % (time.time(), random.random())).hexdigest() + content = "%s:%s" % (time.time(), random.random()) + if six.PY3: + content = content.encode('utf-8') + nonce = md5(content).hexdigest() + + content = "%s:%s" % (time.time(), random.random()) + if six.PY3: + content = content.encode('utf-8') + opaque = md5(content).hexdigest() + self.nonce[nonce] = None parts = {'realm': self.realm, 'qop': 'auth', 'nonce': nonce, 'opaque': opaque } @@ -97,17 +107,22 @@ class AuthDigestAuthenticator(object): """ computes the authentication, raises error if unsuccessful """ if not ha1: return self.build_authentication() - ha2 = md5('%s:%s' % (method, path)).hexdigest() + content = '%s:%s' % (method, path) + if six.PY3: + content = content.encode('utf8') + ha2 = md5(content).hexdigest() if qop: chk = "%s:%s:%s:%s:%s:%s" % (ha1, nonce, nc, cnonce, qop, ha2) else: chk = "%s:%s:%s" % (ha1, nonce, ha2) + if six.PY3: + chk = chk.encode('utf8') if response != md5(chk).hexdigest(): if nonce in self.nonce: del self.nonce[nonce] return self.build_authentication() pnc = self.nonce.get(nonce,'00000000') - if nc <= pnc: + if pnc is not None and nc <= pnc: if nonce in self.nonce: del self.nonce[nonce] return self.build_authentication(stale = True) |