|
@@
-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)
|