mercurial/sslutil.py
changeset 44880 7dd63a8cb1ee
parent 44878 035199ba04ee
child 44888 95903a8d8c97
equal deleted inserted replaced
44879:ab5348bbc55e 44880: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):