comparison mercurial/sslutil.py @ 29268:f200b58497f1

sslutil: reference appropriate config section in messaging Error messages reference the config section defining the host fingerprint. Now that we have multiple sections where this config setting could live, we need to point the user at the appropriate one. We default to the new "hostsecurity" section. But we will still refer them to the "hostfingerprint" section if a value is defined there. There are some corner cases where the messaging might be off. e.g. they could define a SHA-1 fingerprint in both sections. IMO the messaging needs a massive overhaul. I plan to do this as part of future refactoring to security settings.
author Gregory Szorc <gregory.szorc@gmail.com>
date Sat, 28 May 2016 12:58:46 -0700
parents f0ccb6cde3e5
children a05a91a3f120
comparison
equal deleted inserted replaced
29267:f0ccb6cde3e5 29268:f200b58497f1
115 # List of 2-tuple of (hash algorithm, hash). 115 # List of 2-tuple of (hash algorithm, hash).
116 'certfingerprints': [], 116 'certfingerprints': [],
117 # Path to file containing concatenated CA certs. Used by 117 # Path to file containing concatenated CA certs. Used by
118 # SSLContext.load_verify_locations(). 118 # SSLContext.load_verify_locations().
119 'cafile': None, 119 'cafile': None,
120 # Whether the legacy [hostfingerprints] section has data for this host.
121 'legacyfingerprint': False,
120 # ssl.CERT_* constant used by SSLContext.verify_mode. 122 # ssl.CERT_* constant used by SSLContext.verify_mode.
121 'verifymode': None, 123 'verifymode': None,
122 } 124 }
123 125
124 # Look for fingerprints in [hostsecurity] section. Value is a list 126 # Look for fingerprints in [hostsecurity] section. Value is a list
138 140
139 # Fingerprints from [hostfingerprints] are always SHA-1. 141 # Fingerprints from [hostfingerprints] are always SHA-1.
140 for fingerprint in ui.configlist('hostfingerprints', hostname, []): 142 for fingerprint in ui.configlist('hostfingerprints', hostname, []):
141 fingerprint = fingerprint.replace(':', '').lower() 143 fingerprint = fingerprint.replace(':', '').lower()
142 s['certfingerprints'].append(('sha1', fingerprint)) 144 s['certfingerprints'].append(('sha1', fingerprint))
145 s['legacyfingerprint'] = True
143 146
144 # If a host cert fingerprint is defined, it is the only thing that 147 # If a host cert fingerprint is defined, it is the only thing that
145 # matters. No need to validate CA certs. 148 # matters. No need to validate CA certs.
146 if s['certfingerprints']: 149 if s['certfingerprints']:
147 s['verifymode'] = ssl.CERT_NONE 150 s['verifymode'] = ssl.CERT_NONE
348 'sha512': util.sha512(peercert).hexdigest(), 351 'sha512': util.sha512(peercert).hexdigest(),
349 } 352 }
350 nicefingerprint = ':'.join([peerfingerprints['sha1'][x:x + 2] 353 nicefingerprint = ':'.join([peerfingerprints['sha1'][x:x + 2]
351 for x in range(0, len(peerfingerprints['sha1']), 2)]) 354 for x in range(0, len(peerfingerprints['sha1']), 2)])
352 355
356 if settings['legacyfingerprint']:
357 section = 'hostfingerprint'
358 else:
359 section = 'hostsecurity'
360
353 if settings['certfingerprints']: 361 if settings['certfingerprints']:
354 fingerprintmatch = False 362 fingerprintmatch = False
355 for hash, fingerprint in settings['certfingerprints']: 363 for hash, fingerprint in settings['certfingerprints']:
356 if peerfingerprints[hash].lower() == fingerprint: 364 if peerfingerprints[hash].lower() == fingerprint:
357 fingerprintmatch = True 365 fingerprintmatch = True
358 break 366 break
359 if not fingerprintmatch: 367 if not fingerprintmatch:
360 raise error.Abort(_('certificate for %s has unexpected ' 368 raise error.Abort(_('certificate for %s has unexpected '
361 'fingerprint %s') % (host, nicefingerprint), 369 'fingerprint %s') % (host, nicefingerprint),
362 hint=_('check hostfingerprint configuration')) 370 hint=_('check %s configuration') % section)
363 ui.debug('%s certificate matched fingerprint %s\n' % 371 ui.debug('%s certificate matched fingerprint %s\n' %
364 (host, nicefingerprint)) 372 (host, nicefingerprint))
365 return 373 return
366 374
367 # If insecure connections were explicitly requested via --insecure, 375 # If insecure connections were explicitly requested via --insecure,
370 # It may seem odd that this is checked *after* host fingerprint pinning. 378 # It may seem odd that this is checked *after* host fingerprint pinning.
371 # This is for backwards compatibility (for now). The message is also 379 # This is for backwards compatibility (for now). The message is also
372 # the same as below for BC. 380 # the same as below for BC.
373 if ui.insecureconnections: 381 if ui.insecureconnections:
374 ui.warn(_('warning: %s certificate with fingerprint %s not ' 382 ui.warn(_('warning: %s certificate with fingerprint %s not '
375 'verified (check hostfingerprints or web.cacerts ' 383 'verified (check %s or web.cacerts '
376 'config setting)\n') % 384 'config setting)\n') %
377 (host, nicefingerprint)) 385 (host, nicefingerprint, section))
378 return 386 return
379 387
380 if not sock._hgstate['caloaded']: 388 if not sock._hgstate['caloaded']:
381 if strict: 389 if strict:
382 raise error.Abort(_('%s certificate with fingerprint %s not ' 390 raise error.Abort(_('%s certificate with fingerprint %s not '
383 'verified') % (host, nicefingerprint), 391 'verified') % (host, nicefingerprint),
384 hint=_('check hostfingerprints or ' 392 hint=_('check %s or web.cacerts config '
385 'web.cacerts config setting')) 393 'setting') % section)
386 else: 394 else:
387 ui.warn(_('warning: %s certificate with fingerprint %s ' 395 ui.warn(_('warning: %s certificate with fingerprint %s '
388 'not verified (check hostfingerprints or ' 396 'not verified (check %s or web.cacerts config '
389 'web.cacerts config setting)\n') % 397 'setting)\n') %
390 (host, nicefingerprint)) 398 (host, nicefingerprint, section))
391 399
392 return 400 return
393 401
394 msg = _verifycert(peercert2, host) 402 msg = _verifycert(peercert2, host)
395 if msg: 403 if msg:
396 raise error.Abort(_('%s certificate error: %s') % (host, msg), 404 raise error.Abort(_('%s certificate error: %s') % (host, msg),
397 hint=_('configure hostfingerprint %s or use ' 405 hint=_('configure %s %s or use '
398 '--insecure to connect insecurely') % 406 '--insecure to connect insecurely') %
399 nicefingerprint) 407 (section, nicefingerprint))