summaryrefslogtreecommitdiff
path: root/paste/auth
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2015-04-22 02:33:32 +0200
committerVictor Stinner <victor.stinner@gmail.com>2015-04-22 02:33:32 +0200
commit916a56715c777e39461627ea564bc0625712c733 (patch)
treea58fb49cd65f9b7ff24029aeb4dfaccd657128dd /paste/auth
parentd705a0524606c7b9b11f935de5a69d173c61ec0d (diff)
parent6c4ef4b3876812e6bbbb3e4748793997067aa85c (diff)
downloadpaste-git-916a56715c777e39461627ea564bc0625712c733.tar.gz
Merged in mfrobben/paste (pull request #21)
Fix bad reference to iterator variable
Diffstat (limited to 'paste/auth')
-rw-r--r--paste/auth/basic.py4
-rw-r--r--paste/auth/cookie.py19
-rw-r--r--paste/auth/digest.py29
-rw-r--r--paste/auth/form.py2
-rw-r--r--paste/auth/grantip.py14
-rw-r--r--paste/auth/open_id.py10
6 files changed, 51 insertions, 27 deletions
diff --git a/paste/auth/basic.py b/paste/auth/basic.py
index 69db128..24d1731 100644
--- a/paste/auth/basic.py
+++ b/paste/auth/basic.py
@@ -108,14 +108,14 @@ def make_basic(app, global_conf, realm, authfunc, **kw):
use = egg:Paste#auth_basic
realm=myrealm
authfunc=somepackage.somemodule:somefunction
-
+
"""
from paste.util.import_string import eval_import
import types
authfunc = eval_import(authfunc)
assert isinstance(authfunc, types.FunctionType), "authfunc must resolve to a function"
return AuthBasicHandler(app, realm, authfunc)
-
+
if "__main__" == __name__:
import doctest
diff --git a/paste/auth/cookie.py b/paste/auth/cookie.py
index c636824..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;'
@@ -368,7 +377,7 @@ def make_auth_cookie(
The maximum length of the cookie that is sent (default 4k,
which is a typical browser maximum)
-
+
"""
if isinstance(scanlist, six.string_types):
scanlist = scanlist.split()
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)
diff --git a/paste/auth/form.py b/paste/auth/form.py
index 4e6aa49..9be82a2 100644
--- a/paste/auth/form.py
+++ b/paste/auth/form.py
@@ -131,7 +131,7 @@ def make_form(app, global_conf, realm, authfunc, **kw):
use = egg:Paste#auth_form
realm=myrealm
authfunc=somepackage.somemodule:somefunction
-
+
"""
from paste.util.import_string import eval_import
import types
diff --git a/paste/auth/grantip.py b/paste/auth/grantip.py
index 4ea6df5..3fe6e1c 100644
--- a/paste/auth/grantip.py
+++ b/paste/auth/grantip.py
@@ -38,7 +38,7 @@ class GrantIPMiddleware(object):
if roles and isinstance(roles, six.string_types):
roles = roles.split(',')
return (username, roles)
-
+
def __call__(self, environ, start_response):
addr = ip4.ip2int(environ['REMOTE_ADDR'], False)
remove_user = False
@@ -62,7 +62,7 @@ class GrantIPMiddleware(object):
def _set_roles(self, environ, roles):
cur_roles = environ.get('REMOTE_USER_TOKENS', '').split(',')
# Get rid of empty roles:
- cur_roles = filter(None, cur_roles)
+ cur_roles = list(filter(None, cur_roles))
remove_roles = []
for role in roles:
if role.startswith('-'):
@@ -74,8 +74,8 @@ class GrantIPMiddleware(object):
if role in cur_roles:
cur_roles.remove(role)
environ['REMOTE_USER_TOKENS'] = ','.join(cur_roles)
-
-
+
+
def make_grantip(app, global_conf, clobber_username=False, **kw):
"""
Grant roles or usernames based on IP addresses.
@@ -93,7 +93,7 @@ def make_grantip(app, global_conf, clobber_username=False, **kw):
192.168.0.7 = joe
# And one IP is should not be logged in:
192.168.0.10 = __remove__:-editor
-
+
"""
from paste.deploy.converters import asbool
clobber_username = asbool(clobber_username)
@@ -110,5 +110,5 @@ def make_grantip(app, global_conf, clobber_username=False, **kw):
role = ''
ip_map[key] = value
return GrantIPMiddleware(app, ip_map, clobber_username)
-
-
+
+
diff --git a/paste/auth/open_id.py b/paste/auth/open_id.py
index 967e699..f79f7f8 100644
--- a/paste/auth/open_id.py
+++ b/paste/auth/open_id.py
@@ -91,20 +91,20 @@ class AuthOpenIDHandler(object):
``app``
Your WSGI app to call
-
+
``data_store_path``
Directory to store crypto data in for use with OpenID servers.
-
+
``auth_prefix``
Location for authentication process/verification
-
+
``login_redirect``
Location to load after successful process of login
-
+
``catch_401``
If true, then any 401 responses will turn into open ID login
requirements.
-
+
``url_to_username``
A function called like ``url_to_username(environ, url)``, which should
return a string username. If not given, the URL will be the username.