Blame SOURCES/00234-PEP493-updated-implementation.patch

925e6b
@@ -, +, @@ 
925e6b
---
925e6b
 Lib/ssl.py | 53 ++++++++++++++++++++++++++++++++++++++---------------
925e6b
 1 file changed, 38 insertions(+), 15 deletions(-)
925e6b
--- a/Lib/ssl.py	
925e6b
+++ a/Lib/ssl.py	
925e6b
@@ -466,24 +466,47 @@ def _create_unverified_context(protocol=PROTOCOL_SSLv23, cert_reqs=None,
925e6b
 
925e6b
     return context
925e6b
 
925e6b
+_https_verify_envvar = 'PYTHONHTTPSVERIFY'
925e6b
 _cert_verification_config = '/etc/python/cert-verification.cfg'
925e6b
 
925e6b
-def _get_verify_status(protocol):
925e6b
-   context_factory = {
925e6b
-       'platform_default': _create_unverified_context,
925e6b
-       'enable': create_default_context,
925e6b
-       'disable': _create_unverified_context
925e6b
-   }
925e6b
-   import ConfigParser
925e6b
-   try:
925e6b
-       config = ConfigParser.RawConfigParser()
925e6b
-       config.read(_cert_verification_config)
925e6b
-       status = config.get(protocol, 'verify')
925e6b
-   except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
925e6b
-       status = 'platform_default'
925e6b
-   default = context_factory.get('platform_default')
925e6b
-   return context_factory.get(status, default)
925e6b
+# To provide same function name as specified in PEP493 with keeping
925e6b
+# the old name as defined in our previous patch
925e6b
+_get_https_context_factory = lambda: _get_verify_status('https')
925e6b
 
925e6b
+def _get_verify_status(protocol):
925e6b
+    # See https://www.python.org/dev/peps/pep-0493/#recommendation-for-combined-feature-backports
925e6b
+    # Check for an environmental override of the default behaviour
925e6b
+    if not sys.flags.ignore_environment:
925e6b
+        config_setting = os.environ.get(_https_verify_envvar)
925e6b
+        if config_setting is not None:
925e6b
+            if config_setting == '0':
925e6b
+                return _create_unverified_context
925e6b
+            return create_default_context
925e6b
+
925e6b
+    # Check for a system-wide override of the default behaviour
925e6b
+    context_factory = {
925e6b
+        'platform_default': create_default_context,
925e6b
+        'enable': create_default_context,
925e6b
+        'disable': _create_unverified_context
925e6b
+    }
925e6b
+    import ConfigParser
925e6b
+    try:
925e6b
+        config = ConfigParser.RawConfigParser()
925e6b
+        config.read(_cert_verification_config)
925e6b
+        status = config.get(protocol, 'verify')
925e6b
+    except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
925e6b
+        status = 'platform_default'
925e6b
+    default = context_factory.get('platform_default')
925e6b
+    return context_factory.get(status, default)
925e6b
+
925e6b
+# See https://www.python.org/dev/peps/pep-0493/#feature-configuration-api
925e6b
+def _https_verify_certificates(enable=True):
925e6b
+    """Verify server HTTPS certificates by default?"""
925e6b
+    global _create_default_https_context
925e6b
+    if enable:
925e6b
+        _create_default_https_context = create_default_context
925e6b
+    else:
925e6b
+        _create_default_https_context = _create_unverified_context
925e6b
 
925e6b
 # Used by http.client if no context is explicitly passed.
925e6b
 _create_default_https_context = _get_verify_status('https')
925e6b
--- a/Lib/test/test_ssl.py	Thu Jan 14 21:57:57 2016 -0800
925e6b
+++ a/Lib/test/test_ssl.py	Fri Jan 15 17:41:37 2016 +1000
925e6b
@@ -4,6 +4,7 @@
925e6b
 import sys
925e6b
 import unittest
925e6b
 from test import test_support as support
925e6b
+from test.script_helper import assert_python_ok
925e6b
 import asyncore
925e6b
 import socket
925e6b
 import select
925e6b
@@ -1149,6 +1149,57 @@
925e6b
         self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
925e6b
         self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2)
925e6b
 
925e6b
+    def test__https_verify_certificates(self):
925e6b
+        # Unit test to check the contect factory mapping
925e6b
+        # The factories themselves are tested above
925e6b
+        # This test will fail by design if run under PYTHONHTTPSVERIFY=0
925e6b
+        # (as will various test_httplib tests)
925e6b
+
925e6b
+        # Uses a fresh SSL module to avoid affecting the real one
925e6b
+        local_ssl = support.import_fresh_module("ssl")
925e6b
+        # Certificate verification is enabled by default
925e6b
+        self.assertIs(local_ssl._create_default_https_context,
925e6b
+                      local_ssl.create_default_context)
925e6b
+        # Turn default verification off
925e6b
+        local_ssl._https_verify_certificates(enable=False)
925e6b
+        self.assertIs(local_ssl._create_default_https_context,
925e6b
+                      local_ssl._create_unverified_context)
925e6b
+        # And back on
925e6b
+        local_ssl._https_verify_certificates(enable=True)
925e6b
+        self.assertIs(local_ssl._create_default_https_context,
925e6b
+                      local_ssl.create_default_context)
925e6b
+        # The default behaviour is to enable
925e6b
+        local_ssl._https_verify_certificates(enable=False)
925e6b
+        local_ssl._https_verify_certificates()
925e6b
+        self.assertIs(local_ssl._create_default_https_context,
925e6b
+                      local_ssl.create_default_context)
925e6b
+
925e6b
+    def test__https_verify_envvar(self):
925e6b
+        # Unit test to check the PYTHONHTTPSVERIFY handling
925e6b
+        # Need to use a subprocess so it can still be run under -E
925e6b
+        https_is_verified = """import ssl, sys; \
925e6b
+            status = "Error: _create_default_https_context does not verify certs" \
925e6b
+                       if ssl._create_default_https_context is \
925e6b
+                          ssl._create_unverified_context \
925e6b
+                     else None; \
925e6b
+            sys.exit(status)"""
925e6b
+        https_is_not_verified = """import ssl, sys; \
925e6b
+            status = "Error: _create_default_https_context verifies certs" \
925e6b
+                       if ssl._create_default_https_context is \
925e6b
+                          ssl.create_default_context \
925e6b
+                     else None; \
925e6b
+            sys.exit(status)"""
925e6b
+        extra_env = {}
925e6b
+        # Omitting it leaves verification on
925e6b
+        assert_python_ok("-c", https_is_verified, **extra_env)
925e6b
+        # Setting it to zero turns verification off
925e6b
+        extra_env[ssl._https_verify_envvar] = "0"
925e6b
+        assert_python_ok("-c", https_is_not_verified, **extra_env)
925e6b
+        # Any other value should also leave it on
925e6b
+        for setting in ("", "1", "enabled", "foo"):
925e6b
+            extra_env[ssl._https_verify_envvar] = setting
925e6b
+            assert_python_ok("-c", https_is_verified, **extra_env)
925e6b
+
925e6b
     def test_check_hostname(self):
925e6b
         ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
925e6b
         self.assertFalse(ctx.check_hostname)