Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/sslutil.py @ 44939:7dd63a8cb1ee
sslutil: eliminate `_canloaddefaultcerts` by constant-folding code using it
author | Manuel Jacob <me@manueljacob.de> |
---|---|
date | Sat, 30 May 2020 03:23:58 +0200 |
parents | 035199ba04ee |
children | 95903a8d8c97 |
comparison
equal
deleted
inserted
replaced
44938:ab5348bbc55e | 44939:7dd63a8cb1ee |
---|---|
49 supportedprotocols = {b'tls1.0'} | 49 supportedprotocols = {b'tls1.0'} |
50 if util.safehasattr(ssl, b'PROTOCOL_TLSv1_1'): | 50 if util.safehasattr(ssl, b'PROTOCOL_TLSv1_1'): |
51 supportedprotocols.add(b'tls1.1') | 51 supportedprotocols.add(b'tls1.1') |
52 if util.safehasattr(ssl, b'PROTOCOL_TLSv1_2'): | 52 if util.safehasattr(ssl, b'PROTOCOL_TLSv1_2'): |
53 supportedprotocols.add(b'tls1.2') | 53 supportedprotocols.add(b'tls1.2') |
54 | |
55 _canloaddefaultcerts = True | |
56 | 54 |
57 | 55 |
58 def _hostsettings(ui, hostname): | 56 def _hostsettings(ui, hostname): |
59 """Obtain security settings for a hostname. | 57 """Obtain security settings for a hostname. |
60 | 58 |
225 | 223 |
226 s[b'cafile'] = cafile | 224 s[b'cafile'] = cafile |
227 | 225 |
228 # Require certificate validation if CA certs are being loaded and | 226 # Require certificate validation if CA certs are being loaded and |
229 # verification hasn't been disabled above. | 227 # verification hasn't been disabled above. |
230 if cafile or (_canloaddefaultcerts and s[b'allowloaddefaultcerts']): | 228 if cafile or s[b'allowloaddefaultcerts']: |
231 s[b'verifymode'] = ssl.CERT_REQUIRED | 229 s[b'verifymode'] = ssl.CERT_REQUIRED |
232 else: | 230 else: |
233 # At this point we don't have a fingerprint, aren't being | 231 # At this point we don't have a fingerprint, aren't being |
234 # explicitly insecure, and can't load CA certs. Connecting | 232 # explicitly insecure, and can't load CA certs. Connecting |
235 # is insecure. We allow the connection and abort during | 233 # is insecure. We allow the connection and abort during |
719 return exe.startswith(b'/usr/bin/python') or exe.startswith( | 717 return exe.startswith(b'/usr/bin/python') or exe.startswith( |
720 b'/system/library/frameworks/python.framework/' | 718 b'/system/library/frameworks/python.framework/' |
721 ) | 719 ) |
722 | 720 |
723 | 721 |
724 _systemcacertpaths = [ | |
725 # RHEL, CentOS, and Fedora | |
726 b'/etc/pki/tls/certs/ca-bundle.trust.crt', | |
727 # Debian, Ubuntu, Gentoo | |
728 b'/etc/ssl/certs/ca-certificates.crt', | |
729 ] | |
730 | |
731 | |
732 def _defaultcacerts(ui): | 722 def _defaultcacerts(ui): |
733 """return path to default CA certificates or None. | 723 """return path to default CA certificates or None. |
734 | 724 |
735 It is assumed this function is called when the returned certificates | 725 It is assumed this function is called when the returned certificates |
736 file will actually be used to validate connections. Therefore this | 726 file will actually be used to validate connections. Therefore this |
748 if os.path.exists(certs): | 738 if os.path.exists(certs): |
749 ui.debug(b'using ca certificates from certifi\n') | 739 ui.debug(b'using ca certificates from certifi\n') |
750 return pycompat.fsencode(certs) | 740 return pycompat.fsencode(certs) |
751 except (ImportError, AttributeError): | 741 except (ImportError, AttributeError): |
752 pass | 742 pass |
753 | |
754 # On Windows, only the modern ssl module is capable of loading the system | |
755 # CA certificates. If we're not capable of doing that, emit a warning | |
756 # because we'll get a certificate verification error later and the lack | |
757 # of loaded CA certificates will be the reason why. | |
758 # Assertion: this code is only called if certificates are being verified. | |
759 if pycompat.iswindows: | |
760 if not _canloaddefaultcerts: | |
761 ui.warn( | |
762 _( | |
763 b'(unable to load Windows CA certificates; see ' | |
764 b'https://mercurial-scm.org/wiki/SecureConnections for ' | |
765 b'how to configure Mercurial to avoid this message)\n' | |
766 ) | |
767 ) | |
768 | |
769 return None | |
770 | 743 |
771 # Apple's OpenSSL has patches that allow a specially constructed certificate | 744 # Apple's OpenSSL has patches that allow a specially constructed certificate |
772 # to load the system CA store. If we're running on Apple Python, use this | 745 # to load the system CA store. If we're running on Apple Python, use this |
773 # trick. | 746 # trick. |
774 if _plainapplepython(): | 747 if _plainapplepython(): |
775 dummycert = os.path.join( | 748 dummycert = os.path.join( |
776 os.path.dirname(pycompat.fsencode(__file__)), b'dummycert.pem' | 749 os.path.dirname(pycompat.fsencode(__file__)), b'dummycert.pem' |
777 ) | 750 ) |
778 if os.path.exists(dummycert): | 751 if os.path.exists(dummycert): |
779 return dummycert | 752 return dummycert |
780 | |
781 # The Apple OpenSSL trick isn't available to us. If Python isn't able to | |
782 # load system certs, we're out of luck. | |
783 if pycompat.isdarwin: | |
784 # FUTURE Consider looking for Homebrew or MacPorts installed certs | |
785 # files. Also consider exporting the keychain certs to a file during | |
786 # Mercurial install. | |
787 if not _canloaddefaultcerts: | |
788 ui.warn( | |
789 _( | |
790 b'(unable to load CA certificates; see ' | |
791 b'https://mercurial-scm.org/wiki/SecureConnections for ' | |
792 b'how to configure Mercurial to avoid this message)\n' | |
793 ) | |
794 ) | |
795 return None | |
796 | |
797 # / is writable on Windows. Out of an abundance of caution make sure | |
798 # we're not on Windows because paths from _systemcacerts could be installed | |
799 # by non-admin users. | |
800 assert not pycompat.iswindows | |
801 | |
802 # Try to find CA certificates in well-known locations. We print a warning | |
803 # when using a found file because we don't want too much silent magic | |
804 # for security settings. The expectation is that proper Mercurial | |
805 # installs will have the CA certs path defined at install time and the | |
806 # installer/packager will make an appropriate decision on the user's | |
807 # behalf. We only get here and perform this setting as a feature of | |
808 # last resort. | |
809 if not _canloaddefaultcerts: | |
810 for path in _systemcacertpaths: | |
811 if os.path.isfile(path): | |
812 ui.warn( | |
813 _( | |
814 b'(using CA certificates from %s; if you see this ' | |
815 b'message, your Mercurial install is not properly ' | |
816 b'configured; see ' | |
817 b'https://mercurial-scm.org/wiki/SecureConnections ' | |
818 b'for how to configure Mercurial to avoid this ' | |
819 b'message)\n' | |
820 ) | |
821 % path | |
822 ) | |
823 return path | |
824 | |
825 ui.warn( | |
826 _( | |
827 b'(unable to load CA certificates; see ' | |
828 b'https://mercurial-scm.org/wiki/SecureConnections for ' | |
829 b'how to configure Mercurial to avoid this message)\n' | |
830 ) | |
831 ) | |
832 | 753 |
833 return None | 754 return None |
834 | 755 |
835 | 756 |
836 def validatesocket(sock): | 757 def validatesocket(sock): |