Patchwork [5,of,8] sslutil: use certificates provided by certifi if available

login
register
mail settings
Submitter Gregory Szorc
Date July 2, 2016, 2:57 a.m.
Message ID <101e040f8b014fe93880.1467428261@ubuntu-vm-main>
Download mbox | patch
Permalink /patch/15720/
State Superseded
Delegated to: Yuya Nishihara
Headers show

Comments

Gregory Szorc - July 2, 2016, 2:57 a.m.
# HG changeset patch
# User Gregory Szorc <gregory.szorc@gmail.com>
# Date 1467340479 25200
#      Thu Jun 30 19:34:39 2016 -0700
# Node ID 101e040f8b014fe938803c68b502e7b72b4726f8
# Parent  ab3d545871efb2e0405d576f3bda1c935d6b6d31
sslutil: use certificates provided by certifi if available

The "certifi" Python package provides a distribution of the
Mozilla trusted CA certificates as a Python package. If it is
present, we assume the user intends it to be used and we use
it to provide the default CA certificates when certificates
are otherwise not configured.

It's worth noting that this behavior roughly matches the popular
"requests" package, which also attempts to use "certifi" if
present.
Yuya Nishihara - July 3, 2016, 10:26 a.m.
On Fri, 01 Jul 2016 19:57:41 -0700, Gregory Szorc wrote:
> # HG changeset patch
> # User Gregory Szorc <gregory.szorc@gmail.com>
> # Date 1467340479 25200
> #      Thu Jun 30 19:34:39 2016 -0700
> # Node ID 101e040f8b014fe938803c68b502e7b72b4726f8
> # Parent  ab3d545871efb2e0405d576f3bda1c935d6b6d31
> sslutil: use certificates provided by certifi if available
> 
> The "certifi" Python package provides a distribution of the
> Mozilla trusted CA certificates as a Python package. If it is
> present, we assume the user intends it to be used and we use
> it to provide the default CA certificates when certificates
> are otherwise not configured.
> 
> It's worth noting that this behavior roughly matches the popular
> "requests" package, which also attempts to use "certifi" if
> present.
> 
> diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
> --- a/mercurial/sslutil.py
> +++ b/mercurial/sslutil.py
> @@ -12,16 +12,17 @@ from __future__ import absolute_import
>  import hashlib
>  import os
>  import re
>  import ssl
>  import sys
>  
>  from .i18n import _
>  from . import (
> +    demandimport,
>      error,
>      util,
>  )
>  
>  # Python 2.7.9+ overhauled the built-in SSL/TLS features of Python. It added
>  # support for TLS 1.1, TLS 1.2, SNI, system CA stores, etc. These features are
>  # all exposed via the "ssl" module.
>  #
> @@ -427,16 +428,26 @@ def _plainapplepython():
>      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/'))
>  
>  def _defaultcacerts(ui):
>      """return path to default CA certificates or None."""
> +    # The "certifi" Python package provides certificates. If it is installed,
> +    # assume the user intends it to be used and use it.
> +    with demandimport.deactivated():
> +        try:
> +            import certifi
> +            ui.debug('using ca certificates from certifi\n')
> +            return certifi.where()
> +        except Exception:
> +            pass

Any reason to not catch only ImportError?

Patch

diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -12,16 +12,17 @@  from __future__ import absolute_import
 import hashlib
 import os
 import re
 import ssl
 import sys
 
 from .i18n import _
 from . import (
+    demandimport,
     error,
     util,
 )
 
 # Python 2.7.9+ overhauled the built-in SSL/TLS features of Python. It added
 # support for TLS 1.1, TLS 1.2, SNI, system CA stores, etc. These features are
 # all exposed via the "ssl" module.
 #
@@ -427,16 +428,26 @@  def _plainapplepython():
     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/'))
 
 def _defaultcacerts(ui):
     """return path to default CA certificates or None."""
+    # The "certifi" Python package provides certificates. If it is installed,
+    # assume the user intends it to be used and use it.
+    with demandimport.deactivated():
+        try:
+            import certifi
+            ui.debug('using ca certificates from certifi\n')
+            return certifi.where()
+        except Exception:
+            pass
+
     if _plainapplepython():
         dummycert = os.path.join(os.path.dirname(__file__), 'dummycert.pem')
         if os.path.exists(dummycert):
             return dummycert
 
     return None
 
 def validatesocket(sock):