Mercurial > public > mercurial-scm > hg
comparison mercurial/sslutil.py @ 29259:ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
_determinecertoptions() and _hostsettings() are redundant with each
other. _hostsettings() is used the flexible API we want.
We start the process of removing _determinecertoptions() by moving
some of the logic for the verify_mode value into _hostsettings().
As part of this, _determinecertoptions() now takes a settings dict
as its argument. This is technically API incompatible. But since
_determinecertoptions() came into existence a few days ago as part
of this release, I'm not flagging it as such.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 28 May 2016 11:41:21 -0700 |
parents | 6315c1e14f75 |
children | 70bc9912d83d |
comparison
equal
deleted
inserted
replaced
29258:6315c1e14f75 | 29259:ec247e8595f9 |
---|---|
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 # List of 2-tuple of (hash algorithm, hash). | 115 # List of 2-tuple of (hash algorithm, hash). |
116 'certfingerprints': [], | 116 'certfingerprints': [], |
117 # ssl.CERT_* constant used by SSLContext.verify_mode. | |
118 'verifymode': None, | |
117 } | 119 } |
118 | 120 |
119 # Fingerprints from [hostfingerprints] are always SHA-1. | 121 # Fingerprints from [hostfingerprints] are always SHA-1. |
120 for fingerprint in ui.configlist('hostfingerprints', hostname, []): | 122 for fingerprint in ui.configlist('hostfingerprints', hostname, []): |
121 fingerprint = fingerprint.replace(':', '').lower() | 123 fingerprint = fingerprint.replace(':', '').lower() |
122 s['certfingerprints'].append(('sha1', fingerprint)) | 124 s['certfingerprints'].append(('sha1', fingerprint)) |
123 | 125 |
126 # If a host cert fingerprint is defined, it is the only thing that | |
127 # matters. No need to validate CA certs. | |
128 if s['certfingerprints']: | |
129 s['verifymode'] = ssl.CERT_NONE | |
130 | |
131 # If --insecure is used, don't take CAs into consideration. | |
132 elif ui.insecureconnections: | |
133 s['verifymode'] = ssl.CERT_NONE | |
134 | |
135 # TODO assert verifymode is not None once we integrate cacert | |
136 # checking in this function. | |
137 | |
124 return s | 138 return s |
125 | 139 |
126 def _determinecertoptions(ui, host): | 140 def _determinecertoptions(ui, settings): |
127 """Determine certificate options for a connections. | 141 """Determine certificate options for a connections. |
128 | 142 |
129 Returns a tuple of (cert_reqs, ca_certs). | 143 Returns a tuple of (cert_reqs, ca_certs). |
130 """ | 144 """ |
131 # If a host key fingerprint is on file, it is the only thing that matters | 145 if settings['verifymode'] == ssl.CERT_NONE: |
132 # and CA certs don't come into play. | |
133 hostfingerprint = ui.config('hostfingerprints', host) | |
134 if hostfingerprint: | |
135 return ssl.CERT_NONE, None | |
136 | |
137 # The code below sets up CA verification arguments. If --insecure is | |
138 # used, we don't take CAs into consideration, so return early. | |
139 if ui.insecureconnections: | |
140 return ssl.CERT_NONE, None | 146 return ssl.CERT_NONE, None |
141 | 147 |
142 cacerts = ui.config('web', 'cacerts') | 148 cacerts = ui.config('web', 'cacerts') |
143 | 149 |
144 # If a value is set in the config, validate against a path and load | 150 # If a value is set in the config, validate against a path and load |
179 to use. | 185 to use. |
180 """ | 186 """ |
181 if not serverhostname: | 187 if not serverhostname: |
182 raise error.Abort('serverhostname argument is required') | 188 raise error.Abort('serverhostname argument is required') |
183 | 189 |
184 cert_reqs, ca_certs = _determinecertoptions(ui, serverhostname) | 190 settings = _hostsettings(ui, serverhostname) |
191 cert_reqs, ca_certs = _determinecertoptions(ui, settings) | |
185 | 192 |
186 # Despite its name, PROTOCOL_SSLv23 selects the highest protocol | 193 # Despite its name, PROTOCOL_SSLv23 selects the highest protocol |
187 # that both ends support, including TLS protocols. On legacy stacks, | 194 # that both ends support, including TLS protocols. On legacy stacks, |
188 # the highest it likely goes in TLS 1.0. On modern stacks, it can | 195 # the highest it likely goes in TLS 1.0. On modern stacks, it can |
189 # support TLS 1.2. | 196 # support TLS 1.2. |
232 raise error.Abort(_('ssl connection failed')) | 239 raise error.Abort(_('ssl connection failed')) |
233 | 240 |
234 sslsocket._hgstate = { | 241 sslsocket._hgstate = { |
235 'caloaded': caloaded, | 242 'caloaded': caloaded, |
236 'hostname': serverhostname, | 243 'hostname': serverhostname, |
237 'settings': _hostsettings(ui, serverhostname), | 244 'settings': settings, |
238 'ui': ui, | 245 'ui': ui, |
239 } | 246 } |
240 | 247 |
241 return sslsocket | 248 return sslsocket |
242 | 249 |