Rev 3137: (vila) Fix bug #177643 by handling credentials embedded in urls works in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Thu Dec 20 20:33:57 GMT 2007


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 3137
revision-id:pqm at pqm.ubuntu.com-20071220203346-toifx0pb5987jcqo
parent: pqm at pqm.ubuntu.com-20071220173454-9nqwgm3k66f4bmj8
parent: v.ladeuil+lp at free.fr-20071220193845-bwttzbjqjppw8602
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2007-12-20 20:33:46 +0000
message:
  (vila) Fix bug #177643 by handling credentials embedded in urls works
  	again for pycurl
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/tests/test_http.py      testhttp.py-20051018020158-b2eef6e867c514d9
  bzrlib/transport/http/__init__.py http_transport.py-20050711212304-506c5fd1059ace96
  bzrlib/transport/http/_pycurl.py pycurlhttp.py-20060110060940-4e2a705911af77a6
  bzrlib/transport/http/_urllib.py _urlgrabber.py-20060113083826-0bbf7d992fbf090c
  bzrlib/transport/http/_urllib2_wrappers.py _urllib2_wrappers.py-20060913231729-ha9ugi48ktx481ao-1
    ------------------------------------------------------------
    revno: 3134.1.1
    revision-id:v.ladeuil+lp at free.fr-20071220193845-bwttzbjqjppw8602
    parent: pqm at pqm.ubuntu.com-20071220142004-tw2cffgn9fxq5ra0
    parent: v.ladeuil+lp at free.fr-20071220142933-xf5h8kd1885f8nz6
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: trunk
    timestamp: Thu 2007-12-20 20:38:45 +0100
    message:
      Fix bug #177643 by handling credentials embedded in urls works again for pycurl
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/tests/test_http.py      testhttp.py-20051018020158-b2eef6e867c514d9
      bzrlib/transport/http/__init__.py http_transport.py-20050711212304-506c5fd1059ace96
      bzrlib/transport/http/_pycurl.py pycurlhttp.py-20060110060940-4e2a705911af77a6
      bzrlib/transport/http/_urllib.py _urlgrabber.py-20060113083826-0bbf7d992fbf090c
      bzrlib/transport/http/_urllib2_wrappers.py _urllib2_wrappers.py-20060913231729-ha9ugi48ktx481ao-1
    ------------------------------------------------------------
    revno: 3133.1.3
    revision-id:v.ladeuil+lp at free.fr-20071220142933-xf5h8kd1885f8nz6
    parent: v.ladeuil+lp at free.fr-20071220141421-1m9i2monq5d9zgno
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: 177643
    timestamp: Thu 2007-12-20 15:29:33 +0100
    message:
      Fix typo (hi John ;).
    modified:
      bzrlib/transport/http/_urllib2_wrappers.py _urllib2_wrappers.py-20060913231729-ha9ugi48ktx481ao-1
    ------------------------------------------------------------
    revno: 3133.1.2
    revision-id:v.ladeuil+lp at free.fr-20071220141421-1m9i2monq5d9zgno
    parent: v.ladeuil+lp at free.fr-20071220120730-o0nbkwl4a4o70ecs
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: 177643
    timestamp: Thu 2007-12-20 15:14:21 +0100
    message:
      Fix #177643 by making pycurl handle url-embedded credentials again.
      
      * bzrlib/tests/test_http.py:
      Define proper tests for pycurl instead of replacing the urllib
      ones (a correct refactoring is already under work elsewhere). Add
      KnownFailures to document limitations in the pycurl
      implementation (cant prompt for password, no support for
      authentication.conf, cant handle a nonce change for digest auth).
      (TestAuth.test_no_prompt_for_password_when_using_auth_config): Fix
      typo.
      
      * bzrlib/transport/http/__init__.py:
      (HttpTransportBase._remote_path): Don't mention user and passwords
      in urls since bothe implementations handle credentials separately.
      (HttpTransportBase._create_auth): Share default credentials
      creation between both implementation.
      
      * bzrlib/transport/http/_pycurl.py:
      (PyCurlTransport._get_curl): Save user provided credentials.
      (PyCurlTransport._set_curl_options): Set USERPWD explicitely from
      credentials if any have been provided in the url.
      
      * bzrlib/transport/http/_urllib.py:
      (HttpTransport_urllib._remote_path): Deleted, pushed to base class.
      (HttpTransport_urllib._perform): Simplified.
      
      * bzrlib/transport/http/_urllib2_wrappers.py:
      (AbstractAuthHandler._build_password_prompt): Fix typo.
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/tests/test_http.py      testhttp.py-20051018020158-b2eef6e867c514d9
      bzrlib/transport/http/__init__.py http_transport.py-20050711212304-506c5fd1059ace96
      bzrlib/transport/http/_pycurl.py pycurlhttp.py-20060110060940-4e2a705911af77a6
      bzrlib/transport/http/_urllib.py _urlgrabber.py-20060113083826-0bbf7d992fbf090c
      bzrlib/transport/http/_urllib2_wrappers.py _urllib2_wrappers.py-20060913231729-ha9ugi48ktx481ao-1
    ------------------------------------------------------------
    revno: 3133.1.1
    revision-id:v.ladeuil+lp at free.fr-20071220120730-o0nbkwl4a4o70ecs
    parent: pqm at pqm.ubuntu.com-20071220042019-wsij5vgvhgw4qhdt
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: 177643
    timestamp: Thu 2007-12-20 13:07:30 +0100
    message:
      Reproduce bug #177643.
      
      * bzrlib/tests/test_http.py: 
      Switch the tests against pycurl instead of urllib.
    modified:
      bzrlib/tests/test_http.py      testhttp.py-20051018020158-b2eef6e867c514d9
=== modified file 'NEWS'
--- a/NEWS	2007-12-20 15:21:48 +0000
+++ b/NEWS	2007-12-20 20:33:46 +0000
@@ -40,6 +40,9 @@
    * Merge directives now fetch prerequisites from the target branch if
      needed.  (Aaron Bentley)
 
+   * pycurl now handles digest authentication.
+     (Vincent Ladeuil)
+
    * ``reconfigure`` can now convert from repositories.  (Aaron Bentley)
 
    * ``-l`` is now a short form for ``--limit`` in ``log``.  (Matt Nordhoff)
@@ -58,6 +61,10 @@
    * Fix traceback when sending large response bodies over the smart protocol
      on Windows. (Andrew Bennetts, #115781)
 
+   * pycurl authentication handling was broken and incomplete. Fix handling of
+     user:pass embedded in the urls.
+     (Vincent Ladeuil, #177643)
+
    * Transform failures no longer cause ImmortalLimbo errors (Aaron Bentley,
      #137681)
 

=== modified file 'bzrlib/tests/test_http.py'
--- a/bzrlib/tests/test_http.py	2007-12-08 23:15:18 +0000
+++ b/bzrlib/tests/test_http.py	2007-12-20 19:38:45 +0000
@@ -1321,7 +1321,7 @@
         self.assertEquals(expected_prompt, actual_prompt)
 
     def test_no_prompt_for_password_when_using_auth_config(self):
-        user =' joe'
+        user ='joe'
         password = 'foo'
         stdin_content = 'bar\n'  # Not the right password
         self.server.add_user(user, password)
@@ -1450,3 +1450,53 @@
     def create_transport_readonly_server(self):
         return ProxyDigestAuthServer()
 
+
+class TestAuth_pycurl(object):
+    "Tests that can't be applied to pycurl."""
+
+    def test_prompt_for_password(self):
+        raise tests.TestNotApplicable(
+            'pycurl cannot prompt, it handles auth by embedding'
+            ' user:pass in urls only')
+
+    def test_no_prompt_for_password_when_using_auth_config(self):
+        raise tests.TestNotApplicable(
+            'pycurl does not support authentication.conf'
+            ' since it cannot prompt')
+
+
+class TestHTTPBasicAuth_pycurl(TestWithTransport_pycurl, TestAuth_pycurl,
+                               TestHTTPBasicAuth):
+     """Test http basic authentication scheme for pycurl"""
+
+
+class TestHTTPProxyBasicAuth_pycurl(TestWithTransport_pycurl, TestAuth_pycurl,
+                                    TestHTTPProxyBasicAuth):
+     """Test proxy basic authentication scheme for pycurl"""
+
+     def test_empty_pass(self):
+         raise tests.KnownFailure(
+             'some versions of pycurl does not handle empty proxy passwords')
+
+
+class TestHTTPDigestAuth_pycurl(TestWithTransport_pycurl, TestAuth_pycurl,
+                                TestHTTPDigestAuth):
+     """Test http digest authentication scheme for pycurl"""
+
+     def test_changing_nonce(self):
+         raise tests.KnownFailure(
+             'pycurl does not handle a nonce change')
+
+
+class TestHTTPProxyDigestAuth_pycurl(TestWithTransport_pycurl, TestAuth_pycurl,
+                                     TestHTTPProxyDigestAuth):
+     """Test http digest authentication scheme for pycurl"""
+
+     def test_empty_pass(self):
+         raise tests.KnownFailure(
+             'some versions of pycurl does not handle empty proxy passwords')
+
+     def test_changing_nonce(self):
+         raise tests.KnownFailure(
+             'pycurl does not handle a nonce change')
+

=== modified file 'bzrlib/transport/http/__init__.py'
--- a/bzrlib/transport/http/__init__.py	2007-12-12 21:06:05 +0000
+++ b/bzrlib/transport/http/__init__.py	2007-12-20 14:14:21 +0000
@@ -114,15 +114,6 @@
         else:
             self._range_hint = 'multi'
 
-    def _remote_path(self, relpath):
-        """Produce absolute path, adjusting protocol."""
-        relative = urlutils.unescape(relpath).encode('utf-8')
-        path = self._combine_paths(self._path, relative)
-        return self._unsplit_url(self._unqualified_scheme,
-                                 self._user, self._password,
-                                 self._host, self._port,
-                                 path)
-
     def has(self, relpath):
         raise NotImplementedError("has() is abstract on %r" % self)
 
@@ -151,6 +142,24 @@
         """
         raise NotImplementedError(self._get)
 
+    def _remote_path(self, relpath):
+        """See ConnectedTransport._remote_path.
+
+        user and passwords are not embedded in the path provided to the server.
+        """
+        relative = urlutils.unescape(relpath).encode('utf-8')
+        path = self._combine_paths(self._path, relative)
+        return self._unsplit_url(self._unqualified_scheme,
+                                 None, None, self._host, self._port, path)
+
+    def _create_auth(self):
+        """Returns a dict returning the credentials provided at build time."""
+        auth = dict(host=self._host, port=self._port,
+                    user=self._user, password=self._password,
+                    protocol=self._unqualified_scheme,
+                    path=self._path)
+        return auth
+
     def get_request(self):
         return SmartClientHTTPMediumRequest(self)
 

=== modified file 'bzrlib/transport/http/_pycurl.py'
--- a/bzrlib/transport/http/_pycurl.py	2007-12-08 23:15:18 +0000
+++ b/bzrlib/transport/http/_pycurl.py	2007-12-20 14:14:21 +0000
@@ -123,7 +123,10 @@
             # connect to the http server until the first request (which had
             # just called us).
             connection = pycurl.Curl()
-            self._set_connection(connection, None)
+            # First request, initialize credentials.
+            auth = self._create_auth()
+            # Proxy handling is out of reach, so we punt
+            self._set_connection(connection, auth)
         return connection
 
     def has(self, relpath):
@@ -295,6 +298,18 @@
         curl.setopt(pycurl.USERAGENT, ua_str)
         if self.cabundle:
             curl.setopt(pycurl.CAINFO, self.cabundle)
+        # Set accepted auth methods
+        curl.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_ANY)
+        curl.setopt(pycurl.PROXYAUTH, pycurl.HTTPAUTH_ANY)
+        auth = self._get_credentials()
+        user = auth.get('user', None)
+        password = auth.get('password', None)
+        userpass = None
+        if user is not None:
+            userpass = user + ':'
+            if password is not None: # '' is a valid password
+                userpass += password
+            curl.setopt(pycurl.USERPWD, userpass)
 
     def _curl_perform(self, curl, header, more_headers=[]):
         """Perform curl operation and translate exceptions."""

=== modified file 'bzrlib/transport/http/_urllib.py'
--- a/bzrlib/transport/http/_urllib.py	2007-12-03 08:33:06 +0000
+++ b/bzrlib/transport/http/_urllib.py	2007-12-20 14:14:21 +0000
@@ -49,17 +49,6 @@
         else:
             self._opener = self._opener_class()
 
-    def _remote_path(self, relpath):
-        """Produce absolute path, adjusting protocol."""
-        relative = urlutils.unescape(relpath).encode('utf-8')
-        path = self._combine_paths(self._path, relative)
-        # urllib2 will be confused if it find authentication
-        # info (user, password) in the urls. So we handle them separatly.
-
-        # rhaaaa ! confused where ? confused when ? --vila 20070922
-        return self._unsplit_url(self._unqualified_scheme,
-                                 None, None, self._host, self._port, path)
-
     def _perform(self, request):
         """Send the request to the server and handles common errors.
 
@@ -74,15 +63,10 @@
             # request couldn't do it
             connection.cleanup_pipe()
         else:
-            # First request, intialize credentials.
+            # First request, initialize credentials.
             # scheme and realm will be set by the _urllib2_wrappers.AuthHandler
-            user = self._user
-            password = self._password
-            auth = dict(host=self._host, port=self._port,
-                        user=user, password=password,
-                        protocol=self._unqualified_scheme,
-                        path=self._path)
-            # Proxy initialization will be done by first proxied request
+            auth = self._create_auth()
+            # Proxy initialization will be done by the first proxied request
             proxy_auth = dict()
         # Ensure authentication info is provided
         request.auth = auth

=== modified file 'bzrlib/transport/http/_urllib2_wrappers.py'
--- a/bzrlib/transport/http/_urllib2_wrappers.py	2007-12-13 15:44:44 +0000
+++ b/bzrlib/transport/http/_urllib2_wrappers.py	2007-12-20 14:29:33 +0000
@@ -1036,8 +1036,8 @@
         the prompt, so we build the prompt from the authentication dict which
         contains all the needed parts.
 
-        Also, hhtp and proxy AuthHandlers present different prompts to the
-        user. The daughter classes hosuld implements a public
+        Also, http and proxy AuthHandlers present different prompts to the
+        user. The daughter classes should implements a public
         build_password_prompt using this method.
         """
         prompt = '%s' % auth['protocol'].upper() + ' %(user)s@%(host)s'




More information about the bazaar-commits mailing list