summaryrefslogtreecommitdiff
path: root/paste/auth
diff options
context:
space:
mode:
authorJan Pokorn? <jpokorny@redhat.com>2012-03-05 21:14:08 +0100
committerJan Pokorn? <jpokorny@redhat.com>2012-03-05 21:14:08 +0100
commit663ec52ddd568148e000f1e7d2ea65d2ec284dd5 (patch)
tree75016556deeb4a14d7266d8ace9624b5be004b5d /paste/auth
parent531c568bd89a2e34ca3077314587e421c5867091 (diff)
downloadpaste-663ec52ddd568148e000f1e7d2ea65d2ec284dd5.tar.gz
auth/auth_tkt.py: enable overriding digest algorithms
Currently, mod_auth_tkt supports also SHA256 and SHA 512 [1], not just plain MD5. Quoting: ----v---- The default is MD5, which is faster, but has now been shown to be vulnerable to collision attacks. Such attacks are not directly applicable to mod_auth_tkt, which primarily relies on the security of the shared secret rather than the strength of the hashing scheme. More paranoid users will probably prefer to use one of the SHA digest types, however. The default is likely to change in a future version, so setting the digest type explicitly is encouraged. ----^---- Thus, enable it also in this implementation so one can optionally switch to a stronger secure hash. Backward compatibility should be untouched as ``md5`` is being passed as a default kwarg. The only change affecting external world is a new parameter required at ``calculate_digest`` (specifying the digest to use), but as it has probably no use outside the module, this is a non-issue. Alternatively: another optional kwarg. Update (based Ian's comments): The algorithm can also be specified as a string referring to the algorithm known to hashlib (otherwise AttributeError will be raised). Example session I used to check it works as expected (longish): >>> import sys; sys.path.append('../..') >>> from hashlib import sha256, sha512 >>> execfile('auth_tkt.py') >>> AuthTicket('secret', 'me', '0.0.0.0').cookie_value() '39fecb1395af5285232be390eba0eed34f5518c8me!' >>> AuthTicket('secret', 'me', '0.0.0.0', "md5").cookie_value() 'c3b8eacbbbf76a9c993c7dcb99975d504f5518cfme!m,d,5!' >>> AuthTicket('secret', 'me', '0.0.0.0', digest_algo="md5") \ ... .cookie_value() 'db3b04de3c44b5bd0e2b47019e903c064f5518dbme!' >>> AuthTicket('secret', 'me', '0.0.0.0', digest_algo="sha1") \ ... .cookie_value() 'dddaadc2be960b6e89263ae7fb8c39591554103d4f5518edme!' >>> AuthTicket('secret', 'me', '0.0.0.0', digest_algo=sha256) \ ... .cookie_value() 'bf5c9a32e49920f2ca517ec19a9d55e10a83849e5d532e8997891b8ccdbf0e634f551902me!' >>> AuthTicket('secret', 'me', '0.0.0.0', digest_algo="sha256") \ ... .cookie_value() '9cb12df90fd86b868c98353115df4da3b8f9fa83bebecdf0b7918fea5d06b0744f551908me!' >>> AuthTicket('secret', 'me', '0.0.0.0', digest_algo='foo') \ ... .cookie_value() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "auth_tkt.py", line 107, in __init__ self.digest_algo = getattr(hashlib, digest_algo) AttributeError: 'module' object has no attribute 'foo' >>> >>> parse_ticket('secret', \ ... AuthTicket('secret', 'me', '0.0.0.0').cookie_value(),'0.0.0.0') (1330977060, 'me', [''], '') >>> parse_ticket('secret', \ ... AuthTicket('secret', 'me', '0.0.0.0', digest_algo='md5') \ ... .cookie_value(),'0.0.0.0', digest_algo='md5') (1330977096, 'me', [''], '') >>> parse_ticket('secret', \ ... AuthTicket('secret', 'me', '0.0.0.0', digest_algo=sha256) \ ... .cookie_value(),'0.0.0.0', digest_algo=sha256) (1330977115, 'me', [''], '') >>> parse_ticket('secret', \ ... AuthTicket('secret', 'me', '0.0.0.0', digest_algo=sha512) \ ... .cookie_value(),'0.0.0.0', digest_algo=sha512) (1330977125, 'me', [''], '') >>> parse_ticket('secret', \ ... AuthTicket('secret', 'me', '0.0.0.0', digest_algo=sha512) \ ... .cookie_value(),'0.0.0.0') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "auth_tkt.py", line 179, in parse_ticket expected=(expected, digest)) __main__.BadTicket: Digest signature is not correct [1] http://linux.die.net/man/3/mod_auth_tkt
Diffstat (limited to 'paste/auth')
-rw-r--r--paste/auth/auth_tkt.py30
1 files changed, 22 insertions, 8 deletions
diff --git a/paste/auth/auth_tkt.py b/paste/auth/auth_tkt.py
index a20e498..f3240ee 100644
--- a/paste/auth/auth_tkt.py
+++ b/paste/auth/auth_tkt.py
@@ -39,15 +39,16 @@ non-Python code run under Apache.
import time as time_mod
try:
- from hashlib import md5
+ import hashlib
except ImportError:
- from md5 import md5
+ # mimic hashlib (will work for md5, fail for secure hashes)
+ import md5 as hashlib
import Cookie
from paste import request
from urllib import quote as url_quote
from urllib import unquote as url_unquote
-DEFAULT_DIGEST = md5
+DEFAULT_DIGEST = hashlib.md5
class AuthTicket(object):
@@ -58,7 +59,8 @@ class AuthTicket(object):
can include tokens (a list of strings, representing role names),
'user_data', which is arbitrary data available for your own use in
later scripts. Lastly, you can override the timestamp, cookie name,
- whether to secure the cookie and the digest algorithm.
+ whether to secure the cookie and the digest algorithm (for details
+ look at ``AuthTKTMiddleware``).
Once you provide all the arguments, use .cookie_value() to
generate the appropriate authentication ticket. .cookie()
@@ -100,7 +102,11 @@ class AuthTicket(object):
self.time = time
self.cookie_name = cookie_name
self.secure = secure
- self.digest_algo = digest_algo
+ if isinstance(digest_algo, str):
+ # correct specification of digest from hashlib or fail
+ self.digest_algo = getattr(hashlib, digest_algo)
+ else:
+ self.digest_algo = digest_algo
def digest(self):
return calculate_digest(
@@ -142,6 +148,9 @@ def parse_ticket(secret, ticket, ip, digest_algo=DEFAULT_DIGEST):
If the ticket cannot be parsed, ``BadTicket`` will be raised with
an explanation.
"""
+ if isinstance(digest_algo, str):
+ # correct specification of digest from hashlib or fail
+ digest_algo = getattr(hashlib, digest_algo)
digest_hexa_size = digest_algo().digest_size * 2
ticket = ticket.strip('"')
digest = ticket[:digest_hexa_size]
@@ -174,6 +183,7 @@ def parse_ticket(secret, ticket, ip, digest_algo=DEFAULT_DIGEST):
return (timestamp, userid, tokens, user_data)
+# @@: Digest object constructor compatible with named ones in hashlib only
def calculate_digest(ip, timestamp, secret, userid, tokens, user_data,
digest_algo):
secret = maybe_encode(secret)
@@ -241,8 +251,8 @@ class AuthTKTMiddleware(object):
when they visit this page.
``digest_algo``:
- Digest object constructor compatible with named constructors from
- ``hashlib``.
+ Digest algorithm specified as a name of the algorithm provided by
+ ``hashlib`` or as a compatible digest object constructor.
Defaults to ``md5``, as in mod_auth_tkt. The others currently
compatible with mod_auth_tkt are ``sha256`` and ``sha512``.
@@ -276,7 +286,11 @@ class AuthTKTMiddleware(object):
self.no_domain_cookie = no_domain_cookie
self.current_domain_cookie = current_domain_cookie
self.wildcard_cookie = wildcard_cookie
- self.digest_algo = digest_algo
+ if isinstance(digest_algo, str):
+ # correct specification of digest from hashlib or fail
+ self.digest_algo = getattr(hashlib, digest_algo)
+ else:
+ self.digest_algo = digest_algo
def __call__(self, environ, start_response):
cookies = request.get_cookies(environ)