~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/http/_urllib2_wrappers.py

  • Committer: Vincent Ladeuil
  • Date: 2009-05-04 14:48:21 UTC
  • mto: (4349.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4350.
  • Revision ID: v.ladeuil+lp@free.fr-20090504144821-39dvqkikmd3zqkdg
Handle servers proposing several authentication schemes.

* bzrlib/transport/http/_urllib2_wrappers.py:
(AbstractAuthHandler.auth_required): Several schemes can be
proposed by the server, try to match each one in turn.
(BasicAuthHandler.auth_match): Delete dead code.

* bzrlib/tests/test_http.py:
(load_tests): Separate proxy and http authentication tests as they
require different server setups.
(TestAuth.create_transport_readonly_server): Simplified by using
parameter provided by load_tests.
(TestAuth.test_changing_nonce): Adapt to new parametrization.
(TestProxyAuth.create_transport_readonly_server): Deleted.

* bzrlib/tests/http_utils.py:
(DigestAndBasicAuthRequestHandler, HTTPBasicAndDigestAuthServer,
ProxyBasicAndDigestAuthServer): Add a test server proposing both
basic and digest auth schemes but accepting only digest as valid.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1035
1035
                # Let's be ready for next round
1036
1036
                self._retry_count = None
1037
1037
                return None
1038
 
        server_header = headers.get(self.auth_required_header, None)
1039
 
        if server_header is None:
 
1038
        server_headers = headers.getheaders(self.auth_required_header)
 
1039
        if not server_headers:
1040
1040
            # The http error MUST have the associated
1041
1041
            # header. This must never happen in production code.
1042
1042
            raise KeyError('%s not found' % self.auth_required_header)
1043
1043
 
1044
1044
        auth = self.get_auth(request)
1045
1045
        auth['modified'] = False
1046
 
        if self.auth_match(server_header, auth):
1047
 
            # auth_match may have modified auth (by adding the
1048
 
            # password or changing the realm, for example)
1049
 
            if (request.get_header(self.auth_header, None) is not None
1050
 
                and not auth['modified']):
1051
 
                # We already tried that, give up
1052
 
                return None
1053
 
 
1054
 
            if self.requires_username and auth.get('user', None) is None:
1055
 
                # Without a known user, we can't authenticate
1056
 
                return None
1057
 
 
1058
 
            # Housekeeping
1059
 
            request.connection.cleanup_pipe()
1060
 
            response = self.parent.open(request)
1061
 
            if response:
1062
 
                self.auth_successful(request, response)
1063
 
            return response
 
1046
        # FIXME: the auth handler should be selected at a single place instead
 
1047
        # of letting all handlers try to match all headers.
 
1048
        for server_header in server_headers:
 
1049
            # Several schemes can be proposed by the server, try to match each
 
1050
            # one in turn
 
1051
            matching_handler = self.auth_match(server_header, auth)
 
1052
            if matching_handler:
 
1053
                # auth_match may have modified auth (by adding the
 
1054
                # password or changing the realm, for example)
 
1055
                if (request.get_header(self.auth_header, None) is not None
 
1056
                    and not auth['modified']):
 
1057
                    # We already tried that, give up
 
1058
                    return None
 
1059
 
 
1060
                if self.requires_username and auth.get('user', None) is None:
 
1061
                    # Without a known user, we can't authenticate
 
1062
                    return None
 
1063
 
 
1064
                # Housekeeping
 
1065
                request.connection.cleanup_pipe()
 
1066
                # Retry the request with an authentication header added
 
1067
                response = self.parent.open(request)
 
1068
                if response:
 
1069
                    self.auth_successful(request, response)
 
1070
                return response
1064
1071
        # We are not qualified to handle the authentication.
1065
1072
        # Note: the authentication error handling will try all
1066
1073
        # available handlers. If one of them authenticates
1260
1267
 
1261
1268
        match, realm = self.extract_realm(raw_auth)
1262
1269
        if match:
1263
 
            if scheme != 'basic':
1264
 
                return False
1265
 
 
1266
1270
            # Put useful info into auth
1267
1271
            self.update_auth(auth, 'scheme', scheme)
1268
1272
            self.update_auth(auth, 'realm', realm)