##// END OF EJS Templates
url: SSL server certificate verification using web.cacerts file (issue1174)
Henrik Stuart -
r10409:4c94a3df default
parent child Browse files
Show More
@@ -873,6 +873,26 b' Web interface configuration.'
873 Base URL to use when publishing URLs in other locations, so
873 Base URL to use when publishing URLs in other locations, so
874 third-party tools like email notification hooks can construct
874 third-party tools like email notification hooks can construct
875 URLs. Example: ``http://hgserver/repos/``.
875 URLs. Example: ``http://hgserver/repos/``.
876 ``cacerts``
877 Path to file containing a list of PEM encoded certificate authorities
878 that may be used to verify an SSL server's identity. The form must be
879 as follows::
880
881 -----BEGIN CERTIFICATE-----
882 ... (certificate in base64 PEM encoding) ...
883 -----END CERTIFICATE-----
884 -----BEGIN CERTIFICATE-----
885 ... (certificate in base64 PEM encoding) ...
886 -----END CERTIFICATE-----
887
888 This feature is only supported when using Python 2.6. If you wish to
889 use it with earlier versions of Python, install the backported
890 version of the ssl library that is available from
891 ``http://pypi.python.org``.
892
893 You can use OpenSSL's CA certificate file if your platform has one.
894 On most Linux systems this will be ``/etc/ssl/certs/ca-certificates.crt``.
895 Otherwise you will have to generate this file manually.
876 ``contact``
896 ``contact``
877 Name or email address of the person in charge of the repository.
897 Name or email address of the person in charge of the repository.
878 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
898 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
@@ -255,11 +255,48 b' if has_https:'
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)
262
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
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)
@@ -427,6 +464,21 b' 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.
@@ -473,7 +525,9 b' if has_https:'
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
General Comments 0
You need to be logged in to leave comments. Login now