summaryrefslogtreecommitdiff
path: root/macaroonbakery
diff options
context:
space:
mode:
Diffstat (limited to 'macaroonbakery')
-rw-r--r--macaroonbakery/_utils/__init__.py20
-rw-r--r--macaroonbakery/httpbakery/_client.py6
-rw-r--r--macaroonbakery/tests/test_client.py35
-rw-r--r--macaroonbakery/tests/test_utils.py22
4 files changed, 77 insertions, 6 deletions
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):