/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6437.25.1 by Vincent Ladeuil
Provide default paths for ca certs for supported platforms
1
# Copyright (C) 2006-2012 Canonical Ltd
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
16
6238.2.9 by Jelmer Vernooij
Add some tests for ssl.ca_certs config option.
17
"""Implementation of urllib2 tailored to bzr needs
2004.2.1 by John Arbash Meinel
Cleanup of urllib functions
18
2363.4.7 by Vincent Ladeuil
Deeper tests, prepare the auth setting that will avoid the
19
This file complements the urllib2 class hierarchy with custom classes.
2004.2.1 by John Arbash Meinel
Cleanup of urllib functions
20
21
For instance, we create a new HTTPConnection and HTTPSConnection that inherit
22
from the original urllib2.HTTP(s)Connection objects, but also have a new base
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
23
which implements a custom getresponse and cleanup_pipe handlers.
2004.2.1 by John Arbash Meinel
Cleanup of urllib functions
24
25
And then we implement custom HTTPHandler and HTTPSHandler classes, that use
26
the custom HTTPConnection classes.
27
28
We have a custom Response class, which lets us maintain a keep-alive
29
connection even for requests that urllib2 doesn't expect to contain body data.
30
2363.4.10 by Vincent Ladeuil
Complete tests.
31
And a custom Request class that lets us track redirections, and
2363.4.12 by Vincent Ladeuil
Take jam's review comments into account. Fix typos, give better
32
handle authentication schemes.
3430.1.1 by Vincent Ladeuil
Fix bug #229076 by fixing header names before sending the request.
33
34
For coherency with python libraries, we use capitalized header names throughout
35
the code, even if the header names will be titled just before sending the
36
request (see AbstractHTTPHandler.do_open).
2004.2.1 by John Arbash Meinel
Cleanup of urllib functions
37
"""
38
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
39
from __future__ import absolute_import
40
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
41
DEBUG = 0
42
43
# FIXME: Oversimplifying, two kind of exceptions should be
44
# raised, once a request is issued: URLError before we have been
45
# able to process the response, HTTPError after that. Process the
46
# response means we are able to leave the socket clean, so if we
47
# are not able to do that, we should close the connection. The
48
# actual code more or less do that, tests should be written to
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
49
# ensure that.
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
50
4628.1.2 by Vincent Ladeuil
More complete fix.
51
import errno
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
52
import httplib
6238.2.9 by Jelmer Vernooij
Add some tests for ssl.ca_certs config option.
53
import os
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
54
import socket
55
import urllib
56
import urllib2
57
import urlparse
2167.3.4 by v.ladeuil+lp at free
Better fix for #74759, but still not tests.
58
import re
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
59
import sys
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
60
import time
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
61
2004.1.25 by v.ladeuil+lp at free
Shuffle http related test code. Hopefully it ends up at the right place :)
62
from bzrlib import __version__ as bzrlib_version
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
63
from bzrlib import (
2900.2.6 by Vincent Ladeuil
Make http aware of authentication config.
64
    config,
3052.3.3 by Vincent Ladeuil
Add -Dhttp support.
65
    debug,
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
66
    errors,
6238.2.7 by Jelmer Vernooij
Add ssl.cert_reqs.
67
    lazy_import,
2929.3.1 by Vincent Ladeuil
Fix python2.6 deprecation warnings (still 4 failures 5 errors in test suite).
68
    osutils,
3052.3.3 by Vincent Ladeuil
Add -Dhttp support.
69
    trace,
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
70
    transport,
6524.4.2 by Marius Kruger
use ui.ui_factory.show_user_warning to warn about not checking ssl certs, so that we only do it once
71
    ui,
4795.4.5 by Vincent Ladeuil
Make sure all redirection code paths can handle authentication.
72
    urlutils,
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
73
    )
6238.2.7 by Jelmer Vernooij
Add ssl.cert_reqs.
74
lazy_import.lazy_import(globals(), """
75
import ssl
76
""")
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
77
6238.2.9 by Jelmer Vernooij
Add some tests for ssl.ca_certs config option.
78
6437.25.1 by Vincent Ladeuil
Provide default paths for ca certs for supported platforms
79
# Note for packagers: if there is no package providing certs for your platform,
80
# the curl project produces http://curl.haxx.se/ca/cacert.pem weekly.
6437.25.4 by Vincent Ladeuil
Get rid of 'optional' for ssl.ca_reqs to simplify the model.
81
_ssl_ca_certs_known_locations = [
6437.25.3 by Vincent Ladeuil
Simplify: all posix systems will try know locations and select the first
82
    u'/etc/ssl/certs/ca-certificates.crt', # Ubuntu/debian/gentoo
83
    u'/etc/pki/tls/certs/ca-bundle.crt', # Fedora/CentOS/RH
84
    u'/etc/ssl/ca-bundle.pem', # OpenSuse
85
    u'/etc/ssl/cert.pem', # OpenSuse
86
    u"/usr/local/share/certs/ca-root-nss.crt", # FreeBSD
87
    # XXX: Needs checking, can't trust the interweb ;) -- vila 2012-01-25
88
    u'/etc/openssl/certs/ca-certificates.crt', # Solaris
89
    ]
6238.2.8 by Jelmer Vernooij
Move options to bzrlib/transport/http/_urllib2_wrappers.py
90
def default_ca_certs():
6437.25.3 by Vincent Ladeuil
Simplify: all posix systems will try know locations and select the first
91
    if sys.platform == 'win32':
6437.34.1 by Martin Packman
Expect name 'cacert.pem' rather than 'ca_bundle.crt' for curl extracted certs on win32
92
        return os.path.join(os.path.dirname(sys.executable), u"cacert.pem")
6437.25.1 by Vincent Ladeuil
Provide default paths for ca certs for supported platforms
93
    elif sys.platform == 'darwin':
94
        # FIXME: Needs some default value for osx, waiting for osx installers
95
        # guys feedback -- vila 2012-01-25
96
        pass
6437.25.3 by Vincent Ladeuil
Simplify: all posix systems will try know locations and select the first
97
    else:
98
        # Try known locations for friendly OSes providing the root certificates
99
        # without making them hard to use for any https client.
6437.25.4 by Vincent Ladeuil
Get rid of 'optional' for ssl.ca_reqs to simplify the model.
100
        for path in _ssl_ca_certs_known_locations:
6437.25.3 by Vincent Ladeuil
Simplify: all posix systems will try know locations and select the first
101
            if os.path.exists(path):
102
                # First found wins
103
                return path
104
    # A default path that makes sense and will be mentioned in the error
105
    # presented to the user, even if not correct for all platforms
6437.25.4 by Vincent Ladeuil
Get rid of 'optional' for ssl.ca_reqs to simplify the model.
106
    return _ssl_ca_certs_known_locations[0]
6238.2.9 by Jelmer Vernooij
Add some tests for ssl.ca_certs config option.
107
6238.2.8 by Jelmer Vernooij
Move options to bzrlib/transport/http/_urllib2_wrappers.py
108
6238.2.10 by Jelmer Vernooij
Add more tests for ssl.ca_certs option.
109
def ca_certs_from_store(path):
110
    if not os.path.exists(path):
111
        raise ValueError("ca certs path %s does not exist" % path)
112
    return path
113
114
6238.2.8 by Jelmer Vernooij
Move options to bzrlib/transport/http/_urllib2_wrappers.py
115
def cert_reqs_from_store(unicode_str):
116
    import ssl
117
    try:
118
        return {
119
            "required": ssl.CERT_REQUIRED,
120
            "none": ssl.CERT_NONE
121
            }[unicode_str]
122
    except KeyError:
123
        raise ValueError("invalid value %s" % unicode_str)
124
6437.31.1 by Vincent Ladeuil
Default to no ssl cert verification on osx and windows
125
def default_ca_reqs():
126
    if sys.platform in ('win32', 'darwin'):
127
        # FIXME: Once we get a native access to root certificates there, this
128
        # won't needed anymore. See http://pad.lv/920455 -- vila 2012-02-15
129
        return u'none'
130
    else:
131
        return u'required'
6238.2.8 by Jelmer Vernooij
Move options to bzrlib/transport/http/_urllib2_wrappers.py
132
133
opt_ssl_ca_certs = config.Option('ssl.ca_certs',
6238.2.10 by Jelmer Vernooij
Add more tests for ssl.ca_certs option.
134
        from_unicode=ca_certs_from_store,
6238.2.8 by Jelmer Vernooij
Move options to bzrlib/transport/http/_urllib2_wrappers.py
135
        default=default_ca_certs,
6437.25.6 by Vincent Ladeuil
Feedback from mgz.
136
        invalid='warning',
6238.2.8 by Jelmer Vernooij
Move options to bzrlib/transport/http/_urllib2_wrappers.py
137
        help="""\
138
Path to certification authority certificates to trust.
6437.25.6 by Vincent Ladeuil
Feedback from mgz.
139
140
This should be a valid path to a bundle containing all root Certificate
141
Authorities used to verify an https server certificate.
142
143
Use ssl.cert_reqs=none to disable certificate verification.
6238.2.8 by Jelmer Vernooij
Move options to bzrlib/transport/http/_urllib2_wrappers.py
144
""")
145
146
opt_ssl_cert_reqs = config.Option('ssl.cert_reqs',
6437.31.1 by Vincent Ladeuil
Default to no ssl cert verification on osx and windows
147
        default=default_ca_reqs,
6238.2.8 by Jelmer Vernooij
Move options to bzrlib/transport/http/_urllib2_wrappers.py
148
        from_unicode=cert_reqs_from_store,
6238.2.10 by Jelmer Vernooij
Add more tests for ssl.ca_certs option.
149
        invalid='error',
6238.2.8 by Jelmer Vernooij
Move options to bzrlib/transport/http/_urllib2_wrappers.py
150
        help="""\
151
Whether to require a certificate from the remote side. (default:required)
152
153
Possible values:
6238.2.22 by Vincent Ladeuil
Create a specific test permutation for urllib https so we can inject our test ca certs. The wiring in _urllib2_wrappers is a bit hackish and it will need to use auth instead so different certs can be used for proxies and real servers but this could wait until authentication.conf is migrated to the config stacks. With this change in place, all https tests pass without the need to create a dedicated GlobalStore.
154
 * none: Certificates ignored
6437.25.4 by Vincent Ladeuil
Get rid of 'optional' for ssl.ca_reqs to simplify the model.
155
 * required: Certificates required and validated
6238.2.8 by Jelmer Vernooij
Move options to bzrlib/transport/http/_urllib2_wrappers.py
156
""")
157
6238.1.2 by John Arbash Meinel, Jelmer Vernooij
Only attempt to import kerberos module once.
158
checked_kerberos = False
159
kerberos = None
160
161
5393.6.1 by Toshio Kuratomi
Fix branching from lp: repositories under python-2.7
162
class addinfourl(urllib2.addinfourl):
5393.6.3 by Toshio Kuratomi
Fix typo in implementation of python-2.7 xmlrpclib fix and add comment + entry in NEWS
163
    '''Replacement addinfourl class compatible with python-2.7's xmlrpclib
164
165
    In python-2.7, xmlrpclib expects that the response object that it receives
166
    has a getheader method.  httplib.HTTPResponse provides this but
167
    urllib2.addinfourl does not.  Add the necessary functions here, ported to
168
    use the internal data structures of addinfourl.
169
    '''
5393.6.1 by Toshio Kuratomi
Fix branching from lp: repositories under python-2.7
170
171
    def getheader(self, name, default=None):
172
        if self.headers is None:
173
            raise httplib.ResponseNotReady()
5393.6.3 by Toshio Kuratomi
Fix typo in implementation of python-2.7 xmlrpclib fix and add comment + entry in NEWS
174
        return self.headers.getheader(name, default)
5393.6.1 by Toshio Kuratomi
Fix branching from lp: repositories under python-2.7
175
176
    def getheaders(self):
177
        if self.headers is None:
178
            raise httplib.ResponseNotReady()
179
        return self.headers.items()
180
181
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
182
class _ReportingFileSocket(object):
183
184
    def __init__(self, filesock, report_activity=None):
185
        self.filesock = filesock
186
        self._report_activity = report_activity
187
4776.2.1 by Vincent Ladeuil
Support no activity report on http sockets.
188
    def report_activity(self, size, direction):
189
        if self._report_activity:
190
            self._report_activity(size, direction)
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
191
192
    def read(self, size=1):
193
        s = self.filesock.read(size)
4776.2.1 by Vincent Ladeuil
Support no activity report on http sockets.
194
        self.report_activity(len(s), 'read')
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
195
        return s
196
5848.2.1 by John Arbash Meinel
Break compatibility with python <2.6.
197
    def readline(self, size=-1):
198
        s = self.filesock.readline(size)
199
        self.report_activity(len(s), 'read')
200
        return s
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
201
202
    def __getattr__(self, name):
203
        return getattr(self.filesock, name)
204
205
206
class _ReportingSocket(object):
207
208
    def __init__(self, sock, report_activity=None):
3287.3.3 by Andrew Bennetts
A slightly neater hack for forcing buffering, thanks to John.
209
        self.sock = sock
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
210
        self._report_activity = report_activity
211
4776.2.1 by Vincent Ladeuil
Support no activity report on http sockets.
212
    def report_activity(self, size, direction):
213
        if self._report_activity:
214
            self._report_activity(size, direction)
215
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
216
    def sendall(self, s, *args):
4105.1.1 by Andrew Bennetts
Clean-up _ReportingSocket.send/sendall slightly.
217
        self.sock.sendall(s, *args)
4776.2.1 by Vincent Ladeuil
Support no activity report on http sockets.
218
        self.report_activity(len(s), 'write')
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
219
220
    def recv(self, *args):
221
        s = self.sock.recv(*args)
4776.2.1 by Vincent Ladeuil
Support no activity report on http sockets.
222
        self.report_activity(len(s), 'read')
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
223
        return s
3287.3.3 by Andrew Bennetts
A slightly neater hack for forcing buffering, thanks to John.
224
225
    def makefile(self, mode='r', bufsize=-1):
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
226
        # httplib creates a fileobject that doesn't do buffering, which
227
        # makes fp.readline() very expensive because it only reads one byte
228
        # at a time.  So we wrap the socket in an object that forces
229
        # sock.makefile to make a buffered file.
230
        fsock = self.sock.makefile(mode, 65536)
231
        # And wrap that into a reporting kind of fileobject
232
        return _ReportingFileSocket(fsock, self._report_activity)
3287.3.3 by Andrew Bennetts
A slightly neater hack for forcing buffering, thanks to John.
233
234
    def __getattr__(self, name):
235
        return getattr(self.sock, name)
236
237
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
238
# We define our own Response class to keep our httplib pipe clean
239
class Response(httplib.HTTPResponse):
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
240
    """Custom HTTPResponse, to avoid the need to decorate.
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
241
242
    httplib prefers to decorate the returned objects, rather
243
    than using a custom object.
244
    """
245
2004.1.7 by vila
Better handling of passwords (user should be queried only once).
246
    # Some responses have bodies in which we have no interest
5504.4.1 by Vincent Ladeuil
Fix http test spurious failures and get rid of some useless messages in log.
247
    _body_ignored_responses = [301,302, 303, 307, 400, 401, 403, 404, 501]
2004.1.7 by vila
Better handling of passwords (user should be queried only once).
248
3146.3.4 by Vincent Ladeuil
Review feedback, simpler loops.
249
    # in finish() below, we may have to discard several MB in the worst
250
    # case. To avoid buffering that much, we read and discard by chunks
251
    # instead. The underlying file is either a socket or a StringIO, so reading
252
    # 8k chunks should be fine.
253
    _discarded_buf_size = 8192
254
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
255
    def begin(self):
256
        """Begin to read the response from the server.
257
258
        httplib assumes that some responses get no content and do
259
        not even attempt to read the body in that case, leaving
260
        the body in the socket, blocking the next request. Let's
261
        try to workaround that.
262
        """
2004.1.2 by vila
Implements a BasicAuthManager.
263
        httplib.HTTPResponse.begin(self)
2004.1.7 by vila
Better handling of passwords (user should be queried only once).
264
        if self.status in self._body_ignored_responses:
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
265
            if self.debuglevel >= 2:
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
266
                print "For status: [%s]," % self.status,
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
267
                print "will ready body, length: %s" % self.length
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
268
            if not (self.length is None or self.will_close):
269
                # In some cases, we just can't read the body not
270
                # even try or we may encounter a 104, 'Connection
271
                # reset by peer' error if there is indeed no body
272
                # and the server closed the connection just after
273
                # having issued the response headers (even if the
2004.1.37 by v.ladeuil+lp at free
Small refactoring.
274
                # headers indicate a Content-Type...)
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
275
                body = self.read(self.length)
276
                if self.debuglevel >= 9:
3024.2.3 by Vincent Ladeuil
Rewrite http_readv to allow several GET requests. Smoke tested against branch reported in the bug.
277
                    # This one can be huge and is generally not interesting
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
278
                    print "Consumed body: [%s]" % body
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
279
            self.close()
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
280
        elif self.status == 200:
281
            # Whatever the request is, it went ok, so we surely don't want to
282
            # close the connection. Some cases are not correctly detected by
283
            # httplib.HTTPConnection.getresponse (called by
284
            # httplib.HTTPResponse.begin). The CONNECT response for the https
2955.2.1 by Vincent Ladeuil
Fix #160012 by leaving the http pipeline related exceptions raise.
285
            # through proxy case is one.  Note: the 'will_close' below refers
286
            # to the "true" socket between us and the server, whereas the
287
            # 'close()' above refers to the copy of that socket created by
288
            # httplib for the response itself. So, in the if above we close the
289
            # socket to indicate that we are done with the response whereas
290
            # below we keep the socket with the server opened.
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
291
            self.will_close = False
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
292
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
293
    def finish(self):
3059.2.11 by Vincent Ladeuil
Fix typos mentioned by spiv.
294
        """Finish reading the body.
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
295
3059.2.11 by Vincent Ladeuil
Fix typos mentioned by spiv.
296
        In some cases, the client may have left some bytes to read in the
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
297
        body. That will block the next request to succeed if we use a
3059.2.11 by Vincent Ladeuil
Fix typos mentioned by spiv.
298
        persistent connection. If we don't use a persistent connection, well,
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
299
        nothing will block the next request since a new connection will be
300
        issued anyway.
3104.3.3 by Vincent Ladeuil
Jam's and Aaron feedback about bug #175886.
301
302
        :return: the number of bytes left on the socket (may be None)
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
303
        """
3104.3.3 by Vincent Ladeuil
Jam's and Aaron feedback about bug #175886.
304
        pending = None
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
305
        if not self.isclosed():
306
            # Make sure nothing was left to be read on the socket
3104.3.1 by Vincent Ladeuil
Fix #175886 by reading remaining bytes by chunks.
307
            pending = 0
3146.3.2 by Vincent Ladeuil
Fix #179368 by keeping the current range hint on ShortReadvErrors.
308
            data = True
3146.3.4 by Vincent Ladeuil
Review feedback, simpler loops.
309
            while data and self.length:
310
                # read() will update self.length
311
                data = self.read(min(self.length, self._discarded_buf_size))
3104.3.1 by Vincent Ladeuil
Fix #175886 by reading remaining bytes by chunks.
312
                pending += len(data)
313
            if pending:
3146.3.2 by Vincent Ladeuil
Fix #179368 by keeping the current range hint on ShortReadvErrors.
314
                trace.mutter("%s bytes left on the HTTP socket", pending)
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
315
            self.close()
3104.3.3 by Vincent Ladeuil
Jam's and Aaron feedback about bug #175886.
316
        return pending
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
317
2004.1.2 by vila
Implements a BasicAuthManager.
318
2004.2.1 by John Arbash Meinel
Cleanup of urllib functions
319
# Not inheriting from 'object' because httplib.HTTPConnection doesn't.
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
320
class AbstractHTTPConnection:
321
    """A custom HTTP(S) Connection, which can reset itself on a bad response"""
322
323
    response_class = Response
324
3104.3.3 by Vincent Ladeuil
Jam's and Aaron feedback about bug #175886.
325
    # When we detect a server responding with the whole file to range requests,
326
    # we want to warn. But not below a given thresold.
327
    _range_warning_thresold = 1024 * 1024
328
4776.2.1 by Vincent Ladeuil
Support no activity report on http sockets.
329
    def __init__(self, report_activity=None):
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
330
        self._response = None
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
331
        self._report_activity = report_activity
3104.3.3 by Vincent Ladeuil
Jam's and Aaron feedback about bug #175886.
332
        self._ranges_received_whole_file = None
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
333
334
    def _mutter_connect(self):
3104.3.4 by Vincent Ladeuil
Add test.
335
        netloc = '%s:%s' % (self.host, self.port)
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
336
        if self.proxied_host is not None:
337
            netloc += '(proxy for %s)' % self.proxied_host
338
        trace.mutter('* About to connect() to %s' % netloc)
339
340
    def getresponse(self):
341
        """Capture the response to be able to cleanup"""
342
        self._response = httplib.HTTPConnection.getresponse(self)
343
        return self._response
344
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
345
    def cleanup_pipe(self):
3111.1.24 by Vincent Ladeuil
Cleanups.
346
        """Read the remaining bytes of the last response if any."""
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
347
        if self._response is not None:
5504.4.1 by Vincent Ladeuil
Fix http test spurious failures and get rid of some useless messages in log.
348
            try:
349
                pending = self._response.finish()
350
                # Warn the user (once)
351
                if (self._ranges_received_whole_file is None
352
                    and self._response.status == 200
353
                    and pending and pending > self._range_warning_thresold
354
                    ):
355
                    self._ranges_received_whole_file = True
356
                    trace.warning(
357
                        'Got a 200 response when asking for multiple ranges,'
358
                        ' does your server at %s:%s support range requests?',
359
                        self.host, self.port)
360
            except socket.error, e:
361
                # It's conceivable that the socket is in a bad state here
362
                # (including some test cases) and in this case, it doesn't need
363
                # cleaning anymore, so no need to fail, we just get rid of the
364
                # socket and let callers reconnect
365
                if (len(e.args) == 0
366
                    or e.args[0] not in (errno.ECONNRESET, errno.ECONNABORTED)):
367
                    raise
368
                self.close()
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
369
            self._response = None
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
370
        # Preserve our preciousss
371
        sock = self.sock
372
        self.sock = None
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
373
        # Let httplib.HTTPConnection do its housekeeping
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
374
        self.close()
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
375
        # Restore our preciousss
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
376
        self.sock = sock
377
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
378
    def _wrap_socket_for_reporting(self, sock):
379
        """Wrap the socket before anybody use it."""
380
        self.sock = _ReportingSocket(sock, self._report_activity)
381
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
382
383
class HTTPConnection(AbstractHTTPConnection, httplib.HTTPConnection):
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
384
385
    # XXX: Needs refactoring at the caller level.
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
386
    def __init__(self, host, port=None, proxied_host=None,
6238.2.22 by Vincent Ladeuil
Create a specific test permutation for urllib https so we can inject our test ca certs. The wiring in _urllib2_wrappers is a bit hackish and it will need to use auth instead so different certs can be used for proxies and real servers but this could wait until authentication.conf is migrated to the config stacks. With this change in place, all https tests pass without the need to create a dedicated GlobalStore.
387
                 report_activity=None, ca_certs=None):
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
388
        AbstractHTTPConnection.__init__(self, report_activity=report_activity)
2929.3.9 by Vincent Ladeuil
Don't pretend we support HTTP/0.9 since we don't and do that correctly.
389
        # Use strict=True since we don't support HTTP/0.9
390
        httplib.HTTPConnection.__init__(self, host, port, strict=True)
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
391
        self.proxied_host = proxied_host
6238.2.22 by Vincent Ladeuil
Create a specific test permutation for urllib https so we can inject our test ca certs. The wiring in _urllib2_wrappers is a bit hackish and it will need to use auth instead so different certs can be used for proxies and real servers but this could wait until authentication.conf is migrated to the config stacks. With this change in place, all https tests pass without the need to create a dedicated GlobalStore.
392
        # ca_certs is ignored, it's only relevant for https
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
393
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
394
    def connect(self):
395
        if 'http' in debug.debug_flags:
396
            self._mutter_connect()
397
        httplib.HTTPConnection.connect(self)
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
398
        self._wrap_socket_for_reporting(self.sock)
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
399
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
400
6238.2.4 by Jelmer Vernooij
Verify ssl certificates when using urllib.
401
# These two methods were imported from Python 3.2's ssl module
402
6573.1.1 by Andrew Starr-Bochicchio
Fix possible abuse of _urllib2_wrappers.match_hostname() for denial of service using certificates with many wildcards (CVE-2013-2099).
403
def _dnsname_to_pat(dn, max_wildcards=1):
6238.2.4 by Jelmer Vernooij
Verify ssl certificates when using urllib.
404
    pats = []
405
    for frag in dn.split(r'.'):
6573.1.1 by Andrew Starr-Bochicchio
Fix possible abuse of _urllib2_wrappers.match_hostname() for denial of service using certificates with many wildcards (CVE-2013-2099).
406
        if frag.count('*') > max_wildcards:
407
            # Python Issue #17980: avoid denials of service by refusing more
408
            # than one wildcard per fragment.  A survery of established
409
            # policy among SSL implementations showed it to be a
410
            # reasonable choice.
411
            raise ValueError(
412
                "too many wildcards in certificate DNS name: " + repr(dn))
6238.2.4 by Jelmer Vernooij
Verify ssl certificates when using urllib.
413
        if frag == '*':
414
            # When '*' is a fragment by itself, it matches a non-empty dotless
415
            # fragment.
416
            pats.append('[^.]+')
417
        else:
418
            # Otherwise, '*' matches any dotless fragment.
419
            frag = re.escape(frag)
420
            pats.append(frag.replace(r'\*', '[^.]*'))
421
    return re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
422
423
424
def match_hostname(cert, hostname):
425
    """Verify that *cert* (in decoded format as returned by
426
    SSLSocket.getpeercert()) matches the *hostname*.  RFC 2818 rules
427
    are mostly followed, but IP addresses are not accepted for *hostname*.
428
429
    CertificateError is raised on failure. On success, the function
430
    returns nothing.
431
    """
432
    if not cert:
433
        raise ValueError("empty or no certificate")
434
    dnsnames = []
435
    san = cert.get('subjectAltName', ())
436
    for key, value in san:
437
        if key == 'DNS':
438
            if _dnsname_to_pat(value).match(hostname):
439
                return
440
            dnsnames.append(value)
441
    if not san:
442
        # The subject is only checked when subjectAltName is empty
443
        for sub in cert.get('subject', ()):
444
            for key, value in sub:
445
                # XXX according to RFC 2818, the most specific Common Name
446
                # must be used.
447
                if key == 'commonName':
448
                    if _dnsname_to_pat(value).match(hostname):
449
                        return
450
                    dnsnames.append(value)
451
    if len(dnsnames) > 1:
6238.2.21 by Vincent Ladeuil
The https test server will now refuse connections if an ssl error occurs during the handshake. Ssl errors and certificate errors aborts requests without re-trying them.
452
        raise errors.CertificateError(
453
            "hostname %r doesn't match either of %s"
6238.2.4 by Jelmer Vernooij
Verify ssl certificates when using urllib.
454
            % (hostname, ', '.join(map(repr, dnsnames))))
455
    elif len(dnsnames) == 1:
6238.2.21 by Vincent Ladeuil
The https test server will now refuse connections if an ssl error occurs during the handshake. Ssl errors and certificate errors aborts requests without re-trying them.
456
        raise errors.CertificateError("hostname %r doesn't match %r" %
457
                                      (hostname, dnsnames[0]))
6238.2.4 by Jelmer Vernooij
Verify ssl certificates when using urllib.
458
    else:
459
        raise errors.CertificateError("no appropriate commonName or "
460
            "subjectAltName fields were found")
461
462
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
463
class HTTPSConnection(AbstractHTTPConnection, httplib.HTTPSConnection):
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
464
465
    def __init__(self, host, port=None, key_file=None, cert_file=None,
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
466
                 proxied_host=None,
6238.2.22 by Vincent Ladeuil
Create a specific test permutation for urllib https so we can inject our test ca certs. The wiring in _urllib2_wrappers is a bit hackish and it will need to use auth instead so different certs can be used for proxies and real servers but this could wait until authentication.conf is migrated to the config stacks. With this change in place, all https tests pass without the need to create a dedicated GlobalStore.
467
                 report_activity=None, ca_certs=None):
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
468
        AbstractHTTPConnection.__init__(self, report_activity=report_activity)
2929.3.9 by Vincent Ladeuil
Don't pretend we support HTTP/0.9 since we don't and do that correctly.
469
        # Use strict=True since we don't support HTTP/0.9
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
470
        httplib.HTTPSConnection.__init__(self, host, port,
2929.3.9 by Vincent Ladeuil
Don't pretend we support HTTP/0.9 since we don't and do that correctly.
471
                                         key_file, cert_file, strict=True)
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
472
        self.proxied_host = proxied_host
6238.2.22 by Vincent Ladeuil
Create a specific test permutation for urllib https so we can inject our test ca certs. The wiring in _urllib2_wrappers is a bit hackish and it will need to use auth instead so different certs can be used for proxies and real servers but this could wait until authentication.conf is migrated to the config stacks. With this change in place, all https tests pass without the need to create a dedicated GlobalStore.
473
        self.ca_certs = ca_certs
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
474
475
    def connect(self):
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
476
        if 'http' in debug.debug_flags:
477
            self._mutter_connect()
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
478
        httplib.HTTPConnection.connect(self)
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
479
        self._wrap_socket_for_reporting(self.sock)
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
480
        if self.proxied_host is None:
481
            self.connect_to_origin()
482
483
    def connect_to_origin(self):
6238.2.7 by Jelmer Vernooij
Add ssl.cert_reqs.
484
        # FIXME JRV 2011-12-18: Use location config here?
485
        config_stack = config.GlobalStack()
486
        cert_reqs = config_stack.get('ssl.cert_reqs')
6437.50.1 by Martin Packman
Match certs against proxied hostname when using HTTPS proxy
487
        if self.proxied_host is not None:
488
            host = self.proxied_host.split(":", 1)[0]
489
        else:
490
            host = self.host
6238.2.13 by Jelmer Vernooij
add notes on using -Ossl.cert_reqs=none.
491
        if cert_reqs == ssl.CERT_NONE:
6524.4.2 by Marius Kruger
use ui.ui_factory.show_user_warning to warn about not checking ssl certs, so that we only do it once
492
            ui.ui_factory.show_user_warning('not_checking_ssl_cert', host=host)
493
            ui.ui_factory.suppressed_warnings.add('not_checking_ssl_cert')
6437.25.1 by Vincent Ladeuil
Provide default paths for ca certs for supported platforms
494
            ca_certs = None
6238.2.13 by Jelmer Vernooij
add notes on using -Ossl.cert_reqs=none.
495
        else:
6437.25.1 by Vincent Ladeuil
Provide default paths for ca certs for supported platforms
496
            if self.ca_certs is None:
497
                ca_certs = config_stack.get('ssl.ca_certs')
498
            else:
499
                ca_certs = self.ca_certs
6238.2.14 by Jelmer Vernooij
Urgh - only warn if there actually isn't a ca certs file set.
500
            if ca_certs is None:
501
                trace.warning(
6437.25.6 by Vincent Ladeuil
Feedback from mgz.
502
                    "No valid trusted SSL CA certificates file set. See "
6238.2.14 by Jelmer Vernooij
Urgh - only warn if there actually isn't a ca certs file set.
503
                    "'bzr help ssl.ca_certs' for more information on setting "
6437.25.6 by Vincent Ladeuil
Feedback from mgz.
504
                    "trusted CAs.")
6238.2.13 by Jelmer Vernooij
add notes on using -Ossl.cert_reqs=none.
505
        try:
506
            ssl_sock = ssl.wrap_socket(self.sock, self.key_file, self.cert_file,
507
                cert_reqs=cert_reqs, ca_certs=ca_certs)
508
        except ssl.SSLError, e:
6437.25.7 by Vincent Ladeuil
We need a clearer understanding of ssl errors.
509
            trace.note(
510
                "\n"
511
                "See `bzr help ssl.ca_certs` for how to specify trusted CA"
512
                "certificates.\n"
513
                "Pass -Ossl.cert_reqs=none to disable certificate "
514
                "verification entirely.\n")
6238.2.13 by Jelmer Vernooij
add notes on using -Ossl.cert_reqs=none.
515
            raise
6437.25.4 by Vincent Ladeuil
Get rid of 'optional' for ssl.ca_reqs to simplify the model.
516
        if cert_reqs == ssl.CERT_REQUIRED:
517
            peer_cert = ssl_sock.getpeercert()
6437.50.1 by Martin Packman
Match certs against proxied hostname when using HTTPS proxy
518
            match_hostname(peer_cert, host)
6238.2.4 by Jelmer Vernooij
Verify ssl certificates when using urllib.
519
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
520
        # Wrap the ssl socket before anybody use it
521
        self._wrap_socket_for_reporting(ssl_sock)
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
522
523
524
class Request(urllib2.Request):
525
    """A custom Request object.
526
527
    urllib2 determines the request method heuristically (based on
528
    the presence or absence of data). We set the method
529
    statically.
530
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
531
    The Request object tracks:
532
    - the connection the request will be made on.
533
    - the authentication parameters needed to preventively set
534
      the authentication header once a first authentication have
535
       been made.
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
536
    """
537
538
    def __init__(self, method, url, data=None, headers={},
539
                 origin_req_host=None, unverifiable=False,
2520.2.2 by Vincent Ladeuil
Fix #115209 by issuing a single range request on 400: Bad Request
540
                 connection=None, parent=None,
4795.4.2 by Vincent Ladeuil
Revert auth reuse.
541
                 accepted_errors=None):
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
542
        urllib2.Request.__init__(self, url, data, headers,
543
                                 origin_req_host, unverifiable)
544
        self.method = method
545
        self.connection = connection
2520.2.2 by Vincent Ladeuil
Fix #115209 by issuing a single range request on 400: Bad Request
546
        self.accepted_errors = accepted_errors
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
547
        # To handle redirections
548
        self.parent = parent
549
        self.redirected_to = None
2164.2.15 by Vincent Ladeuil
Http redirections are not followed by default. Do not use hints
550
        # Unless told otherwise, redirections are not followed
551
        self.follow_redirections = False
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
552
        # auth and proxy_auth are dicts containing, at least
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
553
        # (scheme, host, port, realm, user, password, protocol, path).
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
554
        # The dict entries are mostly handled by the AuthHandler.
555
        # Some authentication schemes may add more entries.
4795.4.2 by Vincent Ladeuil
Revert auth reuse.
556
        self.auth = {}
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
557
        self.proxy_auth = {}
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
558
        self.proxied_host = None
2420.1.3 by Vincent Ladeuil
Implement http proxy basic authentication.
559
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
560
    def get_method(self):
561
        return self.method
562
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
563
    def set_proxy(self, proxy, type):
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
564
        """Set the proxy and remember the proxied host."""
4776.2.7 by Vincent Ladeuil
Fix proxy CONNECT for non-default ports.
565
        host, port = urllib.splitport(self.get_host())
566
        if port is None:
567
            # We need to set the default port ourselves way before it gets set
568
            # in the HTTP[S]Connection object at build time.
569
            if self.type == 'https':
570
                conn_class = HTTPSConnection
571
            else:
572
                conn_class = HTTPConnection
573
            port = conn_class.default_port
574
        self.proxied_host = '%s:%s' % (host, port)
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
575
        urllib2.Request.set_proxy(self, proxy, type)
4797.75.1 by Andrew Bennetts
Backport fix for bug 558343 from lp:bzr r5220.
576
        # When urllib2 makes a https request with our wrapper code and a proxy,
577
        # it sets Host to the https proxy, not the host we want to talk to.
578
        # I'm fairly sure this is our fault, but what is the cause is an open
579
        # question. -- Robert Collins May 8 2010.
580
        self.add_unredirected_header('Host', self.proxied_host)
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
581
582
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
583
class _ConnectRequest(Request):
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
584
585
    def __init__(self, request):
586
        """Constructor
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
587
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
588
        :param request: the first request sent to the proxied host, already
589
            processed by the opener (i.e. proxied_host is already set).
590
        """
591
        # We give a fake url and redefine get_selector or urllib2 will be
592
        # confused
593
        Request.__init__(self, 'CONNECT', request.get_full_url(),
594
                         connection=request.connection)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
595
        if request.proxied_host is None:
596
            raise AssertionError()
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
597
        self.proxied_host = request.proxied_host
598
599
    def get_selector(self):
600
        return self.proxied_host
601
602
    def set_proxy(self, proxy, type):
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
603
        """Set the proxy without remembering the proxied host.
604
605
        We already know the proxied host by definition, the CONNECT request
606
        occurs only when the connection goes through a proxy. The usual
607
        processing (masquerade the request so that the connection is done to
608
        the proxy while the request is targeted at another host) does not apply
609
        here. In fact, the connection is already established with proxy and we
610
        just want to enable the SSL tunneling.
611
        """
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
612
        urllib2.Request.set_proxy(self, proxy, type)
613
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
614
615
class ConnectionHandler(urllib2.BaseHandler):
616
    """Provides connection-sharing by pre-processing requests.
617
618
    urllib2 provides no way to access the HTTPConnection object
619
    internally used. But we need it in order to achieve
620
    connection sharing. So, we add it to the request just before
621
    it is processed, and then we override the do_open method for
2363.4.7 by Vincent Ladeuil
Deeper tests, prepare the auth setting that will avoid the
622
    http[s] requests in AbstractHTTPHandler.
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
623
    """
624
625
    handler_order = 1000 # after all pre-processings
626
6238.2.22 by Vincent Ladeuil
Create a specific test permutation for urllib https so we can inject our test ca certs. The wiring in _urllib2_wrappers is a bit hackish and it will need to use auth instead so different certs can be used for proxies and real servers but this could wait until authentication.conf is migrated to the config stacks. With this change in place, all https tests pass without the need to create a dedicated GlobalStore.
627
    def __init__(self, report_activity=None, ca_certs=None):
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
628
        self._report_activity = report_activity
6238.2.22 by Vincent Ladeuil
Create a specific test permutation for urllib https so we can inject our test ca certs. The wiring in _urllib2_wrappers is a bit hackish and it will need to use auth instead so different certs can be used for proxies and real servers but this could wait until authentication.conf is migrated to the config stacks. With this change in place, all https tests pass without the need to create a dedicated GlobalStore.
629
        self.ca_certs = ca_certs
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
630
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
631
    def create_connection(self, request, http_connection_class):
632
        host = request.get_host()
633
        if not host:
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
634
            # Just a bit of paranoia here, this should have been
635
            # handled in the higher levels
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
636
            raise errors.InvalidURL(request.get_full_url(), 'no host given.')
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
637
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
638
        # We create a connection (but it will not connect until the first
639
        # request is made)
2004.1.42 by v.ladeuil+lp at free
Fix #70803 by catching the httplib exception.
640
        try:
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
641
            connection = http_connection_class(
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
642
                host, proxied_host=request.proxied_host,
6238.2.22 by Vincent Ladeuil
Create a specific test permutation for urllib https so we can inject our test ca certs. The wiring in _urllib2_wrappers is a bit hackish and it will need to use auth instead so different certs can be used for proxies and real servers but this could wait until authentication.conf is migrated to the config stacks. With this change in place, all https tests pass without the need to create a dedicated GlobalStore.
643
                report_activity=self._report_activity,
644
                ca_certs=self.ca_certs)
2004.1.42 by v.ladeuil+lp at free
Fix #70803 by catching the httplib exception.
645
        except httplib.InvalidURL, exception:
646
            # There is only one occurrence of InvalidURL in httplib
647
            raise errors.InvalidURL(request.get_full_url(),
648
                                    extra='nonnumeric port')
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
649
650
        return connection
651
652
    def capture_connection(self, request, http_connection_class):
653
        """Capture or inject the request connection.
654
655
        Two cases:
656
        - the request have no connection: create a new one,
657
658
        - the request have a connection: this one have been used
659
          already, let's capture it, so that we can give it to
660
          another transport to be reused. We don't do that
661
          ourselves: the Transport object get the connection from
662
          a first request and then propagate it, from request to
663
          request or to cloned transports.
664
        """
665
        connection = request.connection
666
        if connection is None:
667
            # Create a new one
668
            connection = self.create_connection(request, http_connection_class)
669
            request.connection = connection
670
671
        # All connections will pass here, propagate debug level
672
        connection.set_debuglevel(DEBUG)
673
        return request
674
675
    def http_request(self, request):
676
        return self.capture_connection(request, HTTPConnection)
677
678
    def https_request(self, request):
679
        return self.capture_connection(request, HTTPSConnection)
680
681
682
class AbstractHTTPHandler(urllib2.AbstractHTTPHandler):
683
    """A custom handler for HTTP(S) requests.
684
685
    We overrive urllib2.AbstractHTTPHandler to get a better
686
    control of the connection, the ability to implement new
687
    request types and return a response able to cope with
688
    persistent connections.
689
    """
690
691
    # We change our order to be before urllib2 HTTP[S]Handlers
2004.3.1 by vila
Test ConnectionError exceptions.
692
    # and be chosen instead of them (the first http_open called
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
693
    # wins).
694
    handler_order = 400
695
696
    _default_headers = {'Pragma': 'no-cache',
697
                        'Cache-control': 'max-age=0',
698
                        'Connection': 'Keep-Alive',
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
699
                        'User-agent': 'bzr/%s (urllib)' % bzrlib_version,
2004.3.3 by vila
Better (but still incomplete) design for bogus servers.
700
                        'Accept': '*/*',
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
701
                        }
702
703
    def __init__(self):
2004.1.16 by v.ladeuil+lp at free
Add tests against erroneous http status lines.
704
        urllib2.AbstractHTTPHandler.__init__(self, debuglevel=DEBUG)
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
705
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
706
    def http_request(self, request):
707
        """Common headers setting"""
708
709
        request.headers.update(self._default_headers.copy())
710
        # FIXME: We may have to add the Content-Length header if
711
        # we have data to send.
712
        return request
713
2004.1.37 by v.ladeuil+lp at free
Small refactoring.
714
    def retry_or_raise(self, http_class, request, first_try):
715
        """Retry the request (once) or raise the exception.
2004.3.1 by vila
Test ConnectionError exceptions.
716
717
        urllib2 raises exception of application level kind, we
718
        just have to translate them.
719
720
        httplib can raise exceptions of transport level (badly
721
        formatted dialog, loss of connexion or socket level
722
        problems). In that case we should issue the request again
723
        (httplib will close and reopen a new connection if
2004.1.37 by v.ladeuil+lp at free
Small refactoring.
724
        needed).
725
        """
726
        # When an exception occurs, we give back the original
727
        # Traceback or the bugs are hard to diagnose.
728
        exc_type, exc_val, exc_tb = sys.exc_info()
729
        if exc_type == socket.gaierror:
730
            # No need to retry, that will not help
731
            raise errors.ConnectionError("Couldn't resolve host '%s'"
732
                                         % request.get_origin_req_host(),
733
                                         orig_error=exc_val)
2955.2.1 by Vincent Ladeuil
Fix #160012 by leaving the http pipeline related exceptions raise.
734
        elif isinstance(exc_val, httplib.ImproperConnectionState):
735
            # The httplib pipeline is in incorrect state, it's a bug in our
736
            # implementation.
737
            raise exc_type, exc_val, exc_tb
2004.1.37 by v.ladeuil+lp at free
Small refactoring.
738
        else:
739
            if first_try:
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
740
                if self._debuglevel >= 2:
2004.1.37 by v.ladeuil+lp at free
Small refactoring.
741
                    print 'Received exception: [%r]' % exc_val
742
                    print '  On connection: [%r]' % request.connection
743
                    method = request.get_method()
744
                    url = request.get_full_url()
745
                    print '  Will retry, %s %r' % (method, url)
746
                request.connection.close()
747
                response = self.do_open(http_class, request, False)
748
            else:
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
749
                if self._debuglevel >= 2:
2004.1.39 by v.ladeuil+lp at free
Fix a race condition that make selftest fail once in a while.
750
                    print 'Received second exception: [%r]' % exc_val
751
                    print '  On connection: [%r]' % request.connection
2004.1.37 by v.ladeuil+lp at free
Small refactoring.
752
                if exc_type in (httplib.BadStatusLine, httplib.UnknownProtocol):
753
                    # httplib.BadStatusLine and
754
                    # httplib.UnknownProtocol indicates that a
755
                    # bogus server was encountered or a bad
756
                    # connection (i.e. transient errors) is
757
                    # experimented, we have already retried once
758
                    # for that request so we raise the exception.
759
                    my_exception = errors.InvalidHttpResponse(
760
                        request.get_full_url(),
761
                        'Bad status line received',
762
                        orig_error=exc_val)
4628.1.2 by Vincent Ladeuil
More complete fix.
763
                elif (isinstance(exc_val, socket.error) and len(exc_val.args)
5599.3.3 by John Arbash Meinel
Treate WSAECONNABORTED the same as WSAECONNRESET in the http _urllib2 code. Bug #686587
764
                      and exc_val.args[0] in (errno.ECONNRESET, 10053, 10054)):
765
                      # 10053 == WSAECONNABORTED
766
                      # 10054 == WSAECONNRESET
4628.1.2 by Vincent Ladeuil
More complete fix.
767
                    raise errors.ConnectionReset(
768
                        "Connection lost while sending request.")
2004.1.37 by v.ladeuil+lp at free
Small refactoring.
769
                else:
770
                    # All other exception are considered connection related.
771
772
                    # socket errors generally occurs for reasons
773
                    # far outside our scope, so closing the
774
                    # connection and retrying is the best we can
775
                    # do.
776
777
                    my_exception = errors.ConnectionError(
778
                        msg= 'while sending %s %s:' % (request.get_method(),
779
                                                       request.get_selector()),
780
                        orig_error=exc_val)
781
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
782
                if self._debuglevel >= 2:
2004.1.37 by v.ladeuil+lp at free
Small refactoring.
783
                    print 'On connection: [%r]' % request.connection
784
                    method = request.get_method()
785
                    url = request.get_full_url()
786
                    print '  Failed again, %s %r' % (method, url)
787
                    print '  Will raise: [%r]' % my_exception
788
                raise my_exception, None, exc_tb
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
789
        return response
2004.1.37 by v.ladeuil+lp at free
Small refactoring.
790
791
    def do_open(self, http_class, request, first_try=True):
792
        """See urllib2.AbstractHTTPHandler.do_open for the general idea.
793
794
        The request will be retried once if it fails.
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
795
        """
796
        connection = request.connection
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
797
        if connection is None:
798
            raise AssertionError(
799
                'Cannot process a request without a connection')
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
800
2004.1.19 by v.ladeuil+lp at free
Test protocol version in http responses.
801
        # Get all the headers
2004.1.15 by v.ladeuil+lp at free
Better design for bogus servers. Both urllib and pycurl pass tests.
802
        headers = {}
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
803
        headers.update(request.header_items())
804
        headers.update(request.unredirected_hdrs)
3430.1.1 by Vincent Ladeuil
Fix bug #229076 by fixing header names before sending the request.
805
        # Some servers or proxies will choke on headers not properly
806
        # cased. httplib/urllib/urllib2 all use capitalize to get canonical
807
        # header names, but only python2.5 urllib2 use title() to fix them just
808
        # before sending the request. And not all versions of python 2.5 do
809
        # that. Since we replace urllib2.AbstractHTTPHandler.do_open we do it
810
        # ourself below.
3430.1.2 by Vincent Ladeuil
Fixed as per Matt Nordhoff review.
811
        headers = dict((name.title(), val) for name, val in headers.iteritems())
2004.3.1 by vila
Test ConnectionError exceptions.
812
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
813
        try:
3052.3.3 by Vincent Ladeuil
Add -Dhttp support.
814
            method = request.get_method()
815
            url = request.get_selector()
816
            connection._send_request(method, url,
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
817
                                     # FIXME: implements 100-continue
818
                                     #None, # We don't send the body yet
819
                                     request.get_data(),
820
                                     headers)
3052.3.3 by Vincent Ladeuil
Add -Dhttp support.
821
            if 'http' in debug.debug_flags:
822
                trace.mutter('> %s %s' % (method, url))
5957.2.3 by Vincent Ladeuil
Mask credentials in the -Dhttp logging
823
                hdrs = []
824
                for k,v in headers.iteritems():
825
                    # People are often told to paste -Dhttp output to help
826
                    # debug. Don't compromise credentials.
827
                    if k in ('Authorization', 'Proxy-Authorization'):
828
                        v = '<masked>'
829
                    hdrs.append('%s: %s' % (k, v))
3052.3.3 by Vincent Ladeuil
Add -Dhttp support.
830
                trace.mutter('> ' + '\n> '.join(hdrs) + '\n')
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
831
            if self._debuglevel >= 1:
832
                print 'Request sent: [%r] from (%s)' \
833
                    % (request, request.connection.sock.getsockname())
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
834
            response = connection.getresponse()
835
            convert_to_addinfourl = True
6238.2.21 by Vincent Ladeuil
The https test server will now refuse connections if an ssl error occurs during the handshake. Ssl errors and certificate errors aborts requests without re-trying them.
836
        except (ssl.SSLError, errors.CertificateError):
837
            # Something is wrong with either the certificate or the hostname,
838
            # re-trying won't help
839
            raise
2004.1.37 by v.ladeuil+lp at free
Small refactoring.
840
        except (socket.gaierror, httplib.BadStatusLine, httplib.UnknownProtocol,
841
                socket.error, httplib.HTTPException):
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
842
            response = self.retry_or_raise(http_class, request, first_try)
843
            convert_to_addinfourl = False
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
844
845
# FIXME: HTTPConnection does not fully support 100-continue (the
846
# server responses are just ignored)
847
848
#        if code == 100:
849
#            mutter('Will send the body')
850
#            # We can send the body now
851
#            body = request.get_data()
852
#            if body is None:
853
#                raise URLError("No data given")
854
#            connection.send(body)
855
#            response = connection.getresponse()
856
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
857
        if self._debuglevel >= 2:
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
858
            print 'Receives response: %r' % response
859
            print '  For: %r(%r)' % (request.get_method(),
860
                                     request.get_full_url())
861
862
        if convert_to_addinfourl:
863
            # Shamelessly copied from urllib2
864
            req = request
865
            r = response
866
            r.recv = r.read
3287.3.2 by Andrew Bennetts
Buffer 64k, rather than just 8k.
867
            fp = socket._fileobject(r, bufsize=65536)
5393.6.1 by Toshio Kuratomi
Fix branching from lp: repositories under python-2.7
868
            resp = addinfourl(fp, r.msg, req.get_full_url())
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
869
            resp.code = r.status
870
            resp.msg = r.reason
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
871
            resp.version = r.version
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
872
            if self._debuglevel >= 2:
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
873
                print 'Create addinfourl: %r' % resp
874
                print '  For: %r(%r)' % (request.get_method(),
875
                                         request.get_full_url())
3059.2.5 by Vincent Ladeuil
DAMN^64, the http test server is 1.0 not 1.1 :( Better pipe cleaning and less readv caching (since that's the point of the whole fix).
876
            if 'http' in debug.debug_flags:
877
                version = 'HTTP/%d.%d'
878
                try:
879
                    version = version % (resp.version / 10,
880
                                         resp.version % 10)
881
                except:
882
                    version = 'HTTP/%r' % resp.version
883
                trace.mutter('< %s %s %s' % (version, resp.code,
884
                                             resp.msg))
885
                # Use the raw header lines instead of treating resp.info() as a
886
                # dict since we may miss duplicated headers otherwise.
887
                hdrs = [h.rstrip('\r\n') for h in resp.info().headers]
888
                trace.mutter('< ' + '\n< '.join(hdrs) + '\n')
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
889
        else:
890
            resp = response
891
        return resp
892
893
894
class HTTPHandler(AbstractHTTPHandler):
2004.2.1 by John Arbash Meinel
Cleanup of urllib functions
895
    """A custom handler that just thunks into HTTPConnection"""
896
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
897
    def http_open(self, request):
898
        return self.do_open(HTTPConnection, request)
899
900
901
class HTTPSHandler(AbstractHTTPHandler):
2004.2.1 by John Arbash Meinel
Cleanup of urllib functions
902
    """A custom handler that just thunks into HTTPSConnection"""
903
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
904
    https_request = AbstractHTTPHandler.http_request
905
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
906
    def https_open(self, request):
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
907
        connection = request.connection
908
        if connection.sock is None and \
909
                connection.proxied_host is not None and \
910
                request.get_method() != 'CONNECT' : # Don't loop
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
911
            # FIXME: We need a gazillion connection tests here, but we still
912
            # miss a https server :-( :
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
913
            # - with and without proxy
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
914
            # - with and without certificate
915
            # - with self-signed certificate
916
            # - with and without authentication
2929.3.9 by Vincent Ladeuil
Don't pretend we support HTTP/0.9 since we don't and do that correctly.
917
            # - with good and bad credentials (especially the proxy auth around
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
918
            #   CONNECT)
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
919
            # - with basic and digest schemes
920
            # - reconnection on errors
921
            # - connection persistence behaviour (including reconnection)
922
923
            # We are about to connect for the first time via a proxy, we must
924
            # issue a CONNECT request first to establish the encrypted link
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
925
            connect = _ConnectRequest(request)
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
926
            response = self.parent.open(connect)
927
            if response.code != 200:
4797.75.1 by Andrew Bennetts
Backport fix for bug 558343 from lp:bzr r5220.
928
                raise errors.ConnectionError("Can't connect to %s via proxy %s" % (
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
929
                        connect.proxied_host, self.host))
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
930
            # Housekeeping
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
931
            connection.cleanup_pipe()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
932
            # Establish the connection encryption
2540.2.1 by Vincent Ladeuil
Rough, working, tested against squid+apache in basic auth fix for #120678
933
            connection.connect_to_origin()
934
            # Propagate the connection to the original request
935
            request.connection = connection
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
936
        return self.do_open(HTTPSConnection, request)
937
938
class HTTPRedirectHandler(urllib2.HTTPRedirectHandler):
939
    """Handles redirect requests.
940
941
    We have to implement our own scheme because we use a specific
942
    Request object and because we want to implement a specific
943
    policy.
944
    """
945
    _debuglevel = DEBUG
946
    # RFC2616 says that only read requests should be redirected
947
    # without interacting with the user. But bzr use some
948
    # shortcuts to optimize against roundtrips which can leads to
949
    # write requests being issued before read requests of
950
    # containing dirs can be redirected. So we redirect write
951
    # requests in the same way which seems to respect the spirit
952
    # of the RFC if not its letter.
953
954
    def redirect_request(self, req, fp, code, msg, headers, newurl):
955
        """See urllib2.HTTPRedirectHandler.redirect_request"""
956
        # We would have preferred to update the request instead
957
        # of creating a new one, but the urllib2.Request object
958
        # has a too complicated creation process to provide a
959
        # simple enough equivalent update process. Instead, when
2164.2.29 by Vincent Ladeuil
Test the http redirection at the request level even if it's not
960
        # redirecting, we only update the following request in
961
        # the redirect chain with a reference to the parent
962
        # request .
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
963
2164.2.1 by v.ladeuil+lp at free
First rough http branch redirection implementation.
964
        # Some codes make no sense in our context and are treated
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
965
        # as errors:
966
967
        # 300: Multiple choices for different representations of
968
        #      the URI. Using that mechanisn with bzr will violate the
969
        #      protocol neutrality of Transport.
970
971
        # 304: Not modified (SHOULD only occurs with conditional
972
        #      GETs which are not used by our implementation)
973
974
        # 305: Use proxy. I can't imagine this one occurring in
975
        #      our context-- vila/20060909
976
977
        # 306: Unused (if the RFC says so...)
978
2164.2.1 by v.ladeuil+lp at free
First rough http branch redirection implementation.
979
        # If the code is 302 and the request is HEAD, some may
980
        # think that it is a sufficent hint that the file exists
981
        # and that we MAY avoid following the redirections. But
982
        # if we want to be sure, we MUST follow them.
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
983
984
        if code in (301, 302, 303, 307):
985
            return Request(req.get_method(),newurl,
986
                           headers = req.headers,
987
                           origin_req_host = req.get_origin_req_host(),
988
                           unverifiable = True,
989
                           # TODO: It will be nice to be able to
990
                           # detect virtual hosts sharing the same
991
                           # IP address, that will allow us to
992
                           # share the same connection...
993
                           connection = None,
994
                           parent = req,
995
                           )
996
        else:
997
            raise urllib2.HTTPError(req.get_full_url(), code, msg, headers, fp)
998
2164.2.29 by Vincent Ladeuil
Test the http redirection at the request level even if it's not
999
    def http_error_302(self, req, fp, code, msg, headers):
2004.3.1 by vila
Test ConnectionError exceptions.
1000
        """Requests the redirected to URI.
1001
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
1002
        Copied from urllib2 to be able to clean the pipe of the associated
1003
        connection, *before* issuing the redirected request but *after* having
1004
        eventually raised an error.
2004.3.1 by vila
Test ConnectionError exceptions.
1005
        """
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1006
        # Some servers (incorrectly) return multiple Location headers
1007
        # (so probably same goes for URI).  Use first header.
1008
1009
        # TODO: Once we get rid of addinfourl objects, the
1010
        # following will need to be updated to use correct case
1011
        # for headers.
1012
        if 'location' in headers:
1013
            newurl = headers.getheaders('location')[0]
1014
        elif 'uri' in headers:
1015
            newurl = headers.getheaders('uri')[0]
1016
        else:
1017
            return
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
1018
        if self._debuglevel >= 1:
2164.2.1 by v.ladeuil+lp at free
First rough http branch redirection implementation.
1019
            print 'Redirected to: %s (followed: %r)' % (newurl,
1020
                                                        req.follow_redirections)
1021
        if req.follow_redirections is False:
1022
            req.redirected_to = newurl
1023
            return fp
1024
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1025
        newurl = urlparse.urljoin(req.get_full_url(), newurl)
1026
1027
        # This call succeeds or raise an error. urllib2 returns
1028
        # if redirect_request returns None, but our
1029
        # redirect_request never returns None.
1030
        redirected_req = self.redirect_request(req, fp, code, msg, headers,
1031
                                               newurl)
1032
1033
        # loop detection
1034
        # .redirect_dict has a key url if url was previously visited.
1035
        if hasattr(req, 'redirect_dict'):
1036
            visited = redirected_req.redirect_dict = req.redirect_dict
1037
            if (visited.get(newurl, 0) >= self.max_repeats or
1038
                len(visited) >= self.max_redirections):
1039
                raise urllib2.HTTPError(req.get_full_url(), code,
1040
                                        self.inf_msg + msg, headers, fp)
1041
        else:
1042
            visited = redirected_req.redirect_dict = req.redirect_dict = {}
1043
        visited[newurl] = visited.get(newurl, 0) + 1
1044
1045
        # We can close the fp now that we are sure that we won't
1046
        # use it with HTTPError.
1047
        fp.close()
1048
        # We have all we need already in the response
3059.2.2 by Vincent Ladeuil
Read http responses on demand without buffering the whole body
1049
        req.connection.cleanup_pipe()
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1050
1051
        return self.parent.open(redirected_req)
1052
2164.2.29 by Vincent Ladeuil
Test the http redirection at the request level even if it's not
1053
    http_error_301 = http_error_303 = http_error_307 = http_error_302
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1054
1055
2167.3.1 by v.ladeuil+lp at free
Fix bug #74759.
1056
class ProxyHandler(urllib2.ProxyHandler):
1057
    """Handles proxy setting.
1058
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
1059
    Copied and modified from urllib2 to be able to modify the request during
1060
    the request pre-processing instead of modifying it at _open time. As we
1061
    capture (or create) the connection object during request processing, _open
1062
    time was too late.
1063
1064
    The main task is to modify the request so that the connection is done to
1065
    the proxy while the request still refers to the destination host.
1066
1067
    Note: the proxy handling *may* modify the protocol used; the request may be
1068
    against an https server proxied through an http proxy. So, https_request
1069
    will be called, but later it's really http_open that will be called. This
2540.2.3 by Vincent Ladeuil
Take Aaron's comments into account.
1070
    explains why we don't have to call self.parent.open as the urllib2 did.
2167.3.1 by v.ladeuil+lp at free
Fix bug #74759.
1071
    """
1072
1073
    # Proxies must be in front
1074
    handler_order = 100
2167.3.3 by v.ladeuil+lp at free
* bzrlib/transport/http/_urllib2_wrappers.py:
1075
    _debuglevel = DEBUG
2167.3.1 by v.ladeuil+lp at free
Fix bug #74759.
1076
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1077
    def __init__(self, proxies=None):
2167.3.1 by v.ladeuil+lp at free
Fix bug #74759.
1078
        urllib2.ProxyHandler.__init__(self, proxies)
2167.3.4 by v.ladeuil+lp at free
Better fix for #74759, but still not tests.
1079
        # First, let's get rid of urllib2 implementation
2167.3.1 by v.ladeuil+lp at free
Fix bug #74759.
1080
        for type, proxy in self.proxies.items():
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
1081
            if self._debuglevel >= 3:
2167.3.3 by v.ladeuil+lp at free
* bzrlib/transport/http/_urllib2_wrappers.py:
1082
                print 'Will unbind %s_open for %r' % (type, proxy)
2167.3.1 by v.ladeuil+lp at free
Fix bug #74759.
1083
            delattr(self, '%s_open' % type)
1084
4797.75.1 by Andrew Bennetts
Backport fix for bug 558343 from lp:bzr r5220.
1085
        def bind_scheme_request(proxy, scheme):
1086
            if proxy is None:
1087
                return
1088
            scheme_request = scheme + '_request'
1089
            if self._debuglevel >= 3:
1090
                print 'Will bind %s for %r' % (scheme_request, proxy)
1091
            setattr(self, scheme_request,
1092
                lambda request: self.set_proxy(request, scheme))
2167.3.4 by v.ladeuil+lp at free
Better fix for #74759, but still not tests.
1093
        # We are interested only by the http[s] proxies
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
1094
        http_proxy = self.get_proxy_env_var('http')
4797.75.1 by Andrew Bennetts
Backport fix for bug 558343 from lp:bzr r5220.
1095
        bind_scheme_request(http_proxy, 'http')
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
1096
        https_proxy = self.get_proxy_env_var('https')
4797.75.1 by Andrew Bennetts
Backport fix for bug 558343 from lp:bzr r5220.
1097
        bind_scheme_request(https_proxy, 'https')
2167.3.3 by v.ladeuil+lp at free
* bzrlib/transport/http/_urllib2_wrappers.py:
1098
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
1099
    def get_proxy_env_var(self, name, default_to='all'):
1100
        """Get a proxy env var.
1101
2182.1.1 by Aaron Bentley
Respect proxy environment settings (Vincent Ladeuil, #74759)
1102
        Note that we indirectly rely on
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
1103
        urllib.getproxies_environment taking into account the
1104
        uppercased values for proxy variables.
1105
        """
2167.3.3 by v.ladeuil+lp at free
* bzrlib/transport/http/_urllib2_wrappers.py:
1106
        try:
1107
            return self.proxies[name.lower()]
1108
        except KeyError:
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
1109
            if default_to is not None:
1110
                # Try to get the alternate environment variable
1111
                try:
1112
                    return self.proxies[default_to]
1113
                except KeyError:
1114
                    pass
1115
        return None
2167.3.3 by v.ladeuil+lp at free
* bzrlib/transport/http/_urllib2_wrappers.py:
1116
2167.3.4 by v.ladeuil+lp at free
Better fix for #74759, but still not tests.
1117
    def proxy_bypass(self, host):
5639.2.2 by Vincent Ladeuil
Add tests and comments to clarify the feature.
1118
        """Check if host should be proxied or not.
1119
1120
        :returns: True to skip the proxy, False otherwise.
1121
        """
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1122
        no_proxy = self.get_proxy_env_var('no', default_to=None)
5639.2.2 by Vincent Ladeuil
Add tests and comments to clarify the feature.
1123
        bypass = self.evaluate_proxy_bypass(host, no_proxy)
1124
        if bypass is None:
5639.2.1 by Martin Pool
Empty entries in the ``NO_PROXY`` variable are no longer treated as matching every host.
1125
            # Nevertheless, there are platform-specific ways to
1126
            # ignore proxies...
1127
            return urllib.proxy_bypass(host)
1128
        else:
5639.2.2 by Vincent Ladeuil
Add tests and comments to clarify the feature.
1129
            return bypass
5639.2.1 by Martin Pool
Empty entries in the ``NO_PROXY`` variable are no longer treated as matching every host.
1130
1131
    def evaluate_proxy_bypass(self, host, no_proxy):
5639.2.2 by Vincent Ladeuil
Add tests and comments to clarify the feature.
1132
        """Check the host against a comma-separated no_proxy list as a string.
1133
1134
        :param host: ``host:port`` being requested
1135
5639.2.1 by Martin Pool
Empty entries in the ``NO_PROXY`` variable are no longer treated as matching every host.
1136
        :param no_proxy: comma-separated list of hosts to access directly.
5639.2.2 by Vincent Ladeuil
Add tests and comments to clarify the feature.
1137
5639.2.1 by Martin Pool
Empty entries in the ``NO_PROXY`` variable are no longer treated as matching every host.
1138
        :returns: True to skip the proxy, False not to, or None to
1139
            leave it to urllib.
1140
        """
2167.3.4 by v.ladeuil+lp at free
Better fix for #74759, but still not tests.
1141
        if no_proxy is None:
5639.2.2 by Vincent Ladeuil
Add tests and comments to clarify the feature.
1142
            # All hosts are proxied
2167.3.4 by v.ladeuil+lp at free
Better fix for #74759, but still not tests.
1143
            return False
1144
        hhost, hport = urllib.splitport(host)
2182.1.1 by Aaron Bentley
Respect proxy environment settings (Vincent Ladeuil, #74759)
1145
        # Does host match any of the domains mentioned in
1146
        # no_proxy ? The rules about what is authorized in no_proxy
1147
        # are fuzzy (to say the least). We try to allow most
2167.3.4 by v.ladeuil+lp at free
Better fix for #74759, but still not tests.
1148
        # commonly seen values.
1149
        for domain in no_proxy.split(','):
5639.2.1 by Martin Pool
Empty entries in the ``NO_PROXY`` variable are no longer treated as matching every host.
1150
            domain = domain.strip()
1151
            if domain == '':
1152
                continue
2167.3.4 by v.ladeuil+lp at free
Better fix for #74759, but still not tests.
1153
            dhost, dport = urllib.splitport(domain)
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
1154
            if hport == dport or dport is None:
2167.3.4 by v.ladeuil+lp at free
Better fix for #74759, but still not tests.
1155
                # Protect glob chars
1156
                dhost = dhost.replace(".", r"\.")
1157
                dhost = dhost.replace("*", r".*")
1158
                dhost = dhost.replace("?", r".")
2167.3.5 by v.ladeuil+lp at free
Tests for proxies, covering #74759.
1159
                if re.match(dhost, hhost, re.IGNORECASE):
5639.2.2 by Vincent Ladeuil
Add tests and comments to clarify the feature.
1160
                    return True
1161
        # Nothing explicitly avoid the host
1162
        return None
2167.3.4 by v.ladeuil+lp at free
Better fix for #74759, but still not tests.
1163
2167.3.3 by v.ladeuil+lp at free
* bzrlib/transport/http/_urllib2_wrappers.py:
1164
    def set_proxy(self, request, type):
2167.3.4 by v.ladeuil+lp at free
Better fix for #74759, but still not tests.
1165
        if self.proxy_bypass(request.get_host()):
1166
            return request
1167
2167.3.6 by v.ladeuil+lp at free
Take John's comments into account and add more tests.
1168
        proxy = self.get_proxy_env_var(type)
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
1169
        if self._debuglevel >= 3:
2167.3.3 by v.ladeuil+lp at free
* bzrlib/transport/http/_urllib2_wrappers.py:
1170
            print 'set_proxy %s_request for %r' % (type, proxy)
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
1171
        # FIXME: python 2.5 urlparse provides a better _parse_proxy which can
1172
        # grok user:password@host:port as well as
1173
        # http://user:password@host:port
1174
6055.2.1 by Jelmer Vernooij
Add UnparsedUrl.
1175
        parsed_url = transport.ConnectedTransport._split_url(proxy)
1176
        if not parsed_url.host:
4294.2.9 by Robert Collins
Fixup tests broken by cleaning up the layering.
1177
            raise errors.InvalidURL(proxy, 'No host component')
2900.2.15 by Vincent Ladeuil
AuthenticationConfig can be queried for logins too (first step).
1178
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1179
        if request.proxy_auth == {}:
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1180
            # No proxy auth parameter are available, we are handling the first
1181
            # proxied request, intialize.  scheme (the authentication scheme)
1182
            # and realm will be set by the AuthHandler
1183
            request.proxy_auth = {
6055.2.1 by Jelmer Vernooij
Add UnparsedUrl.
1184
                                  'host': parsed_url.host,
1185
                                  'port': parsed_url.port,
1186
                                  'user': parsed_url.user,
1187
                                  'password': parsed_url.password,
1188
                                  'protocol': parsed_url.scheme,
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1189
                                   # We ignore path since we connect to a proxy
1190
                                  'path': None}
6055.2.1 by Jelmer Vernooij
Add UnparsedUrl.
1191
        if parsed_url.port is None:
1192
            phost = parsed_url.host
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1193
        else:
6055.2.1 by Jelmer Vernooij
Add UnparsedUrl.
1194
            phost = parsed_url.host + ':%d' % parsed_url.port
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1195
        request.set_proxy(phost, type)
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
1196
        if self._debuglevel >= 3:
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1197
            print 'set_proxy: proxy set to %s://%s' % (type, phost)
2167.3.1 by v.ladeuil+lp at free
Fix bug #74759.
1198
        return request
1199
1200
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1201
class AbstractAuthHandler(urllib2.BaseHandler):
1202
    """A custom abstract authentication handler for all http authentications.
1203
1204
    Provides the meat to handle authentication errors and
1205
    preventively set authentication headers after the first
1206
    successful authentication.
1207
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1208
    This can be used for http and proxy, as well as for basic, negotiate and
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1209
    digest authentications.
1210
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1211
    This provides an unified interface for all authentication handlers
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1212
    (urllib2 provides far too many with different policies).
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1213
1214
    The interaction between this handler and the urllib2
1215
    framework is not obvious, it works as follow:
1216
1217
    opener.open(request) is called:
1218
1219
    - that may trigger http_request which will add an authentication header
1220
      (self.build_header) if enough info is available.
1221
1222
    - the request is sent to the server,
1223
1224
    - if an authentication error is received self.auth_required is called,
1225
      we acquire the authentication info in the error headers and call
1226
      self.auth_match to check that we are able to try the
1227
      authentication and complete the authentication parameters,
1228
1229
    - we call parent.open(request), that may trigger http_request
1230
      and will add a header (self.build_header), but here we have
1231
      all the required info (keep in mind that the request and
1232
      authentication used in the recursive calls are really (and must be)
1233
      the *same* objects).
1234
1235
    - if the call returns a response, the authentication have been
1236
      successful and the request authentication parameters have been updated.
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1237
    """
1238
4307.4.3 by Vincent Ladeuil
Tighten multiple auth schemes handling.
1239
    scheme = None
1240
    """The scheme as it appears in the server header (lower cased)"""
1241
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1242
    _max_retry = 3
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
1243
    """We don't want to retry authenticating endlessly"""
1244
4050.2.3 by Vincent Ladeuil
Slight cosmetic tweaks.
1245
    requires_username = True
1246
    """Whether the auth mechanism requires a username."""
1247
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1248
    # The following attributes should be defined by daughter
1249
    # classes:
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1250
    # - auth_required_header:  the header received from the server
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1251
    # - auth_header: the header sent in the request
1252
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1253
    def __init__(self):
1254
        # We want to know when we enter into an try/fail cycle of
1255
        # authentications so we initialize to None to indicate that we aren't
1256
        # in such a cycle by default.
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
1257
        self._retry_count = None
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1258
4050.2.2 by Vincent Ladeuil
Ensures all auth handlers correctly parse all auth headers.
1259
    def _parse_auth_header(self, server_header):
1260
        """Parse the authentication header.
1261
1262
        :param server_header: The value of the header sent by the server
1263
            describing the authenticaion request.
1264
1265
        :return: A tuple (scheme, remainder) scheme being the first word in the
1266
            given header (lower cased), remainder may be None.
1267
        """
1268
        try:
1269
            scheme, remainder = server_header.split(None, 1)
1270
        except ValueError:
1271
            scheme = server_header
1272
            remainder = None
1273
        return (scheme.lower(), remainder)
1274
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1275
    def update_auth(self, auth, key, value):
1276
        """Update a value in auth marking the auth as modified if needed"""
1277
        old_value = auth.get(key, None)
1278
        if old_value != value:
1279
            auth[key] = value
1280
            auth['modified'] = True
1281
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1282
    def auth_required(self, request, headers):
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1283
        """Retry the request if the auth scheme is ours.
1284
1285
        :param request: The request needing authentication.
1286
        :param headers: The headers for the authentication error response.
1287
        :return: None or the response for the authenticated request.
1288
        """
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
1289
        # Don't try  to authenticate endlessly
1290
        if self._retry_count is None:
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1291
            # The retry being recusrsive calls, None identify the first retry
1292
            self._retry_count = 1
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
1293
        else:
1294
            self._retry_count += 1
1295
            if self._retry_count > self._max_retry:
1296
                # Let's be ready for next round
1297
                self._retry_count = None
1298
                return None
4307.4.2 by Vincent Ladeuil
Handle servers proposing several authentication schemes.
1299
        server_headers = headers.getheaders(self.auth_required_header)
1300
        if not server_headers:
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1301
            # The http error MUST have the associated
1302
            # header. This must never happen in production code.
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1303
            raise KeyError('%s not found' % self.auth_required_header)
1304
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1305
        auth = self.get_auth(request)
1306
        auth['modified'] = False
4795.4.5 by Vincent Ladeuil
Make sure all redirection code paths can handle authentication.
1307
        # Put some common info in auth if the caller didn't
1308
        if auth.get('path', None) is None:
6055.2.7 by Jelmer Vernooij
Change parse_url to URL.from_string.
1309
            parsed_url = urlutils.URL.from_string(request.get_full_url())
6055.2.1 by Jelmer Vernooij
Add UnparsedUrl.
1310
            self.update_auth(auth, 'protocol', parsed_url.scheme)
1311
            self.update_auth(auth, 'host', parsed_url.host)
1312
            self.update_auth(auth, 'port', parsed_url.port)
1313
            self.update_auth(auth, 'path', parsed_url.path)
4307.4.2 by Vincent Ladeuil
Handle servers proposing several authentication schemes.
1314
        # FIXME: the auth handler should be selected at a single place instead
4307.4.3 by Vincent Ladeuil
Tighten multiple auth schemes handling.
1315
        # of letting all handlers try to match all headers, but the current
1316
        # design doesn't allow a simple implementation.
4307.4.2 by Vincent Ladeuil
Handle servers proposing several authentication schemes.
1317
        for server_header in server_headers:
1318
            # Several schemes can be proposed by the server, try to match each
1319
            # one in turn
1320
            matching_handler = self.auth_match(server_header, auth)
1321
            if matching_handler:
1322
                # auth_match may have modified auth (by adding the
1323
                # password or changing the realm, for example)
1324
                if (request.get_header(self.auth_header, None) is not None
1325
                    and not auth['modified']):
1326
                    # We already tried that, give up
1327
                    return None
1328
4307.4.3 by Vincent Ladeuil
Tighten multiple auth schemes handling.
1329
                # Only the most secure scheme proposed by the server should be
1330
                # used, since the handlers use 'handler_order' to describe that
1331
                # property, the first handler tried takes precedence, the
1332
                # others should not attempt to authenticate if the best one
1333
                # failed.
1334
                best_scheme = auth.get('best_scheme', None)
1335
                if best_scheme is None:
1336
                    # At that point, if current handler should doesn't succeed
1337
                    # the credentials are wrong (or incomplete), but we know
1338
                    # that the associated scheme should be used.
1339
                    best_scheme = auth['best_scheme'] = self.scheme
1340
                if  best_scheme != self.scheme:
1341
                    continue
1342
4307.4.2 by Vincent Ladeuil
Handle servers proposing several authentication schemes.
1343
                if self.requires_username and auth.get('user', None) is None:
1344
                    # Without a known user, we can't authenticate
1345
                    return None
1346
1347
                # Housekeeping
1348
                request.connection.cleanup_pipe()
1349
                # Retry the request with an authentication header added
1350
                response = self.parent.open(request)
1351
                if response:
1352
                    self.auth_successful(request, response)
1353
                return response
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1354
        # We are not qualified to handle the authentication.
1355
        # Note: the authentication error handling will try all
1356
        # available handlers. If one of them authenticates
1357
        # successfully, a response will be returned. If none of
1358
        # them succeeds, None will be returned and the error
1359
        # handler will raise the 401 'Unauthorized' or the 407
1360
        # 'Proxy Authentication Required' error.
1361
        return None
1362
1363
    def add_auth_header(self, request, header):
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1364
        """Add the authentication header to the request"""
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1365
        request.add_unredirected_header(self.auth_header, header)
1366
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1367
    def auth_match(self, header, auth):
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1368
        """Check that we are able to handle that authentication scheme.
1369
1370
        The request authentication parameters may need to be
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1371
        updated with info from the server. Some of these
1372
        parameters, when combined, are considered to be the
1373
        authentication key, if one of them change the
1374
        authentication result may change. 'user' and 'password'
1375
        are exampls, but some auth schemes may have others
1376
        (digest's nonce is an example, digest's nonce_count is a
1377
        *counter-example*). Such parameters must be updated by
1378
        using the update_auth() method.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1379
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1380
        :param header: The authentication header sent by the server.
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1381
        :param auth: The auth parameters already known. They may be
1382
             updated.
1383
        :returns: True if we can try to handle the authentication.
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1384
        """
1385
        raise NotImplementedError(self.auth_match)
1386
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1387
    def build_auth_header(self, auth, request):
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1388
        """Build the value of the header used to authenticate.
1389
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1390
        :param auth: The auth parameters needed to build the header.
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1391
        :param request: The request needing authentication.
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1392
1393
        :return: None or header.
1394
        """
1395
        raise NotImplementedError(self.build_auth_header)
1396
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1397
    def auth_successful(self, request, response):
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1398
        """The authentification was successful for the request.
1399
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1400
        Additional infos may be available in the response.
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1401
1402
        :param request: The succesfully authenticated request.
2420.1.9 by Vincent Ladeuil
Refactor proxy and auth test classes. Tests failing for digest auth.
1403
        :param response: The server response (may contain auth info).
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1404
        """
2540.2.2 by Vincent Ladeuil
Fix #120678 by issuing a CONNECT request when https is used via a proxy.
1405
        # It may happen that we need to reconnect later, let's be ready
1406
        self._retry_count = None
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1407
2900.2.20 by Vincent Ladeuil
http can query AuthenticationConfig for logins too.
1408
    def get_user_password(self, auth):
3910.2.3 by Ben Jansen
Made tweaks requested by John Arbash Meinel.
1409
        """Ask user for a password if none is already available.
1410
3910.2.4 by Vincent Ladeuil
Fixed as per John's review.
1411
        :param auth: authentication info gathered so far (from the initial url
1412
            and then during dialog with the server).
3910.2.3 by Ben Jansen
Made tweaks requested by John Arbash Meinel.
1413
        """
2900.2.20 by Vincent Ladeuil
http can query AuthenticationConfig for logins too.
1414
        auth_conf = config.AuthenticationConfig()
4795.4.4 by Vincent Ladeuil
Protect more access to 'user' and 'password' auth attributes.
1415
        user = auth.get('user', None)
1416
        password = auth.get('password', None)
2900.2.20 by Vincent Ladeuil
http can query AuthenticationConfig for logins too.
1417
        realm = auth['realm']
5484.2.2 by Martin Pool
Cope gracefully if urllib2 doesn't tell us the port number in the authentication callback
1418
        port = auth.get('port', None)
2900.2.20 by Vincent Ladeuil
http can query AuthenticationConfig for logins too.
1419
1420
        if user is None:
3910.2.1 by Ben Jansen
Changed HTTP transport auth so that URLs no longer need to include the username for HTTP Auth to work. Now, if bzr gets a 401 HTTP response, it looks in the authentication config for an appropriate username and password. If it doesn't find a username, it defaults to the local user. If it doesn't find a password, it prompts.
1421
            user = auth_conf.get_user(auth['protocol'], auth['host'],
5484.2.2 by Martin Pool
Cope gracefully if urllib2 doesn't tell us the port number in the authentication callback
1422
                                      port=port, path=auth['path'],
4222.3.12 by Jelmer Vernooij
Check that the HTTP transport prompts for usernames.
1423
                                      realm=realm, ask=True,
1424
                                      prompt=self.build_username_prompt(auth))
3910.2.2 by Vincent Ladeuil
Fix bug #300347 by allowing querying authentication.conf if no
1425
        if user is not None and password is None:
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1426
            password = auth_conf.get_password(
5484.2.2 by Martin Pool
Cope gracefully if urllib2 doesn't tell us the port number in the authentication callback
1427
                auth['protocol'], auth['host'], user,
1428
                port=port,
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1429
                path=auth['path'], realm=realm,
2900.2.19 by Vincent Ladeuil
Mention proxy and https in the password prompts, with tests.
1430
                prompt=self.build_password_prompt(auth))
2900.2.20 by Vincent Ladeuil
http can query AuthenticationConfig for logins too.
1431
1432
        return user, password
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1433
2900.2.19 by Vincent Ladeuil
Mention proxy and https in the password prompts, with tests.
1434
    def _build_password_prompt(self, auth):
1435
        """Build a prompt taking the protocol used into account.
1436
1437
        The AuthHandler is used by http and https, we want that information in
1438
        the prompt, so we build the prompt from the authentication dict which
1439
        contains all the needed parts.
1440
3133.1.3 by Vincent Ladeuil
Fix typo (hi John ;).
1441
        Also, http and proxy AuthHandlers present different prompts to the
3133.1.2 by Vincent Ladeuil
Fix #177643 by making pycurl handle url-embedded credentials again.
1442
        user. The daughter classes should implements a public
2900.2.19 by Vincent Ladeuil
Mention proxy and https in the password prompts, with tests.
1443
        build_password_prompt using this method.
1444
        """
5923.1.2 by Vincent Ladeuil
Fix some more prompts to be unicode.
1445
        prompt = u'%s' % auth['protocol'].upper() + u' %(user)s@%(host)s'
2900.2.19 by Vincent Ladeuil
Mention proxy and https in the password prompts, with tests.
1446
        realm = auth['realm']
1447
        if realm is not None:
5923.1.2 by Vincent Ladeuil
Fix some more prompts to be unicode.
1448
            prompt += u", Realm: '%s'" % realm.decode('utf8')
1449
        prompt += u' password'
2900.2.19 by Vincent Ladeuil
Mention proxy and https in the password prompts, with tests.
1450
        return prompt
1451
4222.3.12 by Jelmer Vernooij
Check that the HTTP transport prompts for usernames.
1452
    def _build_username_prompt(self, auth):
1453
        """Build a prompt taking the protocol used into account.
1454
1455
        The AuthHandler is used by http and https, we want that information in
1456
        the prompt, so we build the prompt from the authentication dict which
1457
        contains all the needed parts.
1458
1459
        Also, http and proxy AuthHandlers present different prompts to the
1460
        user. The daughter classes should implements a public
1461
        build_username_prompt using this method.
1462
        """
5923.1.2 by Vincent Ladeuil
Fix some more prompts to be unicode.
1463
        prompt = u'%s' % auth['protocol'].upper() + u' %(host)s'
4222.3.12 by Jelmer Vernooij
Check that the HTTP transport prompts for usernames.
1464
        realm = auth['realm']
1465
        if realm is not None:
5923.1.2 by Vincent Ladeuil
Fix some more prompts to be unicode.
1466
            prompt += u", Realm: '%s'" % realm.decode('utf8')
1467
        prompt += u' username'
4222.3.12 by Jelmer Vernooij
Check that the HTTP transport prompts for usernames.
1468
        return prompt
1469
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1470
    def http_request(self, request):
1471
        """Insert an authentication header if information is available"""
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1472
        auth = self.get_auth(request)
1473
        if self.auth_params_reusable(auth):
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1474
            self.add_auth_header(request, self.build_auth_header(auth, request))
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1475
        return request
1476
1477
    https_request = http_request # FIXME: Need test
1478
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1479
1480
class NegotiateAuthHandler(AbstractAuthHandler):
1481
    """A authentication handler that handles WWW-Authenticate: Negotiate.
1482
4032.1.4 by John Arbash Meinel
Found 2 more files with trailing whitespace.
1483
    At the moment this handler supports just Kerberos. In the future,
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1484
    NTLM support may also be added.
1485
    """
1486
4307.4.3 by Vincent Ladeuil
Tighten multiple auth schemes handling.
1487
    scheme = 'negotiate'
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1488
    handler_order = 480
4017.5.1 by Jelmer Vernooij
Allow HTTP authentication handlers (such as the NegotiateAuthHandler) to
1489
    requires_username = False
1490
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1491
    def auth_match(self, header, auth):
4050.2.2 by Vincent Ladeuil
Ensures all auth handlers correctly parse all auth headers.
1492
        scheme, raw_auth = self._parse_auth_header(header)
4307.4.3 by Vincent Ladeuil
Tighten multiple auth schemes handling.
1493
        if scheme != self.scheme:
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1494
            return False
1495
        self.update_auth(auth, 'scheme', scheme)
4011.3.2 by Jelmer Vernooij
Only attempt GSSAPI authentication when the kerberos module is present.
1496
        resp = self._auth_match_kerberos(auth)
1497
        if resp is None:
1498
            return False
1499
        # Optionally should try to authenticate using NTLM here
1500
        self.update_auth(auth, 'negotiate_response', resp)
1501
        return True
1502
1503
    def _auth_match_kerberos(self, auth):
1504
        """Try to create a GSSAPI response for authenticating against a host."""
6238.1.2 by John Arbash Meinel, Jelmer Vernooij
Only attempt to import kerberos module once.
1505
        global kerberos, checked_kerberos
1506
        if kerberos is None and not checked_kerberos:
1507
            try:
1508
                import kerberos
1509
            except ImportError:
1510
                kerberos = None
1511
            checked_kerberos = True
1512
        if kerberos is None:
4011.3.2 by Jelmer Vernooij
Only attempt GSSAPI authentication when the kerberos module is present.
1513
            return None
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1514
        ret, vc = kerberos.authGSSClientInit("HTTP@%(host)s" % auth)
1515
        if ret < 1:
4011.3.5 by Jelmer Vernooij
Move import next to other system libs, fix format.
1516
            trace.warning('Unable to create GSSAPI context for %s: %d',
1517
                auth['host'], ret)
4011.3.2 by Jelmer Vernooij
Only attempt GSSAPI authentication when the kerberos module is present.
1518
            return None
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1519
        ret = kerberos.authGSSClientStep(vc, "")
1520
        if ret < 0:
1521
            trace.mutter('authGSSClientStep failed: %d', ret)
4011.3.2 by Jelmer Vernooij
Only attempt GSSAPI authentication when the kerberos module is present.
1522
            return None
1523
        return kerberos.authGSSClientResponse(vc)
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1524
1525
    def build_auth_header(self, auth, request):
4011.3.2 by Jelmer Vernooij
Only attempt GSSAPI authentication when the kerberos module is present.
1526
        return "Negotiate %s" % auth['negotiate_response']
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1527
1528
    def auth_params_reusable(self, auth):
1529
        # If the auth scheme is known, it means a previous
1530
        # authentication was successful, all information is
1531
        # available, no further checks are needed.
4032.1.4 by John Arbash Meinel
Found 2 more files with trailing whitespace.
1532
        return (auth.get('scheme', None) == 'negotiate' and
4011.3.4 by Jelmer Vernooij
review from vila: mention HTTPS, clarify error a bit, move import to top-level.
1533
                auth.get('negotiate_response', None) is not None)
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1534
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1535
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1536
class BasicAuthHandler(AbstractAuthHandler):
1537
    """A custom basic authentication handler."""
1538
4307.4.3 by Vincent Ladeuil
Tighten multiple auth schemes handling.
1539
    scheme = 'basic'
2545.2.1 by Vincent Ladeuil
Fix 121889 by working around urllib2 bug.
1540
    handler_order = 500
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1541
    auth_regexp = re.compile('realm="([^"]*)"', re.I)
1542
1543
    def build_auth_header(self, auth, request):
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1544
        raw = '%s:%s' % (auth['user'], auth['password'])
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1545
        auth_header = 'Basic ' + raw.encode('base64').strip()
1546
        return auth_header
1547
4284.1.1 by Vincent Ladeuil
Fix wrong realm extraction in http basic authentication (reported
1548
    def extract_realm(self, header_value):
1549
        match = self.auth_regexp.search(header_value)
1550
        realm = None
1551
        if match:
1552
            realm = match.group(1)
1553
        return match, realm
1554
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1555
    def auth_match(self, header, auth):
4050.2.2 by Vincent Ladeuil
Ensures all auth handlers correctly parse all auth headers.
1556
        scheme, raw_auth = self._parse_auth_header(header)
4307.4.3 by Vincent Ladeuil
Tighten multiple auth schemes handling.
1557
        if scheme != self.scheme:
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1558
            return False
1559
4284.1.1 by Vincent Ladeuil
Fix wrong realm extraction in http basic authentication (reported
1560
        match, realm = self.extract_realm(raw_auth)
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1561
        if match:
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1562
            # Put useful info into auth
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1563
            self.update_auth(auth, 'scheme', scheme)
1564
            self.update_auth(auth, 'realm', realm)
4795.4.3 by Vincent Ladeuil
Protect access to 'user' and 'password' auth attributes.
1565
            if (auth.get('user', None) is None
1566
                or auth.get('password', None) is None):
2900.2.20 by Vincent Ladeuil
http can query AuthenticationConfig for logins too.
1567
                user, password = self.get_user_password(auth)
1568
                self.update_auth(auth, 'user', user)
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1569
                self.update_auth(auth, 'password', password)
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1570
        return match is not None
1571
1572
    def auth_params_reusable(self, auth):
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1573
        # If the auth scheme is known, it means a previous
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1574
        # authentication was successful, all information is
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1575
        # available, no further checks are needed.
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1576
        return auth.get('scheme', None) == 'basic'
1577
1578
1579
def get_digest_algorithm_impls(algorithm):
1580
    H = None
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1581
    KD = None
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1582
    if algorithm == 'MD5':
2929.3.1 by Vincent Ladeuil
Fix python2.6 deprecation warnings (still 4 failures 5 errors in test suite).
1583
        H = lambda x: osutils.md5(x).hexdigest()
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1584
    elif algorithm == 'SHA':
5849.1.3 by Jelmer Vernooij
Simplify call to sha_string.
1585
        H = osutils.sha_string
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1586
    if H is not None:
1587
        KD = lambda secret, data: H("%s:%s" % (secret, data))
1588
    return H, KD
1589
1590
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1591
def get_new_cnonce(nonce, nonce_count):
1592
    raw = '%s:%d:%s:%s' % (nonce, nonce_count, time.ctime(),
1593
                           urllib2.randombytes(8))
5849.1.1 by Jelmer Vernooij
Use osutils.sha_string() when possible.
1594
    return osutils.sha_string(raw)[:16]
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1595
1596
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1597
class DigestAuthHandler(AbstractAuthHandler):
1598
    """A custom digest authentication handler."""
1599
4307.4.3 by Vincent Ladeuil
Tighten multiple auth schemes handling.
1600
    scheme = 'digest'
4050.2.3 by Vincent Ladeuil
Slight cosmetic tweaks.
1601
    # Before basic as digest is a bit more secure and should be preferred
2545.2.1 by Vincent Ladeuil
Fix 121889 by working around urllib2 bug.
1602
    handler_order = 490
1603
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1604
    def auth_params_reusable(self, auth):
1605
        # If the auth scheme is known, it means a previous
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1606
        # authentication was successful, all information is
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1607
        # available, no further checks are needed.
1608
        return auth.get('scheme', None) == 'digest'
1609
1610
    def auth_match(self, header, auth):
4050.2.2 by Vincent Ladeuil
Ensures all auth handlers correctly parse all auth headers.
1611
        scheme, raw_auth = self._parse_auth_header(header)
4307.4.3 by Vincent Ladeuil
Tighten multiple auth schemes handling.
1612
        if scheme != self.scheme:
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1613
            return False
1614
1615
        # Put the requested authentication info into a dict
1616
        req_auth = urllib2.parse_keqv_list(urllib2.parse_http_list(raw_auth))
1617
1618
        # Check that we can handle that authentication
1619
        qop = req_auth.get('qop', None)
1620
        if qop != 'auth': # No auth-int so far
1621
            return False
1622
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1623
        H, KD = get_digest_algorithm_impls(req_auth.get('algorithm', 'MD5'))
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1624
        if H is None:
1625
            return False
1626
1627
        realm = req_auth.get('realm', None)
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1628
        # Put useful info into auth
1629
        self.update_auth(auth, 'scheme', scheme)
1630
        self.update_auth(auth, 'realm', realm)
4795.4.3 by Vincent Ladeuil
Protect access to 'user' and 'password' auth attributes.
1631
        if auth.get('user', None) is None or auth.get('password', None) is None:
2900.2.20 by Vincent Ladeuil
http can query AuthenticationConfig for logins too.
1632
            user, password = self.get_user_password(auth)
1633
            self.update_auth(auth, 'user', user)
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1634
            self.update_auth(auth, 'password', password)
1635
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1636
        try:
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1637
            if req_auth.get('algorithm', None) is not None:
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1638
                self.update_auth(auth, 'algorithm', req_auth.get('algorithm'))
1639
            nonce = req_auth['nonce']
1640
            if auth.get('nonce', None) != nonce:
1641
                # A new nonce, never used
1642
                self.update_auth(auth, 'nonce_count', 0)
1643
            self.update_auth(auth, 'nonce', nonce)
1644
            self.update_auth(auth, 'qop', qop)
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1645
            auth['opaque'] = req_auth.get('opaque', None)
1646
        except KeyError:
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1647
            # Some required field is not there
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1648
            return False
1649
1650
        return True
1651
1652
    def build_auth_header(self, auth, request):
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1653
        url_scheme, url_selector = urllib.splittype(request.get_selector())
1654
        sel_host, uri = urllib.splithost(url_selector)
1655
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1656
        A1 = '%s:%s:%s' % (auth['user'], auth['realm'], auth['password'])
1657
        A2 = '%s:%s' % (request.get_method(), uri)
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1658
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1659
        nonce = auth['nonce']
1660
        qop = auth['qop']
1661
2420.1.16 by Vincent Ladeuil
Handle nonce changes. Fix a nasty bug breaking the auth parameters sharing.
1662
        nonce_count = auth['nonce_count'] + 1
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1663
        ncvalue = '%08x' % nonce_count
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1664
        cnonce = get_new_cnonce(nonce, nonce_count)
1665
1666
        H, KD = get_digest_algorithm_impls(auth.get('algorithm', 'MD5'))
1667
        nonce_data = '%s:%s:%s:%s:%s' % (nonce, ncvalue, cnonce, qop, H(A2))
1668
        request_digest = KD(H(A1), nonce_data)
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1669
1670
        header = 'Digest '
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1671
        header += 'username="%s", realm="%s", nonce="%s"' % (auth['user'],
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1672
                                                             auth['realm'],
1673
                                                             nonce)
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1674
        header += ', uri="%s"' % uri
1675
        header += ', cnonce="%s", nc=%s' % (cnonce, ncvalue)
1676
        header += ', qop="%s"' % qop
1677
        header += ', response="%s"' % request_digest
1678
        # Append the optional fields
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1679
        opaque = auth.get('opaque', None)
1680
        if opaque:
1681
            header += ', opaque="%s"' % opaque
2420.1.14 by Vincent Ladeuil
Tested against squid-2.6.5 with digest authentication.
1682
        if auth.get('algorithm', None):
1683
            header += ', algorithm="%s"' % auth.get('algorithm')
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1684
1685
        # We have used the nonce once more, update the count
1686
        auth['nonce_count'] = nonce_count
1687
1688
        return header
1689
1690
1691
class HTTPAuthHandler(AbstractAuthHandler):
1692
    """Custom http authentication handler.
2004.3.1 by vila
Test ConnectionError exceptions.
1693
2363.4.12 by Vincent Ladeuil
Take jam's review comments into account. Fix typos, give better
1694
    Send the authentication preventively to avoid the roundtrip
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1695
    associated with the 401 error and keep the revelant info in
1696
    the auth request attribute.
2004.3.1 by vila
Test ConnectionError exceptions.
1697
    """
1698
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1699
    auth_required_header = 'www-authenticate'
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1700
    auth_header = 'Authorization'
1701
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1702
    def get_auth(self, request):
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1703
        """Get the auth params from the request"""
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1704
        return request.auth
1705
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1706
    def set_auth(self, request, auth):
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1707
        """Set the auth params for the request"""
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1708
        request.auth = auth
2004.3.1 by vila
Test ConnectionError exceptions.
1709
2900.2.19 by Vincent Ladeuil
Mention proxy and https in the password prompts, with tests.
1710
    def build_password_prompt(self, auth):
1711
        return self._build_password_prompt(auth)
1712
4222.3.12 by Jelmer Vernooij
Check that the HTTP transport prompts for usernames.
1713
    def build_username_prompt(self, auth):
1714
        return self._build_username_prompt(auth)
1715
2363.4.9 by Vincent Ladeuil
Catch first succesful authentification to avoid further 401
1716
    def http_error_401(self, req, fp, code, msg, headers):
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1717
        return self.auth_required(req, headers)
1718
1719
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1720
class ProxyAuthHandler(AbstractAuthHandler):
1721
    """Custom proxy authentication handler.
2420.1.3 by Vincent Ladeuil
Implement http proxy basic authentication.
1722
1723
    Send the authentication preventively to avoid the roundtrip
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1724
    associated with the 407 error and keep the revelant info in
1725
    the proxy_auth request attribute..
2420.1.3 by Vincent Ladeuil
Implement http proxy basic authentication.
1726
    """
1727
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1728
    auth_required_header = 'proxy-authenticate'
2420.1.7 by Vincent Ladeuil
Tested against squid-2.6.5 with basic authentication.
1729
    # FIXME: the correct capitalization is Proxy-Authorization,
2420.1.8 by Vincent Ladeuil
Interesting typo :-) A mix between capitalize, title and fuzzy may be...
1730
    # but python-2.4 urllib2.Request insist on using capitalize()
2420.1.7 by Vincent Ladeuil
Tested against squid-2.6.5 with basic authentication.
1731
    # instead of title().
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1732
    auth_header = 'Proxy-authorization'
1733
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1734
    def get_auth(self, request):
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1735
        """Get the auth params from the request"""
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1736
        return request.proxy_auth
1737
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1738
    def set_auth(self, request, auth):
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1739
        """Set the auth params for the request"""
2420.1.6 by Vincent Ladeuil
Update NEWS to explain the intent of the modification. Also, use dicts
1740
        request.proxy_auth = auth
2420.1.3 by Vincent Ladeuil
Implement http proxy basic authentication.
1741
2900.2.19 by Vincent Ladeuil
Mention proxy and https in the password prompts, with tests.
1742
    def build_password_prompt(self, auth):
1743
        prompt = self._build_password_prompt(auth)
5923.1.2 by Vincent Ladeuil
Fix some more prompts to be unicode.
1744
        prompt = u'Proxy ' + prompt
2900.2.19 by Vincent Ladeuil
Mention proxy and https in the password prompts, with tests.
1745
        return prompt
1746
4222.3.12 by Jelmer Vernooij
Check that the HTTP transport prompts for usernames.
1747
    def build_username_prompt(self, auth):
1748
        prompt = self._build_username_prompt(auth)
5923.1.2 by Vincent Ladeuil
Fix some more prompts to be unicode.
1749
        prompt = u'Proxy ' + prompt
4222.3.12 by Jelmer Vernooij
Check that the HTTP transport prompts for usernames.
1750
        return prompt
1751
2420.1.3 by Vincent Ladeuil
Implement http proxy basic authentication.
1752
    def http_error_407(self, req, fp, code, msg, headers):
2420.1.5 by Vincent Ladeuil
Refactor http and proxy authentication. Tests passing. proxy password can be prompted too.
1753
        return self.auth_required(req, headers)
2420.1.3 by Vincent Ladeuil
Implement http proxy basic authentication.
1754
1755
2420.1.11 by Vincent Ladeuil
Implement digest authentication. Test suite passes. Tested against apache-2.x.
1756
class HTTPBasicAuthHandler(BasicAuthHandler, HTTPAuthHandler):
1757
    """Custom http basic authentication handler"""
1758
1759
1760
class ProxyBasicAuthHandler(BasicAuthHandler, ProxyAuthHandler):
1761
    """Custom proxy basic authentication handler"""
1762
1763
1764
class HTTPDigestAuthHandler(DigestAuthHandler, HTTPAuthHandler):
1765
    """Custom http basic authentication handler"""
1766
1767
1768
class ProxyDigestAuthHandler(DigestAuthHandler, ProxyAuthHandler):
1769
    """Custom proxy basic authentication handler"""
1770
2420.1.3 by Vincent Ladeuil
Implement http proxy basic authentication.
1771
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1772
class HTTPNegotiateAuthHandler(NegotiateAuthHandler, HTTPAuthHandler):
1773
    """Custom http negotiate authentication handler"""
1774
1775
1776
class ProxyNegotiateAuthHandler(NegotiateAuthHandler, ProxyAuthHandler):
1777
    """Custom proxy negotiate authentication handler"""
1778
1779
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1780
class HTTPErrorProcessor(urllib2.HTTPErrorProcessor):
1781
    """Process HTTP error responses.
1782
1783
    We don't really process the errors, quite the contrary
1784
    instead, we leave our Transport handle them.
1785
    """
1786
2520.2.2 by Vincent Ladeuil
Fix #115209 by issuing a single range request on 400: Bad Request
1787
    accepted_errors = [200, # Ok
1788
                       206, # Partial content
1789
                       404, # Not found
1790
                       ]
1791
    """The error codes the caller will handle.
1792
1793
    This can be specialized in the request on a case-by case basis, but the
1794
    common cases are covered here.
1795
    """
1796
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1797
    def http_response(self, request, response):
1798
        code, msg, hdrs = response.code, response.msg, response.info()
1799
2520.2.2 by Vincent Ladeuil
Fix #115209 by issuing a single range request on 400: Bad Request
1800
        accepted_errors = request.accepted_errors
1801
        if accepted_errors is None:
1802
            accepted_errors = self.accepted_errors
1803
1804
        if code not in accepted_errors:
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1805
            response = self.parent.error('http', request, response,
1806
                                         code, msg, hdrs)
1807
        return response
1808
1809
    https_response = http_response
1810
1811
1812
class HTTPDefaultErrorHandler(urllib2.HTTPDefaultErrorHandler):
1813
    """Translate common errors into bzr Exceptions"""
2004.2.1 by John Arbash Meinel
Cleanup of urllib functions
1814
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1815
    def http_error_default(self, req, fp, code, msg, hdrs):
2520.2.2 by Vincent Ladeuil
Fix #115209 by issuing a single range request on 400: Bad Request
1816
        if code == 403:
3430.3.1 by Vincent Ladeuil
Fix #230223 by making both http implementations raise appropriate exceptions.
1817
            raise errors.TransportError(
1818
                'Server refuses to fulfill the request (403 Forbidden)'
1819
                ' for %s' % req.get_full_url())
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1820
        else:
2004.1.27 by v.ladeuil+lp at free
Fix bug #57644 by issuing an explicit error message.
1821
            raise errors.InvalidHttpResponse(req.get_full_url(),
1822
                                             'Unable to handle http code %d: %s'
1823
                                             % (code, msg))
2004.2.1 by John Arbash Meinel
Cleanup of urllib functions
1824
2520.2.2 by Vincent Ladeuil
Fix #115209 by issuing a single range request on 400: Bad Request
1825
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1826
class Opener(object):
1827
    """A wrapper around urllib2.build_opener
1828
1829
    Daughter classes can override to build their own specific opener
1830
    """
2145.1.1 by mbp at sourcefrog
merge urllib keepalive etc
1831
    # TODO: Provides hooks for daughter classes.
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1832
2004.2.1 by John Arbash Meinel
Cleanup of urllib functions
1833
    def __init__(self,
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1834
                 connection=ConnectionHandler,
1835
                 redirect=HTTPRedirectHandler,
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
1836
                 error=HTTPErrorProcessor,
6238.2.22 by Vincent Ladeuil
Create a specific test permutation for urllib https so we can inject our test ca certs. The wiring in _urllib2_wrappers is a bit hackish and it will need to use auth instead so different certs can be used for proxies and real servers but this could wait until authentication.conf is migrated to the config stacks. With this change in place, all https tests pass without the need to create a dedicated GlobalStore.
1837
                 report_activity=None,
1838
                 ca_certs=None):
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
1839
        self._opener = urllib2.build_opener(
6238.2.22 by Vincent Ladeuil
Create a specific test permutation for urllib https so we can inject our test ca certs. The wiring in _urllib2_wrappers is a bit hackish and it will need to use auth instead so different certs can be used for proxies and real servers but this could wait until authentication.conf is migrated to the config stacks. With this change in place, all https tests pass without the need to create a dedicated GlobalStore.
1840
            connection(report_activity=report_activity, ca_certs=ca_certs),
3945.1.5 by Vincent Ladeuil
Start implementing http activity reporting at socket level.
1841
            redirect, error,
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1842
            ProxyHandler(),
1843
            HTTPBasicAuthHandler(),
1844
            HTTPDigestAuthHandler(),
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1845
            HTTPNegotiateAuthHandler(),
2900.2.16 by Vincent Ladeuil
Make hhtp proxy aware of AuthenticationConfig (for password).
1846
            ProxyBasicAuthHandler(),
1847
            ProxyDigestAuthHandler(),
4011.3.1 by Jelmer Vernooij
Add simple support for GSSAPI authentication over HTTP.
1848
            ProxyNegotiateAuthHandler(),
2004.1.2 by vila
Implements a BasicAuthManager.
1849
            HTTPHandler,
1850
            HTTPSHandler,
1851
            HTTPDefaultErrorHandler,
2004.2.1 by John Arbash Meinel
Cleanup of urllib functions
1852
            )
2520.2.2 by Vincent Ladeuil
Fix #115209 by issuing a single range request on 400: Bad Request
1853
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1854
        self.open = self._opener.open
3111.1.20 by Vincent Ladeuil
Make all the test pass. Looks like we are HTTP/1.1 compliant.
1855
        if DEBUG >= 9:
2004.1.9 by vila
Takes jam's remarks into account when possible, add TODOs for the rest.
1856
            # When dealing with handler order, it's easy to mess
1857
            # things up, the following will help understand which
1858
            # handler is used, when and for what.
2004.1.1 by vila
Connection sharing, with redirection. without authentification.
1859
            import pprint
1860
            pprint.pprint(self._opener.__dict__)