comparison mercurial/sslutil.py @ 24291:760a86865f80

ssl: load CA certificates from system's store by default on Python 2.7.9 This will make it easy to manage in-house CA certificates, which are often used in corporate environment and installed into the Windows' certs store. Unlike Apple python, the dummycert trick isn't necessary on Python 2.7.9. The default web.cacerts will be set as follows: environment web.cacerts behavior ------------- ----------- ----------------------------------------- Apple Python dummycert fall back to system's store Python 2.7.8 '!' never use CA certs (show warning instead) Python 2.7.9+ None load CA certs from system's store
author Yuya Nishihara <yuya@tcha.org>
date Thu, 26 Feb 2015 22:54:13 +0900
parents b76d8c641746
children 241d98d84aed
comparison
equal deleted inserted replaced
24290:b76d8c641746 24291:760a86865f80
8 # GNU General Public License version 2 or any later version. 8 # GNU General Public License version 2 or any later version.
9 import os, sys 9 import os, sys
10 10
11 from mercurial import util 11 from mercurial import util
12 from mercurial.i18n import _ 12 from mercurial.i18n import _
13
14 _canloaddefaultcerts = False
13 try: 15 try:
14 # avoid using deprecated/broken FakeSocket in python 2.6 16 # avoid using deprecated/broken FakeSocket in python 2.6
15 import ssl 17 import ssl
16 CERT_REQUIRED = ssl.CERT_REQUIRED 18 CERT_REQUIRED = ssl.CERT_REQUIRED
17 try: 19 try:
18 ssl_context = ssl.SSLContext 20 ssl_context = ssl.SSLContext
21 _canloaddefaultcerts = util.safehasattr(ssl_context,
22 'load_default_certs')
19 23
20 def ssl_wrap_socket(sock, keyfile, certfile, cert_reqs=ssl.CERT_NONE, 24 def ssl_wrap_socket(sock, keyfile, certfile, cert_reqs=ssl.CERT_NONE,
21 ca_certs=None, serverhostname=None): 25 ca_certs=None, serverhostname=None):
22 # Allow any version of SSL starting with TLSv1 and 26 # Allow any version of SSL starting with TLSv1 and
23 # up. Note that specifying TLSv1 here prohibits use of 27 # up. Note that specifying TLSv1 here prohibits use of
33 if certfile is not None: 37 if certfile is not None:
34 sslcontext.load_cert_chain(certfile, keyfile) 38 sslcontext.load_cert_chain(certfile, keyfile)
35 sslcontext.verify_mode = cert_reqs 39 sslcontext.verify_mode = cert_reqs
36 if ca_certs is not None: 40 if ca_certs is not None:
37 sslcontext.load_verify_locations(cafile=ca_certs) 41 sslcontext.load_verify_locations(cafile=ca_certs)
42 elif _canloaddefaultcerts:
43 sslcontext.load_default_certs()
38 44
39 sslsocket = sslcontext.wrap_socket(sock, 45 sslsocket = sslcontext.wrap_socket(sock,
40 server_hostname=serverhostname) 46 server_hostname=serverhostname)
41 # check if wrap_socket failed silently because socket had been 47 # check if wrap_socket failed silently because socket had been
42 # closed 48 # closed
128 exe = (sys.executable or '').lower() 134 exe = (sys.executable or '').lower()
129 return (exe.startswith('/usr/bin/python') or 135 return (exe.startswith('/usr/bin/python') or
130 exe.startswith('/system/library/frameworks/python.framework/')) 136 exe.startswith('/system/library/frameworks/python.framework/'))
131 137
132 def _defaultcacerts(): 138 def _defaultcacerts():
139 """return path to CA certificates; None for system's store; ! to disable"""
133 if _plainapplepython(): 140 if _plainapplepython():
134 dummycert = os.path.join(os.path.dirname(__file__), 'dummycert.pem') 141 dummycert = os.path.join(os.path.dirname(__file__), 'dummycert.pem')
135 if os.path.exists(dummycert): 142 if os.path.exists(dummycert):
136 return dummycert 143 return dummycert
144 if _canloaddefaultcerts:
145 return None
137 return '!' 146 return '!'
138 147
139 def sslkwargs(ui, host): 148 def sslkwargs(ui, host):
140 kws = {} 149 kws = {}
141 hostfingerprint = ui.config('hostfingerprints', host) 150 hostfingerprint = ui.config('hostfingerprints', host)