[Python-checkins] peps: PEP 493: Incorporate feedback from Tomas Hoger

nick.coghlan python-checkins at python.org
Tue May 19 15:02:08 CEST 2015


https://hg.python.org/peps/rev/b5e0791f27bf
changeset:   5862:b5e0791f27bf
user:        Nick Coghlan <ncoghlan at gmail.com>
date:        Tue May 19 23:02:00 2015 +1000
summary:
  PEP 493: Incorporate feedback from Tomas Hoger

Changes based primarily on design feedback received in
https://bugzilla.redhat.com/show_bug.cgi?id=1173041#c21

Some minor issues were pointed out in private email.

files:
  pep-0493.txt |  205 ++++++++++++++++++++++----------------
  1 files changed, 116 insertions(+), 89 deletions(-)


diff --git a/pep-0493.txt b/pep-0493.txt
--- a/pep-0493.txt
+++ b/pep-0493.txt
@@ -8,6 +8,7 @@
 Content-Type: text/x-rst
 Created: 10-May-2015
 
+
 Abstract
 ========
 
@@ -23,6 +24,7 @@
 *Note that this PEP is not currently accepted, so it is a *proposed*
 recommendation, rather than an active one.*
 
+
 Rationale
 =========
 
@@ -69,6 +71,72 @@
 version of Python 3 (whether published directly by the Python Software
 Foundation or by a redistributor).
 
+
+Recommendation for an environment variable based security downgrade
+===================================================================
+
+Some redistributors may wish to provide a per-application option to disable
+certificate verification in selected applications that run on or embed CPython
+without needing to modify the application itself.
+
+In these cases, a configuration mechanism is needed that provides:
+
+* an opt-out model that allows certificate verification to be selectively
+  turned off for particular applications after upgrading to a version of
+  Python that verifies certificates by default
+* the ability for all users to configure this setting on a per-application
+  basis, rather than on a per-system, or per-Python-installation basis
+
+This approach may be used for any redistributor provided version of Python 2.7,
+including those that advertise themselves as providing Python 2.7.9 or later.
+
+
+Recommended modifications to the Python standard library
+--------------------------------------------------------
+
+The recommended approach to providing a per-application configuration setting
+for HTTPS certificate verification that doesn't require modifications to the
+application itself is to:
+
+* modify the ``ssl`` module to read the ``PYTHONHTTPSVERIFY`` environment
+  variable when the module is first imported into a Python process
+* set the ``ssl._create_default_https_context`` function to be an alias for
+  ``ssl._create_unverified_context`` if this environment variable is present
+  and set to ``'0'``
+* otherwise, set the ``ssl._create_default_https_context`` function to be an
+  alias for ``ssl.create_default_context`` as usual
+
+
+Example implementation
+----------------------
+
+::
+
+    def _get_https_context_factory():
+        config_setting = os.environ.get('PYTHONHTTPSVERIFY')
+        if config_setting == '0':
+            return _create_unverified_context
+        return create_default_context
+
+    _create_default_https_context = _get_https_context_factory()
+
+
+Security Considerations
+-----------------------
+
+Relative to an unmodified version of CPython 2.7.9 or later, this approach
+does introduce a new downgrade attack against the default security settings
+that potentially allows a sufficiently determined attacker to revert Python
+to the vulnerable configuration used in CPython 2.7.8 and earlier releases.
+Such an attack requires the ability to modify the execution environment of
+a Python process prior to the import of the ``ssl`` module.
+
+Redistributors should balance this marginal increase in risk against the
+ability to offer a smoother migration path to their users when deciding whether
+or not it is appropriate for them to implement this per-application "opt out"
+model.
+
+
 Recommendation for backporting to earlier Python versions
 =========================================================
 
@@ -82,22 +150,17 @@
   Python version where the feature was first backported
 * the ability for system administrators to set the default behaviour of Python
   applications and scripts run directly in the system Python installation
-* the ability for system administrators to set the default behaviour of Python
-  applications and scripts run in a ``virtualenv`` created virtual environment
 * the ability for the redistributor to consider changing the default behaviour
   of *new* installations at some point in the future without impacting existing
   installations that have been explicitly configured to skip verifying HTTPS
   certificates by default
 
-The recommended solution for this scenario should also avoid introducing any
-new attack vectors that don't already allow direct attacks against the system
-certificate store.
-
 This approach should not be used for any Python installation that advertises
 itself as providing Python 2.7.9 or later, as most Python users will have the
 reasonable expectation that all such environments will validate HTTPS
 certificates by default.
 
+
 Recommended modifications to the Python standard library
 --------------------------------------------------------
 
@@ -107,12 +170,8 @@
 
 * modify the ``ssl`` module to read a system wide configuration file when the
   module is first imported into a Python process
-* default to verifying HTTPS certificates if this configuration file is not
-  present (this preserves the upstream default behaviour in the absence of the
-  configuration file)
-* if the ``sys.real_prefix`` attribute is defined, read the configuration
-  setting for virtual environments, otherwise read the configuration setting
-  for the system Python
+* define a platform default behaviour (either verifying or not verifying HTTPS
+  certificates) to be used if this configuration file is not present
 * support selection between the following three modes of operation:
 
   * ensure HTTPS certificate verification is enabled
@@ -123,25 +182,26 @@
   either ``ssl.create_default_context`` or ``ssl._create_unverified_context``
   based on the given configuration setting.
 
+
 Recommended file location
 -------------------------
 
 This approach is currently only defined for \*nix system Python installations.
 
 The recommended configuration file name is
-(to be confirmed, currently ``/etc/python/cert-verification.cfg``).
+``/etc/python/cert-verification.cfg``.
 
 The ``.cfg`` filename extension is recommended for consistency with the
 ``pyvenv.cfg`` used by the ``venv`` module in Python 3's standard library.
 
+
 Recommended file format
 -----------------------
 
 The configuration file should use a ConfigParser ini-style format with a
-single section named ``[https]`` containing one required setting ``verify``,
-and one optional setting ``verify_in_virtualenv``.
+single section named ``[https]`` containing one required setting ``verify``.
 
-Permitted values for ``verify`` and ``verify_in_virtualenv`` are:
+Permitted values for ``verify`` are:
 
 * ``enable``: ensure HTTPS certificate verification is enabled by default
 * ``disable``: ensure HTTPS certificate verification is disabled by default
@@ -152,9 +212,6 @@
 ``verify`` setting is set to an unknown value, it should be treated as if the
 configuration file is not present.
 
-If ``sys.real_prefix`` is set, and the ``verify_in_virtualenv`` setting is
-present and set to one of the known options, then it should be used in
-preference to the ``verify`` setting.
 
 Example implementation
 ----------------------
@@ -162,29 +219,22 @@
 ::
 
     def _get_https_context_factory():
-        config_file = '/etc/python/cert-verification.conf'
+        # Check for a system-wide override of the default behaviour
+        config_file = '/etc/python/cert-verification.cfg'
         context_factories = {
             'enable': create_default_context,
             'disable': _create_unverified_context,
             'platform_default': _create_unverified_context, # For now :)
         }
-        # Check for a system-wide override of the default behaviour
-        import configparser
-        config = configparser.RawConfigParser()
+        import ConfigParser
+        config = ConfigParser.RawConfigParser()
         config.read(config_file)
-        section = 'https'
         try:
             verify_mode = config.get('https', 'verify')
         except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
             verify_mode = 'enable'
-        else:
-            # Check if there's a different default for a virtual environment
-            if hasattr(sys, "real_prefix"):
-                try:
-                    verify_mode = config.get('https', 'verify_in_virtualenv')
-                except (ConfigParser.NoOptionError):
-                    pass
-        return context_factories.get(verify_mode, create_default_context)
+        default_factory = context_factories.get('platform_default')
+        return context_factories.get(verify_mode, default_factory)
 
     _create_default_https_context = _get_https_context_factory()
 
@@ -208,7 +258,7 @@
 The intent is that the *only* reason HTTPS verification should be getting
 turned off system wide when using this approach is because:
 
-* an end user is running a redistributor supported version of CPython rather
+* an end user is running a redistributor provided version of CPython rather
   than running upstream CPython directly
 * that redistributor has decided to provide a smoother migration path to
   verifying HTTPS certificates by default than that being provided by the
@@ -218,47 +268,21 @@
   (at least for the time being)
 
 Using an administrator controlled configuration file rather than an environment
-variable not only provides compatibility with the ``-E`` switch, but also
-ensures that in any situation where an attacker gains sufficient access to allow
-them to modify the configuration file, they're likely already in a position to
-attack the system certificate store directly.
+variable has the essential feature of providing a smoother migraiton path, even
+for applications being run with the ``-E`` switch.
 
-Recommendation for an environment variable based security downgrade
-===================================================================
 
-Some redistributors may wish to provide a per-application option to disable
-certificate verification in selected applications that run on or embed CPython
-without needing to modify the application itself.
+Combining the recommendations
+=============================
 
-In these cases, a configuration mechanism is needed that provides:
+If a redistributor chooses to implement both recommendations, then the
+environment variable should take precedence over the system-wide configuration
+setting. This allows the setting to be changed for a given user, virtual
+environment or application, regardless of the system-wide default behaviour.
 
-* an opt-out model that allows certificate verification to be selectively
-  turned off for particular applications after upgrading to a version of
-  Python that verifies certificates by default
-* the ability for all users to configure this setting on a per-application
-  basis, rather than on a per-system, or per-Python-installation basis
-
-This recommendation is not considered appropriate for system wide Python
-installations, but may be suitable for user level Python installations and
-versions of Python embedded in or bundled with particular applications.
-
-This approach may be used for Python installations that advertises
-themselves as providing Python 2.7.9 or later.
-
-Recommended modifications to the Python standard library
---------------------------------------------------------
-
-The recommended approach to providing a per-application configuration setting
-for HTTPS certificate verification that doesn't require modifications to the
-application itself is to:
-
-* modify the ``ssl`` module to read the ``PYTHONHTTPSVERIFY`` environment
-  variable when the module is first imported into a Python process
-* set the ``ssl._create_default_https_context`` function to be an alias for
-  ``ssl._create_unverified_context`` if this environment variable is present
-  and set to '0'
-* otherwise, set the ``ssl._create_default_https_context`` function to be an
-  alias for ``ssl.create_default_context`` as usual
+In this case, if ``PYTHONHTTPSVERIFY`` environment variable is defined, and set
+to anything *other* than ``'0'``, then HTTPS certificate verification should be
+enabled.
 
 Example implementation
 ----------------------
@@ -266,30 +290,33 @@
 ::
 
     def _get_https_context_factory():
+        # Check for am environmental override of the default behaviour
         config_setting = os.environ.get('PYTHONHTTPSVERIFY')
-        if config_setting == '0':
-            return _create_unverified_context
-        return create_default_context
+        if config_setting is not None:
+            if config_setting == '0':
+                return _create_unverified_context
+            return create_default_context
+
+        # Check for a system-wide override of the default behaviour
+        config_file = '/etc/python/cert-verification.cfg'
+        context_factories = {
+            'enable': create_default_context,
+            'disable': _create_unverified_context,
+            'platform_default': _create_unverified_context, # For now :)
+        }
+        import ConfigParser
+        config = ConfigParser.RawConfigParser()
+        config.read(config_file)
+        try:
+            verify_mode = config.get('https', 'verify')
+        except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
+            verify_mode = 'enable'
+        default_factory = context_factories.get('platform_default')
+        return context_factories.get(verify_mode, default_factory)
 
     _create_default_https_context = _get_https_context_factory()
 
 
-Security Considerations
------------------------
-
-Relative to an unmodified version of CPython 2.7.9 or later, this approach
-does introduce a new downgrade attack against the default security settings
-that potentially allows a sufficiently determined attacker to revert Python
-to the vulnerable configuration used in CPython 2.7.8 and earlier releases.
-Such an attack requires the ability to modify the execution environment of
-a Python process prior to the import of the ``ssl`` module.
-
-Redistributors should balance this marginal increase in risk against the
-ability to offer a smoother migration path to their users when deciding whether
-or not it is appropriate for them to implement this per-application "opt out"
-model.
-
-
 Copyright
 =========
 

-- 
Repository URL: https://hg.python.org/peps


More information about the Python-checkins mailing list