[PATCH 2 of 2] sslutil: try to find CA certficates in well-known locations

Augie Fackler raf at durin42.com
Sun Jul 10 14:38:44 EDT 2016


On Wed, Jul 06, 2016 at 09:19:37PM -0700, Gregory Szorc wrote:
> # HG changeset patch
> # User Gregory Szorc <gregory.szorc at gmail.com>
> # Date 1467864960 25200
> #      Wed Jul 06 21:16:00 2016 -0700
> # Node ID af8b4f956c0599ebf3749fe9e7740bc35e4f02fe
> # Parent  93723841473c4aa7bb794144e00a8377198c79f3
> sslutil: try to find CA certficates in well-known locations

Queued these, thanks.

>
> 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).
>
> diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
> --- a/mercurial/sslutil.py
> +++ b/mercurial/sslutil.py
> @@ -425,22 +425,32 @@ def _plainapplepython():
>        cacerts file
>      """
>      if sys.platform != 'darwin' or util.mainfrozen() or not sys.executable:
>          return False
>      exe = os.path.realpath(sys.executable).lower()
>      return (exe.startswith('/usr/bin/python') or
>              exe.startswith('/system/library/frameworks/python.framework/'))
>
> +_systemcacertpaths = [
> +    # RHEL, CentOS, and Fedora
> +    '/etc/pki/tls/certs/ca-bundle.trust.crt',
> +    # Debian, Ubuntu, Gentoo
> +    '/etc/ssl/certs/ca-certificates.crt',
> +]
> +
>  def _defaultcacerts(ui):
>      """return path to default CA certificates or None.
>
>      It is assumed this function is called when the returned certificates
>      file will actually be used to validate connections. Therefore this
>      function may print warnings or debug messages assuming this usage.
> +
> +    We don't print a message when the Python is able to load default
> +    CA certs because this scenario is detected at socket connect time.
>      """
>      # The "certifi" Python package provides certificates. If it is installed,
>      # assume the user intends it to be used and use it.
>      try:
>          import certifi
>          certs = certifi.where()
>          ui.debug('using ca certificates from certifi\n')
>          return certs
> @@ -475,16 +485,38 @@ def _defaultcacerts(ui):
>          # files. Also consider exporting the keychain certs to a file during
>          # Mercurial install.
>          if not _canloaddefaultcerts:
>              ui.warn(_('(unable to load CA certificates; see '
>                        'https://mercurial-scm.org/wiki/SecureConnections for '
>                        'how to configure Mercurial to avoid this message)\n'))
>          return None
>
> +    # Try to find CA certificates in well-known locations. We print a warning
> +    # when using a found file because we don't want too much silent magic
> +    # for security settings. The expectation is that proper Mercurial
> +    # installs will have the CA certs path defined at install time and the
> +    # installer/packager will make an appropriate decision on the user's
> +    # behalf. We only get here and perform this setting as a feature of
> +    # last resort.
> +    if not _canloaddefaultcerts:
> +        for path in _systemcacertpaths:
> +            if os.path.isfile(path):
> +                ui.warn(_('(using CA certificates from %s; if you see this '
> +                          'message, your Mercurial install is not properly '
> +                          'configured; see '
> +                          'https://mercurial-scm.org/wiki/SecureConnections '
> +                          'for how to configure Mercurial to avoid this '
> +                          'message)\n') % path)
> +                return path
> +
> +        ui.warn(_('(unable to load CA certificates; see '
> +                  'https://mercurial-scm.org/wiki/SecureConnections for '
> +                  'how to configure Mercurial to avoid this message)\n'))
> +
>      return None
>
>  def validatesocket(sock):
>      """Validate a socket meets security requiremnets.
>
>      The passed socket must have been created with ``wrapsocket()``.
>      """
>      host = sock._hgstate['hostname']
> diff --git a/tests/test-https.t b/tests/test-https.t
> --- a/tests/test-https.t
> +++ b/tests/test-https.t
> @@ -51,16 +51,17 @@ we are able to load CA certs.
>    $ hg clone https://localhost:$HGPORT/ copy-pull
>    (an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error)
>    abort: error: *certificate verify failed* (glob)
>    [255]
>  #endif
>
>  #if no-sslcontext defaultcacerts
>    $ hg clone https://localhost:$HGPORT/ copy-pull
> +  (using CA certificates from *; if you see this message, your Mercurial install is not properly configured; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
>    abort: error: *certificate verify failed* (glob)
>    [255]
>  #endif
>
>  #if no-sslcontext windows
>    $ hg clone https://localhost:$HGPORT/ copy-pull
>    (unable to load Windows CA certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message)
>    abort: error: *certificate verify failed* (glob)
> @@ -72,16 +73,17 @@ we are able to load CA certs.
>    (unable to load CA certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message)
>    abort: localhost certificate error: no certificate received
>    (set hostsecurity.localhost:certfingerprints=sha256:62:09:97:2f:97:60:e3:65:8f:12:5d:78:9e:35:a1:36:7a:65:4b:0e:9f:ac:db:c3:bc:6e:b6:a3:c0:16:e0:30 config setting or use --insecure to connect insecurely)
>    [255]
>  #endif
>
>  #if defaultcacertsloaded
>    $ hg clone https://localhost:$HGPORT/ copy-pull
> +  (using CA certificates from *; if you see this message, your Mercurial install is not properly configured; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
>    abort: error: *certificate verify failed* (glob)
>    [255]
>  #endif
>
>  #if no-defaultcacerts
>    $ hg clone https://localhost:$HGPORT/ copy-pull
>    (unable to load * certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
>    abort: localhost certificate error: no certificate received
> diff --git a/tests/test-patchbomb-tls.t b/tests/test-patchbomb-tls.t
> --- a/tests/test-patchbomb-tls.t
> +++ b/tests/test-patchbomb-tls.t
> @@ -53,25 +53,27 @@ we are able to load CA certs:
>    [255]
>  #endif
>
>  #if no-sslcontext defaultcacerts
>    $ try
>    this patch series consists of 1 patches.
>
>
> +  (using CA certificates from *; if you see this message, your Mercurial install is not properly configured; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
>    (?i)abort: .*?certificate.verify.failed.* (re)
>    [255]
>  #endif
>
>  #if defaultcacertsloaded
>    $ try
>    this patch series consists of 1 patches.
>
>
> +  (using CA certificates from *; if you see this message, your Mercurial install is not properly configured; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
>    (?i)abort: .*?certificate.verify.failed.* (re)
>    [255]
>
>  #endif
>
>  #if no-defaultcacerts
>    $ try
>    this patch series consists of 1 patches.
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


More information about the Mercurial-devel mailing list