##// END OF EJS Templates
sslutil: convert socket validation from a class to a function (API)...
Gregory Szorc -
r29227:dffe78d8 default
parent child Browse files
Show More
@@ -284,6 +284,6 b' class http2handler(urlreq.httphandler, u'
284
284
285 con = HTTPConnection(host, port, use_ssl=True,
285 con = HTTPConnection(host, port, use_ssl=True,
286 ssl_wrap_socket=sslutil.wrapsocket,
286 ssl_wrap_socket=sslutil.wrapsocket,
287 ssl_validator=sslutil.validator(self.ui, host),
287 ssl_validator=sslutil.validatesocket,
288 **kwargs)
288 **kwargs)
289 return con
289 return con
@@ -139,7 +139,7 b' def _smtp(ui):'
139 s.ehlo()
139 s.ehlo()
140 if (starttls or smtps) and verifycert:
140 if (starttls or smtps) and verifycert:
141 ui.note(_('(verifying remote certificate)\n'))
141 ui.note(_('(verifying remote certificate)\n'))
142 sslutil.validator(ui, mailhost)(s.sock, verifycert == 'strict')
142 sslutil.validatesocket(s.sock, verifycert == 'strict')
143 username = ui.config('smtp', 'username')
143 username = ui.config('smtp', 'username')
144 password = ui.config('smtp', 'password')
144 password = ui.config('smtp', 'password')
145 if username and not password:
145 if username and not password:
@@ -291,77 +291,77 b' def sslkwargs(ui, host):'
291
291
292 return kws
292 return kws
293
293
294 class validator(object):
294 def validatesocket(sock, strict=False):
295 def __init__(self, ui=None, host=None):
295 """Validate a socket meets security requiremnets.
296 pass
297
296
298 def __call__(self, sock, strict=False):
297 The passed socket must have been created with ``wrapsocket()``.
299 host = sock._hgstate['hostname']
298 """
300 ui = sock._hgstate['ui']
299 host = sock._hgstate['hostname']
300 ui = sock._hgstate['ui']
301
301
302 if not sock.cipher(): # work around http://bugs.python.org/issue13721
302 if not sock.cipher(): # work around http://bugs.python.org/issue13721
303 raise error.Abort(_('%s ssl connection error') % host)
303 raise error.Abort(_('%s ssl connection error') % host)
304 try:
304 try:
305 peercert = sock.getpeercert(True)
305 peercert = sock.getpeercert(True)
306 peercert2 = sock.getpeercert()
306 peercert2 = sock.getpeercert()
307 except AttributeError:
307 except AttributeError:
308 raise error.Abort(_('%s ssl connection error') % host)
308 raise error.Abort(_('%s ssl connection error') % host)
309
309
310 if not peercert:
310 if not peercert:
311 raise error.Abort(_('%s certificate error: '
311 raise error.Abort(_('%s certificate error: '
312 'no certificate received') % host)
312 'no certificate received') % host)
313
313
314 # If a certificate fingerprint is pinned, use it and only it to
314 # If a certificate fingerprint is pinned, use it and only it to
315 # validate the remote cert.
315 # validate the remote cert.
316 hostfingerprints = ui.configlist('hostfingerprints', host)
316 hostfingerprints = ui.configlist('hostfingerprints', host)
317 peerfingerprint = util.sha1(peercert).hexdigest()
317 peerfingerprint = util.sha1(peercert).hexdigest()
318 nicefingerprint = ":".join([peerfingerprint[x:x + 2]
318 nicefingerprint = ":".join([peerfingerprint[x:x + 2]
319 for x in xrange(0, len(peerfingerprint), 2)])
319 for x in xrange(0, len(peerfingerprint), 2)])
320 if hostfingerprints:
320 if hostfingerprints:
321 fingerprintmatch = False
321 fingerprintmatch = False
322 for hostfingerprint in hostfingerprints:
322 for hostfingerprint in hostfingerprints:
323 if peerfingerprint.lower() == \
323 if peerfingerprint.lower() == \
324 hostfingerprint.replace(':', '').lower():
324 hostfingerprint.replace(':', '').lower():
325 fingerprintmatch = True
325 fingerprintmatch = True
326 break
326 break
327 if not fingerprintmatch:
327 if not fingerprintmatch:
328 raise error.Abort(_('certificate for %s has unexpected '
328 raise error.Abort(_('certificate for %s has unexpected '
329 'fingerprint %s') % (host, nicefingerprint),
329 'fingerprint %s') % (host, nicefingerprint),
330 hint=_('check hostfingerprint configuration'))
330 hint=_('check hostfingerprint configuration'))
331 ui.debug('%s certificate matched fingerprint %s\n' %
331 ui.debug('%s certificate matched fingerprint %s\n' %
332 (host, nicefingerprint))
332 (host, nicefingerprint))
333 return
333 return
334
334
335 # If insecure connections were explicitly requested via --insecure,
335 # If insecure connections were explicitly requested via --insecure,
336 # print a warning and do no verification.
336 # print a warning and do no verification.
337 #
337 #
338 # It may seem odd that this is checked *after* host fingerprint pinning.
338 # It may seem odd that this is checked *after* host fingerprint pinning.
339 # This is for backwards compatibility (for now). The message is also
339 # This is for backwards compatibility (for now). The message is also
340 # the same as below for BC.
340 # the same as below for BC.
341 if ui.insecureconnections:
341 if ui.insecureconnections:
342 ui.warn(_('warning: %s certificate with fingerprint %s not '
342 ui.warn(_('warning: %s certificate with fingerprint %s not '
343 'verified (check hostfingerprints or web.cacerts '
343 'verified (check hostfingerprints or web.cacerts '
344 'config setting)\n') %
344 'config setting)\n') %
345 (host, nicefingerprint))
345 (host, nicefingerprint))
346 return
346 return
347
347
348 if not sock._hgstate['caloaded']:
348 if not sock._hgstate['caloaded']:
349 if strict:
349 if strict:
350 raise error.Abort(_('%s certificate with fingerprint %s not '
350 raise error.Abort(_('%s certificate with fingerprint %s not '
351 'verified') % (host, nicefingerprint),
351 'verified') % (host, nicefingerprint),
352 hint=_('check hostfingerprints or '
352 hint=_('check hostfingerprints or '
353 'web.cacerts config setting'))
353 'web.cacerts config setting'))
354 else:
354 else:
355 ui.warn(_('warning: %s certificate with fingerprint %s '
355 ui.warn(_('warning: %s certificate with fingerprint %s '
356 'not verified (check hostfingerprints or '
356 'not verified (check hostfingerprints or '
357 'web.cacerts config setting)\n') %
357 'web.cacerts config setting)\n') %
358 (host, nicefingerprint))
358 (host, nicefingerprint))
359
359
360 return
360 return
361
361
362 msg = _verifycert(peercert2, host)
362 msg = _verifycert(peercert2, host)
363 if msg:
363 if msg:
364 raise error.Abort(_('%s certificate error: %s') % (host, msg),
364 raise error.Abort(_('%s certificate error: %s') % (host, msg),
365 hint=_('configure hostfingerprint %s or use '
365 hint=_('configure hostfingerprint %s or use '
366 '--insecure to connect insecurely') %
366 '--insecure to connect insecurely') %
367 nicefingerprint)
367 nicefingerprint)
@@ -356,7 +356,7 b' if has_https:'
356 self.sock = sslutil.wrapsocket(
356 self.sock = sslutil.wrapsocket(
357 self.sock, self.key_file, self.cert_file, serverhostname=host,
357 self.sock, self.key_file, self.cert_file, serverhostname=host,
358 **sslutil.sslkwargs(self.ui, host))
358 **sslutil.sslkwargs(self.ui, host))
359 sslutil.validator(self.ui, host)(self.sock)
359 sslutil.validatesocket(self.sock)
360
360
361 class httpshandler(keepalive.KeepAliveHandler, urlreq.httpshandler):
361 class httpshandler(keepalive.KeepAliveHandler, urlreq.httpshandler):
362 def __init__(self, ui):
362 def __init__(self, ui):
General Comments 0
You need to be logged in to leave comments. Login now