Show More
@@ -114,6 +114,9 b' def _hostsettings(ui, hostname):' | |||
|
114 | 114 | s = { |
|
115 | 115 | # List of 2-tuple of (hash algorithm, hash). |
|
116 | 116 | 'certfingerprints': [], |
|
117 | # Path to file containing concatenated CA certs. Used by | |
|
118 | # SSLContext.load_verify_locations(). | |
|
119 | 'cafile': None, | |
|
117 | 120 | # ssl.CERT_* constant used by SSLContext.verify_mode. |
|
118 | 121 | 'verifymode': None, |
|
119 | 122 | } |
@@ -132,45 +135,39 b' def _hostsettings(ui, hostname):' | |||
|
132 | 135 | elif ui.insecureconnections: |
|
133 | 136 | s['verifymode'] = ssl.CERT_NONE |
|
134 | 137 | |
|
135 | # TODO assert verifymode is not None once we integrate cacert | |
|
136 | # checking in this function. | |
|
138 | # Try to hook up CA certificate validation unless something above | |
|
139 | # makes it not necessary. | |
|
140 | if s['verifymode'] is None: | |
|
141 | # Find global certificates file in config. | |
|
142 | cafile = ui.config('web', 'cacerts') | |
|
143 | ||
|
144 | if cafile: | |
|
145 | cafile = util.expandpath(cafile) | |
|
146 | if not os.path.exists(cafile): | |
|
147 | raise error.Abort(_('could not find web.cacerts: %s') % cafile) | |
|
148 | else: | |
|
149 | # No global CA certs. See if we can load defaults. | |
|
150 | cafile = _defaultcacerts() | |
|
151 | if cafile: | |
|
152 | ui.debug('using %s to enable OS X system CA\n' % cafile) | |
|
153 | ||
|
154 | s['cafile'] = cafile | |
|
155 | ||
|
156 | # Require certificate validation if CA certs are being loaded and | |
|
157 | # verification hasn't been disabled above. | |
|
158 | if cafile or _canloaddefaultcerts: | |
|
159 | s['verifymode'] = ssl.CERT_REQUIRED | |
|
160 | else: | |
|
161 | # At this point we don't have a fingerprint, aren't being | |
|
162 | # explicitly insecure, and can't load CA certs. Connecting | |
|
163 | # at this point is insecure. But we do it for BC reasons. | |
|
164 | # TODO abort here to make secure by default. | |
|
165 | s['verifymode'] = ssl.CERT_NONE | |
|
166 | ||
|
167 | assert s['verifymode'] is not None | |
|
137 | 168 | |
|
138 | 169 | return s |
|
139 | 170 | |
|
140 | def _determinecertoptions(ui, settings): | |
|
141 | """Determine certificate options for a connections. | |
|
142 | ||
|
143 | Returns a tuple of (cert_reqs, ca_certs). | |
|
144 | """ | |
|
145 | if settings['verifymode'] == ssl.CERT_NONE: | |
|
146 | return ssl.CERT_NONE, None | |
|
147 | ||
|
148 | cacerts = ui.config('web', 'cacerts') | |
|
149 | ||
|
150 | # If a value is set in the config, validate against a path and load | |
|
151 | # and require those certs. | |
|
152 | if cacerts: | |
|
153 | cacerts = util.expandpath(cacerts) | |
|
154 | if not os.path.exists(cacerts): | |
|
155 | raise error.Abort(_('could not find web.cacerts: %s') % cacerts) | |
|
156 | ||
|
157 | return ssl.CERT_REQUIRED, cacerts | |
|
158 | ||
|
159 | # No CAs in config. See if we can load defaults. | |
|
160 | cacerts = _defaultcacerts() | |
|
161 | ||
|
162 | # We found an alternate CA bundle to use. Load it. | |
|
163 | if cacerts: | |
|
164 | ui.debug('using %s to enable OS X system CA\n' % cacerts) | |
|
165 | ui.setconfig('web', 'cacerts', cacerts, 'defaultcacerts') | |
|
166 | return ssl.CERT_REQUIRED, cacerts | |
|
167 | ||
|
168 | # FUTURE this can disappear once wrapsocket() is secure by default. | |
|
169 | if _canloaddefaultcerts: | |
|
170 | return ssl.CERT_REQUIRED, None | |
|
171 | ||
|
172 | return ssl.CERT_NONE, None | |
|
173 | ||
|
174 | 171 | def wrapsocket(sock, keyfile, certfile, ui, serverhostname=None): |
|
175 | 172 | """Add SSL/TLS to a socket. |
|
176 | 173 | |
@@ -188,7 +185,6 b' def wrapsocket(sock, keyfile, certfile, ' | |||
|
188 | 185 | raise error.Abort('serverhostname argument is required') |
|
189 | 186 | |
|
190 | 187 | settings = _hostsettings(ui, serverhostname) |
|
191 | cert_reqs, ca_certs = _determinecertoptions(ui, settings) | |
|
192 | 188 | |
|
193 | 189 | # Despite its name, PROTOCOL_SSLv23 selects the highest protocol |
|
194 | 190 | # that both ends support, including TLS protocols. On legacy stacks, |
@@ -215,7 +211,7 b' def wrapsocket(sock, keyfile, certfile, ' | |||
|
215 | 211 | sslcontext.options |= OP_NO_SSLv2 | OP_NO_SSLv3 |
|
216 | 212 | |
|
217 | 213 | # This still works on our fake SSLContext. |
|
218 |
sslcontext.verify_mode = |
|
|
214 | sslcontext.verify_mode = settings['verifymode'] | |
|
219 | 215 | |
|
220 | 216 | if certfile is not None: |
|
221 | 217 | def password(): |
@@ -223,8 +219,8 b' def wrapsocket(sock, keyfile, certfile, ' | |||
|
223 | 219 | return ui.getpass(_('passphrase for %s: ') % f, '') |
|
224 | 220 | sslcontext.load_cert_chain(certfile, keyfile, password) |
|
225 | 221 | |
|
226 |
if |
|
|
227 |
sslcontext.load_verify_locations(cafile= |
|
|
222 | if settings['cafile'] is not None: | |
|
223 | sslcontext.load_verify_locations(cafile=settings['cafile']) | |
|
228 | 224 | caloaded = True |
|
229 | 225 | else: |
|
230 | 226 | # This is a no-op on old Python. |
General Comments 0
You need to be logged in to leave comments.
Login now