From 2105a515d749b74eef9a6bb6af008aa6a842e313 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 20 Aug 2018 17:53:45 +0100 Subject: New upstream version 1.1.4 --- macaroonbakery/_utils/__init__.py | 20 +++++++++++++++++++- macaroonbakery/httpbakery/_client.py | 6 +----- macaroonbakery/tests/test_client.py | 35 +++++++++++++++++++++++++++++++++++ macaroonbakery/tests/test_utils.py | 22 ++++++++++++++++++++++ 4 files changed, 77 insertions(+), 6 deletions(-) (limited to 'macaroonbakery') diff --git a/macaroonbakery/_utils/__init__.py b/macaroonbakery/_utils/__init__.py index f2779e0..977cdbe 100644 --- a/macaroonbakery/_utils/__init__.py +++ b/macaroonbakery/_utils/__init__.py @@ -2,6 +2,7 @@ # Licensed under the LGPLv3, see LICENCE file for details. import base64 import binascii +import ipaddress import json import webbrowser from datetime import datetime @@ -134,7 +135,9 @@ def cookie( it must be a naive timestamp in UTC. ''' u = urlparse(url) - domain = u.hostname or u.netloc + domain = u.hostname + if '.' not in domain and not _is_ip_addr(domain): + domain += ".local" port = str(u.port) if u.port is not None else None secure = u.scheme == 'https' if expires is not None: @@ -160,3 +163,18 @@ def cookie( rest=None, rfc2109=False, ) + + +def _is_ip_addr(h): + if six.PY2: + # the python2.7 backport of ipaddr needs a bytestring passed in + try: + h = h.decode('ascii') + except UnicodeDecodeError: + # If there are non-ascii chars it's not an address anyway + return False + try: + ipaddress.ip_address(h) + except ValueError: + return False + return True diff --git a/macaroonbakery/httpbakery/_client.py b/macaroonbakery/httpbakery/_client.py index 4fe0ab1..2510f73 100644 --- a/macaroonbakery/httpbakery/_client.py +++ b/macaroonbakery/httpbakery/_client.py @@ -290,12 +290,8 @@ def _prepare_discharge_hook(req, client): Retry.count) ) client.handle_error(error, req.url) - # Replace the private _cookies from req as it is a copy of - # the original cookie jar passed into the requests method and we need - # to set the cookie for this request. - req._cookies = client.cookies req.headers.pop('Cookie', None) - req.prepare_cookies(req._cookies) + req.prepare_cookies(client.cookies) req.headers[BAKERY_PROTOCOL_HEADER] = \ str(bakery.LATEST_VERSION) with requests.Session() as s: diff --git a/macaroonbakery/tests/test_client.py b/macaroonbakery/tests/test_client.py index bfc7807..4061a8a 100644 --- a/macaroonbakery/tests/test_client.py +++ b/macaroonbakery/tests/test_client.py @@ -55,6 +55,41 @@ class TestClient(TestCase): finally: httpd.shutdown() + def test_cookie_domain_host_not_fqdn(self): + # See + # https://github.com/go-macaroon-bakery/py-macaroon-bakery/issues/53 + + b = new_bakery('loc', None, None) + + def handler(*args): + GetHandler(b, None, None, None, None, AGES, *args) + try: + httpd = HTTPServer(('', 0), handler) + thread = threading.Thread(target=httpd.serve_forever) + thread.start() + srv_macaroon = b.oven.macaroon( + version=bakery.LATEST_VERSION, expiry=AGES, + caveats=None, ops=[TEST_OP]) + self.assertEquals(srv_macaroon.macaroon.location, 'loc') + client = httpbakery.Client() + # Note: by using "localhost" instead of the presumably numeric address held + # in httpd.server_address, we're triggering the no-FQDN logic in the cookie + # code. + resp = requests.get( + url='http://localhost:' + str(httpd.server_address[1]), + cookies=client.cookies, auth=client.auth()) + resp.raise_for_status() + self.assertEquals(resp.text, 'done') + except httpbakery.BakeryException: + pass # interacion required exception is expected + finally: + httpd.shutdown() + + # the cookie has the .local domain appended + [cookie] = client.cookies + self.assertEqual(cookie.name, 'macaroon-test') + self.assertEqual(cookie.domain, 'localhost.local') + def test_single_party_with_header(self): b = new_bakery('loc', None, None) diff --git a/macaroonbakery/tests/test_utils.py b/macaroonbakery/tests/test_utils.py index 65edeb4..4ed3e81 100644 --- a/macaroonbakery/tests/test_utils.py +++ b/macaroonbakery/tests/test_utils.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + # Copyright 2017 Canonical Ltd. # Licensed under the LGPLv3, see LICENCE file for details. @@ -26,6 +28,26 @@ class CookieTest(TestCase): ValueError, cookie, 'http://example.com', 'test', 'value', expires=timestamp) + def test_cookie_with_hostname_not_fqdn(self): + c = cookie('http://myhost', 'test', 'value') + self.assertEqual(c.domain, 'myhost.local') + + def test_cookie_with_hostname_ipv4(self): + c = cookie('http://1.2.3.4', 'test', 'value') + self.assertEqual(c.domain, '1.2.3.4') + + def test_cookie_with_hostname_ipv6(self): + c = cookie('http://[dead::beef]', 'test', 'value') + self.assertEqual(c.domain, 'dead::beef') + + def test_cookie_with_hostname_like_ipv4(self): + c = cookie('http://1.2.3.4.com', 'test', 'value') + self.assertEqual(c.domain, '1.2.3.4.com') + + def test_cookie_with_hostname_not_ascii(self): + c = cookie('http://κουλουράκι', 'test', 'value') + self.assertEqual(c.domain, 'κουλουράκι.local') + class TestB64Decode(TestCase): def test_decode(self): -- cgit v1.2.3