[Python-checkins] peps: Update PEP 493 based on python-dev discussion

nick.coghlan python-checkins at python.org
Tue May 12 14:14:52 CEST 2015


https://hg.python.org/peps/rev/b395246d0af7
changeset:   5843:b395246d0af7
user:        Nick Coghlan <ncoghlan at gmail.com>
date:        Tue May 12 22:14:44 2015 +1000
summary:
  Update PEP 493 based on python-dev discussion

files:
  pep-0493.txt |  233 +++++++++++++++++++++++++++++++-------
  1 files changed, 191 insertions(+), 42 deletions(-)


diff --git a/pep-0493.txt b/pep-0493.txt
--- a/pep-0493.txt
+++ b/pep-0493.txt
@@ -51,70 +51,152 @@
 to allow system administrators to disable the feature by default in their
 Standard Operating Environment definition has been determined not to work in
 at least some cases. The specific case of interest to the authors of this PEP
-is the one where a commercial redistributor aims to provide their users with
-a smoother migration path than the standard one provided by consuming the
-upstream CPython 2.7 distribution directly [#].
-
-.. [#] https://bugzilla.redhat.com/show_bug.cgi?id=1173041
+is the one where a commercial redistributor aims to provide their users with a
+`smoother migration path <https://bugzilla.redhat.com/show_bug.cgi?id=1173041>`__
+than the standard one provided by consuming the upstream CPython 2.7
+distribution directly, but other potential challenges have also been pointed
+out with updating embedded Python runtimes and other user level installations
+of Python.
 
 Rather than allowing a plethora of mutually incompatibile migration techniques
-to bloom, this PEP proposes a recommended approach for redistributors to take
-when addressing this problem on behalf of their users that provides the
-following capabilities:
+to bloom, this PEP proposes two alternative approaches that redistributors
+may take when addressing these problems. Redistributors may choose to implement
+one, both, or neither of these approaches based on their assessment of the
+needs of their particular userbase.
 
-* infrastructure administrators restoring the old behaviour as part of their
-  standard system configuration
-* redistributors restoring the old behaviour as part of their standard
-  platform configuration
-* infrastructure administators optionally and explicitly opting in to accepting
-  a change in default behaviour at a future point in time as determined by their
-  chosen redistributor
+These designs are being proposed as a recommendation for redistributors, rather
+than as new upstream features, as they are needed purely to support legacy
+environments migrating from older versions of Python 2.7. Neither approach
+is being proposed as an upstream Python 2.7 feature, nor as a feature in any
+version of Python 3 (whether published directly by the Python Software
+Foundation or by a redistributor).
 
-It aims to do this without introducing any new attack vectors that allow
-the security configuration to be downgraded back to the older less secure
-defaults.
+Recommendation for backporting to earlier Python versions
+=========================================================
 
-This design is being proposed as a recommendation for redistributors, rather
-than as a new upstream feature, as it is needed primarily to support legacy
-environments migrating from older versions of Python 2.7 (The PEP authors
-aren't *opposed* to this capability existing as an upstream feature, we just
-don't need that ourselves - our aim is to avoid different redistributors
-doing different things, not to push the change upstream).
+Some redistributors, most notably Linux distributions, may choose to backport
+the PEP 476 HTTPS verification changes to modified Python versions based on
+earlier Python 2 maintenance releases. In these cases, a configuration
+mechanism is needed that provides:
 
-Recommendation
-==============
+* an opt-in model that allows the decision to enable HTTPS certificate
+  verification to be made independently of the decision to upgrade to the
+  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
 
-To smooth the migration path to verifying HTTPS certificates by default, it is
-recommended that redistributors:
+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.
 
-* patch the ``ssl`` module to read a global configuration file when the module
-  is imported
-* default to verifying certificates if this configuration file is not present
-* support the following three modes of operation in that configuration file:
+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
+--------------------------------------------------------
+
+The recommended approach to backporting the PEP 476 modifications to an earlier
+point release is to implement the following changes relative to the default
+PEP 476 behaviour implemented in Python 2.7.9+:
+
+* 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
+* support selection between the following three modes of operation:
 
   * ensure HTTPS certificate verification is enabled
   * ensure HTTPS certificate verification is disabled
-  * delegate the decision to the redistributor modifying upstream Python
+  * delegate the decision to the redistributor providing this Python version
 
-An example patch is available at [#].
-
-.. [#] https://bugs.python.org/issue23857
+* set the ``ssl._create_default_https_context`` function to be an alias for
+  either ``ssl.create_default_context`` or ``ssl._create_unverified_context``
+  based on the given configuration setting.
 
 Recommended file location
 -------------------------
 
-TBD separately for \*nix and Windows
+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``).
+
+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
 -----------------------
 
-ConfigParser ini-style format, other details TBD
+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``.
+
+Permitted values for ``verify`` and ``verify_in_virtualenv`` are:
+
+* ``enable``: ensure HTTPS certificate verification is enabled by default
+* ``disable``: ensure HTTPS certificate verification is disabled by default
+* ``platform_default``: delegate the decision to the redistributor providing
+  this particular Python version
+
+If the ``[https]`` section or the ``verify`` setting are missing, or if the
+``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
+----------------------
+
+::
+
+    def _get_https_context_factory():
+        config_file = '/etc/python/cert-verification.conf'
+        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()
+        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)
+
+    _create_default_https_context = _get_https_context_factory()
+
 
 Security Considerations
-=======================
+-----------------------
 
-The specific recommendations here are designed to work for privileged, security
-sensitive processes, being run in the following locked down configuration:
+The specific recommendations for the backporting case are designed to work for
+privileged, security sensitive processes, even those being run in the following
+locked down configuration:
 
 * run from a locked down administrator controlled directory rather than a normal
   user directory (preventing ``sys.path[0]`` based privilege escalation attacks)
@@ -126,7 +208,7 @@
   escalation attacks)
 
 The intent is that the *only* reason HTTPS verification should be getting
-turned off globally is because:
+turned off system wide when using this approach is because:
 
 * an end user is running a redistributor supported version of CPython rather
   than running upstream CPython directly
@@ -143,6 +225,73 @@
 them to modify the configuration file, they're likely already in a position to
 attack the system certificate store directly.
 
+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 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
+
+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.
+
+
 Copyright
 =========
 

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


More information about the Python-checkins mailing list