Mercurial > hg-stable
comparison mercurial/url.py @ 10409:4c94a3df4b10
url: SSL server certificate verification using web.cacerts file (issue1174)
author | Henrik Stuart <hg@hstuart.dk> |
---|---|
date | Wed, 10 Feb 2010 20:27:46 +0100 |
parents | 50fb1fe143ff |
children | af4c42ec19ed |
comparison
equal
deleted
inserted
replaced
10408:50fb1fe143ff | 10409:4c94a3df4b10 |
---|---|
253 if has_https: | 253 if has_https: |
254 try: | 254 try: |
255 # avoid using deprecated/broken FakeSocket in python 2.6 | 255 # avoid using deprecated/broken FakeSocket in python 2.6 |
256 import ssl | 256 import ssl |
257 _ssl_wrap_socket = ssl.wrap_socket | 257 _ssl_wrap_socket = ssl.wrap_socket |
258 CERT_REQUIRED = ssl.CERT_REQUIRED | |
258 except ImportError: | 259 except ImportError: |
259 def _ssl_wrap_socket(sock, key_file, cert_file): | 260 CERT_REQUIRED = 2 |
261 | |
262 def _ssl_wrap_socket(sock, key_file, cert_file, | |
263 cert_reqs=CERT_REQUIRED, ca_certs=None): | |
264 if ca_certs: | |
265 raise util.Abort(_( | |
266 'certificate checking requires Python 2.6')) | |
267 | |
260 ssl = socket.ssl(sock, key_file, cert_file) | 268 ssl = socket.ssl(sock, key_file, cert_file) |
261 return httplib.FakeSocket(sock, ssl) | 269 return httplib.FakeSocket(sock, ssl) |
270 | |
271 _GLOBAL_DEFAULT_TIMEOUT = object() | |
272 | |
273 try: | |
274 _create_connection = socket.create_connection | |
275 except ImportError: | |
276 def _create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT, | |
277 source_address=None): | |
278 # lifted from Python 2.6 | |
279 | |
280 msg = "getaddrinfo returns an empty list" | |
281 host, port = address | |
282 for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): | |
283 af, socktype, proto, canonname, sa = res | |
284 sock = None | |
285 try: | |
286 sock = socket.socket(af, socktype, proto) | |
287 if timeout is not _GLOBAL_DEFAULT_TIMEOUT: | |
288 sock.settimeout(timeout) | |
289 if source_address: | |
290 sock.bind(source_address) | |
291 sock.connect(sa) | |
292 return sock | |
293 | |
294 except socket.error, msg: | |
295 if sock is not None: | |
296 sock.close() | |
297 | |
298 raise socket.error, msg | |
262 | 299 |
263 class httpconnection(keepalive.HTTPConnection): | 300 class httpconnection(keepalive.HTTPConnection): |
264 # must be able to send big bundle as stream. | 301 # must be able to send big bundle as stream. |
265 send = _gen_sendfile(keepalive.HTTPConnection) | 302 send = _gen_sendfile(keepalive.HTTPConnection) |
266 | 303 |
425 | 462 |
426 if has_https: | 463 if has_https: |
427 class BetterHTTPS(httplib.HTTPSConnection): | 464 class BetterHTTPS(httplib.HTTPSConnection): |
428 send = keepalive.safesend | 465 send = keepalive.safesend |
429 | 466 |
467 def connect(self): | |
468 if hasattr(self, 'ui'): | |
469 cacerts = self.ui.config('web', 'cacerts') | |
470 else: | |
471 cacerts = None | |
472 | |
473 if cacerts: | |
474 sock = _create_connection((self.host, self.port)) | |
475 self.sock = _ssl_wrap_socket(sock, self.key_file, | |
476 self.cert_file, cert_reqs=CERT_REQUIRED, | |
477 ca_certs=cacerts) | |
478 self.ui.debug(_('server identity verification succeeded\n')) | |
479 else: | |
480 httplib.HTTPSConnection.connect(self) | |
481 | |
430 class httpsconnection(BetterHTTPS): | 482 class httpsconnection(BetterHTTPS): |
431 response_class = keepalive.HTTPResponse | 483 response_class = keepalive.HTTPResponse |
432 # must be able to send big bundle as stream. | 484 # must be able to send big bundle as stream. |
433 send = _gen_sendfile(BetterHTTPS) | 485 send = _gen_sendfile(BetterHTTPS) |
434 getresponse = keepalive.wrapgetresponse(httplib.HTTPSConnection) | 486 getresponse = keepalive.wrapgetresponse(httplib.HTTPSConnection) |
471 # hgrc, we prefer these | 523 # hgrc, we prefer these |
472 if self.auth and 'key' in self.auth and 'cert' in self.auth: | 524 if self.auth and 'key' in self.auth and 'cert' in self.auth: |
473 keyfile = self.auth['key'] | 525 keyfile = self.auth['key'] |
474 certfile = self.auth['cert'] | 526 certfile = self.auth['cert'] |
475 | 527 |
476 return httpsconnection(host, port, keyfile, certfile, *args, **kwargs) | 528 conn = httpsconnection(host, port, keyfile, certfile, *args, **kwargs) |
529 conn.ui = self.ui | |
530 return conn | |
477 | 531 |
478 # In python < 2.5 AbstractDigestAuthHandler raises a ValueError if | 532 # In python < 2.5 AbstractDigestAuthHandler raises a ValueError if |
479 # it doesn't know about the auth type requested. This can happen if | 533 # it doesn't know about the auth type requested. This can happen if |
480 # somebody is using BasicAuth and types a bad password. | 534 # somebody is using BasicAuth and types a bad password. |
481 class httpdigestauthhandler(urllib2.HTTPDigestAuthHandler): | 535 class httpdigestauthhandler(urllib2.HTTPDigestAuthHandler): |