diff options
| author | Michael Merickel <michael@merickel.org> | 2013-03-19 16:17:00 -0700 |
|---|---|---|
| committer | Michael Merickel <michael@merickel.org> | 2013-03-19 16:17:00 -0700 |
| commit | 813eb45a18fb040bf211b5bf1b0164d5dbca678c (patch) | |
| tree | 7be18eb7f977b6c6974b5864f8bb9b39926d9afa | |
| parent | 5491a8e4da58d08279d6023a33d76369296e94f7 (diff) | |
| parent | 4b711020a33bcbcc931132c2333d9c819dbac344 (diff) | |
| download | pyramid-813eb45a18fb040bf211b5bf1b0164d5dbca678c.tar.gz pyramid-813eb45a18fb040bf211b5bf1b0164d5dbca678c.tar.bz2 pyramid-813eb45a18fb040bf211b5bf1b0164d5dbca678c.zip | |
Merge branch 'bugfix/ipv6_compat' of bertjwregeer/pyramid into fix.831
| -rw-r--r-- | CONTRIBUTORS.txt | 2 | ||||
| -rw-r--r-- | pyramid/authentication.py | 18 | ||||
| -rw-r--r-- | pyramid/tests/test_authentication.py | 52 |
3 files changed, 67 insertions, 5 deletions
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 971c172f8..02fb81528 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -192,3 +192,5 @@ Contributors - Robert Jackiewicz, 2012/11/12 - John Anderson, 2012/11/14 + +- Bert JW Regeer, 2013/02/01 diff --git a/pyramid/authentication.py b/pyramid/authentication.py index 4f6ed2c1d..43353f3e2 100644 --- a/pyramid/authentication.py +++ b/pyramid/authentication.py @@ -450,6 +450,10 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy): Default: ``False``. Make the requesting IP address part of the authentication data in the cookie. Optional. + For IPv6 this option is not recommended. It ties the authentication + ticket to that individual's IPv6 address. Depending on the network they + are on, the IPv6 address that a user is using may expire quickly. + ``timeout`` Default: ``None``. Maximum number of seconds which a newly @@ -736,9 +740,17 @@ def calculate_digest(ip, timestamp, secret, userid, tokens, user_data, tokens = bytes_(tokens, 'utf-8') user_data = bytes_(user_data, 'utf-8') hash_obj = hashlib.new(hashalg) - hash_obj.update( - encode_ip_timestamp(ip, timestamp) + secret + userid + b'\0' - + tokens + b'\0' + user_data) + + # Check to see if this is an IPv6 address + if ':' in ip: + ip_timestamp = ip + str(int(timestamp)) + ip_timestamp = bytes_(ip_timestamp) + else: + # encode_ip_timestamp not required, left in for backwards compatibility + ip_timestamp = encode_ip_timestamp(ip, timestamp) + + hash_obj.update(ip_timestamp + secret + userid + b'\0' + + tokens + b'\0' + user_data) digest = hash_obj.hexdigest() hash_obj2 = hashlib.new(hashalg) hash_obj2.update(bytes_(digest) + secret) diff --git a/pyramid/tests/test_authentication.py b/pyramid/tests/test_authentication.py index 123e4f9f5..cfabf9a9d 100644 --- a/pyramid/tests/test_authentication.py +++ b/pyramid/tests/test_authentication.py @@ -561,9 +561,13 @@ class TestAuthTktCookieHelper(unittest.TestCase): helper.BadTicket = auth_tkt.BadTicket return helper - def _makeRequest(self, cookie=None): + def _makeRequest(self, cookie=None, ipv6=False): environ = {'wsgi.version': (1,0)} - environ['REMOTE_ADDR'] = '1.1.1.1' + + if ipv6 is False: + environ['REMOTE_ADDR'] = '1.1.1.1' + else: + environ['REMOTE_ADDR'] = '::1' environ['SERVER_NAME'] = 'localhost' return DummyRequest(environ, cookie=cookie) @@ -612,6 +616,23 @@ class TestAuthTktCookieHelper(unittest.TestCase): self.assertEqual(environ['REMOTE_USER_DATA'],'') self.assertEqual(environ['AUTH_TYPE'],'cookie') + def test_identify_good_cookie_include_ipv6(self): + helper = self._makeOne('secret', include_ip=True) + request = self._makeRequest('ticket', ipv6=True) + result = helper.identify(request) + self.assertEqual(len(result), 4) + self.assertEqual(result['tokens'], ()) + self.assertEqual(result['userid'], 'userid') + self.assertEqual(result['userdata'], '') + self.assertEqual(result['timestamp'], 0) + self.assertEqual(helper.auth_tkt.value, 'ticket') + self.assertEqual(helper.auth_tkt.remote_addr, '::1') + self.assertEqual(helper.auth_tkt.secret, 'secret') + environ = request.environ + self.assertEqual(environ['REMOTE_USER_TOKENS'], ()) + self.assertEqual(environ['REMOTE_USER_DATA'],'') + self.assertEqual(environ['AUTH_TYPE'],'cookie') + def test_identify_good_cookie_dont_include_ip(self): helper = self._makeOne('secret', include_ip=False) request = self._makeRequest('ticket') @@ -1098,6 +1119,20 @@ class TestAuthTicket(unittest.TestCase): self.assertEqual(result, '66f9cc3e423dc57c91df696cf3d1f0d80000000auserid!a,b!') + def test_ipv4(self): + ticket = self._makeOne('secret', 'userid', '198.51.100.1', + time=10, hashalg='sha256') + result = ticket.cookie_value() + self.assertEqual(result, 'b3e7156db4f8abde4439c4a6499a0668f9e7ffd7fa27b'\ + '798400ecdade8d76c530000000auserid!') + + def test_ipv6(self): + ticket = self._makeOne('secret', 'userid', '2001:db8::1', + time=10, hashalg='sha256') + result = ticket.cookie_value() + self.assertEqual(result, 'd025b601a0f12ca6d008aa35ff3a22b7d8f3d1c1456c8'\ + '5becf8760cd7a2fa4910000000auserid!') + class TestBadTicket(unittest.TestCase): def _makeOne(self, msg, expected=None): from pyramid.authentication import BadTicket @@ -1141,6 +1176,19 @@ class Test_parse_ticket(unittest.TestCase): result = self._callFUT('secret', ticket, '0.0.0.0', 'sha512') self.assertEqual(result, (10, 'userid', ['a', 'b'], '')) + def test_ipv4(self): + ticket = 'b3e7156db4f8abde4439c4a6499a0668f9e7ffd7fa27b798400ecdade8d7'\ + '6c530000000auserid!' + result = self._callFUT('secret', ticket, '198.51.100.1', 'sha256') + self.assertEqual(result, (10, 'userid', [''], '')) + + def test_ipv6(self): + ticket = 'd025b601a0f12ca6d008aa35ff3a22b7d8f3d1c1456c85becf8760cd7a2f'\ + 'a4910000000auserid!' + result = self._callFUT('secret', ticket, '2001:db8::1', 'sha256') + self.assertEqual(result, (10, 'userid', [''], '')) + pass + class TestSessionAuthenticationPolicy(unittest.TestCase): def _getTargetClass(self): from pyramid.authentication import SessionAuthenticationPolicy |
