[Checkins] SVN: zope.session/trunk/ Fix Python 2.4 compatibility issue when using third-party hashlib. Also, use CookieClientIdManager's secret as the hmac key and the client id as the hmac message, instead of the other way around, since it is the client id's authenticity we are verifying.
Patrick Strawderman
patrick at zope.com
Mon Nov 23 10:19:22 EST 2009
Log message for revision 105964:
Fix Python 2.4 compatibility issue when using third-party hashlib. Also, use CookieClientIdManager's secret as the hmac key and the client id as the hmac message, instead of the other way around, since it is the client id's authenticity we are verifying.
Changed:
U zope.session/trunk/CHANGES.txt
U zope.session/trunk/src/zope/session/http.py
-=-
Modified: zope.session/trunk/CHANGES.txt
===================================================================
--- zope.session/trunk/CHANGES.txt 2009-11-23 14:55:03 UTC (rev 105963)
+++ zope.session/trunk/CHANGES.txt 2009-11-23 15:19:21 UTC (rev 105964)
@@ -4,13 +4,19 @@
3.9.2 (unreleased)
------------------
+- Fix Python 2.4 hmac compatibility issue by only using hashlib in
+ Python versions 2.5 and above.
+
+- Use the CookieClientIdManager's secret as the hmac key instead of the
+ message when constructing and verifying client ids.
+
- Make it possible to construct CookieClientIdManager passing cookie namespace
and/or secret as constructor's arguments.
- Use zope.schema.fieldproperty.FieldProperty for "namespace" attribute of
CookieClientIdManager, just like for other attributes in its interface.
Also, make ICookieClientIdManager's "namespace" field an ASCIILine, so
- it accepts only non-unicode strings for cookie names.
+ it accepts only non-unicode strings for cookie names.
3.9.1 (2009-04-20)
------------------
@@ -24,7 +30,7 @@
- Drop dependency on ``zope.annotation``. Instead, we make classes implement
`IAttributeAnnotatable` in ZCML configuration, only if ``zope.annotation``
- is available. If your code relies on annotatable `CookieClientIdManager`
+ is available. If your code relies on annotatable `CookieClientIdManager`
and `PersistentSessionDataContainer` and you don't include the zcml classes
configuration of this package, you'll need to use `classImplements` function
from ``zope.interface`` to make those classes implement `IAttributeAnnotatable`
@@ -35,7 +41,7 @@
- Zope 3 application bootstrapping code for session utilities was moved into
zope.app.appsetup package, thus drop dependency on zope.app.appsetup in this
- package.
+ package.
- Drop testing dependencies, as we don't need anything behind zope.testing and
previous dependencies was simply migrated from zope.app.session before.
@@ -93,7 +99,7 @@
- Only set the client-id cookie if it isn't already set and try to
prevent the header from being cached. This is to minimize risk from
- broken caches handing the same client id out to multiple users.
+ broken caches handing the same client id out to multiple users.
3.5.2 (2008-06-12)
------------------
Modified: zope.session/trunk/src/zope/session/http.py
===================================================================
--- zope.session/trunk/src/zope/session/http.py 2009-11-23 14:55:03 UTC (rev 105963)
+++ zope.session/trunk/src/zope/session/http.py 2009-11-23 15:19:21 UTC (rev 105964)
@@ -20,17 +20,15 @@
import random
import re
import string
+import sys
import time
from cStringIO import StringIO
-try:
+
+if sys.version_info[:2] >= (2, 5):
from hashlib import sha1
-except ImportError:
- # Python 2.4
- import sha as sha1
-try:
from email.utils import formatdate
-except ImportError:
- # Python 2.4
+else:
+ import sha as sha1
from email.Utils import formatdate
import zope.location
@@ -141,43 +139,43 @@
def __init__(self, namespace=None, secret=None):
"""Create the cookie-based cleint id manager
-
+
We can pass namespace (cookie name) and/or secret string
for generating client unique ids.
-
+
If we don't pass either of them, they will be generated
automatically, this is very handy when storing id manager
in the persistent database, so they are saved between
application restarts.
-
+
>>> manager1 = CookieClientIdManager()
>>> len(manager1.namespace) > 0
True
>>> len(manager1.secret) > 0
True
-
+
We can specify cookie name by hand.
-
+
>>> manager2 = CookieClientIdManager('service_cookie')
>>> manager2.namespace
'service_cookie'
-
+
If we want to use CookieClientIdManager object as a non-persistent
utility, we need to specify some constant secret, so it won't be
recreated on each application restart.
-
+
>>> manager3 = CookieClientIdManager(secret='some_secret')
>>> manager3.secret
'some_secret'
-
+
Of course, we can specify both cookie name and secret.
-
+
>>> manager4 = CookieClientIdManager('service_cookie', 'some_secret')
>>> manager4.namespace
'service_cookie'
>>> manager4.secret
'some_secret'
-
+
"""
if namespace is None:
namespace = "zope3_cs_%x" % (int(time.time()) - 1000000000)
@@ -228,7 +226,7 @@
An exception to this is if the cookieLifetime is set to a
non-zero integer value, in which case we do set it on every
request, regardless of when it was last set:
-
+
>>> bim.cookieLifetime = 3600 # one hour
>>> id == bim.getClientId(request2)
True
@@ -248,12 +246,12 @@
>>> print request.response.getCookie(bim.namespace)
None
-
+
>>> request = HTTPRequest(StringIO(''), {'REQUEST_METHOD': 'POST'})
>>> id = bim.getClientId(request)
>>> id == bim.getClientId(request)
True
-
+
>>> request.response.getCookie(bim.namespace) is not None
True
@@ -311,7 +309,7 @@
s = digestEncode(digest)
# we store a HMAC of the random value together with it, which makes
# our session ids unforgeable.
- mac = hmac.new(s, self.secret, digestmod=sha1).digest()
+ mac = hmac.new(self.secret, s, digestmod=sha1).digest()
return s + digestEncode(mac)
def getRequestId(self, request):
@@ -361,7 +359,7 @@
>>> bim.setRequestId(request, id_uni)
>>> bim.getRequestId(request) == id_uni
True
-
+
If another server is managing the ClientId cookies (Apache, Nginx)
we're returning their value without checking:
@@ -371,7 +369,7 @@
>>> request3._cookies = {'uid': 'AQAAf0Y4gjgAAAQ3AwMEAg=='}
>>> bim.getRequestId(request3)
'AQAAf0Y4gjgAAAQ3AwMEAg=='
-
+
"""
response_cookie = request.response.getCookie(self.namespace)
if response_cookie:
@@ -382,7 +380,7 @@
if self.thirdparty:
return sid
else:
-
+
# If there is an id set on the response, use that but
# don't trust it. We need to check the response in case
# there has already been a new session created during the
@@ -391,11 +389,11 @@
if sid is None or len(sid) != 54:
return None
s, mac = sid[:27], sid[27:]
-
+
# call encode() on value s a workaround a bug where the hmac
# module only accepts str() types in Python 2.6
if (digestEncode(hmac.new(
- s.encode(), self.secret, digestmod=sha1
+ self.secret, s.encode(), digestmod=sha1
).digest()) != mac):
return None
else:
@@ -460,7 +458,7 @@
If the secure attribute is set to a true value, then the
secure cookie option is included.
-
+
>>> bim.thirdparty = False
>>> bim.cookieLifetime = None
>>> request = HTTPRequest(StringIO(''), {}, None)
More information about the checkins
mailing list