comparison mercurial/sslutil.py @ 29288:7dee15dee53c

sslutil: add devel.disableloaddefaultcerts to disable CA loading There are various tests for behavior when CA certs aren't loaded. Previously, we would pass --insecure to disable loading of CA certs. This has worked up to this point because the error message for --insecure and no CAs loaded is the same. Upcoming commits will change the error message for --insecure and will change behavior when CAs aren't loaded. This commit introduces the ability to disable loading of CA certs by setting devel.disableloaddefaultcerts. This allows a testing backdoor to disable loading of CA certs even if system/default CA certs are available. The flag is purposefully not exposed to end-users because there should not be a need for this in the wild: certificate pinning and --insecure provide workarounds to disable cert loading/validation. Tests have been updated to use the new method. The variable used to disable CA certs has been renamed because the method is not OS X specific.
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 01 Jun 2016 19:57:20 -0700
parents fbccb334efe7
children 3536673a25ae
comparison
equal deleted inserted replaced
29287:fbccb334efe7 29288:7dee15dee53c
110 """Obtain security settings for a hostname. 110 """Obtain security settings for a hostname.
111 111
112 Returns a dict of settings relevant to that hostname. 112 Returns a dict of settings relevant to that hostname.
113 """ 113 """
114 s = { 114 s = {
115 # Whether we should attempt to load default/available CA certs
116 # if an explicit ``cafile`` is not defined.
117 'allowloaddefaultcerts': True,
115 # List of 2-tuple of (hash algorithm, hash). 118 # List of 2-tuple of (hash algorithm, hash).
116 'certfingerprints': [], 119 'certfingerprints': [],
117 # Path to file containing concatenated CA certs. Used by 120 # Path to file containing concatenated CA certs. Used by
118 # SSLContext.load_verify_locations(). 121 # SSLContext.load_verify_locations().
119 'cafile': None, 122 'cafile': None,
154 # If --insecure is used, don't take CAs into consideration. 157 # If --insecure is used, don't take CAs into consideration.
155 elif ui.insecureconnections: 158 elif ui.insecureconnections:
156 s['disablecertverification'] = True 159 s['disablecertverification'] = True
157 s['verifymode'] = ssl.CERT_NONE 160 s['verifymode'] = ssl.CERT_NONE
158 161
162 if ui.configbool('devel', 'disableloaddefaultcerts'):
163 s['allowloaddefaultcerts'] = False
164
159 # Try to hook up CA certificate validation unless something above 165 # Try to hook up CA certificate validation unless something above
160 # makes it not necessary. 166 # makes it not necessary.
161 if s['verifymode'] is None: 167 if s['verifymode'] is None:
162 # Find global certificates file in config. 168 # Find global certificates file in config.
163 cafile = ui.config('web', 'cacerts') 169 cafile = ui.config('web', 'cacerts')
174 180
175 s['cafile'] = cafile 181 s['cafile'] = cafile
176 182
177 # Require certificate validation if CA certs are being loaded and 183 # Require certificate validation if CA certs are being loaded and
178 # verification hasn't been disabled above. 184 # verification hasn't been disabled above.
179 if cafile or _canloaddefaultcerts: 185 if cafile or (_canloaddefaultcerts and s['allowloaddefaultcerts']):
180 s['verifymode'] = ssl.CERT_REQUIRED 186 s['verifymode'] = ssl.CERT_REQUIRED
181 else: 187 else:
182 # At this point we don't have a fingerprint, aren't being 188 # At this point we don't have a fingerprint, aren't being
183 # explicitly insecure, and can't load CA certs. Connecting 189 # explicitly insecure, and can't load CA certs. Connecting
184 # at this point is insecure. But we do it for BC reasons. 190 # at this point is insecure. But we do it for BC reasons.
241 sslcontext.load_cert_chain(certfile, keyfile, password) 247 sslcontext.load_cert_chain(certfile, keyfile, password)
242 248
243 if settings['cafile'] is not None: 249 if settings['cafile'] is not None:
244 sslcontext.load_verify_locations(cafile=settings['cafile']) 250 sslcontext.load_verify_locations(cafile=settings['cafile'])
245 caloaded = True 251 caloaded = True
246 else: 252 elif settings['allowloaddefaultcerts']:
247 # This is a no-op on old Python. 253 # This is a no-op on old Python.
248 sslcontext.load_default_certs() 254 sslcontext.load_default_certs()
249 caloaded = _canloaddefaultcerts 255 caloaded = True
256 else:
257 caloaded = False
250 258
251 sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname) 259 sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname)
252 # check if wrap_socket failed silently because socket had been 260 # check if wrap_socket failed silently because socket had been
253 # closed 261 # closed
254 # - see http://bugs.python.org/issue13721 262 # - see http://bugs.python.org/issue13721