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