comparison mercurial/sslutil.py @ 29500:4b16a5bd9948

sslutil: try to find CA certficates in well-known locations Many Linux distros and other Nixen have CA certificates in well-defined locations. Rather than potentially fail to load any CA certificates at all (which will always result in a certificate verification failure), we scan for paths to known CA certificate files and load one if seen. Because a proper Mercurial install will have the path to the CA certificate file defined at install time, we print a warning that the install isn't proper and provide a URL with instructions to correct things. We only perform path-based fallback on Pythons that don't know how to call into OpenSSL to load the default verify locations. This is because we trust that Python/OpenSSL is properly configured and knows better than Mercurial. So this new code effectively only runs on Python <2.7.9 (technically Pythons without the modern ssl module).
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 06 Jul 2016 21:16:00 -0700
parents 9c5325c79683
children be68a4445041
comparison
equal deleted inserted replaced
29499:9c5325c79683 29500:4b16a5bd9948
428 return False 428 return False
429 exe = os.path.realpath(sys.executable).lower() 429 exe = os.path.realpath(sys.executable).lower()
430 return (exe.startswith('/usr/bin/python') or 430 return (exe.startswith('/usr/bin/python') or
431 exe.startswith('/system/library/frameworks/python.framework/')) 431 exe.startswith('/system/library/frameworks/python.framework/'))
432 432
433 _systemcacertpaths = [
434 # RHEL, CentOS, and Fedora
435 '/etc/pki/tls/certs/ca-bundle.trust.crt',
436 # Debian, Ubuntu, Gentoo
437 '/etc/ssl/certs/ca-certificates.crt',
438 ]
439
433 def _defaultcacerts(ui): 440 def _defaultcacerts(ui):
434 """return path to default CA certificates or None. 441 """return path to default CA certificates or None.
435 442
436 It is assumed this function is called when the returned certificates 443 It is assumed this function is called when the returned certificates
437 file will actually be used to validate connections. Therefore this 444 file will actually be used to validate connections. Therefore this
438 function may print warnings or debug messages assuming this usage. 445 function may print warnings or debug messages assuming this usage.
446
447 We don't print a message when the Python is able to load default
448 CA certs because this scenario is detected at socket connect time.
439 """ 449 """
440 # The "certifi" Python package provides certificates. If it is installed, 450 # The "certifi" Python package provides certificates. If it is installed,
441 # assume the user intends it to be used and use it. 451 # assume the user intends it to be used and use it.
442 try: 452 try:
443 import certifi 453 import certifi
478 ui.warn(_('(unable to load CA certificates; see ' 488 ui.warn(_('(unable to load CA certificates; see '
479 'https://mercurial-scm.org/wiki/SecureConnections for ' 489 'https://mercurial-scm.org/wiki/SecureConnections for '
480 'how to configure Mercurial to avoid this message)\n')) 490 'how to configure Mercurial to avoid this message)\n'))
481 return None 491 return None
482 492
493 # Try to find CA certificates in well-known locations. We print a warning
494 # when using a found file because we don't want too much silent magic
495 # for security settings. The expectation is that proper Mercurial
496 # installs will have the CA certs path defined at install time and the
497 # installer/packager will make an appropriate decision on the user's
498 # behalf. We only get here and perform this setting as a feature of
499 # last resort.
500 if not _canloaddefaultcerts:
501 for path in _systemcacertpaths:
502 if os.path.isfile(path):
503 ui.warn(_('(using CA certificates from %s; if you see this '
504 'message, your Mercurial install is not properly '
505 'configured; see '
506 'https://mercurial-scm.org/wiki/SecureConnections '
507 'for how to configure Mercurial to avoid this '
508 'message)\n') % path)
509 return path
510
511 ui.warn(_('(unable to load CA certificates; see '
512 'https://mercurial-scm.org/wiki/SecureConnections for '
513 'how to configure Mercurial to avoid this message)\n'))
514
483 return None 515 return None
484 516
485 def validatesocket(sock): 517 def validatesocket(sock):
486 """Validate a socket meets security requiremnets. 518 """Validate a socket meets security requiremnets.
487 519