Mercurial > hg
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 |