Merge lp:~mbp/bzr/654684-password into lp:bzr

Proposed by Martin Pool
Status: Merged
Approved by: Vincent Ladeuil
Approved revision: no longer in the source branch.
Merged at revision: 5487
Proposed branch: lp:~mbp/bzr/654684-password
Merge into: lp:bzr
Diff against target: 141 lines (+63/-26)
3 files modified
NEWS (+4/-0)
bzrlib/tests/test_http.py (+55/-24)
bzrlib/transport/http/_urllib2_wrappers.py (+4/-2)
To merge this branch: bzr merge lp:~mbp/bzr/654684-password
Reviewer Review Type Date Requested Status
Vincent Ladeuil Approve
Review via email: mp+38185@code.launchpad.net

Commit message

avoid "KeyError: port" in urllib authentication callback

Description of the change

This is a somewhat shallow fix for bug 654684, but it does add a narrow unit test.

It seems that sometimes urllib2 doesn't give us back a 'port' entry in the authentication callback: I would guess this is when there is no port in the url. This just copes with that and adds a test that we do.

Possibly this indicates a missing test at a different level that could provoke urllib2 to give this behaviour. It might be hard to write that test because we can't listen on port 80 in a test to simulate the situation. (Maybe someone can think of a creative way to hit it.)

To post a comment you must log in.
Revision history for this message
Vincent Ladeuil (vila) wrote :

I'm slightly worried that there could other occurrences of the same problem, but since port=None is handled in the rest of the stack, I see no reason to be pedantic either.

Nice unit tests by the way.

review: Approve
Revision history for this message
Martin Pool (mbp) wrote :

sent to pqm by email

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'NEWS'
--- NEWS 2010-10-12 06:18:54 +0000
+++ NEWS 2010-10-12 07:29:40 +0000
@@ -28,6 +28,10 @@
28* Don't force openssh to use protocol=2, since that is now the default.28* Don't force openssh to use protocol=2, since that is now the default.
29 (Neil Martinsen-Burrell, #561061)29 (Neil Martinsen-Burrell, #561061)
3030
31* Fix ``KeyError: 'port'`` when getting the stored password for an http
32 URL.
33 (Martin Pool, #654684)
34
31* Make ``bzr tag --quiet`` really quiet. (Neil Martinsen-Burrell, #239523)35* Make ``bzr tag --quiet`` really quiet. (Neil Martinsen-Burrell, #239523)
3236
33Improvements37Improvements
3438
=== modified file 'bzrlib/tests/test_http.py'
--- bzrlib/tests/test_http.py 2010-10-11 22:40:23 +0000
+++ bzrlib/tests/test_http.py 2010-10-12 07:29:40 +0000
@@ -1604,11 +1604,11 @@
1604 ui.ui_factory = tests.TestUIFactory(stdin=stdin_content,1604 ui.ui_factory = tests.TestUIFactory(stdin=stdin_content,
1605 stderr=tests.StringIOWrapper())1605 stderr=tests.StringIOWrapper())
1606 # Create a minimal config file with the right password1606 # Create a minimal config file with the right password
1607 conf = config.AuthenticationConfig()1607 _setup_authentication_config(
1608 conf._get_config().update(1608 scheme='http',
1609 {'httptest': {'scheme': 'http', 'port': self.server.port,1609 port=self.server.port,
1610 'user': user, 'password': password}})1610 user=user,
1611 conf._save()1611 password=password)
1612 # Issue a request to the server to connect1612 # Issue a request to the server to connect
1613 self.assertEqual('contents of a\n',t.get('a').read())1613 self.assertEqual('contents of a\n',t.get('a').read())
1614 # stdin should have been left untouched1614 # stdin should have been left untouched
@@ -1616,25 +1616,6 @@
1616 # Only one 'Authentication Required' error should occur1616 # Only one 'Authentication Required' error should occur
1617 self.assertEqual(1, self.server.auth_required_errors)1617 self.assertEqual(1, self.server.auth_required_errors)
16181618
1619 def test_user_from_auth_conf(self):
1620 if self._testing_pycurl():
1621 raise tests.TestNotApplicable(
1622 'pycurl does not support authentication.conf')
1623 user = 'joe'
1624 password = 'foo'
1625 self.server.add_user(user, password)
1626 # Create a minimal config file with the right password
1627 conf = config.AuthenticationConfig()
1628 conf._get_config().update(
1629 {'httptest': {'scheme': 'http', 'port': self.server.port,
1630 'user': user, 'password': password}})
1631 conf._save()
1632 t = self.get_user_transport(None, None)
1633 # Issue a request to the server to connect
1634 self.assertEqual('contents of a\n', t.get('a').read())
1635 # Only one 'Authentication Required' error should occur
1636 self.assertEqual(1, self.server.auth_required_errors)
1637
1638 def test_changing_nonce(self):1619 def test_changing_nonce(self):
1639 if self._auth_server not in (http_utils.HTTPDigestAuthServer,1620 if self._auth_server not in (http_utils.HTTPDigestAuthServer,
1640 http_utils.ProxyDigestAuthServer):1621 http_utils.ProxyDigestAuthServer):
@@ -1656,6 +1637,56 @@
1656 # initial 'who are you' and a second 'who are you' with the new nonce)1637 # initial 'who are you' and a second 'who are you' with the new nonce)
1657 self.assertEqual(2, self.server.auth_required_errors)1638 self.assertEqual(2, self.server.auth_required_errors)
16581639
1640 def test_user_from_auth_conf(self):
1641 if self._testing_pycurl():
1642 raise tests.TestNotApplicable(
1643 'pycurl does not support authentication.conf')
1644 user = 'joe'
1645 password = 'foo'
1646 self.server.add_user(user, password)
1647 _setup_authentication_config(
1648 scheme='http',
1649 port=self.server.port,
1650 user=user,
1651 password=password)
1652 t = self.get_user_transport(None, None)
1653 # Issue a request to the server to connect
1654 self.assertEqual('contents of a\n', t.get('a').read())
1655 # Only one 'Authentication Required' error should occur
1656 self.assertEqual(1, self.server.auth_required_errors)
1657
1658
1659def _setup_authentication_config(**kwargs):
1660 conf = config.AuthenticationConfig()
1661 conf._get_config().update({'httptest': kwargs})
1662 conf._save()
1663
1664
1665
1666class TestUrllib2AuthHandler(tests.TestCaseWithTransport):
1667 """Unit tests for glue by which urllib2 asks us for authentication"""
1668
1669 def test_get_user_password_without_port(self):
1670 """We cope if urllib2 doesn't tell us the port.
1671
1672 See https://bugs.launchpad.net/bzr/+bug/654684
1673 """
1674 user = 'joe'
1675 password = 'foo'
1676 _setup_authentication_config(
1677 scheme='http',
1678 host='localhost',
1679 user=user,
1680 password=password)
1681 handler = _urllib2_wrappers.HTTPAuthHandler()
1682 got_pass = handler.get_user_password(dict(
1683 user='joe',
1684 protocol='http',
1685 host='localhost',
1686 path='/',
1687 realm='Realm',
1688 ))
1689 self.assertEquals((user, password), got_pass)
16591690
16601691
1661class TestProxyAuth(TestAuth):1692class TestProxyAuth(TestAuth):
16621693
=== modified file 'bzrlib/transport/http/_urllib2_wrappers.py'
--- bzrlib/transport/http/_urllib2_wrappers.py 2010-10-08 10:50:51 +0000
+++ bzrlib/transport/http/_urllib2_wrappers.py 2010-10-12 07:29:40 +0000
@@ -1202,15 +1202,17 @@
1202 user = auth.get('user', None)1202 user = auth.get('user', None)
1203 password = auth.get('password', None)1203 password = auth.get('password', None)
1204 realm = auth['realm']1204 realm = auth['realm']
1205 port = auth.get('port', None)
12051206
1206 if user is None:1207 if user is None:
1207 user = auth_conf.get_user(auth['protocol'], auth['host'],1208 user = auth_conf.get_user(auth['protocol'], auth['host'],
1208 port=auth['port'], path=auth['path'],1209 port=port, path=auth['path'],
1209 realm=realm, ask=True,1210 realm=realm, ask=True,
1210 prompt=self.build_username_prompt(auth))1211 prompt=self.build_username_prompt(auth))
1211 if user is not None and password is None:1212 if user is not None and password is None:
1212 password = auth_conf.get_password(1213 password = auth_conf.get_password(
1213 auth['protocol'], auth['host'], user, port=auth['port'],1214 auth['protocol'], auth['host'], user,
1215 port=port,
1214 path=auth['path'], realm=realm,1216 path=auth['path'], realm=realm,
1215 prompt=self.build_password_prompt(auth))1217 prompt=self.build_password_prompt(auth))
12161218