Mercurial > hg
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 |