diff --git a/.gitignore b/.gitignore index 9699aed..5ff5abd 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/Python-2.7.8.tar.xz +SOURCES/Python-2.7.13.tar.xz diff --git a/.python27-python.metadata b/.python27-python.metadata index 94bb874..9fe5e72 100644 --- a/.python27-python.metadata +++ b/.python27-python.metadata @@ -1 +1 @@ -9c6281eeace0c3646fa556c8087bb1b7e033c9c4 SOURCES/Python-2.7.8.tar.xz +18a8f30a0356c751b8d0ea6f76e764cab13ee046 SOURCES/Python-2.7.13.tar.xz diff --git a/SOURCES/00001-pydocnogui.patch b/SOURCES/00001-pydocnogui.patch index 3b34842..dde2c7b 100644 --- a/SOURCES/00001-pydocnogui.patch +++ b/SOURCES/00001-pydocnogui.patch @@ -1,9 +1,19 @@ -diff -up Python-2.7.3/Lib/pydoc.py.no_gui Python-2.7.3/Lib/pydoc.py ---- Python-2.7.3/Lib/pydoc.py.no_gui 2012-04-09 19:07:31.000000000 -0400 -+++ Python-2.7.3/Lib/pydoc.py 2013-02-19 13:48:44.480054515 -0500 -@@ -19,9 +19,6 @@ of all available modules. - Run "pydoc -p " to start an HTTP server on a given port on the - local machine to generate documentation web pages. +From cfe43d895a3cd9b053f6b4fbb2c419f2c5065257 Mon Sep 17 00:00:00 2001 +From: Tomas Orsava +Date: Tue, 10 Jan 2017 11:05:27 +0100 +Subject: [PATCH] Removes the "-g" option from "pydoc" + +--- + Lib/pydoc.py | 11 +---------- + 1 file changed, 1 insertion(+), 10 deletions(-) + +diff --git a/Lib/pydoc.py b/Lib/pydoc.py +index b4b190f..183027d 100755 +--- a/Lib/pydoc.py ++++ b/Lib/pydoc.py +@@ -20,9 +20,6 @@ Run "pydoc -p " to start an HTTP server on a given port on the + local machine to generate documentation web pages. Port number 0 can be + used to get an arbitrary unused port. -For platforms without a command line, "pydoc -g" starts the HTTP server -and also pops up a little window for controlling it. @@ -11,7 +21,7 @@ diff -up Python-2.7.3/Lib/pydoc.py.no_gui Python-2.7.3/Lib/pydoc.py Run "pydoc -w " to write out the HTML documentation for a module to a file named ".html". -@@ -2290,9 +2287,6 @@ def cli(): +@@ -2341,9 +2338,6 @@ def cli(): writing = 0 for opt, val in opts: @@ -21,9 +31,9 @@ diff -up Python-2.7.3/Lib/pydoc.py.no_gui Python-2.7.3/Lib/pydoc.py if opt == '-k': apropos(val) return -@@ -2346,13 +2340,10 @@ def cli(): - %s -p - Start an HTTP server on the given port on the local machine. +@@ -2398,13 +2392,10 @@ def cli(): + Start an HTTP server on the given port on the local machine. Port + number 0 can be used to get an arbitrary unused port. -%s -g - Pop up a graphical interface for finding and serving documentation. @@ -36,3 +46,6 @@ diff -up Python-2.7.3/Lib/pydoc.py.no_gui Python-2.7.3/Lib/pydoc.py +""" % (cmd, os.sep, cmd, cmd, cmd, os.sep) if __name__ == '__main__': cli() +-- +2.11.0 + diff --git a/SOURCES/00055-systemtap.patch b/SOURCES/00055-systemtap.patch index 67ec005..63bc3f8 100644 --- a/SOURCES/00055-systemtap.patch +++ b/SOURCES/00055-systemtap.patch @@ -88,8 +88,8 @@ diff -up Python-2.7rc1/Makefile.pre.in.systemtap Python-2.7rc1/Makefile.pre.in .PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure .PHONY: frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools .PHONY: frameworkaltinstallunixtools recheck autoconf clean clobber distclean --.PHONY: smelly funny patchcheck touch altmaninstall -+.PHONY: smelly funny patchcheck touch altmaninstall buildinclude +-.PHONY: smelly funny patchcheck touch altmaninstall commoninstall ++.PHONY: smelly funny patchcheck touch altmaninstall commoninstall buildinclude .PHONY: gdbhooks # IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/SOURCES/00134-fix-COUNT_ALLOCS-failure-in-test_sys.patch b/SOURCES/00134-fix-COUNT_ALLOCS-failure-in-test_sys.patch index 38381ef..71e7f68 100644 --- a/SOURCES/00134-fix-COUNT_ALLOCS-failure-in-test_sys.patch +++ b/SOURCES/00134-fix-COUNT_ALLOCS-failure-in-test_sys.patch @@ -1,9 +1,11 @@ ---- Python-2.7.2/Lib/test/test_sys.py.mark-tests-that-fail-in-rpmbuild 2011-09-08 18:02:31.627362039 -0400 -+++ Python-2.7.2/Lib/test/test_sys.py 2011-09-08 18:15:29.450308851 -0400 -@@ -734,6 +734,11 @@ class SizeofTest(unittest.TestCase): - # (PyTypeObject + PyNumberMethods + PyMappingMethods + - # PySequenceMethods + PyBufferProcs) - s = vsize('P2P15Pl4PP9PP11PI') + struct.calcsize('41P 10P 3P 6P') +diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py +index 0dd4258..d9b3267 100644 +--- a/Lib/test/test_sys.py ++++ b/Lib/test/test_sys.py +@@ -769,6 +769,11 @@ class SizeofTest(unittest.TestCase): + '10P' # PySequenceMethods + '6P' # PyBufferProcs + '2P') + + # COUNT_ALLOCS adds further fields to the end of a PyTypeObject: + if hasattr(sys, 'getcounts'): diff --git a/SOURCES/00136-skip-tests-of-seeking-stdin-in-rpmbuild.patch b/SOURCES/00136-skip-tests-of-seeking-stdin-in-rpmbuild.patch index 1214055..4d7626f 100644 --- a/SOURCES/00136-skip-tests-of-seeking-stdin-in-rpmbuild.patch +++ b/SOURCES/00136-skip-tests-of-seeking-stdin-in-rpmbuild.patch @@ -6,6 +6,6 @@ diff -up Python-2.7.6/Lib/test/test_file2k.py.stdin-test Python-2.7.6/Lib/test/t f.close() + @unittest._skipInRpmBuild('seems not to raise the exception when run in Koji') - def testStdin(self): - # This causes the interpreter to exit on OSF1 v5.1. - if sys.platform != 'osf1V5': + def testStdinSeek(self): + if sys.platform == 'osf1V5': + # This causes the interpreter to exit on OSF1 v5.1. diff --git a/SOURCES/00137-skip-distutils-tests-that-fail-in-rpmbuild.patch b/SOURCES/00137-skip-distutils-tests-that-fail-in-rpmbuild.patch index 8653772..7122a29 100644 --- a/SOURCES/00137-skip-distutils-tests-that-fail-in-rpmbuild.patch +++ b/SOURCES/00137-skip-distutils-tests-that-fail-in-rpmbuild.patch @@ -7,6 +7,6 @@ diff -up Python-2.7.3/Lib/distutils/tests/test_bdist_rpm.py.mark-tests-that-fail +@unittest._skipInRpmBuild("don't try to nest one rpm build inside another rpm build") class BuildRpmTestCase(support.TempdirManager, + support.EnvironGuard, support.LoggingSilencer, - unittest.TestCase): diff -up Python-2.7.3/Lib/distutils/tests/test_build_ext.py.mark-tests-that-fail-in-rpmbuild Python-2.7.3/Lib/distutils/tests/test_build_ext.py diff --git a/SOURCES/00146-hashlib-fips.patch b/SOURCES/00146-hashlib-fips.patch index 696aa29..0510636 100644 --- a/SOURCES/00146-hashlib-fips.patch +++ b/SOURCES/00146-hashlib-fips.patch @@ -1,6 +1,20 @@ -diff -up Python-2.7.2/Lib/hashlib.py.hashlib-fips Python-2.7.2/Lib/hashlib.py ---- Python-2.7.2/Lib/hashlib.py.hashlib-fips 2011-06-11 11:46:24.000000000 -0400 -+++ Python-2.7.2/Lib/hashlib.py 2011-09-14 00:21:26.194252001 -0400 +From 26f7f9f07c549b2f7c0bc6eb9f52c554c2cd941f Mon Sep 17 00:00:00 2001 +From: Tomas Orsava +Date: Tue, 10 Jan 2017 17:12:52 +0100 +Subject: [PATCH] Support OpenSSL FIPS mode + +--- + Lib/hashlib.py | 86 +++++++----------- + Lib/test/test_hashlib.py | 132 ++++++++++++++++++--------- + Modules/Setup.dist | 8 +- + Modules/_hashopenssl.c | 228 +++++++++++++++++++++++++++++++++++++---------- + setup.py | 15 ---- + 5 files changed, 305 insertions(+), 164 deletions(-) + +diff --git a/Lib/hashlib.py b/Lib/hashlib.py +index bbd06b9..72361bb 100644 +--- a/Lib/hashlib.py ++++ b/Lib/hashlib.py @@ -6,9 +6,12 @@ __doc__ = """hashlib module - A common interface to many hash functions. @@ -17,7 +31,7 @@ diff -up Python-2.7.2/Lib/hashlib.py.hashlib-fips Python-2.7.2/Lib/hashlib.py Named constructor functions are also available, these are much faster than using new(): -@@ -24,6 +27,20 @@ the zlib module. +@@ -25,6 +28,20 @@ the zlib module. Choose your hash function wisely. Some have known collision weaknesses. sha384 and sha512 will be slow on 32 bit platforms. @@ -38,8 +52,8 @@ diff -up Python-2.7.2/Lib/hashlib.py.hashlib-fips Python-2.7.2/Lib/hashlib.py Hash objects have these methods: - update(arg): Update the hash object with the string arg. Repeated calls are equivalent to a single call with the concatenation of all -@@ -63,74 +80,39 @@ algorithms = __always_supported - __all__ = __always_supported + ('new', 'algorithms', 'pbkdf2_hmac') +@@ -69,66 +86,31 @@ __all__ = __always_supported + ('new', 'algorithms_guaranteed', + 'pbkdf2_hmac') -def __get_builtin_constructor(name): @@ -116,8 +130,9 @@ diff -up Python-2.7.2/Lib/hashlib.py.hashlib-fips Python-2.7.2/Lib/hashlib.py try: import _hashlib - new = __hash_new - __get_hash = __get_openssl_constructor +@@ -137,8 +119,8 @@ try: + algorithms_available = algorithms_available.union( + _hashlib.openssl_md_meth_names) except ImportError: - new = __py_new - __get_hash = __get_builtin_constructor @@ -126,16 +141,17 @@ diff -up Python-2.7.2/Lib/hashlib.py.hashlib-fips Python-2.7.2/Lib/hashlib.py for __func_name in __always_supported: # try them all, some may not work due to the OpenSSL -@@ -143,4 +125,4 @@ for __func_name in __always_supported: +@@ -218,4 +200,4 @@ except ImportError: # Cleanup locals() del __always_supported, __func_name, __get_hash -del __py_new, __hash_new, __get_openssl_constructor +del __hash_new, __get_openssl_constructor -diff -up Python-2.7.2/Lib/test/test_hashlib.py.hashlib-fips Python-2.7.2/Lib/test/test_hashlib.py ---- Python-2.7.2/Lib/test/test_hashlib.py.hashlib-fips 2011-06-11 11:46:25.000000000 -0400 -+++ Python-2.7.2/Lib/test/test_hashlib.py 2011-09-14 01:08:55.525254195 -0400 -@@ -32,6 +32,19 @@ def hexstr(s): +diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py +index 471ebb4..410a4ef 100644 +--- a/Lib/test/test_hashlib.py ++++ b/Lib/test/test_hashlib.py +@@ -34,6 +34,19 @@ def hexstr(s): r = r + h[(i >> 4) & 0xF] + h[i & 0xF] return r @@ -155,7 +171,7 @@ diff -up Python-2.7.2/Lib/test/test_hashlib.py.hashlib-fips Python-2.7.2/Lib/tes class HashLibTestCase(unittest.TestCase): supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1', -@@ -61,10 +74,10 @@ class HashLibTestCase(unittest.TestCase) +@@ -63,10 +76,10 @@ class HashLibTestCase(unittest.TestCase): # of hashlib.new given the algorithm name. for algorithm, constructors in self.constructors_to_test.items(): constructors.add(getattr(hashlib, algorithm)) @@ -169,7 +185,7 @@ diff -up Python-2.7.2/Lib/test/test_hashlib.py.hashlib-fips Python-2.7.2/Lib/tes constructors.add(_test_algorithm_via_hashlib_new) _hashlib = self._conditional_import_module('_hashlib') -@@ -78,28 +91,13 @@ class HashLibTestCase(unittest.TestCase) +@@ -80,28 +93,13 @@ class HashLibTestCase(unittest.TestCase): if constructor: constructors.add(constructor) @@ -199,7 +215,7 @@ diff -up Python-2.7.2/Lib/test/test_hashlib.py.hashlib-fips Python-2.7.2/Lib/tes c.hexdigest() def test_algorithms_attribute(self): -@@ -115,28 +113,9 @@ class HashLibTestCase(unittest.TestCase) +@@ -122,28 +120,9 @@ class HashLibTestCase(unittest.TestCase): self.assertRaises(ValueError, hashlib.new, 'spam spam spam spam spam') self.assertRaises(TypeError, hashlib.new, 1) @@ -229,7 +245,7 @@ diff -up Python-2.7.2/Lib/test/test_hashlib.py.hashlib-fips Python-2.7.2/Lib/tes self.assertTrue(hexstr(h.digest()) == h.hexdigest()) def test_large_update(self): -@@ -145,16 +125,16 @@ class HashLibTestCase(unittest.TestCase) +@@ -153,16 +132,16 @@ class HashLibTestCase(unittest.TestCase): abcs = aas + bees + cees for name in self.supported_hash_names: @@ -249,7 +265,7 @@ diff -up Python-2.7.2/Lib/test/test_hashlib.py.hashlib-fips Python-2.7.2/Lib/tes self.assertEqual(m1.digest(), m3.digest(), name+' new problem.') def check(self, name, data, digest): -@@ -162,7 +142,7 @@ class HashLibTestCase(unittest.TestCase) +@@ -170,7 +149,7 @@ class HashLibTestCase(unittest.TestCase): # 2 is for hashlib.name(...) and hashlib.new(name, ...) self.assertGreaterEqual(len(constructors), 2) for hash_object_constructor in constructors: @@ -258,7 +274,7 @@ diff -up Python-2.7.2/Lib/test/test_hashlib.py.hashlib-fips Python-2.7.2/Lib/tes self.assertEqual( computed, digest, "Hash algorithm %s constructed using %s returned hexdigest" -@@ -172,7 +152,8 @@ class HashLibTestCase(unittest.TestCase) +@@ -195,7 +174,8 @@ class HashLibTestCase(unittest.TestCase): def check_unicode(self, algorithm_name): # Unicode objects are not allowed as input. @@ -268,7 +284,7 @@ diff -up Python-2.7.2/Lib/test/test_hashlib.py.hashlib-fips Python-2.7.2/Lib/tes self.check(algorithm_name, u'spam', expected) def test_unicode(self): -@@ -354,6 +335,70 @@ class HashLibTestCase(unittest.TestCase) +@@ -394,6 +374,70 @@ class HashLibTestCase(unittest.TestCase): self.assertEqual(expected_hash, hasher.hexdigest()) @@ -339,10 +355,11 @@ diff -up Python-2.7.2/Lib/test/test_hashlib.py.hashlib-fips Python-2.7.2/Lib/tes class KDFTests(unittest.TestCase): pbkdf2_test_vectors = [ (b'password', b'salt', 1, None), -diff -up Python-2.7.2/Modules/Setup.dist.hashlib-fips Python-2.7.2/Modules/Setup.dist ---- Python-2.7.2/Modules/Setup.dist.hashlib-fips 2011-09-14 00:21:26.163252001 -0400 -+++ Python-2.7.2/Modules/Setup.dist 2011-09-14 00:21:26.201252001 -0400 -@@ -248,14 +248,14 @@ imageop imageop.c # Operations on images +diff --git a/Modules/Setup.dist b/Modules/Setup.dist +index 138fb33..051fd41 100644 +--- a/Modules/Setup.dist ++++ b/Modules/Setup.dist +@@ -252,14 +252,14 @@ imageop imageop.c # Operations on images # Message-Digest Algorithm, described in RFC 1321. The necessary files # md5.c and md5.h are included here. @@ -361,46 +378,25 @@ diff -up Python-2.7.2/Modules/Setup.dist.hashlib-fips Python-2.7.2/Modules/Setup # SGI IRIX specific modules -- off by default. -diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py ---- Python-2.7.2/setup.py.hashlib-fips 2011-09-14 00:21:25.722252001 -0400 -+++ Python-2.7.2/setup.py 2011-09-14 00:21:26.203252001 -0400 -@@ -768,21 +768,6 @@ class PyBuildExt(build_ext): - print ("warning: openssl 0x%08x is too old for _hashlib" % - openssl_ver) - missing.append('_hashlib') -- if COMPILED_WITH_PYDEBUG or not have_usable_openssl: -- # The _sha module implements the SHA1 hash algorithm. -- exts.append( Extension('_sha', ['shamodule.c']) ) -- # The _md5 module implements the RSA Data Security, Inc. MD5 -- # Message-Digest Algorithm, described in RFC 1321. The -- # necessary files md5.c and md5.h are included here. -- exts.append( Extension('_md5', -- sources = ['md5module.c', 'md5.c'], -- depends = ['md5.h']) ) -- -- min_sha2_openssl_ver = 0x00908000 -- if COMPILED_WITH_PYDEBUG or openssl_ver < min_sha2_openssl_ver: -- # OpenSSL doesn't do these until 0.9.8 so we'll bring our own hash -- exts.append( Extension('_sha256', ['sha256module.c']) ) -- exts.append( Extension('_sha512', ['sha512module.c']) ) - - # Modules that provide persistent dictionary-like semantics. You will - # probably want to arrange for at least one of them to be available on ---- Python-2.7.8/Modules/_hashopenssl.c.orig 2014-06-30 04:05:41.000000000 +0200 -+++ Python-2.7.8/Modules/_hashopenssl.c 2014-07-14 14:21:59.546386572 +0200 -@@ -36,6 +36,8 @@ +diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c +index 75b3a3d..851b9cc 100644 +--- a/Modules/_hashopenssl.c ++++ b/Modules/_hashopenssl.c +@@ -36,6 +36,7 @@ #endif /* EVP is the preferred interface to hashing in OpenSSL */ +#include -+#include #include - #include #include -@@ -67,11 +69,19 @@ - + /* We use the object interface to discover what hashes OpenSSL supports. */ +@@ -81,9 +82,19 @@ typedef struct { static PyTypeObject EVPtype; + +-#define DEFINE_CONSTS_FOR_NEW(Name) \ +- static PyObject *CONST_ ## Name ## _name_obj = NULL; \ +- static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL; +/* Struct to hold all the cached information we need on a specific algorithm. + We have one of these per algorithm */ +typedef struct { @@ -411,17 +407,13 @@ diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py + EVP_MD_CTX *ctx_ptrs[2]; + PyObject *error_msgs[2]; +} EVPCachedInfo; - --#define DEFINE_CONSTS_FOR_NEW(Name) \ -- static PyObject *CONST_ ## Name ## _name_obj = NULL; \ -- static EVP_MD_CTX CONST_new_ ## Name ## _ctx; \ -- static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL; ++ +#define DEFINE_CONSTS_FOR_NEW(Name) \ + static EVPCachedInfo cached_info_ ##Name; DEFINE_CONSTS_FOR_NEW(md5) DEFINE_CONSTS_FOR_NEW(sha1) -@@ -117,6 +127,48 @@ +@@ -166,6 +177,48 @@ EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len) } } @@ -470,7 +462,7 @@ diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py /* Internal methods for a hash object */ static void -@@ -315,14 +367,15 @@ +@@ -386,14 +439,15 @@ EVP_repr(PyObject *self) static int EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds) { @@ -489,13 +481,13 @@ diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py return -1; } -@@ -338,7 +391,12 @@ +@@ -409,7 +463,12 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds) PyBuffer_Release(&view); return -1; } -- EVP_DigestInit(&self->ctx, digest); -+ mc_ctx_init(&self->ctx, usedforsecurity); -+ if (!EVP_DigestInit_ex(&self->ctx, digest, NULL)) { +- EVP_DigestInit(self->ctx, digest); ++ mc_ctx_init(self->ctx, usedforsecurity); ++ if (!EVP_DigestInit_ex(self->ctx, digest, NULL)) { + set_evp_exception(); + PyBuffer_Release(&view); + return -1; @@ -503,7 +495,7 @@ diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py self->name = name_obj; Py_INCREF(self->name); -@@ -422,7 +480,8 @@ +@@ -493,7 +552,8 @@ static PyTypeObject EVPtype = { static PyObject * EVPnew(PyObject *name_obj, const EVP_MD *digest, const EVP_MD_CTX *initial_ctx, @@ -513,13 +505,13 @@ diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py { EVPobject *self; -@@ -437,7 +496,12 @@ +@@ -508,7 +568,12 @@ EVPnew(PyObject *name_obj, if (initial_ctx) { - EVP_MD_CTX_copy(&self->ctx, initial_ctx); + EVP_MD_CTX_copy(self->ctx, initial_ctx); } else { -- EVP_DigestInit(&self->ctx, digest); -+ mc_ctx_init(&self->ctx, usedforsecurity); -+ if (!EVP_DigestInit_ex(&self->ctx, digest, NULL)) { +- EVP_DigestInit(self->ctx, digest); ++ mc_ctx_init(self->ctx, usedforsecurity); ++ if (!EVP_DigestInit_ex(self->ctx, digest, NULL)) { + set_evp_exception(); + Py_DECREF(self); + return NULL; @@ -527,7 +519,7 @@ diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py } if (cp && len) { -@@ -461,20 +525,28 @@ +@@ -532,20 +597,28 @@ PyDoc_STRVAR(EVP_new__doc__, An optional string argument may be provided and will be\n\ automatically hashed.\n\ \n\ @@ -560,7 +552,7 @@ diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py return NULL; } -@@ -487,7 +559,7 @@ +@@ -558,7 +631,7 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict) digest = EVP_get_digestbyname(name); ret_obj = EVPnew(name_obj, digest, NULL, (unsigned char*)view.buf, @@ -569,13 +561,13 @@ diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py PyBuffer_Release(&view); return ret_obj; -@@ -713,51 +785,111 @@ - #endif +@@ -818,51 +891,111 @@ generate_hash_name_list(void) + /* - * This macro generates constructor function definitions for specific - * hash algorithms. These constructors are much faster than calling -- * the generic one passing it a python string and are noticably +- * the generic one passing it a python string and are noticeably - * faster than calling a python new() wrapper. Thats important for + * This macro and function generates a family of constructor function + * definitions for specific hash algorithms. These constructors are much @@ -669,7 +661,7 @@ diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py - if (CONST_ ## NAME ## _name_obj == NULL) { \ - CONST_ ## NAME ## _name_obj = PyString_FromString(#NAME); \ - if (EVP_get_digestbyname(#NAME)) { \ -- CONST_new_ ## NAME ## _ctx_p = &CONST_new_ ## NAME ## _ctx; \ +- CONST_new_ ## NAME ## _ctx_p = EVP_MD_CTX_new(); \ - EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \ - } \ - } \ @@ -711,13 +703,14 @@ diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py GEN_CONSTRUCTOR(md5) GEN_CONSTRUCTOR(sha1) #ifdef _OPENSSL_SUPPORTS_SHA2 -@@ -794,13 +926,10 @@ +@@ -899,14 +1032,11 @@ init_hashlib(void) { - PyObject *m; + PyObject *m, *openssl_md_meth_names; + SSL_load_error_strings(); + SSL_library_init(); OpenSSL_add_all_digests(); + ERR_load_crypto_strings(); - /* TODO build EVP_functions openssl_* entries dynamically based - * on what hashes are supported rather than listing many @@ -727,3 +720,32 @@ diff -up Python-2.7.2/setup.py.hashlib-fips Python-2.7.2/setup.py Py_TYPE(&EVPtype) = &PyType_Type; if (PyType_Ready(&EVPtype) < 0) return; +diff --git a/setup.py b/setup.py +index 9fe7634..63ed760 100644 +--- a/setup.py ++++ b/setup.py +@@ -874,21 +874,6 @@ class PyBuildExt(build_ext): + print ("warning: openssl 0x%08x is too old for _hashlib" % + openssl_ver) + missing.append('_hashlib') +- if COMPILED_WITH_PYDEBUG or not have_usable_openssl: +- # The _sha module implements the SHA1 hash algorithm. +- exts.append( Extension('_sha', ['shamodule.c']) ) +- # The _md5 module implements the RSA Data Security, Inc. MD5 +- # Message-Digest Algorithm, described in RFC 1321. The +- # necessary files md5.c and md5.h are included here. +- exts.append( Extension('_md5', +- sources = ['md5module.c', 'md5.c'], +- depends = ['md5.h']) ) +- +- min_sha2_openssl_ver = 0x00908000 +- if COMPILED_WITH_PYDEBUG or openssl_ver < min_sha2_openssl_ver: +- # OpenSSL doesn't do these until 0.9.8 so we'll bring our own hash +- exts.append( Extension('_sha256', ['sha256module.c']) ) +- exts.append( Extension('_sha512', ['sha512module.c']) ) + + # Modules that provide persistent dictionary-like semantics. You will + # probably want to arrange for at least one of them to be available on +-- +2.11.0 + diff --git a/SOURCES/00153-fix-test_gdb-noise.patch b/SOURCES/00153-fix-test_gdb-noise.patch index 50a0917..a1b26d0 100644 --- a/SOURCES/00153-fix-test_gdb-noise.patch +++ b/SOURCES/00153-fix-test_gdb-noise.patch @@ -1,26 +1,8 @@ --- Lib/test/test_gdb.py.old 2012-04-11 21:04:01.367073855 -0400 +++ Lib/test/test_gdb.py 2012-04-12 08:52:58.320288761 -0400 -@@ -96,6 +96,15 @@ class DebuggerTests(unittest.TestCase): - # Generate a list of commands in gdb's language: - commands = ['set breakpoint pending yes', - 'break %s' % breakpoint, -+ -+ # GDB as of Fedora 17 onwards can distinguish between the -+ # value of a variable at entry vs current value: -+ # http://sourceware.org/gdb/onlinedocs/gdb/Variables.html -+ # which leads to the selftests failing with errors like this: -+ # AssertionError: 'v@entry=()' != '()' -+ # Disable this: -+ 'set print entry-values no', -+ - 'run'] - if cmds_after_breakpoint: - commands += cmds_after_breakpoint ---- Lib/test/test_gdb.py.old 2012-04-11 21:04:01.367073855 -0400 -+++ Lib/test/test_gdb.py 2012-04-12 08:52:58.320288761 -0400 @@ -144,6 +153,10 @@ - 'Do you need "set solib-search-path" or ' - '"set sysroot"?', + 'Missing separate debuginfo for ', + 'Try: zypper install -C ', ) + ignore_patterns += ('warning: Unable to open', + 'Missing separate debuginfo for', diff --git a/SOURCES/00156-gdb-autoload-safepath.patch b/SOURCES/00156-gdb-autoload-safepath.patch index 54a5a6e..a16fe8d 100644 --- a/SOURCES/00156-gdb-autoload-safepath.patch +++ b/SOURCES/00156-gdb-autoload-safepath.patch @@ -21,11 +21,13 @@ diff -up Python-2.7.3/Lib/test/test_gdb.py.gdb-autoload-safepath Python-2.7.3/Li class DebuggerTests(unittest.TestCase): """Test that the debugger can debug Python.""" -@@ -112,15 +125,28 @@ class DebuggerTests(unittest.TestCase): - 'set print entry-values no', +diff -up Python-2.7.10/Lib/test/test_gdb.py.ms Python-2.7.10/Lib/test/test_gdb.py +--- Python-2.7.10/Lib/test/test_gdb.py.ms 2015-05-25 17:00:25.028462615 +0200 ++++ Python-2.7.10/Lib/test/test_gdb.py 2015-05-25 17:01:53.166359822 +0200 +@@ -153,6 +153,17 @@ class DebuggerTests(unittest.TestCase): 'run'] -+ + + if HAS_AUTOLOAD_SAFEPATH: + # Recent GDBs will only auto-load scripts from certain safe + # locations. @@ -36,16 +38,19 @@ diff -up Python-2.7.3/Lib/test/test_gdb.py.gdb-autoload-safepath Python-2.7.3/Li + else: + init_commands = [] + - if cmds_after_breakpoint: - commands += cmds_after_breakpoint ++ + # GDB as of 7.4 onwards can distinguish between the + # value of a variable at entry vs current value: + # http://sourceware.org/gdb/onlinedocs/gdb/Variables.html +@@ -167,10 +178,11 @@ class DebuggerTests(unittest.TestCase): else: commands += ['backtrace'] +- # print commands + # print init_commands - # print commands # Use "commands" to generate the arguments with which to invoke "gdb": - args = ["gdb", "--batch"] + args = ["gdb", "--batch", "-nx"] + args += ['--init-eval-command=%s' % cmd for cmd in init_commands] args += ['--eval-command=%s' % cmd for cmd in commands] args += ["--args", diff --git a/SOURCES/00166-fix-fake-repr-in-gdb-hooks.patch b/SOURCES/00166-fix-fake-repr-in-gdb-hooks.patch deleted file mode 100644 index 5f3781c..0000000 --- a/SOURCES/00166-fix-fake-repr-in-gdb-hooks.patch +++ /dev/null @@ -1,125 +0,0 @@ -diff -up Python-2.7.3/Tools/gdb/libpython.py.fix-fake-repr-in-gdb-hooks Python-2.7.3/Tools/gdb/libpython.py ---- Python-2.7.3/Tools/gdb/libpython.py.fix-fake-repr-in-gdb-hooks 2013-02-19 17:21:33.541181366 -0500 -+++ Python-2.7.3/Tools/gdb/libpython.py 2013-02-19 17:21:42.090180782 -0500 -@@ -105,6 +105,24 @@ class TruncatedStringIO(object): - def getvalue(self): - return self._val - -+class FakeProxy(object): -+ """ -+ Class representing a non-descript PyObject* value in the inferior -+ process for when we don't have a custom scraper, intended to have -+ a sane repr(). -+ """ -+ def __init__(self, tp_name, address): -+ self.tp_name = tp_name -+ self.address = address -+ -+ def __repr__(self): -+ # For the NULL pointer, we have no way of knowing a type, so -+ # special-case it as per -+ # http://bugs.python.org/issue8032#msg100882 -+ if self.address == 0: -+ return '0x0' -+ return '<%s at remote 0x%x>' % (self.tp_name, self.address) -+ - class PyObjectPtr(object): - """ - Class wrapping a gdb.Value that's a either a (PyObject*) within the -@@ -232,28 +250,8 @@ class PyObjectPtr(object): - visiting object graphs with loops). Analogous to Py_ReprEnter and - Py_ReprLeave - ''' -- -- class FakeRepr(object): -- """ -- Class representing a non-descript PyObject* value in the inferior -- process for when we don't have a custom scraper, intended to have -- a sane repr(). -- """ -- -- def __init__(self, tp_name, address): -- self.tp_name = tp_name -- self.address = address -- -- def __repr__(self): -- # For the NULL pointer, we have no way of knowing a type, so -- # special-case it as per -- # http://bugs.python.org/issue8032#msg100882 -- if self.address == 0: -- return '0x0' -- return '<%s at remote 0x%x>' % (self.tp_name, self.address) -- -- return FakeRepr(self.safe_tp_name(), -- long(self._gdbval)) -+ return FakeProxy(self.safe_tp_name(), -+ long(self._gdbval)) - - def write_repr(self, out, visited): - ''' -@@ -384,7 +382,7 @@ def _write_instance_repr(out, visited, n - if not first: - out.write(', ') - first = False -- out.write(pyop_arg.proxyval(visited)) -+ out.write(str(pyop_arg.proxyval(visited))) - out.write('=') - pyop_val.write_repr(out, visited) - out.write(')') -@@ -785,6 +783,8 @@ class PyNoneStructPtr(PyObjectPtr): - def proxyval(self, visited): - return None - -+class CantReadFilename(ValueError): -+ pass - - class PyFrameObjectPtr(PyObjectPtr): - _typename = 'PyFrameObject' -@@ -861,7 +861,10 @@ class PyFrameObjectPtr(PyObjectPtr): - '''Get the path of the current Python source file, as a string''' - if self.is_optimized_out(): - return '(frame information optimized out)' -- return self.co_filename.proxyval(set()) -+ value = self.co_filename.proxyval(set()) -+ if isinstance(value, FakeProxy): -+ raise CantReadFilename('unable to extract filename)') -+ return value - - def current_line_num(self): - '''Get current line number as an integer (1-based) -@@ -907,7 +910,7 @@ class PyFrameObjectPtr(PyObjectPtr): - out.write(', ') - first = False - -- out.write(pyop_name.proxyval(visited)) -+ out.write(str(pyop_name.proxyval(visited))) - out.write('=') - pyop_value.write_repr(out, visited) - -@@ -1252,8 +1255,11 @@ class Frame(object): - if pyop: - sys.stdout.write('#%i %s\n' % (self.get_index(), pyop.get_truncated_repr(MAX_OUTPUT_LEN))) - if not pyop.is_optimized_out(): -- line = pyop.current_line() -- sys.stdout.write(' %s\n' % line.strip()) -+ try: -+ line = pyop.current_line() -+ sys.stdout.write(' %s\n' % line.strip()) -+ except CantReadFilename: -+ sys.stdout.write(' %s\n' % '(unable to read filename)') - else: - sys.stdout.write('#%i (unable to read python frame information)\n' % self.get_index()) - else: -@@ -1303,7 +1309,11 @@ class PyList(gdb.Command): - print('Unable to read information on python frame') - return - -- filename = pyop.filename() -+ try: -+ filename = pyop.filename() -+ except CantReadFilename: -+ print("Unable to extract filename from python frame") -+ return - lineno = pyop.current_line_num() - - if start is None: diff --git a/SOURCES/00167-disable-stack-navigation-tests-when-optimized-in-test_gdb.patch b/SOURCES/00167-disable-stack-navigation-tests-when-optimized-in-test_gdb.patch index 3fa94fb..f056e9a 100644 --- a/SOURCES/00167-disable-stack-navigation-tests-when-optimized-in-test_gdb.patch +++ b/SOURCES/00167-disable-stack-navigation-tests-when-optimized-in-test_gdb.patch @@ -1,7 +1,21 @@ -diff -up Python-2.7.3/Lib/test/test_gdb.py.disable-stack-navigation-tests-when-optimized-in-test_gdb Python-2.7.3/Lib/test/test_gdb.py ---- Python-2.7.3/Lib/test/test_gdb.py.disable-stack-navigation-tests-when-optimized-in-test_gdb 2013-02-20 12:27:05.669526425 -0500 -+++ Python-2.7.3/Lib/test/test_gdb.py 2013-02-20 12:27:05.715526422 -0500 -@@ -653,10 +653,10 @@ class PyListTests(DebuggerTests): +From 084421eb30e9ae981731aae4038cc934b3feb71d Mon Sep 17 00:00:00 2001 +From: Tomas Orsava +Date: Wed, 11 Jan 2017 15:14:09 +0100 +Subject: [PATCH] Don't run any of the stack navigation tests in test_gdb when + Python is optimized, + +since there appear to be many different ways in which gdb can +fail to read the PyFrameObject* for arbitrary places in the callstack, +presumably due to compiler optimization (rhbz#912025) +--- + Lib/test/test_gdb.py | 13 +++---------- + 1 file changed, 3 insertions(+), 10 deletions(-) + +diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py +index 38e570f..6d45da8 100644 +--- a/Lib/test/test_gdb.py ++++ b/Lib/test/test_gdb.py +@@ -697,10 +697,10 @@ class PyListTests(DebuggerTests): ' 3 def foo(a, b, c):\n', bt) @@ -15,7 +29,7 @@ diff -up Python-2.7.3/Lib/test/test_gdb.py.disable-stack-navigation-tests-when-o def test_pyup_command(self): 'Verify that the "py-up" command works' bt = self.get_stack_trace(script=self.get_sample_script(), -@@ -667,7 +667,6 @@ class StackNavigationTests(DebuggerTests +@@ -711,7 +711,6 @@ class StackNavigationTests(DebuggerTests): baz\(a, b, c\) $''') @@ -23,15 +37,17 @@ diff -up Python-2.7.3/Lib/test/test_gdb.py.disable-stack-navigation-tests-when-o def test_down_at_bottom(self): 'Verify handling of "py-down" at the bottom of the stack' bt = self.get_stack_trace(script=self.get_sample_script(), -@@ -675,7 +674,6 @@ $''') +@@ -719,9 +718,6 @@ $''') self.assertEndsWith(bt, 'Unable to find a newer python frame\n') - @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands") +- @unittest.skipIf(python_is_optimized(), +- "Python was compiled with optimizations") def test_up_at_top(self): 'Verify handling of "py-up" at the top of the stack' bt = self.get_stack_trace(script=self.get_sample_script(), -@@ -683,9 +681,6 @@ $''') +@@ -729,9 +725,6 @@ $''') self.assertEndsWith(bt, 'Unable to find an older python frame\n') @@ -41,3 +57,6 @@ diff -up Python-2.7.3/Lib/test/test_gdb.py.disable-stack-navigation-tests-when-o def test_up_then_down(self): 'Verify "py-up" followed by "py-down"' bt = self.get_stack_trace(script=self.get_sample_script(), +-- +2.11.0 + diff --git a/SOURCES/00170-gc-assertions.patch b/SOURCES/00170-gc-assertions.patch index 3fb37ff..f3a0838 100644 --- a/SOURCES/00170-gc-assertions.patch +++ b/SOURCES/00170-gc-assertions.patch @@ -3,8 +3,8 @@ diff -up Python-2.7.3/Lib/test/test_gc.py.gc-assertions Python-2.7.3/Lib/test/te +++ Python-2.7.3/Lib/test/test_gc.py 2013-02-20 16:39:52.720489297 -0500 @@ -1,6 +1,7 @@ import unittest --from test.test_support import verbose, run_unittest -+from test.test_support import verbose, run_unittest, import_module +-from test.test_support import verbose, run_unittest, start_threads ++from test.test_support import verbose, run_unittest, start_threads, import_module import sys +import sysconfig import time diff --git a/SOURCES/00180-python-add-support-for-ppc64p7.patch b/SOURCES/00180-python-add-support-for-ppc64p7.patch index 022944a..ef94c86 100644 --- a/SOURCES/00180-python-add-support-for-ppc64p7.patch +++ b/SOURCES/00180-python-add-support-for-ppc64p7.patch @@ -1,12 +1,13 @@ -diff -r de35eae9048a config.sub ---- a/config.sub Wed Apr 24 23:33:20 2013 +0200 -+++ b/config.sub Thu Apr 25 08:51:00 2013 +0200 -@@ -1008,7 +1008,7 @@ +diff --git a/config.sub b/config.sub +index 3478c1f..e422173 100755 +--- a/config.sub ++++ b/config.sub +@@ -1040,7 +1040,7 @@ case $basic_machine in ;; ppc64) basic_machine=powerpc64-unknown ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) + ppc64le | powerpc64little) basic_machine=powerpc64le-unknown diff --git a/SOURCES/00181-allow-arbitrary-timeout-in-condition-wait.patch b/SOURCES/00181-allow-arbitrary-timeout-in-condition-wait.patch index 665965d..757c7dd 100644 --- a/SOURCES/00181-allow-arbitrary-timeout-in-condition-wait.patch +++ b/SOURCES/00181-allow-arbitrary-timeout-in-condition-wait.patch @@ -24,8 +24,8 @@ index cb49c4a..c9795a5 100644 if not gotit: if __debug__: @@ -599,7 +602,7 @@ class _Event(_Verbose): - finally: - self.__cond.release() + with self.__cond: + self.__flag = False - def wait(self, timeout=None): + def wait(self, timeout=None, balancing=True): @@ -33,14 +33,14 @@ index cb49c4a..c9795a5 100644 If the internal flag is true on entry, return immediately. Otherwise, @@ -617,7 +620,7 @@ class _Event(_Verbose): - self.__cond.acquire() - try: + """ + with self.__cond: if not self.__flag: - self.__cond.wait(timeout) + self.__cond.wait(timeout, balancing) return self.__flag - finally: - self.__cond.release() + + # Helper to generate new thread names @@ -908,7 +911,7 @@ class Thread(_Verbose): if 'dummy_threading' not in _sys.modules: raise diff --git a/SOURCES/00184-ctypes-should-build-with-libffi-multilib-wrapper.patch b/SOURCES/00184-ctypes-should-build-with-libffi-multilib-wrapper.patch deleted file mode 100644 index 8230986..0000000 --- a/SOURCES/00184-ctypes-should-build-with-libffi-multilib-wrapper.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -up Python-2.7.5/setup.py.orig Python-2.7.5/setup.py ---- Python-2.7.5/setup.py.orig 2013-07-17 15:20:12.086820082 +0200 -+++ Python-2.7.5/setup.py 2013-07-17 15:21:28.490023903 +0200 -@@ -2050,7 +2050,8 @@ class PyBuildExt(build_ext): - if not line: - ffi_inc = None - break -- if line.startswith('#define LIBFFI_H'): -+ if line.startswith('#define LIBFFI_H') or \ -+ line.startswith('#define ffi_wrapper_h'): - break - ffi_lib = None - if ffi_inc is not None: diff --git a/SOURCES/00189-gdb-py-bt-dont-raise-exception-from-eval.patch b/SOURCES/00189-gdb-py-bt-dont-raise-exception-from-eval.patch index 4e82859..4ef2a5d 100644 --- a/SOURCES/00189-gdb-py-bt-dont-raise-exception-from-eval.patch +++ b/SOURCES/00189-gdb-py-bt-dont-raise-exception-from-eval.patch @@ -6,6 +6,6 @@ return '(frame information optimized out)' + if self.filename() == '': + return '(in an eval block)' - with open(self.filename(), 'r') as f: - all_lines = f.readlines() - # Convert from 1-based current_line_num to 0-based list offset: + filename = self.filename() + try: + f = open(filename, 'r') diff --git a/SOURCES/00191-disable-NOOP.patch b/SOURCES/00191-disable-NOOP.patch index fbe9474..2d4189a 100644 --- a/SOURCES/00191-disable-NOOP.patch +++ b/SOURCES/00191-disable-NOOP.patch @@ -1,12 +1,12 @@ diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py -index 81806c9..e7881b9 100644 +index 1bb6690..28ed25d 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -182,6 +182,7 @@ class DebuggingServerTests(unittest.TestCase): - smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) + smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) smtp.quit() + @unittest._skipInRpmBuild("Does not work in network-free environment") def testNOOP(self): - smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) + smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15) expected = (250, 'Ok') diff --git a/SOURCES/00198-add-rewheel-module.patch b/SOURCES/00198-add-rewheel-module.patch new file mode 100644 index 0000000..029f24f --- /dev/null +++ b/SOURCES/00198-add-rewheel-module.patch @@ -0,0 +1,249 @@ +diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py +index 14c9adb..e20104e 100644 +--- a/Lib/ensurepip/__init__.py ++++ b/Lib/ensurepip/__init__.py +@@ -7,6 +7,7 @@ import pkgutil + import shutil + import sys + import tempfile ++from ensurepip import rewheel + + + __all__ = ["version", "bootstrap"] +@@ -43,6 +44,8 @@ def _run_pip(args, additional_paths=None): + + # Install the bundled software + import pip ++ if args[0] in ["install", "list", "wheel"]: ++ args.append('--pre') + pip.main(args) + + +@@ -93,21 +96,40 @@ def bootstrap(root=None, upgrade=False, user=False, + # omit pip and easy_install + os.environ["ENSUREPIP_OPTIONS"] = "install" + ++ whls = [] ++ rewheel_dir = None ++ # try to see if we have system-wide versions of _PROJECTS ++ dep_records = rewheel.find_system_records([p[0] for p in _PROJECTS]) ++ # TODO: check if system-wide versions are the newest ones ++ # if --upgrade is used? ++ if all(dep_records): ++ # if we have all _PROJECTS installed system-wide, we'll recreate ++ # wheels from them and install those ++ rewheel_dir = tempfile.mkdtemp() ++ for dr in dep_records: ++ new_whl = rewheel.rewheel_from_record(dr, rewheel_dir) ++ whls.append(os.path.join(rewheel_dir, new_whl)) ++ else: ++ # if we don't have all the _PROJECTS installed system-wide, ++ # let's just fall back to bundled wheels ++ for project, version in _PROJECTS: ++ whl = os.path.join( ++ os.path.dirname(__file__), ++ "_bundled", ++ "{}-{}-py2.py3-none-any.whl".format(project, version) ++ ) ++ whls.append(whl) ++ + tmpdir = tempfile.mkdtemp() + try: + # Put our bundled wheels into a temporary directory and construct the + # additional paths that need added to sys.path + additional_paths = [] +- for project, version in _PROJECTS: +- wheel_name = "{}-{}-py2.py3-none-any.whl".format(project, version) +- whl = pkgutil.get_data( +- "ensurepip", +- "_bundled/{}".format(wheel_name), +- ) +- with open(os.path.join(tmpdir, wheel_name), "wb") as fp: +- fp.write(whl) +- +- additional_paths.append(os.path.join(tmpdir, wheel_name)) ++ for whl in whls: ++ shutil.copy(whl, tmpdir) ++ additional_paths.append(os.path.join(tmpdir, os.path.basename(whl))) ++ if rewheel_dir: ++ shutil.rmtree(rewheel_dir) + + # Construct the arguments to be passed to the pip command + args = ["install", "--no-index", "--find-links", tmpdir] +diff --git a/Lib/ensurepip/rewheel/__init__.py b/Lib/ensurepip/rewheel/__init__.py +new file mode 100644 +index 0000000..75c2094 +--- /dev/null ++++ b/Lib/ensurepip/rewheel/__init__.py +@@ -0,0 +1,158 @@ ++import argparse ++import codecs ++import csv ++import email.parser ++import os ++import io ++import re ++import site ++import subprocess ++import sys ++import zipfile ++ ++def run(): ++ parser = argparse.ArgumentParser(description='Recreate wheel of package with given RECORD.') ++ parser.add_argument('record_path', ++ help='Path to RECORD file') ++ parser.add_argument('-o', '--output-dir', ++ help='Dir where to place the wheel, defaults to current working dir.', ++ dest='outdir', ++ default=os.path.curdir) ++ ++ ns = parser.parse_args() ++ retcode = 0 ++ try: ++ print(rewheel_from_record(**vars(ns))) ++ except BaseException as e: ++ print('Failed: {}'.format(e)) ++ retcode = 1 ++ sys.exit(1) ++ ++def find_system_records(projects): ++ """Return list of paths to RECORD files for system-installed projects. ++ ++ If a project is not installed, the resulting list contains None instead ++ of a path to its RECORD ++ """ ++ records = [] ++ # get system site-packages dirs ++ if hasattr(sys, 'real_prefix'): ++ #we are in python2 virtualenv and sys.real_prefix is the original sys.prefix ++ _orig_prefixes = site.PREFIXES ++ setattr(site, 'PREFIXES', [sys.real_prefix]*2) ++ sys_sitepack = site.getsitepackages() ++ setattr(site, 'PREFIXES', _orig_prefixes) ++ elif hasattr(sys, 'base_prefix'): # python3 venv doesn't inject real_prefix to sys ++ # we are on python3 and base(_exec)_prefix is unchanged in venv ++ sys_sitepack = site.getsitepackages([sys.base_prefix, sys.base_exec_prefix]) ++ else: ++ # we are in python2 without virtualenv ++ sys_sitepack = site.getsitepackages() ++ ++ sys_sitepack = [sp for sp in sys_sitepack if os.path.exists(sp)] ++ # try to find all projects in all system site-packages ++ for project in projects: ++ path = None ++ for sp in sys_sitepack: ++ dist_info_re = os.path.join(sp, project) + '-[^\{0}]+\.dist-info'.format(os.sep) ++ candidates = [os.path.join(sp, p) for p in os.listdir(sp)] ++ # filter out candidate dirs based on the above regexp ++ filtered = [c for c in candidates if re.match(dist_info_re, c)] ++ # if we have 0 or 2 or more dirs, something is wrong... ++ if len(filtered) == 1: ++ path = filtered[0] ++ if path is not None: ++ records.append(os.path.join(path, 'RECORD')) ++ else: ++ records.append(None) ++ return records ++ ++def rewheel_from_record(record_path, outdir): ++ """Recreates a whee of package with given record_path and returns path ++ to the newly created wheel.""" ++ site_dir = os.path.dirname(os.path.dirname(record_path)) ++ record_relpath = record_path[len(site_dir):].strip(os.path.sep) ++ to_write, to_omit = get_records_to_pack(site_dir, record_relpath) ++ new_wheel_name = get_wheel_name(record_path) ++ new_wheel_path = os.path.join(outdir, new_wheel_name + '.whl') ++ ++ new_wheel = zipfile.ZipFile(new_wheel_path, mode='w', compression=zipfile.ZIP_DEFLATED) ++ # we need to write a new record with just the files that we will write, ++ # e.g. not binaries and *.pyc/*.pyo files ++ if sys.version_info[0] < 3: ++ new_record = io.BytesIO() ++ else: ++ new_record = io.StringIO() ++ writer = csv.writer(new_record) ++ ++ # handle files that we can write straight away ++ for f, sha_hash, size in to_write: ++ new_wheel.write(os.path.join(site_dir, f), arcname=f) ++ writer.writerow([f, sha_hash,size]) ++ ++ # rewrite the old wheel file with a new computed one ++ writer.writerow([record_relpath, '', '']) ++ new_wheel.writestr(record_relpath, new_record.getvalue()) ++ ++ new_wheel.close() ++ ++ return new_wheel.filename ++ ++def get_wheel_name(record_path): ++ """Return proper name of the wheel, without .whl.""" ++ ++ wheel_info_path = os.path.join(os.path.dirname(record_path), 'WHEEL') ++ with codecs.open(wheel_info_path, encoding='utf-8') as wheel_info_file: ++ wheel_info = email.parser.Parser().parsestr(wheel_info_file.read().encode('utf-8')) ++ ++ metadata_path = os.path.join(os.path.dirname(record_path), 'METADATA') ++ with codecs.open(metadata_path, encoding='utf-8') as metadata_file: ++ metadata = email.parser.Parser().parsestr(metadata_file.read().encode('utf-8')) ++ ++ # construct name parts according to wheel spec ++ distribution = metadata.get('Name') ++ version = metadata.get('Version') ++ build_tag = '' # nothing for now ++ lang_tag = [] ++ for t in wheel_info.get_all('Tag'): ++ lang_tag.append(t.split('-')[0]) ++ lang_tag = '.'.join(lang_tag) ++ abi_tag, plat_tag = wheel_info.get('Tag').split('-')[1:3] ++ # leave out build tag, if it is empty ++ to_join = filter(None, [distribution, version, build_tag, lang_tag, abi_tag, plat_tag]) ++ return '-'.join(list(to_join)) ++ ++def get_records_to_pack(site_dir, record_relpath): ++ """Accepts path of sitedir and path of RECORD file relative to it. ++ Returns two lists: ++ - list of files that can be written to new RECORD straight away ++ - list of files that shouldn't be written or need some processing ++ (pyc and pyo files, scripts) ++ """ ++ record_file_path = os.path.join(site_dir, record_relpath) ++ with codecs.open(record_file_path, encoding='utf-8') as record_file: ++ record_contents = record_file.read() ++ # temporary fix for https://github.com/pypa/pip/issues/1376 ++ # we need to ignore files under ".data" directory ++ data_dir = os.path.dirname(record_relpath).strip(os.path.sep) ++ data_dir = data_dir[:-len('dist-info')] + 'data' ++ ++ to_write = [] ++ to_omit = [] ++ for l in record_contents.splitlines(): ++ spl = l.split(',') ++ if len(spl) == 3: ++ # new record will omit (or write differently): ++ # - abs paths, paths with ".." (entry points), ++ # - pyc+pyo files ++ # - the old RECORD file ++ # TODO: is there any better way to recognize an entry point? ++ if os.path.isabs(spl[0]) or spl[0].startswith('..') or \ ++ spl[0].endswith('.pyc') or spl[0].endswith('.pyo') or \ ++ spl[0] == record_relpath or spl[0].startswith(data_dir): ++ to_omit.append(spl) ++ else: ++ to_write.append(spl) ++ else: ++ pass # bad RECORD or empty line ++ return to_write, to_omit +diff --git a/Makefile.pre.in b/Makefile.pre.in +index ca33158..44bdde5 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1066,7 +1066,7 @@ LIBSUBDIRS= lib-tk lib-tk/test lib-tk/test/test_tkinter \ + test/tracedmodules \ + encodings compiler hotshot \ + email email/mime email/test email/test/data \ +- ensurepip ensurepip/_bundled \ ++ ensurepip ensurepip/_bundled ensurepip/rewheel\ + json json/tests \ + sqlite3 sqlite3/test \ + logging bsddb bsddb/test csv importlib wsgiref \ diff --git a/SOURCES/00213-pep466-pyunicode_fromformat-fix-formats.patch b/SOURCES/00213-pep466-pyunicode_fromformat-fix-formats.patch deleted file mode 100644 index b964896..0000000 --- a/SOURCES/00213-pep466-pyunicode_fromformat-fix-formats.patch +++ /dev/null @@ -1,176 +0,0 @@ - -# HG changeset patch -# User Victor Stinner -# Date 1406673545 -7200 -# Node ID 263701e0b77e3160bc6a835087f838bd6b24092a -# Parent 6c47c6d2033e20e9b35f1d22e0e797961d6e680f -Issue #22023: Fix %S, %R and %V formats of PyUnicode_FromFormat(). - -diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c ---- a/Objects/unicodeobject.c -+++ b/Objects/unicodeobject.c -@@ -690,7 +690,12 @@ makefmt(char *fmt, int longflag, int siz - *fmt = '\0'; - } - --#define appendstring(string) {for (copy = string;*copy;) *s++ = *copy++;} -+#define appendstring(string) \ -+ do { \ -+ for (copy = string;*copy; copy++) { \ -+ *s++ = (unsigned char)*copy; \ -+ } \ -+ } while (0) - - PyObject * - PyUnicode_FromFormatV(const char *format, va_list vargs) -@@ -845,7 +850,7 @@ PyUnicode_FromFormatV(const char *format - str = PyObject_Str(obj); - if (!str) - goto fail; -- n += PyUnicode_GET_SIZE(str); -+ n += PyString_GET_SIZE(str); - /* Remember the str and switch to the next slot */ - *callresult++ = str; - break; -@@ -1006,15 +1011,10 @@ PyUnicode_FromFormatV(const char *format - case 'S': - case 'R': - { -- Py_UNICODE *ucopy; -- Py_ssize_t usize; -- Py_ssize_t upos; -+ const char *str = PyString_AS_STRING(*callresult); - /* unused, since we already have the result */ - (void) va_arg(vargs, PyObject *); -- ucopy = PyUnicode_AS_UNICODE(*callresult); -- usize = PyUnicode_GET_SIZE(*callresult); -- for (upos = 0; upos forget it */ - Py_DECREF(*callresult); - /* switch to next unicode()/repr() result */ - - -diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py -index f068ca6..883e93e 100644 ---- a/Lib/test/test_unicode.py -+++ b/Lib/test/test_unicode.py -@@ -1639,6 +1639,117 @@ class UnicodeTest( - self.assertEqual(u'{:{f}}{g}{}'.format(1, 3, g='g', f=2), u' 1g3') - self.assertEqual(u'{f:{}}{}{g}'.format(2, 4, f=1, g='g'), u' 14g') - -+ # Test PyUnicode_FromFormat() -+ def test_from_format(self): -+ test_support.import_module('ctypes') -+ from ctypes import ( -+ pythonapi, py_object, sizeof, -+ c_int, c_long, c_longlong, c_ssize_t, -+ c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p) -+ if sys.maxunicode == 0xffff: -+ name = "PyUnicodeUCS2_FromFormat" -+ else: -+ name = "PyUnicodeUCS4_FromFormat" -+ _PyUnicode_FromFormat = getattr(pythonapi, name) -+ _PyUnicode_FromFormat.restype = py_object -+ -+ def PyUnicode_FromFormat(format, *args): -+ cargs = tuple( -+ py_object(arg) if isinstance(arg, unicode) else arg -+ for arg in args) -+ return _PyUnicode_FromFormat(format, *cargs) -+ -+ def check_format(expected, format, *args): -+ text = PyUnicode_FromFormat(format, *args) -+ self.assertEqual(expected, text) -+ -+ # ascii format, non-ascii argument -+ check_format(u'ascii\x7f=unicode\xe9', -+ b'ascii\x7f=%U', u'unicode\xe9') -+ -+ # non-ascii format, ascii argument: ensure that PyUnicode_FromFormatV() -+ # raises an error -+ #self.assertRaisesRegex(ValueError, -+ # '^PyUnicode_FromFormatV\(\) expects an ASCII-encoded format ' -+ # 'string, got a non-ASCII byte: 0xe9$', -+ # PyUnicode_FromFormat, b'unicode\xe9=%s', u'ascii') -+ -+ # test "%c" -+ check_format(u'\uabcd', -+ b'%c', c_int(0xabcd)) -+ if sys.maxunicode > 0xffff: -+ check_format(u'\U0010ffff', -+ b'%c', c_int(0x10ffff)) -+ with self.assertRaises(OverflowError): -+ PyUnicode_FromFormat(b'%c', c_int(0x110000)) -+ # Issue #18183 -+ if sys.maxunicode > 0xffff: -+ check_format(u'\U00010000\U00100000', -+ b'%c%c', c_int(0x10000), c_int(0x100000)) -+ -+ # test "%" -+ check_format(u'%', -+ b'%') -+ check_format(u'%', -+ b'%%') -+ check_format(u'%s', -+ b'%%s') -+ check_format(u'[%]', -+ b'[%%]') -+ check_format(u'%abc', -+ b'%%%s', b'abc') -+ -+ # test %S -+ check_format(u"repr=abc", -+ b'repr=%S', u'abc') -+ -+ # test %R -+ check_format(u"repr=u'abc'", -+ b'repr=%R', u'abc') -+ -+ # test integer formats (%i, %d, %u) -+ check_format(u'010', -+ b'%03i', c_int(10)) -+ check_format(u'0010', -+ b'%0.4i', c_int(10)) -+ check_format(u'-123', -+ b'%i', c_int(-123)) -+ -+ check_format(u'-123', -+ b'%d', c_int(-123)) -+ check_format(u'-123', -+ b'%ld', c_long(-123)) -+ check_format(u'-123', -+ b'%zd', c_ssize_t(-123)) -+ -+ check_format(u'123', -+ b'%u', c_uint(123)) -+ check_format(u'123', -+ b'%lu', c_ulong(123)) -+ check_format(u'123', -+ b'%zu', c_size_t(123)) -+ -+ # test long output -+ PyUnicode_FromFormat(b'%p', c_void_p(-1)) -+ -+ # test %V -+ check_format(u'repr=abc', -+ b'repr=%V', u'abc', b'xyz') -+ check_format(u'repr=\xe4\xba\xba\xe6\xb0\x91', -+ b'repr=%V', None, b'\xe4\xba\xba\xe6\xb0\x91') -+ check_format(u'repr=abc\xff', -+ b'repr=%V', None, b'abc\xff') -+ -+ # not supported: copy the raw format string. these tests are just here -+ # to check for crashs and should not be considered as specifications -+ check_format(u'%s', -+ b'%1%s', b'abc') -+ check_format(u'%1abc', -+ b'%1abc') -+ check_format(u'%+i', -+ b'%+i', c_int(10)) -+ check_format(u'%s', -+ b'%.%s', b'abc') - def test_raiseMemError(self): - # Ensure that the freelist contains a consistent object, even - # when a string allocation fails with a MemoryError. diff --git a/SOURCES/00214-pep466-backport-py3-ssl-changes.patch b/SOURCES/00214-pep466-backport-py3-ssl-changes.patch deleted file mode 100644 index 094533f..0000000 --- a/SOURCES/00214-pep466-backport-py3-ssl-changes.patch +++ /dev/null @@ -1,12893 +0,0 @@ - -# HG changeset patch -# User Benjamin Peterson -# Date 1408562090 18000 -# Node ID 221a1f9155e2a8b4d12015261b83a2ce3a0c62a2 -# Parent c1edc4e43eb103254c5d96f1708542623fe08f17 -backport many ssl features from Python 3 (closes #21308) - -A contribution of Alex Gaynor and David Reid with the generous support of -Rackspace. May God have mercy on their souls. - -diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst ---- a/Doc/library/ssl.rst -+++ b/Doc/library/ssl.rst -@@ -28,19 +28,14 @@ probably additional platforms, as long a - - Some behavior may be platform dependent, since calls are made to the - operating system socket APIs. The installed version of OpenSSL may also -- cause variations in behavior. -+ cause variations in behavior. For example, TLSv1.1 and TLSv1.2 come with -+ openssl version 1.0.1. - - .. warning:: -- The ssl module won't validate certificates by default. When used in -- client mode, this means you are vulnerable to man-in-the-middle attacks. -+ Don't use this module without reading the :ref:`ssl-security`. Doing so -+ may lead to a false sense of security, as the default settings of the -+ ssl module are not necessarily appropriate for your application. - --.. warning:: -- -- OpenSSL's internal random number generator does not properly handle fork. -- Applications must change the PRNG state of the parent process if they use -- any SSL feature with :func:`os.fork`. Any successful call of -- :func:`~ssl.RAND_add`, :func:`~ssl.RAND_bytes` or -- :func:`~ssl.RAND_pseudo_bytes` is sufficient. - - This section documents the objects and functions in the ``ssl`` module; for more - general information about TLS, SSL, and certificates, the reader is referred to -@@ -49,23 +44,101 @@ the documents in the "See Also" section - This module provides a class, :class:`ssl.SSLSocket`, which is derived from the - :class:`socket.socket` type, and provides a socket-like wrapper that also - encrypts and decrypts the data going over the socket with SSL. It supports --additional :meth:`read` and :meth:`write` methods, along with a method, --:meth:`getpeercert`, to retrieve the certificate of the other side of the --connection, and a method, :meth:`cipher`, to retrieve the cipher being used for --the secure connection. -+additional methods such as :meth:`getpeercert`, which retrieves the -+certificate of the other side of the connection, and :meth:`cipher`,which -+retrieves the cipher being used for the secure connection. -+ -+For more sophisticated applications, the :class:`ssl.SSLContext` class -+helps manage settings and certificates, which can then be inherited -+by SSL sockets created through the :meth:`SSLContext.wrap_socket` method. -+ - - Functions, Constants, and Exceptions - ------------------------------------ - - .. exception:: SSLError - -- Raised to signal an error from the underlying SSL implementation. This -- signifies some problem in the higher-level encryption and authentication -- layer that's superimposed on the underlying network connection. This error -- is a subtype of :exc:`socket.error`, which in turn is a subtype of -- :exc:`IOError`. -+ Raised to signal an error from the underlying SSL implementation (currently -+ provided by the OpenSSL library). This signifies some problem in the -+ higher-level encryption and authentication layer that's superimposed on the -+ underlying network connection. This error is a subtype of -+ :exc:`socket.error`, which in turn is a subtype of :exc:`IOError`. The -+ error code and message of :exc:`SSLError` instances are provided by the -+ OpenSSL library. - --.. function:: wrap_socket (sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version={see docs}, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None) -+ .. attribute:: library -+ -+ A string mnemonic designating the OpenSSL submodule in which the error -+ occurred, such as ``SSL``, ``PEM`` or ``X509``. The range of possible -+ values depends on the OpenSSL version. -+ -+ .. versionadded:: 2.7.9 -+ -+ .. attribute:: reason -+ -+ A string mnemonic designating the reason this error occurred, for -+ example ``CERTIFICATE_VERIFY_FAILED``. The range of possible -+ values depends on the OpenSSL version. -+ -+ .. versionadded:: 2.7.9 -+ -+.. exception:: SSLZeroReturnError -+ -+ A subclass of :exc:`SSLError` raised when trying to read or write and -+ the SSL connection has been closed cleanly. Note that this doesn't -+ mean that the underlying transport (read TCP) has been closed. -+ -+ .. versionadded:: 2.7.9 -+ -+.. exception:: SSLWantReadError -+ -+ A subclass of :exc:`SSLError` raised by a :ref:`non-blocking SSL socket -+ ` when trying to read or write data, but more data needs -+ to be received on the underlying TCP transport before the request can be -+ fulfilled. -+ -+ .. versionadded:: 2.7.9 -+ -+.. exception:: SSLWantWriteError -+ -+ A subclass of :exc:`SSLError` raised by a :ref:`non-blocking SSL socket -+ ` when trying to read or write data, but more data needs -+ to be sent on the underlying TCP transport before the request can be -+ fulfilled. -+ -+ .. versionadded:: 2.7.9 -+ -+.. exception:: SSLSyscallError -+ -+ A subclass of :exc:`SSLError` raised when a system error was encountered -+ while trying to fulfill an operation on a SSL socket. Unfortunately, -+ there is no easy way to inspect the original errno number. -+ -+ .. versionadded:: 2.7.9 -+ -+.. exception:: SSLEOFError -+ -+ A subclass of :exc:`SSLError` raised when the SSL connection has been -+ terminated abruptly. Generally, you shouldn't try to reuse the underlying -+ transport when this error is encountered. -+ -+ .. versionadded:: 2.7.9 -+ -+.. exception:: CertificateError -+ -+ Raised to signal an error with a certificate (such as mismatching -+ hostname). Certificate errors detected by OpenSSL, though, raise -+ an :exc:`SSLError`. -+ -+ -+Socket creation -+^^^^^^^^^^^^^^^ -+ -+The following function allows for standalone socket creation. Starting from -+Python 2.7.9, it can be more flexible to use :meth:`SSLContext.wrap_socket` -+instead. -+ -+.. function:: wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version={see docs}, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None) - - Takes an instance ``sock`` of :class:`socket.socket`, and returns an instance - of :class:`ssl.SSLSocket`, a subtype of :class:`socket.socket`, which wraps -@@ -85,19 +158,6 @@ Functions, Constants, and Exceptions - connection. See the discussion of :ref:`ssl-certificates` for more - information on how the certificate is stored in the ``certfile``. - -- Often the private key is stored in the same file as the certificate; in this -- case, only the ``certfile`` parameter need be passed. If the private key is -- stored in a separate file, both parameters must be used. If the private key -- is stored in the ``certfile``, it should come before the first certificate in -- the certificate chain:: -- -- -----BEGIN RSA PRIVATE KEY----- -- ... (private key in base64 encoding) ... -- -----END RSA PRIVATE KEY----- -- -----BEGIN CERTIFICATE----- -- ... (certificate in base64 PEM encoding) ... -- -----END CERTIFICATE----- -- - The parameter ``server_side`` is a boolean which identifies whether - server-side or client-side behavior is desired from this socket. - -@@ -127,14 +187,16 @@ Functions, Constants, and Exceptions - - .. table:: - -- ======================== ========= ========= ========== ========= -- *client* / **server** **SSLv2** **SSLv3** **SSLv23** **TLSv1** -- ------------------------ --------- --------- ---------- --------- -- *SSLv2* yes no yes no -- *SSLv3* no yes yes no -- *SSLv23* yes no yes no -- *TLSv1* no no yes yes -- ======================== ========= ========= ========== ========= -+ ======================== ========= ========= ========== ========= =========== =========== -+ *client* / **server** **SSLv2** **SSLv3** **SSLv23** **TLSv1** **TLSv1.1** **TLSv1.2** -+ ------------------------ --------- --------- ---------- --------- ----------- ----------- -+ *SSLv2* yes no yes no no no -+ *SSLv3* no yes yes no no no -+ *SSLv23* yes no yes no no no -+ *TLSv1* no no yes yes no no -+ *TLSv1.1* no no yes no yes no -+ *TLSv1.2* no no yes no no yes -+ ======================== ========= ========= ========== ========= =========== =========== - - .. note:: - -@@ -161,22 +223,79 @@ Functions, Constants, and Exceptions - The parameter ``suppress_ragged_eofs`` specifies how the - :meth:`SSLSocket.read` method should signal unexpected EOF from the other end - of the connection. If specified as :const:`True` (the default), it returns a -- normal EOF in response to unexpected EOF errors raised from the underlying -- socket; if :const:`False`, it will raise the exceptions back to the caller. -+ normal EOF (an empty bytes object) in response to unexpected EOF errors -+ raised from the underlying socket; if :const:`False`, it will raise the -+ exceptions back to the caller. - - .. versionchanged:: 2.7 - New optional argument *ciphers*. - -+ -+Context creation -+^^^^^^^^^^^^^^^^ -+ -+A convenience function helps create :class:`SSLContext` objects for common -+purposes. -+ -+.. function:: create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, capath=None, cadata=None) -+ -+ Return a new :class:`SSLContext` object with default settings for -+ the given *purpose*. The settings are chosen by the :mod:`ssl` module, -+ and usually represent a higher security level than when calling the -+ :class:`SSLContext` constructor directly. -+ -+ *cafile*, *capath*, *cadata* represent optional CA certificates to -+ trust for certificate verification, as in -+ :meth:`SSLContext.load_verify_locations`. If all three are -+ :const:`None`, this function can choose to trust the system's default -+ CA certificates instead. -+ -+ The settings in Python 2.7.9 are: :data:`PROTOCOL_SSLv23`, -+ :data:`OP_NO_SSLv2`, and :data:`OP_NO_SSLv3` with high encryption cipher -+ suites without RC4 and without unauthenticated cipher suites. Passing -+ :data:`~Purpose.SERVER_AUTH` as *purpose* sets -+ :data:`~SSLContext.verify_mode` to :data:`CERT_REQUIRED` and either loads CA -+ certificates (when at least one of *cafile*, *capath* or *cadata* is given) -+ or uses :meth:`SSLContext.load_default_certs` to load default CA -+ certificates. -+ -+ .. note:: -+ The protocol, options, cipher and other settings may change to more -+ restrictive values anytime without prior deprecation. The values -+ represent a fair balance between compatibility and security. -+ -+ If your application needs specific settings, you should create a -+ :class:`SSLContext` and apply the settings yourself. -+ -+ .. note:: -+ If you find that when certain older clients or servers attempt to connect -+ with a :class:`SSLContext` created by this function that they get an -+ error stating "Protocol or cipher suite mismatch", it may be that they -+ only support SSL3.0 which this function excludes using the -+ :data:`OP_NO_SSLv3`. SSL3.0 has problematic security due to a number of -+ poor implementations and it's reliance on MD5 within the protocol. If you -+ wish to continue to use this function but still allow SSL 3.0 connections -+ you can re-enable them using:: -+ -+ ctx = ssl.create_default_context(Purpose.CLIENT_AUTH) -+ ctx.options &= ~ssl.OP_NO_SSLv3 -+ -+ .. versionadded:: 2.7.9 -+ -+ -+Random generation -+^^^^^^^^^^^^^^^^^ -+ - .. function:: RAND_status() - - Returns ``True`` if the SSL pseudo-random number generator has been seeded with -- 'enough' randomness, and False otherwise. You can use :func:`ssl.RAND_egd` -+ 'enough' randomness, and ``False`` otherwise. You can use :func:`ssl.RAND_egd` - and :func:`ssl.RAND_add` to increase the randomness of the pseudo-random - number generator. - - .. function:: RAND_egd(path) - -- If you are running an entropy-gathering daemon (EGD) somewhere, and ``path`` -+ If you are running an entropy-gathering daemon (EGD) somewhere, and *path* - is the pathname of a socket connection open to it, this will read 256 bytes - of randomness from the socket, and add it to the SSL pseudo-random number - generator to increase the security of generated secret keys. This is -@@ -187,28 +306,66 @@ Functions, Constants, and Exceptions - - .. function:: RAND_add(bytes, entropy) - -- Mixes the given ``bytes`` into the SSL pseudo-random number generator. The -- parameter ``entropy`` (a float) is a lower bound on the entropy contained in -+ Mixes the given *bytes* into the SSL pseudo-random number generator. The -+ parameter *entropy* (a float) is a lower bound on the entropy contained in - string (so you can always use :const:`0.0`). See :rfc:`1750` for more - information on sources of entropy. - --.. function:: cert_time_to_seconds(timestring) -+Certificate handling -+^^^^^^^^^^^^^^^^^^^^ - -- Returns a floating-point value containing a normal seconds-after-the-epoch -- time value, given the time-string representing the "notBefore" or "notAfter" -- date from a certificate. -+.. function:: match_hostname(cert, hostname) - -- Here's an example:: -+ Verify that *cert* (in decoded format as returned by -+ :meth:`SSLSocket.getpeercert`) matches the given *hostname*. The rules -+ applied are those for checking the identity of HTTPS servers as outlined -+ in :rfc:`2818` and :rfc:`6125`, except that IP addresses are not currently -+ supported. In addition to HTTPS, this function should be suitable for -+ checking the identity of servers in various SSL-based protocols such as -+ FTPS, IMAPS, POPS and others. - -- >>> import ssl -- >>> ssl.cert_time_to_seconds("May 9 00:00:00 2007 GMT") -- 1178694000.0 -- >>> import time -- >>> time.ctime(ssl.cert_time_to_seconds("May 9 00:00:00 2007 GMT")) -- 'Wed May 9 00:00:00 2007' -- >>> -+ :exc:`CertificateError` is raised on failure. On success, the function -+ returns nothing:: - --.. function:: get_server_certificate (addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None) -+ >>> cert = {'subject': ((('commonName', 'example.com'),),)} -+ >>> ssl.match_hostname(cert, "example.com") -+ >>> ssl.match_hostname(cert, "example.org") -+ Traceback (most recent call last): -+ File "", line 1, in -+ File "/home/py3k/Lib/ssl.py", line 130, in match_hostname -+ ssl.CertificateError: hostname 'example.org' doesn't match 'example.com' -+ -+ .. versionadded:: 2.7.9 -+ -+ -+.. function:: cert_time_to_seconds(cert_time) -+ -+ Return the time in seconds since the Epoch, given the ``cert_time`` -+ string representing the "notBefore" or "notAfter" date from a -+ certificate in ``"%b %d %H:%M:%S %Y %Z"`` strptime format (C -+ locale). -+ -+ Here's an example: -+ -+ .. doctest:: newcontext -+ -+ >>> import ssl -+ >>> timestamp = ssl.cert_time_to_seconds("Jan 5 09:34:43 2018 GMT") -+ >>> timestamp -+ 1515144883 -+ >>> from datetime import datetime -+ >>> print(datetime.utcfromtimestamp(timestamp)) -+ 2018-01-05 09:34:43 -+ -+ "notBefore" or "notAfter" dates must use GMT (:rfc:`5280`). -+ -+ .. versionchanged:: 2.7.9 -+ Interpret the input time as a time in UTC as specified by 'GMT' -+ timezone in the input string. Local timezone was used -+ previously. Return an integer (no fractions of a second in the -+ input format) -+ -+.. function:: get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None) - - Given the address ``addr`` of an SSL-protected server, as a (*hostname*, - *port-number*) pair, fetches the server's certificate, and returns it as a -@@ -219,36 +376,144 @@ Functions, Constants, and Exceptions - will attempt to validate the server certificate against that set of root - certificates, and will fail if the validation attempt fails. - --.. function:: DER_cert_to_PEM_cert (DER_cert_bytes) -+ .. versionchanged:: 2.7.9 -+ -+ This function is now IPv6-compatible, and the default *ssl_version* is -+ changed from :data:`PROTOCOL_SSLv3` to :data:`PROTOCOL_SSLv23` for -+ maximum compatibility with modern servers. -+ -+.. function:: DER_cert_to_PEM_cert(DER_cert_bytes) - - Given a certificate as a DER-encoded blob of bytes, returns a PEM-encoded - string version of the same certificate. - --.. function:: PEM_cert_to_DER_cert (PEM_cert_string) -+.. function:: PEM_cert_to_DER_cert(PEM_cert_string) - - Given a certificate as an ASCII PEM string, returns a DER-encoded sequence of - bytes for that same certificate. - -+.. function:: get_default_verify_paths() -+ -+ Returns a named tuple with paths to OpenSSL's default cafile and capath. -+ The paths are the same as used by -+ :meth:`SSLContext.set_default_verify_paths`. The return value is a -+ :term:`named tuple` ``DefaultVerifyPaths``: -+ -+ * :attr:`cafile` - resolved path to cafile or None if the file doesn't exist, -+ * :attr:`capath` - resolved path to capath or None if the directory doesn't exist, -+ * :attr:`openssl_cafile_env` - OpenSSL's environment key that points to a cafile, -+ * :attr:`openssl_cafile` - hard coded path to a cafile, -+ * :attr:`openssl_capath_env` - OpenSSL's environment key that points to a capath, -+ * :attr:`openssl_capath` - hard coded path to a capath directory -+ -+ .. versionadded:: 2.7.9 -+ -+.. function:: enum_certificates(store_name) -+ -+ Retrieve certificates from Windows' system cert store. *store_name* may be -+ one of ``CA``, ``ROOT`` or ``MY``. Windows may provide additional cert -+ stores, too. -+ -+ The function returns a list of (cert_bytes, encoding_type, trust) tuples. -+ The encoding_type specifies the encoding of cert_bytes. It is either -+ :const:`x509_asn` for X.509 ASN.1 data or :const:`pkcs_7_asn` for -+ PKCS#7 ASN.1 data. Trust specifies the purpose of the certificate as a set -+ of OIDS or exactly ``True`` if the certificate is trustworthy for all -+ purposes. -+ -+ Example:: -+ -+ >>> ssl.enum_certificates("CA") -+ [(b'data...', 'x509_asn', {'1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2'}), -+ (b'data...', 'x509_asn', True)] -+ -+ Availability: Windows. -+ -+ .. versionadded:: 2.7.9 -+ -+.. function:: enum_crls(store_name) -+ -+ Retrieve CRLs from Windows' system cert store. *store_name* may be -+ one of ``CA``, ``ROOT`` or ``MY``. Windows may provide additional cert -+ stores, too. -+ -+ The function returns a list of (cert_bytes, encoding_type, trust) tuples. -+ The encoding_type specifies the encoding of cert_bytes. It is either -+ :const:`x509_asn` for X.509 ASN.1 data or :const:`pkcs_7_asn` for -+ PKCS#7 ASN.1 data. -+ -+ Availability: Windows. -+ -+ .. versionadded:: 2.7.9 -+ -+ -+Constants -+^^^^^^^^^ -+ - .. data:: CERT_NONE - -- Value to pass to the ``cert_reqs`` parameter to :func:`sslobject` when no -- certificates will be required or validated from the other side of the socket -- connection. -+ Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs`` -+ parameter to :func:`wrap_socket`. In this mode (the default), no -+ certificates will be required from the other side of the socket connection. -+ If a certificate is received from the other end, no attempt to validate it -+ is made. -+ -+ See the discussion of :ref:`ssl-security` below. - - .. data:: CERT_OPTIONAL - -- Value to pass to the ``cert_reqs`` parameter to :func:`sslobject` when no -- certificates will be required from the other side of the socket connection, -- but if they are provided, will be validated. Note that use of this setting -- requires a valid certificate validation file also be passed as a value of the -- ``ca_certs`` parameter. -+ Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs`` -+ parameter to :func:`wrap_socket`. In this mode no certificates will be -+ required from the other side of the socket connection; but if they -+ are provided, validation will be attempted and an :class:`SSLError` -+ will be raised on failure. -+ -+ Use of this setting requires a valid set of CA certificates to -+ be passed, either to :meth:`SSLContext.load_verify_locations` or as a -+ value of the ``ca_certs`` parameter to :func:`wrap_socket`. - - .. data:: CERT_REQUIRED - -- Value to pass to the ``cert_reqs`` parameter to :func:`sslobject` when -- certificates will be required from the other side of the socket connection. -- Note that use of this setting requires a valid certificate validation file -- also be passed as a value of the ``ca_certs`` parameter. -+ Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs`` -+ parameter to :func:`wrap_socket`. In this mode, certificates are -+ required from the other side of the socket connection; an :class:`SSLError` -+ will be raised if no certificate is provided, or if its validation fails. -+ -+ Use of this setting requires a valid set of CA certificates to -+ be passed, either to :meth:`SSLContext.load_verify_locations` or as a -+ value of the ``ca_certs`` parameter to :func:`wrap_socket`. -+ -+.. data:: VERIFY_DEFAULT -+ -+ Possible value for :attr:`SSLContext.verify_flags`. In this mode, -+ certificate revocation lists (CRLs) are not checked. By default OpenSSL -+ does neither require nor verify CRLs. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: VERIFY_CRL_CHECK_LEAF -+ -+ Possible value for :attr:`SSLContext.verify_flags`. In this mode, only the -+ peer cert is check but non of the intermediate CA certificates. The mode -+ requires a valid CRL that is signed by the peer cert's issuer (its direct -+ ancestor CA). If no proper has been loaded -+ :attr:`SSLContext.load_verify_locations`, validation will fail. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: VERIFY_CRL_CHECK_CHAIN -+ -+ Possible value for :attr:`SSLContext.verify_flags`. In this mode, CRLs of -+ all certificates in the peer cert chain are checked. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: VERIFY_X509_STRICT -+ -+ Possible value for :attr:`SSLContext.verify_flags` to disable workarounds -+ for broken X.509 certificates. -+ -+ .. versionadded:: 2.7.9 - - .. data:: PROTOCOL_SSLv2 - -@@ -275,9 +540,136 @@ Functions, Constants, and Exceptions - - .. data:: PROTOCOL_TLSv1 - -- Selects TLS version 1 as the channel encryption protocol. This is the most -+ Selects TLS version 1.0 as the channel encryption protocol. -+ -+.. data:: PROTOCOL_TLSv1_1 -+ -+ Selects TLS version 1.1 as the channel encryption protocol. -+ Available only with openssl version 1.0.1+. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: PROTOCOL_TLSv1_2 -+ -+ Selects TLS version 1.2 as the channel encryption protocol. This is the most - modern version, and probably the best choice for maximum protection, if both -- sides can speak it. -+ sides can speak it. Available only with openssl version 1.0.1+. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_ALL -+ -+ Enables workarounds for various bugs present in other SSL implementations. -+ This option is set by default. It does not necessarily set the same -+ flags as OpenSSL's ``SSL_OP_ALL`` constant. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_NO_SSLv2 -+ -+ Prevents an SSLv2 connection. This option is only applicable in -+ conjunction with :const:`PROTOCOL_SSLv23`. It prevents the peers from -+ choosing SSLv2 as the protocol version. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_NO_SSLv3 -+ -+ Prevents an SSLv3 connection. This option is only applicable in -+ conjunction with :const:`PROTOCOL_SSLv23`. It prevents the peers from -+ choosing SSLv3 as the protocol version. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_NO_TLSv1 -+ -+ Prevents a TLSv1 connection. This option is only applicable in -+ conjunction with :const:`PROTOCOL_SSLv23`. It prevents the peers from -+ choosing TLSv1 as the protocol version. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_NO_TLSv1_1 -+ -+ Prevents a TLSv1.1 connection. This option is only applicable in conjunction -+ with :const:`PROTOCOL_SSLv23`. It prevents the peers from choosing TLSv1.1 as -+ the protocol version. Available only with openssl version 1.0.1+. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_NO_TLSv1_2 -+ -+ Prevents a TLSv1.2 connection. This option is only applicable in conjunction -+ with :const:`PROTOCOL_SSLv23`. It prevents the peers from choosing TLSv1.2 as -+ the protocol version. Available only with openssl version 1.0.1+. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_CIPHER_SERVER_PREFERENCE -+ -+ Use the server's cipher ordering preference, rather than the client's. -+ This option has no effect on client sockets and SSLv2 server sockets. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_SINGLE_DH_USE -+ -+ Prevents re-use of the same DH key for distinct SSL sessions. This -+ improves forward secrecy but requires more computational resources. -+ This option only applies to server sockets. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_SINGLE_ECDH_USE -+ -+ Prevents re-use of the same ECDH key for distinct SSL sessions. This -+ improves forward secrecy but requires more computational resources. -+ This option only applies to server sockets. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: OP_NO_COMPRESSION -+ -+ Disable compression on the SSL channel. This is useful if the application -+ protocol supports its own compression scheme. -+ -+ This option is only available with OpenSSL 1.0.0 and later. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: HAS_ECDH -+ -+ Whether the OpenSSL library has built-in support for Elliptic Curve-based -+ Diffie-Hellman key exchange. This should be true unless the feature was -+ explicitly disabled by the distributor. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: HAS_SNI -+ -+ Whether the OpenSSL library has built-in support for the *Server Name -+ Indication* extension to the SSLv3 and TLSv1 protocols (as defined in -+ :rfc:`4366`). When true, you can use the *server_hostname* argument to -+ :meth:`SSLContext.wrap_socket`. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: HAS_NPN -+ -+ Whether the OpenSSL library has built-in support for *Next Protocol -+ Negotiation* as described in the `NPN draft specification -+ `_. When true, -+ you can use the :meth:`SSLContext.set_npn_protocols` method to advertise -+ which protocols you want to support. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: CHANNEL_BINDING_TYPES -+ -+ List of supported TLS channel binding types. Strings in this list -+ can be used as arguments to :meth:`SSLSocket.get_channel_binding`. -+ -+ .. versionadded:: 2.7.9 - - .. data:: OPENSSL_VERSION - -@@ -309,9 +701,40 @@ Functions, Constants, and Exceptions - - .. versionadded:: 2.7 - -+.. data:: ALERT_DESCRIPTION_HANDSHAKE_FAILURE -+ ALERT_DESCRIPTION_INTERNAL_ERROR -+ ALERT_DESCRIPTION_* - --SSLSocket Objects ------------------- -+ Alert Descriptions from :rfc:`5246` and others. The `IANA TLS Alert Registry -+ `_ -+ contains this list and references to the RFCs where their meaning is defined. -+ -+ Used as the return value of the callback function in -+ :meth:`SSLContext.set_servername_callback`. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: Purpose.SERVER_AUTH -+ -+ Option for :func:`create_default_context` and -+ :meth:`SSLContext.load_default_certs`. This value indicates that the -+ context may be used to authenticate Web servers (therefore, it will -+ be used to create client-side sockets). -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: Purpose.CLIENT_AUTH -+ -+ Option for :func:`create_default_context` and -+ :meth:`SSLContext.load_default_certs`. This value indicates that the -+ context may be used to authenticate Web clients (therefore, it will -+ be used to create server-side sockets). -+ -+ .. versionadded:: 2.7.9 -+ -+ -+SSL Sockets -+----------- - - SSL sockets provide the following methods of :ref:`socket-objects`: - -@@ -334,37 +757,64 @@ SSL sockets provide the following method - - However, since the SSL (and TLS) protocol has its own framing atop - of TCP, the SSL sockets abstraction can, in certain respects, diverge from --the specification of normal, OS-level sockets. -+the specification of normal, OS-level sockets. See especially the -+:ref:`notes on non-blocking sockets `. - - SSL sockets also have the following additional methods and attributes: - -+.. method:: SSLSocket.do_handshake() -+ -+ Perform the SSL setup handshake. -+ -+ .. versionchanged:: 2.7.9 -+ -+ The handshake method also performs :func:`match_hostname` when the -+ :attr:`~SSLContext.check_hostname` attribute of the socket's -+ :attr:`~SSLSocket.context` is true. -+ - .. method:: SSLSocket.getpeercert(binary_form=False) - - If there is no certificate for the peer on the other end of the connection, -- returns ``None``. -+ return ``None``. If the SSL handshake hasn't been done yet, raise -+ :exc:`ValueError`. - - If the ``binary_form`` parameter is :const:`False`, and a certificate was - received from the peer, this method returns a :class:`dict` instance. If the - certificate was not validated, the dict is empty. If the certificate was -- validated, it returns a dict with the keys ``subject`` (the principal for -- which the certificate was issued), and ``notAfter`` (the time after which the -- certificate should not be trusted). The certificate was already validated, -- so the ``notBefore`` and ``issuer`` fields are not returned. If a -- certificate contains an instance of the *Subject Alternative Name* extension -- (see :rfc:`3280`), there will also be a ``subjectAltName`` key in the -- dictionary. -+ validated, it returns a dict with several keys, amongst them ``subject`` -+ (the principal for which the certificate was issued) and ``issuer`` -+ (the principal issuing the certificate). If a certificate contains an -+ instance of the *Subject Alternative Name* extension (see :rfc:`3280`), -+ there will also be a ``subjectAltName`` key in the dictionary. - -- The "subject" field is a tuple containing the sequence of relative -- distinguished names (RDNs) given in the certificate's data structure for the -- principal, and each RDN is a sequence of name-value pairs:: -+ The ``subject`` and ``issuer`` fields are tuples containing the sequence -+ of relative distinguished names (RDNs) given in the certificate's data -+ structure for the respective fields, and each RDN is a sequence of -+ name-value pairs. Here is a real-world example:: - -- {'notAfter': 'Feb 16 16:54:50 2013 GMT', -- 'subject': ((('countryName', u'US'),), -- (('stateOrProvinceName', u'Delaware'),), -- (('localityName', u'Wilmington'),), -- (('organizationName', u'Python Software Foundation'),), -- (('organizationalUnitName', u'SSL'),), -- (('commonName', u'somemachine.python.org'),))} -+ {'issuer': ((('countryName', 'IL'),), -+ (('organizationName', 'StartCom Ltd.'),), -+ (('organizationalUnitName', -+ 'Secure Digital Certificate Signing'),), -+ (('commonName', -+ 'StartCom Class 2 Primary Intermediate Server CA'),)), -+ 'notAfter': 'Nov 22 08:15:19 2013 GMT', -+ 'notBefore': 'Nov 21 03:09:52 2011 GMT', -+ 'serialNumber': '95F0', -+ 'subject': ((('description', '571208-SLe257oHY9fVQ07Z'),), -+ (('countryName', 'US'),), -+ (('stateOrProvinceName', 'California'),), -+ (('localityName', 'San Francisco'),), -+ (('organizationName', 'Electronic Frontier Foundation, Inc.'),), -+ (('commonName', '*.eff.org'),), -+ (('emailAddress', 'hostmaster@eff.org'),)), -+ 'subjectAltName': (('DNS', '*.eff.org'), ('DNS', 'eff.org')), -+ 'version': 3} -+ -+ .. note:: -+ -+ To validate a certificate for a particular service, you can use the -+ :func:`match_hostname` function. - - If the ``binary_form`` parameter is :const:`True`, and a certificate was - provided, this method returns the DER-encoded form of the entire certificate -@@ -380,40 +830,388 @@ SSL sockets also have the following addi - :const:`None` if you used :const:`CERT_NONE` (rather than - :const:`CERT_OPTIONAL` or :const:`CERT_REQUIRED`). - -+ .. versionchanged:: 2.7.9 -+ The returned dictionary includes additional items such as ``issuer`` and -+ ``notBefore``. Additionall :exc:`ValueError` is raised when the handshake -+ isn't done. The returned dictionary includes additional X509v3 extension -+ items such as ``crlDistributionPoints``, ``caIssuers`` and ``OCSP`` URIs. -+ - .. method:: SSLSocket.cipher() - - Returns a three-value tuple containing the name of the cipher being used, the - version of the SSL protocol that defines its use, and the number of secret - bits being used. If no connection has been established, returns ``None``. - --.. method:: SSLSocket.do_handshake() -+.. method:: SSLSocket.compression() - -- Perform a TLS/SSL handshake. If this is used with a non-blocking socket, it -- may raise :exc:`SSLError` with an ``arg[0]`` of :const:`SSL_ERROR_WANT_READ` -- or :const:`SSL_ERROR_WANT_WRITE`, in which case it must be called again until -- it completes successfully. For example, to simulate the behavior of a -- blocking socket, one might write:: -+ Return the compression algorithm being used as a string, or ``None`` -+ if the connection isn't compressed. - -- while True: -- try: -- s.do_handshake() -- break -- except ssl.SSLError as err: -- if err.args[0] == ssl.SSL_ERROR_WANT_READ: -- select.select([s], [], []) -- elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: -- select.select([], [s], []) -- else: -- raise -+ If the higher-level protocol supports its own compression mechanism, -+ you can use :data:`OP_NO_COMPRESSION` to disable SSL-level compression. -+ -+ .. versionadded:: 2.7.9 -+ -+.. method:: SSLSocket.get_channel_binding(cb_type="tls-unique") -+ -+ Get channel binding data for current connection, as a bytes object. Returns -+ ``None`` if not connected or the handshake has not been completed. -+ -+ The *cb_type* parameter allow selection of the desired channel binding -+ type. Valid channel binding types are listed in the -+ :data:`CHANNEL_BINDING_TYPES` list. Currently only the 'tls-unique' channel -+ binding, defined by :rfc:`5929`, is supported. :exc:`ValueError` will be -+ raised if an unsupported channel binding type is requested. -+ -+ .. versionadded:: 2.7.9 -+ -+.. method:: SSLSocket.selected_npn_protocol() -+ -+ Returns the protocol that was selected during the TLS/SSL handshake. If -+ :meth:`SSLContext.set_npn_protocols` was not called, or if the other party -+ does not support NPN, or if the handshake has not yet happened, this will -+ return ``None``. -+ -+ .. versionadded:: 2.7.9 - - .. method:: SSLSocket.unwrap() - - Performs the SSL shutdown handshake, which removes the TLS layer from the - underlying socket, and returns the underlying socket object. This can be - used to go from encrypted operation over a connection to unencrypted. The -- socket instance returned should always be used for further communication with -- the other side of the connection, rather than the original socket instance -- (which may not function properly after the unwrap). -+ returned socket should always be used for further communication with the -+ other side of the connection, rather than the original socket. -+ -+.. attribute:: SSLSocket.context -+ -+ The :class:`SSLContext` object this SSL socket is tied to. If the SSL -+ socket was created using the top-level :func:`wrap_socket` function -+ (rather than :meth:`SSLContext.wrap_socket`), this is a custom context -+ object created for this SSL socket. -+ -+ .. versionadded:: 2.7.9 -+ -+ -+SSL Contexts -+------------ -+ -+.. versionadded:: 2.7.9 -+ -+An SSL context holds various data longer-lived than single SSL connections, -+such as SSL configuration options, certificate(s) and private key(s). -+It also manages a cache of SSL sessions for server-side sockets, in order -+to speed up repeated connections from the same clients. -+ -+.. class:: SSLContext(protocol) -+ -+ Create a new SSL context. You must pass *protocol* which must be one -+ of the ``PROTOCOL_*`` constants defined in this module. -+ :data:`PROTOCOL_SSLv23` is currently recommended for maximum -+ interoperability. -+ -+ .. seealso:: -+ :func:`create_default_context` lets the :mod:`ssl` module choose -+ security settings for a given purpose. -+ -+ -+:class:`SSLContext` objects have the following methods and attributes: -+ -+.. method:: SSLContext.cert_store_stats() -+ -+ Get statistics about quantities of loaded X.509 certificates, count of -+ X.509 certificates flagged as CA certificates and certificate revocation -+ lists as dictionary. -+ -+ Example for a context with one CA cert and one other cert:: -+ -+ >>> context.cert_store_stats() -+ {'crl': 0, 'x509_ca': 1, 'x509': 2} -+ -+ -+.. method:: SSLContext.load_cert_chain(certfile, keyfile=None, password=None) -+ -+ Load a private key and the corresponding certificate. The *certfile* -+ string must be the path to a single file in PEM format containing the -+ certificate as well as any number of CA certificates needed to establish -+ the certificate's authenticity. The *keyfile* string, if present, must -+ point to a file containing the private key in. Otherwise the private -+ key will be taken from *certfile* as well. See the discussion of -+ :ref:`ssl-certificates` for more information on how the certificate -+ is stored in the *certfile*. -+ -+ The *password* argument may be a function to call to get the password for -+ decrypting the private key. It will only be called if the private key is -+ encrypted and a password is necessary. It will be called with no arguments, -+ and it should return a string, bytes, or bytearray. If the return value is -+ a string it will be encoded as UTF-8 before using it to decrypt the key. -+ Alternatively a string, bytes, or bytearray value may be supplied directly -+ as the *password* argument. It will be ignored if the private key is not -+ encrypted and no password is needed. -+ -+ If the *password* argument is not specified and a password is required, -+ OpenSSL's built-in password prompting mechanism will be used to -+ interactively prompt the user for a password. -+ -+ An :class:`SSLError` is raised if the private key doesn't -+ match with the certificate. -+ -+.. method:: SSLContext.load_default_certs(purpose=Purpose.SERVER_AUTH) -+ -+ Load a set of default "certification authority" (CA) certificates from -+ default locations. On Windows it loads CA certs from the ``CA`` and -+ ``ROOT`` system stores. On other systems it calls -+ :meth:`SSLContext.set_default_verify_paths`. In the future the method may -+ load CA certificates from other locations, too. -+ -+ The *purpose* flag specifies what kind of CA certificates are loaded. The -+ default settings :data:`Purpose.SERVER_AUTH` loads certificates, that are -+ flagged and trusted for TLS web server authentication (client side -+ sockets). :data:`Purpose.CLIENT_AUTH` loads CA certificates for client -+ certificate verification on the server side. -+ -+.. method:: SSLContext.load_verify_locations(cafile=None, capath=None, cadata=None) -+ -+ Load a set of "certification authority" (CA) certificates used to validate -+ other peers' certificates when :data:`verify_mode` is other than -+ :data:`CERT_NONE`. At least one of *cafile* or *capath* must be specified. -+ -+ This method can also load certification revocation lists (CRLs) in PEM or -+ DER format. In order to make use of CRLs, :attr:`SSLContext.verify_flags` -+ must be configured properly. -+ -+ The *cafile* string, if present, is the path to a file of concatenated -+ CA certificates in PEM format. See the discussion of -+ :ref:`ssl-certificates` for more information about how to arrange the -+ certificates in this file. -+ -+ The *capath* string, if present, is -+ the path to a directory containing several CA certificates in PEM format, -+ following an `OpenSSL specific layout -+ `_. -+ -+ The *cadata* object, if present, is either an ASCII string of one or more -+ PEM-encoded certificates or a bytes-like object of DER-encoded -+ certificates. Like with *capath* extra lines around PEM-encoded -+ certificates are ignored but at least one certificate must be present. -+ -+.. method:: SSLContext.get_ca_certs(binary_form=False) -+ -+ Get a list of loaded "certification authority" (CA) certificates. If the -+ ``binary_form`` parameter is :const:`False` each list -+ entry is a dict like the output of :meth:`SSLSocket.getpeercert`. Otherwise -+ the method returns a list of DER-encoded certificates. The returned list -+ does not contain certificates from *capath* unless a certificate was -+ requested and loaded by a SSL connection. -+ -+.. method:: SSLContext.set_default_verify_paths() -+ -+ Load a set of default "certification authority" (CA) certificates from -+ a filesystem path defined when building the OpenSSL library. Unfortunately, -+ there's no easy way to know whether this method succeeds: no error is -+ returned if no certificates are to be found. When the OpenSSL library is -+ provided as part of the operating system, though, it is likely to be -+ configured properly. -+ -+.. method:: SSLContext.set_ciphers(ciphers) -+ -+ Set the available ciphers for sockets created with this context. -+ It should be a string in the `OpenSSL cipher list format -+ `_. -+ If no cipher can be selected (because compile-time options or other -+ configuration forbids use of all the specified ciphers), an -+ :class:`SSLError` will be raised. -+ -+ .. note:: -+ when connected, the :meth:`SSLSocket.cipher` method of SSL sockets will -+ give the currently selected cipher. -+ -+.. method:: SSLContext.set_npn_protocols(protocols) -+ -+ Specify which protocols the socket should advertise during the SSL/TLS -+ handshake. It should be a list of strings, like ``['http/1.1', 'spdy/2']``, -+ ordered by preference. The selection of a protocol will happen during the -+ handshake, and will play out according to the `NPN draft specification -+ `_. After a -+ successful handshake, the :meth:`SSLSocket.selected_npn_protocol` method will -+ return the agreed-upon protocol. -+ -+ This method will raise :exc:`NotImplementedError` if :data:`HAS_NPN` is -+ False. -+ -+.. method:: SSLContext.set_servername_callback(server_name_callback) -+ -+ Register a callback function that will be called after the TLS Client Hello -+ handshake message has been received by the SSL/TLS server when the TLS client -+ specifies a server name indication. The server name indication mechanism -+ is specified in :rfc:`6066` section 3 - Server Name Indication. -+ -+ Only one callback can be set per ``SSLContext``. If *server_name_callback* -+ is ``None`` then the callback is disabled. Calling this function a -+ subsequent time will disable the previously registered callback. -+ -+ The callback function, *server_name_callback*, will be called with three -+ arguments; the first being the :class:`ssl.SSLSocket`, the second is a string -+ that represents the server name that the client is intending to communicate -+ (or :const:`None` if the TLS Client Hello does not contain a server name) -+ and the third argument is the original :class:`SSLContext`. The server name -+ argument is the IDNA decoded server name. -+ -+ A typical use of this callback is to change the :class:`ssl.SSLSocket`'s -+ :attr:`SSLSocket.context` attribute to a new object of type -+ :class:`SSLContext` representing a certificate chain that matches the server -+ name. -+ -+ Due to the early negotiation phase of the TLS connection, only limited -+ methods and attributes are usable like -+ :meth:`SSLSocket.selected_npn_protocol` and :attr:`SSLSocket.context`. -+ :meth:`SSLSocket.getpeercert`, :meth:`SSLSocket.getpeercert`, -+ :meth:`SSLSocket.cipher` and :meth:`SSLSocket.compress` methods require that -+ the TLS connection has progressed beyond the TLS Client Hello and therefore -+ will not contain return meaningful values nor can they be called safely. -+ -+ The *server_name_callback* function must return ``None`` to allow the -+ TLS negotiation to continue. If a TLS failure is required, a constant -+ :const:`ALERT_DESCRIPTION_* ` can be -+ returned. Other return values will result in a TLS fatal error with -+ :const:`ALERT_DESCRIPTION_INTERNAL_ERROR`. -+ -+ If there is an IDNA decoding error on the server name, the TLS connection -+ will terminate with an :const:`ALERT_DESCRIPTION_INTERNAL_ERROR` fatal TLS -+ alert message to the client. -+ -+ If an exception is raised from the *server_name_callback* function the TLS -+ connection will terminate with a fatal TLS alert message -+ :const:`ALERT_DESCRIPTION_HANDSHAKE_FAILURE`. -+ -+ This method will raise :exc:`NotImplementedError` if the OpenSSL library -+ had OPENSSL_NO_TLSEXT defined when it was built. -+ -+.. method:: SSLContext.load_dh_params(dhfile) -+ -+ Load the key generation parameters for Diffie-Helman (DH) key exchange. -+ Using DH key exchange improves forward secrecy at the expense of -+ computational resources (both on the server and on the client). -+ The *dhfile* parameter should be the path to a file containing DH -+ parameters in PEM format. -+ -+ This setting doesn't apply to client sockets. You can also use the -+ :data:`OP_SINGLE_DH_USE` option to further improve security. -+ -+.. method:: SSLContext.set_ecdh_curve(curve_name) -+ -+ Set the curve name for Elliptic Curve-based Diffie-Hellman (ECDH) key -+ exchange. ECDH is significantly faster than regular DH while arguably -+ as secure. The *curve_name* parameter should be a string describing -+ a well-known elliptic curve, for example ``prime256v1`` for a widely -+ supported curve. -+ -+ This setting doesn't apply to client sockets. You can also use the -+ :data:`OP_SINGLE_ECDH_USE` option to further improve security. -+ -+ This method is not available if :data:`HAS_ECDH` is False. -+ -+ .. seealso:: -+ `SSL/TLS & Perfect Forward Secrecy `_ -+ Vincent Bernat. -+ -+.. method:: SSLContext.wrap_socket(sock, server_side=False, \ -+ do_handshake_on_connect=True, suppress_ragged_eofs=True, \ -+ server_hostname=None) -+ -+ Wrap an existing Python socket *sock* and return an :class:`SSLSocket` -+ object. *sock* must be a :data:`~socket.SOCK_STREAM` socket; other socket -+ types are unsupported. -+ -+ The returned SSL socket is tied to the context, its settings and -+ certificates. The parameters *server_side*, *do_handshake_on_connect* -+ and *suppress_ragged_eofs* have the same meaning as in the top-level -+ :func:`wrap_socket` function. -+ -+ On client connections, the optional parameter *server_hostname* specifies -+ the hostname of the service which we are connecting to. This allows a -+ single server to host multiple SSL-based services with distinct certificates, -+ quite similarly to HTTP virtual hosts. Specifying *server_hostname* -+ will raise a :exc:`ValueError` if the OpenSSL library doesn't have support -+ for it (that is, if :data:`HAS_SNI` is :const:`False`). Specifying -+ *server_hostname* will also raise a :exc:`ValueError` if *server_side* -+ is true. -+ -+.. method:: SSLContext.session_stats() -+ -+ Get statistics about the SSL sessions created or managed by this context. -+ A dictionary is returned which maps the names of each `piece of information -+ `_ to their -+ numeric values. For example, here is the total number of hits and misses -+ in the session cache since the context was created:: -+ -+ >>> stats = context.session_stats() -+ >>> stats['hits'], stats['misses'] -+ (0, 0) -+ -+.. method:: SSLContext.get_ca_certs(binary_form=False) -+ -+ Returns a list of dicts with information of loaded CA certs. If the -+ optional argument is true, returns a DER-encoded copy of the CA -+ certificate. -+ -+ .. note:: -+ Certificates in a capath directory aren't loaded unless they have -+ been used at least once. -+ -+.. attribute:: SSLContext.check_hostname -+ -+ Wether to match the peer cert's hostname with :func:`match_hostname` in -+ :meth:`SSLSocket.do_handshake`. The context's -+ :attr:`~SSLContext.verify_mode` must be set to :data:`CERT_OPTIONAL` or -+ :data:`CERT_REQUIRED`, and you must pass *server_hostname* to -+ :meth:`~SSLContext.wrap_socket` in order to match the hostname. -+ -+ Example:: -+ -+ import socket, ssl -+ -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.check_hostname = True -+ context.load_default_certs() -+ -+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -+ ssl_sock = context.wrap_socket(s, server_hostname='www.verisign.com') -+ ssl_sock.connect(('www.verisign.com', 443)) -+ -+ .. note:: -+ -+ This features requires OpenSSL 0.9.8f or newer. -+ -+.. attribute:: SSLContext.options -+ -+ An integer representing the set of SSL options enabled on this context. -+ The default value is :data:`OP_ALL`, but you can specify other options -+ such as :data:`OP_NO_SSLv2` by ORing them together. -+ -+ .. note:: -+ With versions of OpenSSL older than 0.9.8m, it is only possible -+ to set options, not to clear them. Attempting to clear an option -+ (by resetting the corresponding bits) will raise a ``ValueError``. -+ -+.. attribute:: SSLContext.protocol -+ -+ The protocol version chosen when constructing the context. This attribute -+ is read-only. -+ -+.. attribute:: SSLContext.verify_flags -+ -+ The flags for certificate verification operations. You can set flags like -+ :data:`VERIFY_CRL_CHECK_LEAF` by ORing them together. By default OpenSSL -+ does neither require nor verify certificate revocation lists (CRLs). -+ Available only with openssl version 0.9.8+. -+ -+.. attribute:: SSLContext.verify_mode -+ -+ Whether to try to verify other peers' certificates and how to behave -+ if verification fails. This attribute must be one of -+ :data:`CERT_NONE`, :data:`CERT_OPTIONAL` or :data:`CERT_REQUIRED`. -+ - - .. index:: single: certificates - -@@ -460,6 +1258,9 @@ and a footer line:: - ... (certificate in base64 PEM encoding) ... - -----END CERTIFICATE----- - -+Certificate chains -+^^^^^^^^^^^^^^^^^^ -+ - The Python files which contain certificates can contain a sequence of - certificates, sometimes called a *certificate chain*. This chain should start - with the specific certificate for the principal who "is" the client or server, -@@ -483,24 +1284,35 @@ certification authority's certificate:: - ... (the root certificate for the CA's issuer)... - -----END CERTIFICATE----- - -+CA certificates -+^^^^^^^^^^^^^^^ -+ - If you are going to require validation of the other side of the connection's - certificate, you need to provide a "CA certs" file, filled with the certificate - chains for each issuer you are willing to trust. Again, this file just contains - these chains concatenated together. For validation, Python will use the first --chain it finds in the file which matches. -+chain it finds in the file which matches. The platform's certificates file can -+be used by calling :meth:`SSLContext.load_default_certs`, this is done -+automatically with :func:`.create_default_context`. - --Some "standard" root certificates are available from various certification --authorities: `Thawte `_, `Verisign --`_, `Positive SSL --`_ --(used by python.org), `Equifax and GeoTrust --`_. -+Combined key and certificate -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - --In general, if you are using SSL3 or TLS1, you don't need to put the full chain --in your "CA certs" file; you only need the root certificates, and the remote --peer is supposed to furnish the other certificates necessary to chain from its --certificate to a root certificate. See :rfc:`4158` for more discussion of the --way in which certification chains can be built. -+Often the private key is stored in the same file as the certificate; in this -+case, only the ``certfile`` parameter to :meth:`SSLContext.load_cert_chain` -+and :func:`wrap_socket` needs to be passed. If the private key is stored -+with the certificate, it should come before the first certificate in -+the certificate chain:: -+ -+ -----BEGIN RSA PRIVATE KEY----- -+ ... (private key in base64 encoding) ... -+ -----END RSA PRIVATE KEY----- -+ -----BEGIN CERTIFICATE----- -+ ... (certificate in base64 PEM encoding) ... -+ -----END CERTIFICATE----- -+ -+Self-signed certificates -+^^^^^^^^^^^^^^^^^^^^^^^^ - - If you are going to create a server that provides SSL-encrypted connection - services, you will need to acquire a certificate for that service. There are -@@ -555,87 +1367,156 @@ should use the following idiom:: - Client-side operation - ^^^^^^^^^^^^^^^^^^^^^ - --This example connects to an SSL server, prints the server's address and --certificate, sends some bytes, and reads part of the response:: -+This example connects to an SSL server and prints the server's certificate:: - - import socket, ssl, pprint - - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -- - # require a certificate from the server - ssl_sock = ssl.wrap_socket(s, - ca_certs="/etc/ca_certs_file", - cert_reqs=ssl.CERT_REQUIRED) -- - ssl_sock.connect(('www.verisign.com', 443)) - -- print repr(ssl_sock.getpeername()) -- print ssl_sock.cipher() -- print pprint.pformat(ssl_sock.getpeercert()) -- -- # Set a simple HTTP request -- use httplib in actual code. -- ssl_sock.write("""GET / HTTP/1.0\r -- Host: www.verisign.com\r\n\r\n""") -- -- # Read a chunk of data. Will not necessarily -- # read all the data returned by the server. -- data = ssl_sock.read() -- -+ pprint.pprint(ssl_sock.getpeercert()) - # note that closing the SSLSocket will also close the underlying socket - ssl_sock.close() - --As of September 6, 2007, the certificate printed by this program looked like -+As of January 6, 2012, the certificate printed by this program looks like - this:: - -- {'notAfter': 'May 8 23:59:59 2009 GMT', -- 'subject': ((('serialNumber', u'2497886'),), -- (('1.3.6.1.4.1.311.60.2.1.3', u'US'),), -- (('1.3.6.1.4.1.311.60.2.1.2', u'Delaware'),), -- (('countryName', u'US'),), -- (('postalCode', u'94043'),), -- (('stateOrProvinceName', u'California'),), -- (('localityName', u'Mountain View'),), -- (('streetAddress', u'487 East Middlefield Road'),), -- (('organizationName', u'VeriSign, Inc.'),), -- (('organizationalUnitName', -- u'Production Security Services'),), -- (('organizationalUnitName', -- u'Terms of use at www.verisign.com/rpa (c)06'),), -- (('commonName', u'www.verisign.com'),))} -+ {'issuer': ((('countryName', 'US'),), -+ (('organizationName', 'VeriSign, Inc.'),), -+ (('organizationalUnitName', 'VeriSign Trust Network'),), -+ (('organizationalUnitName', -+ 'Terms of use at https://www.verisign.com/rpa (c)06'),), -+ (('commonName', -+ 'VeriSign Class 3 Extended Validation SSL SGC CA'),)), -+ 'notAfter': 'May 25 23:59:59 2012 GMT', -+ 'notBefore': 'May 26 00:00:00 2010 GMT', -+ 'serialNumber': '53D2BEF924A7245E83CA01E46CAA2477', -+ 'subject': ((('1.3.6.1.4.1.311.60.2.1.3', 'US'),), -+ (('1.3.6.1.4.1.311.60.2.1.2', 'Delaware'),), -+ (('businessCategory', 'V1.0, Clause 5.(b)'),), -+ (('serialNumber', '2497886'),), -+ (('countryName', 'US'),), -+ (('postalCode', '94043'),), -+ (('stateOrProvinceName', 'California'),), -+ (('localityName', 'Mountain View'),), -+ (('streetAddress', '487 East Middlefield Road'),), -+ (('organizationName', 'VeriSign, Inc.'),), -+ (('organizationalUnitName', ' Production Security Services'),), -+ (('commonName', 'www.verisign.com'),)), -+ 'subjectAltName': (('DNS', 'www.verisign.com'), -+ ('DNS', 'verisign.com'), -+ ('DNS', 'www.verisign.net'), -+ ('DNS', 'verisign.net'), -+ ('DNS', 'www.verisign.mobi'), -+ ('DNS', 'verisign.mobi'), -+ ('DNS', 'www.verisign.eu'), -+ ('DNS', 'verisign.eu')), -+ 'version': 3} - --which is a fairly poorly-formed ``subject`` field. -+This other example first creates an SSL context, instructs it to verify -+certificates sent by peers, and feeds it a set of recognized certificate -+authorities (CA):: -+ -+ >>> context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ >>> context.verify_mode = ssl.CERT_REQUIRED -+ >>> context.load_verify_locations("/etc/ssl/certs/ca-bundle.crt") -+ -+(it is assumed your operating system places a bundle of all CA certificates -+in ``/etc/ssl/certs/ca-bundle.crt``; if not, you'll get an error and have -+to adjust the location) -+ -+When you use the context to connect to a server, :const:`CERT_REQUIRED` -+validates the server certificate: it ensures that the server certificate -+was signed with one of the CA certificates, and checks the signature for -+correctness:: -+ -+ >>> conn = context.wrap_socket(socket.socket(socket.AF_INET)) -+ >>> conn.connect(("linuxfr.org", 443)) -+ -+You should then fetch the certificate and check its fields for conformity:: -+ -+ >>> cert = conn.getpeercert() -+ >>> ssl.match_hostname(cert, "linuxfr.org") -+ -+Visual inspection shows that the certificate does identify the desired service -+(that is, the HTTPS host ``linuxfr.org``):: -+ -+ >>> pprint.pprint(cert) -+ {'issuer': ((('organizationName', 'CAcert Inc.'),), -+ (('organizationalUnitName', 'http://www.CAcert.org'),), -+ (('commonName', 'CAcert Class 3 Root'),)), -+ 'notAfter': 'Jun 7 21:02:24 2013 GMT', -+ 'notBefore': 'Jun 8 21:02:24 2011 GMT', -+ 'serialNumber': 'D3E9', -+ 'subject': ((('commonName', 'linuxfr.org'),),), -+ 'subjectAltName': (('DNS', 'linuxfr.org'), -+ ('othername', ''), -+ ('DNS', 'linuxfr.org'), -+ ('othername', ''), -+ ('DNS', 'dev.linuxfr.org'), -+ ('othername', ''), -+ ('DNS', 'prod.linuxfr.org'), -+ ('othername', ''), -+ ('DNS', 'alpha.linuxfr.org'), -+ ('othername', ''), -+ ('DNS', '*.linuxfr.org'), -+ ('othername', '')), -+ 'version': 3} -+ -+Now that you are assured of its authenticity, you can proceed to talk with -+the server:: -+ -+ >>> conn.sendall(b"HEAD / HTTP/1.0\r\nHost: linuxfr.org\r\n\r\n") -+ >>> pprint.pprint(conn.recv(1024).split(b"\r\n")) -+ [b'HTTP/1.1 302 Found', -+ b'Date: Sun, 16 May 2010 13:43:28 GMT', -+ b'Server: Apache/2.2', -+ b'Location: https://linuxfr.org/pub/', -+ b'Vary: Accept-Encoding', -+ b'Connection: close', -+ b'Content-Type: text/html; charset=iso-8859-1', -+ b'', -+ b''] -+ -+See the discussion of :ref:`ssl-security` below. -+ - - Server-side operation - ^^^^^^^^^^^^^^^^^^^^^ - --For server operation, typically you'd need to have a server certificate, and --private key, each in a file. You'd open a socket, bind it to a port, call --:meth:`listen` on it, then start waiting for clients to connect:: -+For server operation, typically you'll need to have a server certificate, and -+private key, each in a file. You'll first create a context holding the key -+and the certificate, so that clients can check your authenticity. Then -+you'll open a socket, bind it to a port, call :meth:`listen` on it, and start -+waiting for clients to connect:: - - import socket, ssl - -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ context.load_cert_chain(certfile="mycertfile", keyfile="mykeyfile") -+ - bindsocket = socket.socket() - bindsocket.bind(('myaddr.mydomain.com', 10023)) - bindsocket.listen(5) - --When one did, you'd call :meth:`accept` on the socket to get the new socket from --the other end, and use :func:`wrap_socket` to create a server-side SSL context --for it:: -+When a client connects, you'll call :meth:`accept` on the socket to get the -+new socket from the other end, and use the context's :meth:`SSLContext.wrap_socket` -+method to create a server-side SSL socket for the connection:: - - while True: - newsocket, fromaddr = bindsocket.accept() -- connstream = ssl.wrap_socket(newsocket, -- server_side=True, -- certfile="mycertfile", -- keyfile="mykeyfile", -- ssl_version=ssl.PROTOCOL_TLSv1) -+ connstream = context.wrap_socket(newsocket, server_side=True) - try: - deal_with_client(connstream) - finally: - connstream.shutdown(socket.SHUT_RDWR) - connstream.close() - --Then you'd read data from the ``connstream`` and do something with it till you -+Then you'll read data from the ``connstream`` and do something with it till you - are finished with the client (or the client is finished with you):: - - def deal_with_client(connstream): -@@ -649,7 +1530,138 @@ are finished with the client (or the cli - data = connstream.read() - # finished with client - --And go back to listening for new client connections. -+And go back to listening for new client connections (of course, a real server -+would probably handle each client connection in a separate thread, or put -+the sockets in non-blocking mode and use an event loop). -+ -+ -+.. _ssl-nonblocking: -+ -+Notes on non-blocking sockets -+----------------------------- -+ -+When working with non-blocking sockets, there are several things you need -+to be aware of: -+ -+- Calling :func:`~select.select` tells you that the OS-level socket can be -+ read from (or written to), but it does not imply that there is sufficient -+ data at the upper SSL layer. For example, only part of an SSL frame might -+ have arrived. Therefore, you must be ready to handle :meth:`SSLSocket.recv` -+ and :meth:`SSLSocket.send` failures, and retry after another call to -+ :func:`~select.select`. -+ -+- Conversely, since the SSL layer has its own framing, a SSL socket may -+ still have data available for reading without :func:`~select.select` -+ being aware of it. Therefore, you should first call -+ :meth:`SSLSocket.recv` to drain any potentially available data, and then -+ only block on a :func:`~select.select` call if still necessary. -+ -+ (of course, similar provisions apply when using other primitives such as -+ :func:`~select.poll`, or those in the :mod:`selectors` module) -+ -+- The SSL handshake itself will be non-blocking: the -+ :meth:`SSLSocket.do_handshake` method has to be retried until it returns -+ successfully. Here is a synopsis using :func:`~select.select` to wait for -+ the socket's readiness:: -+ -+ while True: -+ try: -+ sock.do_handshake() -+ break -+ except ssl.SSLWantReadError: -+ select.select([sock], [], []) -+ except ssl.SSLWantWriteError: -+ select.select([], [sock], []) -+ -+ -+.. _ssl-security: -+ -+Security considerations -+----------------------- -+ -+Best defaults -+^^^^^^^^^^^^^ -+ -+For **client use**, if you don't have any special requirements for your -+security policy, it is highly recommended that you use the -+:func:`create_default_context` function to create your SSL context. -+It will load the system's trusted CA certificates, enable certificate -+validation and hostname checking, and try to choose reasonably secure -+protocol and cipher settings. -+ -+If a client certificate is needed for the connection, it can be added with -+:meth:`SSLContext.load_cert_chain`. -+ -+By contrast, if you create the SSL context by calling the :class:`SSLContext` -+constructor yourself, it will not have certificate validation nor hostname -+checking enabled by default. If you do so, please read the paragraphs below -+to achieve a good security level. -+ -+Manual settings -+^^^^^^^^^^^^^^^ -+ -+Verifying certificates -+'''''''''''''''''''''' -+ -+When calling the :class:`SSLContext` constructor directly, -+:const:`CERT_NONE` is the default. Since it does not authenticate the other -+peer, it can be insecure, especially in client mode where most of time you -+would like to ensure the authenticity of the server you're talking to. -+Therefore, when in client mode, it is highly recommended to use -+:const:`CERT_REQUIRED`. However, it is in itself not sufficient; you also -+have to check that the server certificate, which can be obtained by calling -+:meth:`SSLSocket.getpeercert`, matches the desired service. For many -+protocols and applications, the service can be identified by the hostname; -+in this case, the :func:`match_hostname` function can be used. This common -+check is automatically performed when :attr:`SSLContext.check_hostname` is -+enabled. -+ -+In server mode, if you want to authenticate your clients using the SSL layer -+(rather than using a higher-level authentication mechanism), you'll also have -+to specify :const:`CERT_REQUIRED` and similarly check the client certificate. -+ -+ .. note:: -+ -+ In client mode, :const:`CERT_OPTIONAL` and :const:`CERT_REQUIRED` are -+ equivalent unless anonymous ciphers are enabled (they are disabled -+ by default). -+ -+Protocol versions -+''''''''''''''''' -+ -+SSL version 2 is considered insecure and is therefore dangerous to use. If -+you want maximum compatibility between clients and servers, it is recommended -+to use :const:`PROTOCOL_SSLv23` as the protocol version and then disable -+SSLv2 explicitly using the :data:`SSLContext.options` attribute:: -+ -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ context.options |= ssl.OP_NO_SSLv2 -+ -+The SSL context created above will allow SSLv3 and TLSv1 (and later, if -+supported by your system) connections, but not SSLv2. -+ -+Cipher selection -+'''''''''''''''' -+ -+If you have advanced security requirements, fine-tuning of the ciphers -+enabled when negotiating a SSL session is possible through the -+:meth:`SSLContext.set_ciphers` method. Starting from Python 2.7.9, the -+ssl module disables certain weak ciphers by default, but you may want -+to further restrict the cipher choice. Be sure to read OpenSSL's documentation -+about the `cipher list format `_. -+If you want to check which ciphers are enabled by a given cipher list, use the -+``openssl ciphers`` command on your system. -+ -+Multi-processing -+^^^^^^^^^^^^^^^^ -+ -+If using this module as part of a multi-processed application (using, -+for example the :mod:`multiprocessing` or :mod:`concurrent.futures` modules), -+be aware that OpenSSL's internal random number generator does not properly -+handle forked processes. Applications must change the PRNG state of the -+parent process if they use any SSL feature with :func:`os.fork`. Any -+successful call of :func:`~ssl.RAND_add`, :func:`~ssl.RAND_bytes` or -+:func:`~ssl.RAND_pseudo_bytes` is sufficient. - - - .. seealso:: -@@ -668,3 +1680,15 @@ And go back to listening for new client - - `RFC 3280: Internet X.509 Public Key Infrastructure Certificate and CRL Profile `_ - Housley et. al. -+ -+ `RFC 4366: Transport Layer Security (TLS) Extensions `_ -+ Blake-Wilson et. al. -+ -+ `RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 `_ -+ T. Dierks et. al. -+ -+ `RFC 6066: Transport Layer Security (TLS) Extensions `_ -+ D. Eastlake -+ -+ `IANA TLS: Transport Layer Security (TLS) Parameters `_ -+ IANA -diff --git a/Lib/ssl.py b/Lib/ssl.py ---- a/Lib/ssl.py -+++ b/Lib/ssl.py -@@ -1,8 +1,7 @@ - # Wrapper module for _ssl, providing some additional facilities - # implemented in Python. Written by Bill Janssen. - --"""\ --This module provides some more Pythonic support for SSL. -+"""This module provides some more Pythonic support for SSL. - - Object types: - -@@ -53,62 +52,462 @@ PROTOCOL_SSLv2 - PROTOCOL_SSLv3 - PROTOCOL_SSLv23 - PROTOCOL_TLSv1 -+PROTOCOL_TLSv1_1 -+PROTOCOL_TLSv1_2 -+ -+The following constants identify various SSL alert message descriptions as per -+http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6 -+ -+ALERT_DESCRIPTION_CLOSE_NOTIFY -+ALERT_DESCRIPTION_UNEXPECTED_MESSAGE -+ALERT_DESCRIPTION_BAD_RECORD_MAC -+ALERT_DESCRIPTION_RECORD_OVERFLOW -+ALERT_DESCRIPTION_DECOMPRESSION_FAILURE -+ALERT_DESCRIPTION_HANDSHAKE_FAILURE -+ALERT_DESCRIPTION_BAD_CERTIFICATE -+ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE -+ALERT_DESCRIPTION_CERTIFICATE_REVOKED -+ALERT_DESCRIPTION_CERTIFICATE_EXPIRED -+ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN -+ALERT_DESCRIPTION_ILLEGAL_PARAMETER -+ALERT_DESCRIPTION_UNKNOWN_CA -+ALERT_DESCRIPTION_ACCESS_DENIED -+ALERT_DESCRIPTION_DECODE_ERROR -+ALERT_DESCRIPTION_DECRYPT_ERROR -+ALERT_DESCRIPTION_PROTOCOL_VERSION -+ALERT_DESCRIPTION_INSUFFICIENT_SECURITY -+ALERT_DESCRIPTION_INTERNAL_ERROR -+ALERT_DESCRIPTION_USER_CANCELLED -+ALERT_DESCRIPTION_NO_RENEGOTIATION -+ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION -+ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE -+ALERT_DESCRIPTION_UNRECOGNIZED_NAME -+ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE -+ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE -+ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY - """ - - import textwrap -+import re -+import sys -+import os -+from collections import namedtuple -+from contextlib import closing - - import _ssl # if we can't import it, let the error propagate - - from _ssl import OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_INFO, OPENSSL_VERSION --from _ssl import SSLError -+from _ssl import _SSLContext -+from _ssl import ( -+ SSLError, SSLZeroReturnError, SSLWantReadError, SSLWantWriteError, -+ SSLSyscallError, SSLEOFError, -+ ) - from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED -+from _ssl import (VERIFY_DEFAULT, VERIFY_CRL_CHECK_LEAF, VERIFY_CRL_CHECK_CHAIN, -+ VERIFY_X509_STRICT) -+from _ssl import txt2obj as _txt2obj, nid2obj as _nid2obj - from _ssl import RAND_status, RAND_egd, RAND_add --from _ssl import \ -- SSL_ERROR_ZERO_RETURN, \ -- SSL_ERROR_WANT_READ, \ -- SSL_ERROR_WANT_WRITE, \ -- SSL_ERROR_WANT_X509_LOOKUP, \ -- SSL_ERROR_SYSCALL, \ -- SSL_ERROR_SSL, \ -- SSL_ERROR_WANT_CONNECT, \ -- SSL_ERROR_EOF, \ -- SSL_ERROR_INVALID_ERROR_CODE --from _ssl import PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 --_PROTOCOL_NAMES = { -- PROTOCOL_TLSv1: "TLSv1", -- PROTOCOL_SSLv23: "SSLv23", -- PROTOCOL_SSLv3: "SSLv3", --} -+ -+def _import_symbols(prefix): -+ for n in dir(_ssl): -+ if n.startswith(prefix): -+ globals()[n] = getattr(_ssl, n) -+ -+_import_symbols('OP_') -+_import_symbols('ALERT_DESCRIPTION_') -+_import_symbols('SSL_ERROR_') -+_import_symbols('PROTOCOL_') -+ -+from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN -+ -+from _ssl import _OPENSSL_API_VERSION -+ -+_PROTOCOL_NAMES = {value: name for name, value in globals().items() if name.startswith('PROTOCOL_')} -+ - try: -- from _ssl import PROTOCOL_SSLv2 - _SSLv2_IF_EXISTS = PROTOCOL_SSLv2 --except ImportError: -+except NameError: - _SSLv2_IF_EXISTS = None --else: -- _PROTOCOL_NAMES[PROTOCOL_SSLv2] = "SSLv2" - - from socket import socket, _fileobject, _delegate_methods, error as socket_error --from socket import getnameinfo as _getnameinfo --from socket import SOL_SOCKET, SO_TYPE, SOCK_STREAM -+if sys.platform == "win32": -+ from _ssl import enum_certificates, enum_crls -+ -+from socket import socket, AF_INET, SOCK_STREAM, create_connection -+from socket import SOL_SOCKET, SO_TYPE - import base64 # for DER-to-PEM translation - import errno - -+if _ssl.HAS_TLS_UNIQUE: -+ CHANNEL_BINDING_TYPES = ['tls-unique'] -+else: -+ CHANNEL_BINDING_TYPES = [] -+ - # Disable weak or insecure ciphers by default - # (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL') --_DEFAULT_CIPHERS = 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2' -+# Enable a better set of ciphers by default -+# This list has been explicitly chosen to: -+# * Prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE) -+# * Prefer ECDHE over DHE for better performance -+# * Prefer any AES-GCM over any AES-CBC for better performance and security -+# * Then Use HIGH cipher suites as a fallback -+# * Then Use 3DES as fallback which is secure but slow -+# * Finally use RC4 as a fallback which is problematic but needed for -+# compatibility some times. -+# * Disable NULL authentication, NULL encryption, and MD5 MACs for security -+# reasons -+_DEFAULT_CIPHERS = ( -+ 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:' -+ 'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:ECDH+RC4:' -+ 'DH+RC4:RSA+RC4:!aNULL:!eNULL:!MD5' -+) - -+# Restricted and more secure ciphers for the server side -+# This list has been explicitly chosen to: -+# * Prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE) -+# * Prefer ECDHE over DHE for better performance -+# * Prefer any AES-GCM over any AES-CBC for better performance and security -+# * Then Use HIGH cipher suites as a fallback -+# * Then Use 3DES as fallback which is secure but slow -+# * Disable NULL authentication, NULL encryption, MD5 MACs, DSS, and RC4 for -+# security reasons -+_RESTRICTED_SERVER_CIPHERS = ( -+ 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:' -+ 'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:!aNULL:' -+ '!eNULL:!MD5:!DSS:!RC4' -+) -+ -+ -+class CertificateError(ValueError): -+ pass -+ -+ -+def _dnsname_match(dn, hostname, max_wildcards=1): -+ """Matching according to RFC 6125, section 6.4.3 -+ -+ http://tools.ietf.org/html/rfc6125#section-6.4.3 -+ """ -+ pats = [] -+ if not dn: -+ return False -+ -+ pieces = dn.split(r'.') -+ leftmost = pieces[0] -+ remainder = pieces[1:] -+ -+ wildcards = leftmost.count('*') -+ if wildcards > max_wildcards: -+ # Issue #17980: avoid denials of service by refusing more -+ # than one wildcard per fragment. A survery of established -+ # policy among SSL implementations showed it to be a -+ # reasonable choice. -+ raise CertificateError( -+ "too many wildcards in certificate DNS name: " + repr(dn)) -+ -+ # speed up common case w/o wildcards -+ if not wildcards: -+ return dn.lower() == hostname.lower() -+ -+ # RFC 6125, section 6.4.3, subitem 1. -+ # The client SHOULD NOT attempt to match a presented identifier in which -+ # the wildcard character comprises a label other than the left-most label. -+ if leftmost == '*': -+ # When '*' is a fragment by itself, it matches a non-empty dotless -+ # fragment. -+ pats.append('[^.]+') -+ elif leftmost.startswith('xn--') or hostname.startswith('xn--'): -+ # RFC 6125, section 6.4.3, subitem 3. -+ # The client SHOULD NOT attempt to match a presented identifier -+ # where the wildcard character is embedded within an A-label or -+ # U-label of an internationalized domain name. -+ pats.append(re.escape(leftmost)) -+ else: -+ # Otherwise, '*' matches any dotless string, e.g. www* -+ pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) -+ -+ # add the remaining fragments, ignore any wildcards -+ for frag in remainder: -+ pats.append(re.escape(frag)) -+ -+ pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) -+ return pat.match(hostname) -+ -+ -+def match_hostname(cert, hostname): -+ """Verify that *cert* (in decoded format as returned by -+ SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 -+ rules are followed, but IP addresses are not accepted for *hostname*. -+ -+ CertificateError is raised on failure. On success, the function -+ returns nothing. -+ """ -+ if not cert: -+ raise ValueError("empty or no certificate, match_hostname needs a " -+ "SSL socket or SSL context with either " -+ "CERT_OPTIONAL or CERT_REQUIRED") -+ dnsnames = [] -+ san = cert.get('subjectAltName', ()) -+ for key, value in san: -+ if key == 'DNS': -+ if _dnsname_match(value, hostname): -+ return -+ dnsnames.append(value) -+ if not dnsnames: -+ # The subject is only checked when there is no dNSName entry -+ # in subjectAltName -+ for sub in cert.get('subject', ()): -+ for key, value in sub: -+ # XXX according to RFC 2818, the most specific Common Name -+ # must be used. -+ if key == 'commonName': -+ if _dnsname_match(value, hostname): -+ return -+ dnsnames.append(value) -+ if len(dnsnames) > 1: -+ raise CertificateError("hostname %r " -+ "doesn't match either of %s" -+ % (hostname, ', '.join(map(repr, dnsnames)))) -+ elif len(dnsnames) == 1: -+ raise CertificateError("hostname %r " -+ "doesn't match %r" -+ % (hostname, dnsnames[0])) -+ else: -+ raise CertificateError("no appropriate commonName or " -+ "subjectAltName fields were found") -+ -+ -+DefaultVerifyPaths = namedtuple("DefaultVerifyPaths", -+ "cafile capath openssl_cafile_env openssl_cafile openssl_capath_env " -+ "openssl_capath") -+ -+def get_default_verify_paths(): -+ """Return paths to default cafile and capath. -+ """ -+ parts = _ssl.get_default_verify_paths() -+ -+ # environment vars shadow paths -+ cafile = os.environ.get(parts[0], parts[1]) -+ capath = os.environ.get(parts[2], parts[3]) -+ -+ return DefaultVerifyPaths(cafile if os.path.isfile(cafile) else None, -+ capath if os.path.isdir(capath) else None, -+ *parts) -+ -+ -+class _ASN1Object(namedtuple("_ASN1Object", "nid shortname longname oid")): -+ """ASN.1 object identifier lookup -+ """ -+ __slots__ = () -+ -+ def __new__(cls, oid): -+ return super(_ASN1Object, cls).__new__(cls, *_txt2obj(oid, name=False)) -+ -+ @classmethod -+ def fromnid(cls, nid): -+ """Create _ASN1Object from OpenSSL numeric ID -+ """ -+ return super(_ASN1Object, cls).__new__(cls, *_nid2obj(nid)) -+ -+ @classmethod -+ def fromname(cls, name): -+ """Create _ASN1Object from short name, long name or OID -+ """ -+ return super(_ASN1Object, cls).__new__(cls, *_txt2obj(name, name=True)) -+ -+ -+class Purpose(_ASN1Object): -+ """SSLContext purpose flags with X509v3 Extended Key Usage objects -+ """ -+ -+Purpose.SERVER_AUTH = Purpose('1.3.6.1.5.5.7.3.1') -+Purpose.CLIENT_AUTH = Purpose('1.3.6.1.5.5.7.3.2') -+ -+ -+class SSLContext(_SSLContext): -+ """An SSLContext holds various SSL-related configuration options and -+ data, such as certificates and possibly a private key.""" -+ -+ __slots__ = ('protocol', '__weakref__') -+ _windows_cert_stores = ("CA", "ROOT") -+ -+ def __new__(cls, protocol, *args, **kwargs): -+ self = _SSLContext.__new__(cls, protocol) -+ if protocol != _SSLv2_IF_EXISTS: -+ self.set_ciphers(_DEFAULT_CIPHERS) -+ return self -+ -+ def __init__(self, protocol): -+ self.protocol = protocol -+ -+ def wrap_socket(self, sock, server_side=False, -+ do_handshake_on_connect=True, -+ suppress_ragged_eofs=True, -+ server_hostname=None): -+ return SSLSocket(sock=sock, server_side=server_side, -+ do_handshake_on_connect=do_handshake_on_connect, -+ suppress_ragged_eofs=suppress_ragged_eofs, -+ server_hostname=server_hostname, -+ _context=self) -+ -+ def set_npn_protocols(self, npn_protocols): -+ protos = bytearray() -+ for protocol in npn_protocols: -+ b = protocol.encode('ascii') -+ if len(b) == 0 or len(b) > 255: -+ raise SSLError('NPN protocols must be 1 to 255 in length') -+ protos.append(len(b)) -+ protos.extend(b) -+ -+ self._set_npn_protocols(protos) -+ -+ def _load_windows_store_certs(self, storename, purpose): -+ certs = bytearray() -+ for cert, encoding, trust in enum_certificates(storename): -+ # CA certs are never PKCS#7 encoded -+ if encoding == "x509_asn": -+ if trust is True or purpose.oid in trust: -+ certs.extend(cert) -+ self.load_verify_locations(cadata=certs) -+ return certs -+ -+ def load_default_certs(self, purpose=Purpose.SERVER_AUTH): -+ if not isinstance(purpose, _ASN1Object): -+ raise TypeError(purpose) -+ if sys.platform == "win32": -+ for storename in self._windows_cert_stores: -+ self._load_windows_store_certs(storename, purpose) -+ else: -+ self.set_default_verify_paths() -+ -+ -+def create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, -+ capath=None, cadata=None): -+ """Create a SSLContext object with default settings. -+ -+ NOTE: The protocol and settings may change anytime without prior -+ deprecation. The values represent a fair balance between maximum -+ compatibility and security. -+ """ -+ if not isinstance(purpose, _ASN1Object): -+ raise TypeError(purpose) -+ -+ context = SSLContext(PROTOCOL_SSLv23) -+ -+ # SSLv2 considered harmful. -+ context.options |= OP_NO_SSLv2 -+ -+ # SSLv3 has problematic security and is only required for really old -+ # clients such as IE6 on Windows XP -+ context.options |= OP_NO_SSLv3 -+ -+ # disable compression to prevent CRIME attacks (OpenSSL 1.0+) -+ context.options |= getattr(_ssl, "OP_NO_COMPRESSION", 0) -+ -+ if purpose == Purpose.SERVER_AUTH: -+ # verify certs and host name in client mode -+ context.verify_mode = CERT_REQUIRED -+ context.check_hostname = True -+ elif purpose == Purpose.CLIENT_AUTH: -+ # Prefer the server's ciphers by default so that we get stronger -+ # encryption -+ context.options |= getattr(_ssl, "OP_CIPHER_SERVER_PREFERENCE", 0) -+ -+ # Use single use keys in order to improve forward secrecy -+ context.options |= getattr(_ssl, "OP_SINGLE_DH_USE", 0) -+ context.options |= getattr(_ssl, "OP_SINGLE_ECDH_USE", 0) -+ -+ # disallow ciphers with known vulnerabilities -+ context.set_ciphers(_RESTRICTED_SERVER_CIPHERS) -+ -+ if cafile or capath or cadata: -+ context.load_verify_locations(cafile, capath, cadata) -+ elif context.verify_mode != CERT_NONE: -+ # no explicit cafile, capath or cadata but the verify mode is -+ # CERT_OPTIONAL or CERT_REQUIRED. Let's try to load default system -+ # root CA certificates for the given purpose. This may fail silently. -+ context.load_default_certs(purpose) -+ return context -+ -+ -+def _create_stdlib_context(protocol=PROTOCOL_SSLv23, cert_reqs=None, -+ check_hostname=False, purpose=Purpose.SERVER_AUTH, -+ certfile=None, keyfile=None, -+ cafile=None, capath=None, cadata=None): -+ """Create a SSLContext object for Python stdlib modules -+ -+ All Python stdlib modules shall use this function to create SSLContext -+ objects in order to keep common settings in one place. The configuration -+ is less restrict than create_default_context()'s to increase backward -+ compatibility. -+ """ -+ if not isinstance(purpose, _ASN1Object): -+ raise TypeError(purpose) -+ -+ context = SSLContext(protocol) -+ # SSLv2 considered harmful. -+ context.options |= OP_NO_SSLv2 -+ -+ if cert_reqs is not None: -+ context.verify_mode = cert_reqs -+ context.check_hostname = check_hostname -+ -+ if keyfile and not certfile: -+ raise ValueError("certfile must be specified") -+ if certfile or keyfile: -+ context.load_cert_chain(certfile, keyfile) -+ -+ # load CA root certs -+ if cafile or capath or cadata: -+ context.load_verify_locations(cafile, capath, cadata) -+ elif context.verify_mode != CERT_NONE: -+ # no explicit cafile, capath or cadata but the verify mode is -+ # CERT_OPTIONAL or CERT_REQUIRED. Let's try to load default system -+ # root CA certificates for the given purpose. This may fail silently. -+ context.load_default_certs(purpose) -+ -+ return context - - class SSLSocket(socket): -- - """This class implements a subtype of socket.socket that wraps - the underlying OS socket in an SSL context when necessary, and - provides read and write methods over that channel.""" - -- def __init__(self, sock, keyfile=None, certfile=None, -+ def __init__(self, sock=None, keyfile=None, certfile=None, - server_side=False, cert_reqs=CERT_NONE, - ssl_version=PROTOCOL_SSLv23, ca_certs=None, - do_handshake_on_connect=True, -- suppress_ragged_eofs=True, ciphers=None): -+ family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None, -+ suppress_ragged_eofs=True, npn_protocols=None, ciphers=None, -+ server_hostname=None, -+ _context=None): -+ -+ self._makefile_refs = 0 -+ if _context: -+ self._context = _context -+ else: -+ if server_side and not certfile: -+ raise ValueError("certfile must be specified for server-side " -+ "operations") -+ if keyfile and not certfile: -+ raise ValueError("certfile must be specified") -+ if certfile and not keyfile: -+ keyfile = certfile -+ self._context = SSLContext(ssl_version) -+ self._context.verify_mode = cert_reqs -+ if ca_certs: -+ self._context.load_verify_locations(ca_certs) -+ if certfile: -+ self._context.load_cert_chain(certfile, keyfile) -+ if npn_protocols: -+ self._context.set_npn_protocols(npn_protocols) -+ if ciphers: -+ self._context.set_ciphers(ciphers) -+ self.keyfile = keyfile -+ self.certfile = certfile -+ self.cert_reqs = cert_reqs -+ self.ssl_version = ssl_version -+ self.ca_certs = ca_certs -+ self.ciphers = ciphers - # Can't use sock.type as other flags (such as SOCK_NONBLOCK) get - # mixed in. - if sock.getsockopt(SOL_SOCKET, SO_TYPE) != SOCK_STREAM: -@@ -122,98 +520,160 @@ class SSLSocket(socket): - delattr(self, attr) - except AttributeError: - pass -+ if server_side and server_hostname: -+ raise ValueError("server_hostname can only be specified " -+ "in client mode") -+ if self._context.check_hostname and not server_hostname: -+ if HAS_SNI: -+ raise ValueError("check_hostname requires server_hostname") -+ else: -+ raise ValueError("check_hostname requires server_hostname, " -+ "but it's not supported by your OpenSSL " -+ "library") -+ self.server_side = server_side -+ self.server_hostname = server_hostname -+ self.do_handshake_on_connect = do_handshake_on_connect -+ self.suppress_ragged_eofs = suppress_ragged_eofs - -- if ciphers is None and ssl_version != _SSLv2_IF_EXISTS: -- ciphers = _DEFAULT_CIPHERS -- -- if certfile and not keyfile: -- keyfile = certfile -- # see if it's connected -+ # See if we are connected - try: -- socket.getpeername(self) -- except socket_error, e: -+ self.getpeername() -+ except socket_error as e: - if e.errno != errno.ENOTCONN: - raise -- # no, no connection yet -- self._connected = False -- self._sslobj = None -+ connected = False - else: -- # yes, create the SSL object -- self._connected = True -- self._sslobj = _ssl.sslwrap(self._sock, server_side, -- keyfile, certfile, -- cert_reqs, ssl_version, ca_certs, -- ciphers) -- if do_handshake_on_connect: -- self.do_handshake() -- self.keyfile = keyfile -- self.certfile = certfile -- self.cert_reqs = cert_reqs -- self.ssl_version = ssl_version -- self.ca_certs = ca_certs -- self.ciphers = ciphers -- self.do_handshake_on_connect = do_handshake_on_connect -- self.suppress_ragged_eofs = suppress_ragged_eofs -+ connected = True -+ -+ self._closed = False -+ self._sslobj = None -+ self._connected = connected -+ if connected: -+ # create the SSL object -+ try: -+ self._sslobj = self._context._wrap_socket(self._sock, server_side, -+ server_hostname, ssl_sock=self) -+ if do_handshake_on_connect: -+ timeout = self.gettimeout() -+ if timeout == 0.0: -+ # non-blocking -+ raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets") -+ self.do_handshake() -+ -+ except (OSError, ValueError): -+ self.close() -+ raise -- self._makefile_refs = 0 - -- def read(self, len=1024): -+ @property -+ def context(self): -+ return self._context - -+ @context.setter -+ def context(self, ctx): -+ self._context = ctx -+ self._sslobj.context = ctx -+ -+ def dup(self): -+ raise NotImplemented("Can't dup() %s instances" % -+ self.__class__.__name__) -+ -+ def _checkClosed(self, msg=None): -+ # raise an exception here if you wish to check for spurious closes -+ pass -+ -+ def _check_connected(self): -+ if not self._connected: -+ # getpeername() will raise ENOTCONN if the socket is really -+ # not connected; note that we can be connected even without -+ # _connected being set, e.g. if connect() first returned -+ # EAGAIN. -+ self.getpeername() -+ -+ def read(self, len=0, buffer=None): - """Read up to LEN bytes and return them. - Return zero-length string on EOF.""" - -+ self._checkClosed() -+ if not self._sslobj: -+ raise ValueError("Read on closed or unwrapped SSL socket.") - try: -- return self._sslobj.read(len) -- except SSLError, x: -+ if buffer is not None: -+ v = self._sslobj.read(len, buffer) -+ else: -+ v = self._sslobj.read(len or 1024) -+ return v -+ except SSLError as x: - if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs: -- return '' -+ if buffer is not None: -+ return 0 -+ else: -+ return b'' - else: - raise - - def write(self, data): -- - """Write DATA to the underlying SSL channel. Returns - number of bytes of DATA actually transmitted.""" - -+ self._checkClosed() -+ if not self._sslobj: -+ raise ValueError("Write on closed or unwrapped SSL socket.") - return self._sslobj.write(data) - - def getpeercert(self, binary_form=False): -- - """Returns a formatted version of the data in the - certificate provided by the other end of the SSL channel. - Return None if no certificate was provided, {} if a - certificate was provided, but not validated.""" - -+ self._checkClosed() -+ self._check_connected() - return self._sslobj.peer_certificate(binary_form) - -+ def selected_npn_protocol(self): -+ self._checkClosed() -+ if not self._sslobj or not _ssl.HAS_NPN: -+ return None -+ else: -+ return self._sslobj.selected_npn_protocol() -+ - def cipher(self): -- -+ self._checkClosed() - if not self._sslobj: - return None - else: - return self._sslobj.cipher() - -+ def compression(self): -+ self._checkClosed() -+ if not self._sslobj: -+ return None -+ else: -+ return self._sslobj.compression() -+ - def send(self, data, flags=0): -+ self._checkClosed() - if self._sslobj: - if flags != 0: - raise ValueError( - "non-zero flags not allowed in calls to send() on %s" % - self.__class__) -- while True: -- try: -- v = self._sslobj.write(data) -- except SSLError, x: -- if x.args[0] == SSL_ERROR_WANT_READ: -- return 0 -- elif x.args[0] == SSL_ERROR_WANT_WRITE: -- return 0 -- else: -- raise -+ try: -+ v = self._sslobj.write(data) -+ except SSLError as x: -+ if x.args[0] == SSL_ERROR_WANT_READ: -+ return 0 -+ elif x.args[0] == SSL_ERROR_WANT_WRITE: -+ return 0 - else: -- return v -+ raise -+ else: -+ return v - else: - return self._sock.send(data, flags) - - def sendto(self, data, flags_or_addr, addr=None): -+ self._checkClosed() - if self._sslobj: - raise ValueError("sendto not allowed on instances of %s" % - self.__class__) -@@ -222,7 +683,9 @@ class SSLSocket(socket): - else: - return self._sock.sendto(data, flags_or_addr, addr) - -+ - def sendall(self, data, flags=0): -+ self._checkClosed() - if self._sslobj: - if flags != 0: - raise ValueError( -@@ -238,6 +701,7 @@ class SSLSocket(socket): - return socket.sendall(self, data, flags) - - def recv(self, buflen=1024, flags=0): -+ self._checkClosed() - if self._sslobj: - if flags != 0: - raise ValueError( -@@ -248,6 +712,7 @@ class SSLSocket(socket): - return self._sock.recv(buflen, flags) - - def recv_into(self, buffer, nbytes=None, flags=0): -+ self._checkClosed() - if buffer and (nbytes is None): - nbytes = len(buffer) - elif nbytes is None: -@@ -257,14 +722,12 @@ class SSLSocket(socket): - raise ValueError( - "non-zero flags not allowed in calls to recv_into() on %s" % - self.__class__) -- tmp_buffer = self.read(nbytes) -- v = len(tmp_buffer) -- buffer[:v] = tmp_buffer -- return v -+ return self.read(nbytes, buffer) - else: - return self._sock.recv_into(buffer, nbytes, flags) - - def recvfrom(self, buflen=1024, flags=0): -+ self._checkClosed() - if self._sslobj: - raise ValueError("recvfrom not allowed on instances of %s" % - self.__class__) -@@ -272,27 +735,23 @@ class SSLSocket(socket): - return self._sock.recvfrom(buflen, flags) - - def recvfrom_into(self, buffer, nbytes=None, flags=0): -+ self._checkClosed() - if self._sslobj: - raise ValueError("recvfrom_into not allowed on instances of %s" % - self.__class__) - else: - return self._sock.recvfrom_into(buffer, nbytes, flags) - -+ - def pending(self): -+ self._checkClosed() - if self._sslobj: - return self._sslobj.pending() - else: - return 0 - -- def unwrap(self): -- if self._sslobj: -- s = self._sslobj.shutdown() -- self._sslobj = None -- return s -- else: -- raise ValueError("No SSL wrapper around " + str(self)) -- - def shutdown(self, how): -+ self._checkClosed() - self._sslobj = None - socket.shutdown(self, how) - -@@ -303,32 +762,55 @@ class SSLSocket(socket): - else: - self._makefile_refs -= 1 - -- def do_handshake(self): -+ def unwrap(self): -+ if self._sslobj: -+ s = self._sslobj.shutdown() -+ self._sslobj = None -+ return s -+ else: -+ raise ValueError("No SSL wrapper around " + str(self)) - -+ def _real_close(self): -+ self._sslobj = None -+ socket._real_close(self) -+ -+ def do_handshake(self, block=False): - """Perform a TLS/SSL handshake.""" -+ self._check_connected() -+ timeout = self.gettimeout() -+ try: -+ if timeout == 0.0 and block: -+ self.settimeout(None) -+ self._sslobj.do_handshake() -+ finally: -+ self.settimeout(timeout) - -- self._sslobj.do_handshake() -+ if self.context.check_hostname: -+ if not self.server_hostname: -+ raise ValueError("check_hostname needs server_hostname " -+ "argument") -+ match_hostname(self.getpeercert(), self.server_hostname) - -- def _real_connect(self, addr, return_errno): -+ def _real_connect(self, addr, connect_ex): -+ if self.server_side: -+ raise ValueError("can't connect in server-side mode") - # Here we assume that the socket is client-side, and not - # connected at the time of the call. We connect it, then wrap it. - if self._connected: - raise ValueError("attempt to connect already-connected SSLSocket!") -- self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile, -- self.cert_reqs, self.ssl_version, -- self.ca_certs, self.ciphers) -+ self._sslobj = self.context._wrap_socket(self._sock, False, self.server_hostname, ssl_sock=self) - try: -- if return_errno: -+ if connect_ex: - rc = socket.connect_ex(self, addr) - else: - rc = None - socket.connect(self, addr) - if not rc: -+ self._connected = True - if self.do_handshake_on_connect: - self.do_handshake() -- self._connected = True - return rc -- except socket_error: -+ except (OSError, ValueError): - self._sslobj = None - raise - -@@ -343,27 +825,16 @@ class SSLSocket(socket): - return self._real_connect(addr, True) - - def accept(self): -- - """Accepts a new connection from a remote client, and returns - a tuple containing that new connection wrapped with a server-side - SSL channel, and the address of the remote client.""" - - newsock, addr = socket.accept(self) -- try: -- return (SSLSocket(newsock, -- keyfile=self.keyfile, -- certfile=self.certfile, -- server_side=True, -- cert_reqs=self.cert_reqs, -- ssl_version=self.ssl_version, -- ca_certs=self.ca_certs, -- ciphers=self.ciphers, -- do_handshake_on_connect=self.do_handshake_on_connect, -- suppress_ragged_eofs=self.suppress_ragged_eofs), -- addr) -- except socket_error as e: -- newsock.close() -- raise e -+ newsock = self.context.wrap_socket(newsock, -+ do_handshake_on_connect=self.do_handshake_on_connect, -+ suppress_ragged_eofs=self.suppress_ragged_eofs, -+ server_side=True) -+ return newsock, addr - - def makefile(self, mode='r', bufsize=-1): - -@@ -376,54 +847,81 @@ class SSLSocket(socket): - # the file-like object. - return _fileobject(self, mode, bufsize, close=True) - -+ def get_channel_binding(self, cb_type="tls-unique"): -+ """Get channel binding data for current connection. Raise ValueError -+ if the requested `cb_type` is not supported. Return bytes of the data -+ or None if the data is not available (e.g. before the handshake). -+ """ -+ if cb_type not in CHANNEL_BINDING_TYPES: -+ raise ValueError("Unsupported channel binding type") -+ if cb_type != "tls-unique": -+ raise NotImplementedError( -+ "{0} channel binding type not implemented" -+ .format(cb_type)) -+ if self._sslobj is None: -+ return None -+ return self._sslobj.tls_unique_cb() - - - def wrap_socket(sock, keyfile=None, certfile=None, - server_side=False, cert_reqs=CERT_NONE, - ssl_version=PROTOCOL_SSLv23, ca_certs=None, - do_handshake_on_connect=True, -- suppress_ragged_eofs=True, ciphers=None): -+ suppress_ragged_eofs=True, -+ ciphers=None): - -- return SSLSocket(sock, keyfile=keyfile, certfile=certfile, -+ return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile, - server_side=server_side, cert_reqs=cert_reqs, - ssl_version=ssl_version, ca_certs=ca_certs, - do_handshake_on_connect=do_handshake_on_connect, - suppress_ragged_eofs=suppress_ragged_eofs, - ciphers=ciphers) - -- - # some utility functions - - def cert_time_to_seconds(cert_time): -+ """Return the time in seconds since the Epoch, given the timestring -+ representing the "notBefore" or "notAfter" date from a certificate -+ in ``"%b %d %H:%M:%S %Y %Z"`` strptime format (C locale). - -- """Takes a date-time string in standard ASN1_print form -- ("MON DAY 24HOUR:MINUTE:SEC YEAR TIMEZONE") and return -- a Python time value in seconds past the epoch.""" -+ "notBefore" or "notAfter" dates must use UTC (RFC 5280). - -- import time -- return time.mktime(time.strptime(cert_time, "%b %d %H:%M:%S %Y GMT")) -+ Month is one of: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec -+ UTC should be specified as GMT (see ASN1_TIME_print()) -+ """ -+ from time import strptime -+ from calendar import timegm -+ -+ months = ( -+ "Jan","Feb","Mar","Apr","May","Jun", -+ "Jul","Aug","Sep","Oct","Nov","Dec" -+ ) -+ time_format = ' %d %H:%M:%S %Y GMT' # NOTE: no month, fixed GMT -+ try: -+ month_number = months.index(cert_time[:3].title()) + 1 -+ except ValueError: -+ raise ValueError('time data %r does not match ' -+ 'format "%%b%s"' % (cert_time, time_format)) -+ else: -+ # found valid month -+ tt = strptime(cert_time[3:], time_format) -+ # return an integer, the previous mktime()-based implementation -+ # returned a float (fractional seconds are always zero here). -+ return timegm((tt[0], month_number) + tt[2:6]) - - PEM_HEADER = "-----BEGIN CERTIFICATE-----" - PEM_FOOTER = "-----END CERTIFICATE-----" - - def DER_cert_to_PEM_cert(der_cert_bytes): -- - """Takes a certificate in binary DER format and returns the - PEM version of it as a string.""" - -- if hasattr(base64, 'standard_b64encode'): -- # preferred because older API gets line-length wrong -- f = base64.standard_b64encode(der_cert_bytes) -- return (PEM_HEADER + '\n' + -- textwrap.fill(f, 64) + '\n' + -- PEM_FOOTER + '\n') -- else: -- return (PEM_HEADER + '\n' + -- base64.encodestring(der_cert_bytes) + -- PEM_FOOTER + '\n') -+ f = base64.standard_b64encode(der_cert_bytes).decode('ascii') -+ return (PEM_HEADER + '\n' + -+ textwrap.fill(f, 64) + '\n' + -+ PEM_FOOTER + '\n') - - def PEM_cert_to_DER_cert(pem_cert_string): -- - """Takes a certificate in ASCII PEM format and returns the - DER-encoded version of it as a byte sequence""" - -@@ -434,25 +932,25 @@ def PEM_cert_to_DER_cert(pem_cert_string - raise ValueError("Invalid PEM encoding; must end with %s" - % PEM_FOOTER) - d = pem_cert_string.strip()[len(PEM_HEADER):-len(PEM_FOOTER)] -- return base64.decodestring(d) -+ return base64.decodestring(d.encode('ASCII', 'strict')) - --def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None): -- -+def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None): - """Retrieve the certificate from the server at the specified address, - and return it as a PEM-encoded string. - If 'ca_certs' is specified, validate the server cert against it. - If 'ssl_version' is specified, use it in the connection attempt.""" - - host, port = addr -- if (ca_certs is not None): -+ if ca_certs is not None: - cert_reqs = CERT_REQUIRED - else: - cert_reqs = CERT_NONE -- s = wrap_socket(socket(), ssl_version=ssl_version, -- cert_reqs=cert_reqs, ca_certs=ca_certs) -- s.connect(addr) -- dercert = s.getpeercert(True) -- s.close() -+ context = _create_stdlib_context(ssl_version, -+ cert_reqs=cert_reqs, -+ cafile=ca_certs) -+ with closing(create_connection(addr)) as sock: -+ with closing(context.wrap_socket(sock)) as sslsock: -+ dercert = sslsock.getpeercert(True) - return DER_cert_to_PEM_cert(dercert) - - def get_protocol_name(protocol_code): -diff --git a/Lib/test/capath/4e1295a3.0 b/Lib/test/capath/4e1295a3.0 -new file mode 100644 ---- /dev/null -+++ b/Lib/test/capath/4e1295a3.0 -@@ -0,0 +1,14 @@ -+-----BEGIN CERTIFICATE----- -+MIICLDCCAdYCAQAwDQYJKoZIhvcNAQEEBQAwgaAxCzAJBgNVBAYTAlBUMRMwEQYD -+VQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5ldXJv -+bmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMTEmJy -+dXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZpMB4X -+DTk2MDkwNTAzNDI0M1oXDTk2MTAwNTAzNDI0M1owgaAxCzAJBgNVBAYTAlBUMRMw -+EQYDVQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5l -+dXJvbmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMT -+EmJydXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZp -+MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL7+aty3S1iBA/+yxjxv4q1MUTd1kjNw -+L4lYKbpzzlmC5beaQXeQ2RmGMTXU+mDvuqItjVHOK3DvPK7lTcSGftUCAwEAATAN -+BgkqhkiG9w0BAQQFAANBAFqPEKFjk6T6CKTHvaQeEAsX0/8YHPHqH/9AnhSjrwuX -+9EBc0n6bVGhN7XaXd6sJ7dym9sbsWxb+pJdurnkxjx4= -+-----END CERTIFICATE----- -diff --git a/Lib/test/capath/5ed36f99.0 b/Lib/test/capath/5ed36f99.0 -new file mode 100644 ---- /dev/null -+++ b/Lib/test/capath/5ed36f99.0 -@@ -0,0 +1,41 @@ -+-----BEGIN CERTIFICATE----- -+MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 -+IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB -+IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA -+Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO -+BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi -+MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ -+ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -+CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ -+8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6 -+zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y -+fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7 -+w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc -+G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k -+epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q -+laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ -+QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU -+fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826 -+YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w -+ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY -+gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe -+MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0 -+IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy -+dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw -+czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0 -+dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl -+aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC -+AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg -+b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB -+ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc -+nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg -+18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c -+gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl -+Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY -+sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T -+SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF -+CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum -+GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk -+zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW -+omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD -+-----END CERTIFICATE----- -diff --git a/Lib/test/capath/6e88d7b8.0 b/Lib/test/capath/6e88d7b8.0 -new file mode 100644 ---- /dev/null -+++ b/Lib/test/capath/6e88d7b8.0 -@@ -0,0 +1,14 @@ -+-----BEGIN CERTIFICATE----- -+MIICLDCCAdYCAQAwDQYJKoZIhvcNAQEEBQAwgaAxCzAJBgNVBAYTAlBUMRMwEQYD -+VQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5ldXJv -+bmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMTEmJy -+dXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZpMB4X -+DTk2MDkwNTAzNDI0M1oXDTk2MTAwNTAzNDI0M1owgaAxCzAJBgNVBAYTAlBUMRMw -+EQYDVQQIEwpRdWVlbnNsYW5kMQ8wDQYDVQQHEwZMaXNib2ExFzAVBgNVBAoTDk5l -+dXJvbmlvLCBMZGEuMRgwFgYDVQQLEw9EZXNlbnZvbHZpbWVudG8xGzAZBgNVBAMT -+EmJydXR1cy5uZXVyb25pby5wdDEbMBkGCSqGSIb3DQEJARYMc2FtcG9AaWtpLmZp -+MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL7+aty3S1iBA/+yxjxv4q1MUTd1kjNw -+L4lYKbpzzlmC5beaQXeQ2RmGMTXU+mDvuqItjVHOK3DvPK7lTcSGftUCAwEAATAN -+BgkqhkiG9w0BAQQFAANBAFqPEKFjk6T6CKTHvaQeEAsX0/8YHPHqH/9AnhSjrwuX -+9EBc0n6bVGhN7XaXd6sJ7dym9sbsWxb+pJdurnkxjx4= -+-----END CERTIFICATE----- -diff --git a/Lib/test/capath/99d0fa06.0 b/Lib/test/capath/99d0fa06.0 -new file mode 100644 ---- /dev/null -+++ b/Lib/test/capath/99d0fa06.0 -@@ -0,0 +1,41 @@ -+-----BEGIN CERTIFICATE----- -+MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 -+IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB -+IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA -+Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO -+BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi -+MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ -+ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC -+CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ -+8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6 -+zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y -+fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7 -+w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc -+G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k -+epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q -+laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ -+QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU -+fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826 -+YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w -+ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY -+gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe -+MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0 -+IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy -+dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw -+czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0 -+dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl -+aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC -+AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg -+b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB -+ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc -+nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg -+18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c -+gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl -+Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY -+sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T -+SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF -+CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum -+GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk -+zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW -+omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD -+-----END CERTIFICATE----- -diff --git a/Lib/test/dh512.pem b/Lib/test/dh512.pem -new file mode 100644 ---- /dev/null -+++ b/Lib/test/dh512.pem -@@ -0,0 +1,9 @@ -+-----BEGIN DH PARAMETERS----- -+MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak -+XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC -+-----END DH PARAMETERS----- -+ -+These are the 512 bit DH parameters from "Assigned Number for SKIP Protocols" -+(http://www.skip-vpn.org/spec/numbers.html). -+See there for how they were generated. -+Note that g is not a generator, but this is not a problem since p is a safe prime. -diff --git a/Lib/test/keycert.passwd.pem b/Lib/test/keycert.passwd.pem -new file mode 100644 ---- /dev/null -+++ b/Lib/test/keycert.passwd.pem -@@ -0,0 +1,33 @@ -+-----BEGIN RSA PRIVATE KEY----- -+Proc-Type: 4,ENCRYPTED -+DEK-Info: DES-EDE3-CBC,1A8D9D2A02EC698A -+ -+kJYbfZ8L0sfe9Oty3gw0aloNnY5E8fegRfQLZlNoxTl6jNt0nIwI8kDJ36CZgR9c -+u3FDJm/KqrfUoz8vW+qEnWhSG7QPX2wWGPHd4K94Yz/FgrRzZ0DoK7XxXq9gOtVA -+AVGQhnz32p+6WhfGsCr9ArXEwRZrTk/FvzEPaU5fHcoSkrNVAGX8IpSVkSDwEDQr -+Gv17+cfk99UV1OCza6yKHoFkTtrC+PZU71LomBabivS2Oc4B9hYuSR2hF01wTHP+ -+YlWNagZOOVtNz4oKK9x9eNQpmfQXQvPPTfusexKIbKfZrMvJoxcm1gfcZ0H/wK6P -+6wmXSG35qMOOztCZNtperjs1wzEBXznyK8QmLcAJBjkfarABJX9vBEzZV0OUKhy+ -+noORFwHTllphbmydLhu6ehLUZMHPhzAS5UN7srtpSN81eerDMy0RMUAwA7/PofX1 -+94Me85Q8jP0PC9ETdsJcPqLzAPETEYu0ELewKRcrdyWi+tlLFrpE5KT/s5ecbl9l -+7B61U4Kfd1PIXc/siINhU3A3bYK+845YyUArUOnKf1kEox7p1RpD7yFqVT04lRTo -+cibNKATBusXSuBrp2G6GNuhWEOSafWCKJQAzgCYIp6ZTV2khhMUGppc/2H3CF6cO -+zX0KtlPVZC7hLkB6HT8SxYUwF1zqWY7+/XPPdc37MeEZ87Q3UuZwqORLY+Z0hpgt -+L5JXBCoklZhCAaN2GqwFLXtGiRSRFGY7xXIhbDTlE65Wv1WGGgDLMKGE1gOz3yAo -+2jjG1+yAHJUdE69XTFHSqSkvaloA1W03LdMXZ9VuQJ/ySXCie6ABAQ== -+-----END RSA PRIVATE KEY----- -+-----BEGIN CERTIFICATE----- -+MIICVDCCAb2gAwIBAgIJANfHOBkZr8JOMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV -+BAYTAlhZMRcwFQYDVQQHEw5DYXN0bGUgQW50aHJheDEjMCEGA1UEChMaUHl0aG9u -+IFNvZnR3YXJlIEZvdW5kYXRpb24xEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0xMDEw -+MDgyMzAxNTZaFw0yMDEwMDUyMzAxNTZaMF8xCzAJBgNVBAYTAlhZMRcwFQYDVQQH -+Ew5DYXN0bGUgQW50aHJheDEjMCEGA1UEChMaUHl0aG9uIFNvZnR3YXJlIEZvdW5k -+YXRpb24xEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -+gYkCgYEA21vT5isq7F68amYuuNpSFlKDPrMUCa4YWYqZRt2OZ+/3NKaZ2xAiSwr7 -+6MrQF70t5nLbSPpqE5+5VrS58SY+g/sXLiFd6AplH1wJZwh78DofbFYXUggktFMt -+pTyiX8jtP66bkcPkDADA089RI1TQR6Ca+n7HFa7c1fabVV6i3zkCAwEAAaMYMBYw -+FAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBBQUAA4GBAHPctQBEQ4wd -+BJ6+JcpIraopLn8BGhbjNWj40mmRqWB/NAWF6M5ne7KpGAu7tLeG4hb1zLaldK8G -+lxy2GPSRF6LFS48dpEj2HbMv2nvv6xxalDMJ9+DicWgAKTQ6bcX2j3GUkCR0g/T1 -+CRlNBAAlvhKzO7Clpf9l0YKBEfraJByX -+-----END CERTIFICATE----- -diff --git a/Lib/test/keycert3.pem b/Lib/test/keycert3.pem -new file mode 100644 ---- /dev/null -+++ b/Lib/test/keycert3.pem -@@ -0,0 +1,73 @@ -+-----BEGIN PRIVATE KEY----- -+MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMLgD0kAKDb5cFyP -+jbwNfR5CtewdXC+kMXAWD8DLxiTTvhMW7qVnlwOm36mZlszHKvsRf05lT4pegiFM -+9z2j1OlaN+ci/X7NU22TNN6crYSiN77FjYJP464j876ndSxyD+rzys386T+1r1aZ -+aggEdkj1TsSsv1zWIYKlPIjlvhuxAgMBAAECgYA0aH+T2Vf3WOPv8KdkcJg6gCRe -+yJKXOWgWRcicx/CUzOEsTxmFIDPLxqAWA3k7v0B+3vjGw5Y9lycV/5XqXNoQI14j -+y09iNsumds13u5AKkGdTJnZhQ7UKdoVHfuP44ZdOv/rJ5/VD6F4zWywpe90pcbK+ -+AWDVtusgGQBSieEl1QJBAOyVrUG5l2yoUBtd2zr/kiGm/DYyXlIthQO/A3/LngDW -+5/ydGxVsT7lAVOgCsoT+0L4efTh90PjzW8LPQrPBWVMCQQDS3h/FtYYd5lfz+FNL -+9CEe1F1w9l8P749uNUD0g317zv1tatIqVCsQWHfVHNdVvfQ+vSFw38OORO00Xqs9 -+1GJrAkBkoXXEkxCZoy4PteheO/8IWWLGGr6L7di6MzFl1lIqwT6D8L9oaV2vynFT -+DnKop0pa09Unhjyw57KMNmSE2SUJAkEArloTEzpgRmCq4IK2/NpCeGdHS5uqRlbh -+1VIa/xGps7EWQl5Mn8swQDel/YP3WGHTjfx7pgSegQfkyaRtGpZ9OQJAa9Vumj8m -+JAAtI0Bnga8hgQx7BhTQY4CadDxyiRGOGYhwUzYVCqkb2sbVRH9HnwUaJT7cWBY3 -+RnJdHOMXWem7/w== -+-----END PRIVATE KEY----- -+Certificate: -+ Data: -+ Version: 1 (0x0) -+ Serial Number: 12723342612721443281 (0xb09264b1f2da21d1) -+ Signature Algorithm: sha1WithRSAEncryption -+ Issuer: C=XY, O=Python Software Foundation CA, CN=our-ca-server -+ Validity -+ Not Before: Jan 4 19:47:07 2013 GMT -+ Not After : Nov 13 19:47:07 2022 GMT -+ Subject: C=XY, L=Castle Anthrax, O=Python Software Foundation, CN=localhost -+ Subject Public Key Info: -+ Public Key Algorithm: rsaEncryption -+ Public-Key: (1024 bit) -+ Modulus: -+ 00:c2:e0:0f:49:00:28:36:f9:70:5c:8f:8d:bc:0d: -+ 7d:1e:42:b5:ec:1d:5c:2f:a4:31:70:16:0f:c0:cb: -+ c6:24:d3:be:13:16:ee:a5:67:97:03:a6:df:a9:99: -+ 96:cc:c7:2a:fb:11:7f:4e:65:4f:8a:5e:82:21:4c: -+ f7:3d:a3:d4:e9:5a:37:e7:22:fd:7e:cd:53:6d:93: -+ 34:de:9c:ad:84:a2:37:be:c5:8d:82:4f:e3:ae:23: -+ f3:be:a7:75:2c:72:0f:ea:f3:ca:cd:fc:e9:3f:b5: -+ af:56:99:6a:08:04:76:48:f5:4e:c4:ac:bf:5c:d6: -+ 21:82:a5:3c:88:e5:be:1b:b1 -+ Exponent: 65537 (0x10001) -+ Signature Algorithm: sha1WithRSAEncryption -+ 2f:42:5f:a3:09:2c:fa:51:88:c7:37:7f:ea:0e:63:f0:a2:9a: -+ e5:5a:e2:c8:20:f0:3f:60:bc:c8:0f:b6:c6:76:ce:db:83:93: -+ f5:a3:33:67:01:8e:04:cd:00:9a:73:fd:f3:35:86:fa:d7:13: -+ e2:46:c6:9d:c0:29:53:d4:a9:90:b8:77:4b:e6:83:76:e4:92: -+ d6:9c:50:cf:43:d0:c6:01:77:61:9a:de:9b:70:f7:72:cd:59: -+ 00:31:69:d9:b4:ca:06:9c:6d:c3:c7:80:8c:68:e6:b5:a2:f8: -+ ef:1d:bb:16:9f:77:77:ef:87:62:22:9b:4d:69:a4:3a:1a:f1: -+ 21:5e:8c:32:ac:92:fd:15:6b:18:c2:7f:15:0d:98:30:ca:75: -+ 8f:1a:71:df:da:1d:b2:ef:9a:e8:2d:2e:02:fd:4a:3c:aa:96: -+ 0b:06:5d:35:b3:3d:24:87:4b:e0:b0:58:60:2f:45:ac:2e:48: -+ 8a:b0:99:10:65:27:ff:cc:b1:d8:fd:bd:26:6b:b9:0c:05:2a: -+ f4:45:63:35:51:07:ed:83:85:fe:6f:69:cb:bb:40:a8:ae:b6: -+ 3b:56:4a:2d:a4:ed:6d:11:2c:4d:ed:17:24:fd:47:bc:d3:41: -+ a2:d3:06:fe:0c:90:d8:d8:94:26:c4:ff:cc:a1:d8:42:77:eb: -+ fc:a9:94:71 -+-----BEGIN CERTIFICATE----- -+MIICpDCCAYwCCQCwkmSx8toh0TANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJY -+WTEmMCQGA1UECgwdUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24gQ0ExFjAUBgNV -+BAMMDW91ci1jYS1zZXJ2ZXIwHhcNMTMwMTA0MTk0NzA3WhcNMjIxMTEzMTk0NzA3 -+WjBfMQswCQYDVQQGEwJYWTEXMBUGA1UEBxMOQ2FzdGxlIEFudGhyYXgxIzAhBgNV -+BAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMRIwEAYDVQQDEwlsb2NhbGhv -+c3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMLgD0kAKDb5cFyPjbwNfR5C -+tewdXC+kMXAWD8DLxiTTvhMW7qVnlwOm36mZlszHKvsRf05lT4pegiFM9z2j1Ola -+N+ci/X7NU22TNN6crYSiN77FjYJP464j876ndSxyD+rzys386T+1r1aZaggEdkj1 -+TsSsv1zWIYKlPIjlvhuxAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAC9CX6MJLPpR -+iMc3f+oOY/CimuVa4sgg8D9gvMgPtsZ2ztuDk/WjM2cBjgTNAJpz/fM1hvrXE+JG -+xp3AKVPUqZC4d0vmg3bkktacUM9D0MYBd2Ga3ptw93LNWQAxadm0ygacbcPHgIxo -+5rWi+O8duxafd3fvh2Iim01ppDoa8SFejDKskv0VaxjCfxUNmDDKdY8acd/aHbLv -+mugtLgL9SjyqlgsGXTWzPSSHS+CwWGAvRawuSIqwmRBlJ//Msdj9vSZruQwFKvRF -+YzVRB+2Dhf5vacu7QKiutjtWSi2k7W0RLE3tFyT9R7zTQaLTBv4MkNjYlCbE/8yh -+2EJ36/yplHE= -+-----END CERTIFICATE----- -diff --git a/Lib/test/keycert4.pem b/Lib/test/keycert4.pem -new file mode 100644 ---- /dev/null -+++ b/Lib/test/keycert4.pem -@@ -0,0 +1,73 @@ -+-----BEGIN PRIVATE KEY----- -+MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAK5UQiMI5VkNs2Qv -+L7gUaiDdFevNUXRjU4DHAe3ZzzYLZNE69h9gO9VCSS16tJ5fT5VEu0EZyGr0e3V2 -+NkX0ZoU0Hc/UaY4qx7LHmn5SYZpIxhJnkf7SyHJK1zUaGlU0/LxYqIuGCtF5dqx1 -+L2OQhEx1GM6RydHdgX69G64LXcY5AgMBAAECgYAhsRMfJkb9ERLMl/oG/5sLQu9L -+pWDKt6+ZwdxzlZbggQ85CMYshjLKIod2DLL/sLf2x1PRXyRG131M1E3k8zkkz6de -+R1uDrIN/x91iuYzfLQZGh8bMY7Yjd2eoroa6R/7DjpElGejLxOAaDWO0ST2IFQy9 -+myTGS2jSM97wcXfsSQJBANP3jelJoS5X6BRjTSneY21wcocxVuQh8pXpErALVNsT -+drrFTeaBuZp7KvbtnIM5g2WRNvaxLZlAY/hXPJvi6ncCQQDSix1cebml6EmPlEZS -+Mm8gwI2F9ufUunwJmBJcz826Do0ZNGByWDAM/JQZH4FX4GfAFNuj8PUb+GQfadkx -+i1DPAkEA0lVsNHojvuDsIo8HGuzarNZQT2beWjJ1jdxh9t7HrTx7LIps6rb/fhOK -+Zs0R6gVAJaEbcWAPZ2tFyECInAdnsQJAUjaeXXjuxFkjOFym5PvqpvhpivEx78Bu -+JPTr3rAKXmfGMxxfuOa0xK1wSyshP6ZR/RBn/+lcXPKubhHQDOegwwJAJF1DBQnN -++/tLmOPULtDwfP4Zixn+/8GmGOahFoRcu6VIGHmRilJTn6MOButw7Glv2YdeC6l/ -+e83Gq6ffLVfKNQ== -+-----END PRIVATE KEY----- -+Certificate: -+ Data: -+ Version: 1 (0x0) -+ Serial Number: 12723342612721443282 (0xb09264b1f2da21d2) -+ Signature Algorithm: sha1WithRSAEncryption -+ Issuer: C=XY, O=Python Software Foundation CA, CN=our-ca-server -+ Validity -+ Not Before: Jan 4 19:47:07 2013 GMT -+ Not After : Nov 13 19:47:07 2022 GMT -+ Subject: C=XY, L=Castle Anthrax, O=Python Software Foundation, CN=fakehostname -+ Subject Public Key Info: -+ Public Key Algorithm: rsaEncryption -+ Public-Key: (1024 bit) -+ Modulus: -+ 00:ae:54:42:23:08:e5:59:0d:b3:64:2f:2f:b8:14: -+ 6a:20:dd:15:eb:cd:51:74:63:53:80:c7:01:ed:d9: -+ cf:36:0b:64:d1:3a:f6:1f:60:3b:d5:42:49:2d:7a: -+ b4:9e:5f:4f:95:44:bb:41:19:c8:6a:f4:7b:75:76: -+ 36:45:f4:66:85:34:1d:cf:d4:69:8e:2a:c7:b2:c7: -+ 9a:7e:52:61:9a:48:c6:12:67:91:fe:d2:c8:72:4a: -+ d7:35:1a:1a:55:34:fc:bc:58:a8:8b:86:0a:d1:79: -+ 76:ac:75:2f:63:90:84:4c:75:18:ce:91:c9:d1:dd: -+ 81:7e:bd:1b:ae:0b:5d:c6:39 -+ Exponent: 65537 (0x10001) -+ Signature Algorithm: sha1WithRSAEncryption -+ ad:45:8a:8e:ef:c6:ef:04:41:5c:2c:4a:84:dc:02:76:0c:d0: -+ 66:0f:f0:16:04:58:4d:fd:68:b7:b8:d3:a8:41:a5:5c:3c:6f: -+ 65:3c:d1:f8:ce:43:35:e7:41:5f:53:3d:c9:2c:c3:7d:fc:56: -+ 4a:fa:47:77:38:9d:bb:97:28:0a:3b:91:19:7f:bc:74:ae:15: -+ 6b:bd:20:36:67:45:a5:1e:79:d7:75:e6:89:5c:6d:54:84:d1: -+ 95:d7:a7:b4:33:3c:af:37:c4:79:8f:5e:75:dc:75:c2:18:fb: -+ 61:6f:2d:dc:38:65:5b:ba:67:28:d0:88:d7:8d:b9:23:5a:8e: -+ e8:c6:bb:db:ce:d5:b8:41:2a:ce:93:08:b6:95:ad:34:20:18: -+ d5:3b:37:52:74:50:0b:07:2c:b0:6d:a4:4c:7b:f4:e0:fd:d1: -+ af:17:aa:20:cd:62:e3:f0:9d:37:69:db:41:bd:d4:1c:fb:53: -+ 20:da:88:9d:76:26:67:ce:01:90:a7:80:1d:a9:5b:39:73:68: -+ 54:0a:d1:2a:03:1b:8f:3c:43:5d:5d:c4:51:f1:a7:e7:11:da: -+ 31:2c:49:06:af:04:f4:b8:3c:99:c4:20:b9:06:36:a2:00:92: -+ 61:1d:0c:6d:24:05:e2:82:e1:47:db:a0:5f:ba:b9:fb:ba:fa: -+ 49:12:1e:ce -+-----BEGIN CERTIFICATE----- -+MIICpzCCAY8CCQCwkmSx8toh0jANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJY -+WTEmMCQGA1UECgwdUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24gQ0ExFjAUBgNV -+BAMMDW91ci1jYS1zZXJ2ZXIwHhcNMTMwMTA0MTk0NzA3WhcNMjIxMTEzMTk0NzA3 -+WjBiMQswCQYDVQQGEwJYWTEXMBUGA1UEBxMOQ2FzdGxlIEFudGhyYXgxIzAhBgNV -+BAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMRUwEwYDVQQDEwxmYWtlaG9z -+dG5hbWUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK5UQiMI5VkNs2QvL7gU -+aiDdFevNUXRjU4DHAe3ZzzYLZNE69h9gO9VCSS16tJ5fT5VEu0EZyGr0e3V2NkX0 -+ZoU0Hc/UaY4qx7LHmn5SYZpIxhJnkf7SyHJK1zUaGlU0/LxYqIuGCtF5dqx1L2OQ -+hEx1GM6RydHdgX69G64LXcY5AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAK1Fio7v -+xu8EQVwsSoTcAnYM0GYP8BYEWE39aLe406hBpVw8b2U80fjOQzXnQV9TPcksw338 -+Vkr6R3c4nbuXKAo7kRl/vHSuFWu9IDZnRaUeedd15olcbVSE0ZXXp7QzPK83xHmP -+XnXcdcIY+2FvLdw4ZVu6ZyjQiNeNuSNajujGu9vO1bhBKs6TCLaVrTQgGNU7N1J0 -+UAsHLLBtpEx79OD90a8XqiDNYuPwnTdp20G91Bz7UyDaiJ12JmfOAZCngB2pWzlz -+aFQK0SoDG488Q11dxFHxp+cR2jEsSQavBPS4PJnEILkGNqIAkmEdDG0kBeKC4Ufb -+oF+6ufu6+kkSHs4= -+-----END CERTIFICATE----- -diff --git a/Lib/test/make_ssl_certs.py b/Lib/test/make_ssl_certs.py -new file mode 100644 ---- /dev/null -+++ b/Lib/test/make_ssl_certs.py -@@ -0,0 +1,176 @@ -+"""Make the custom certificate and private key files used by test_ssl -+and friends.""" -+ -+import os -+import shutil -+import sys -+import tempfile -+from subprocess import * -+ -+req_template = """ -+ [req] -+ distinguished_name = req_distinguished_name -+ x509_extensions = req_x509_extensions -+ prompt = no -+ -+ [req_distinguished_name] -+ C = XY -+ L = Castle Anthrax -+ O = Python Software Foundation -+ CN = {hostname} -+ -+ [req_x509_extensions] -+ subjectAltName = DNS:{hostname} -+ -+ [ ca ] -+ default_ca = CA_default -+ -+ [ CA_default ] -+ dir = cadir -+ database = $dir/index.txt -+ crlnumber = $dir/crl.txt -+ default_md = sha1 -+ default_days = 3600 -+ default_crl_days = 3600 -+ certificate = pycacert.pem -+ private_key = pycakey.pem -+ serial = $dir/serial -+ RANDFILE = $dir/.rand -+ -+ policy = policy_match -+ -+ [ policy_match ] -+ countryName = match -+ stateOrProvinceName = optional -+ organizationName = match -+ organizationalUnitName = optional -+ commonName = supplied -+ emailAddress = optional -+ -+ [ policy_anything ] -+ countryName = optional -+ stateOrProvinceName = optional -+ localityName = optional -+ organizationName = optional -+ organizationalUnitName = optional -+ commonName = supplied -+ emailAddress = optional -+ -+ -+ [ v3_ca ] -+ -+ subjectKeyIdentifier=hash -+ authorityKeyIdentifier=keyid:always,issuer -+ basicConstraints = CA:true -+ -+ """ -+ -+here = os.path.abspath(os.path.dirname(__file__)) -+ -+def make_cert_key(hostname, sign=False): -+ print("creating cert for " + hostname) -+ tempnames = [] -+ for i in range(3): -+ with tempfile.NamedTemporaryFile(delete=False) as f: -+ tempnames.append(f.name) -+ req_file, cert_file, key_file = tempnames -+ try: -+ with open(req_file, 'w') as f: -+ f.write(req_template.format(hostname=hostname)) -+ args = ['req', '-new', '-days', '3650', '-nodes', -+ '-newkey', 'rsa:1024', '-keyout', key_file, -+ '-config', req_file] -+ if sign: -+ with tempfile.NamedTemporaryFile(delete=False) as f: -+ tempnames.append(f.name) -+ reqfile = f.name -+ args += ['-out', reqfile ] -+ -+ else: -+ args += ['-x509', '-out', cert_file ] -+ check_call(['openssl'] + args) -+ -+ if sign: -+ args = ['ca', '-config', req_file, '-out', cert_file, '-outdir', 'cadir', -+ '-policy', 'policy_anything', '-batch', '-infiles', reqfile ] -+ check_call(['openssl'] + args) -+ -+ -+ with open(cert_file, 'r') as f: -+ cert = f.read() -+ with open(key_file, 'r') as f: -+ key = f.read() -+ return cert, key -+ finally: -+ for name in tempnames: -+ os.remove(name) -+ -+TMP_CADIR = 'cadir' -+ -+def unmake_ca(): -+ shutil.rmtree(TMP_CADIR) -+ -+def make_ca(): -+ os.mkdir(TMP_CADIR) -+ with open(os.path.join('cadir','index.txt'),'a+') as f: -+ pass # empty file -+ with open(os.path.join('cadir','crl.txt'),'a+') as f: -+ f.write("00") -+ with open(os.path.join('cadir','index.txt.attr'),'w+') as f: -+ f.write('unique_subject = no') -+ -+ with tempfile.NamedTemporaryFile("w") as t: -+ t.write(req_template.format(hostname='our-ca-server')) -+ t.flush() -+ with tempfile.NamedTemporaryFile() as f: -+ args = ['req', '-new', '-days', '3650', '-extensions', 'v3_ca', '-nodes', -+ '-newkey', 'rsa:2048', '-keyout', 'pycakey.pem', -+ '-out', f.name, -+ '-subj', '/C=XY/L=Castle Anthrax/O=Python Software Foundation CA/CN=our-ca-server'] -+ check_call(['openssl'] + args) -+ args = ['ca', '-config', t.name, '-create_serial', -+ '-out', 'pycacert.pem', '-batch', '-outdir', TMP_CADIR, -+ '-keyfile', 'pycakey.pem', '-days', '3650', -+ '-selfsign', '-extensions', 'v3_ca', '-infiles', f.name ] -+ check_call(['openssl'] + args) -+ args = ['ca', '-config', t.name, '-gencrl', '-out', 'revocation.crl'] -+ check_call(['openssl'] + args) -+ -+if __name__ == '__main__': -+ os.chdir(here) -+ cert, key = make_cert_key('localhost') -+ with open('ssl_cert.pem', 'w') as f: -+ f.write(cert) -+ with open('ssl_key.pem', 'w') as f: -+ f.write(key) -+ print("password protecting ssl_key.pem in ssl_key.passwd.pem") -+ check_call(['openssl','rsa','-in','ssl_key.pem','-out','ssl_key.passwd.pem','-des3','-passout','pass:somepass']) -+ check_call(['openssl','rsa','-in','ssl_key.pem','-out','keycert.passwd.pem','-des3','-passout','pass:somepass']) -+ -+ with open('keycert.pem', 'w') as f: -+ f.write(key) -+ f.write(cert) -+ -+ with open('keycert.passwd.pem', 'a+') as f: -+ f.write(cert) -+ -+ # For certificate matching tests -+ make_ca() -+ cert, key = make_cert_key('fakehostname') -+ with open('keycert2.pem', 'w') as f: -+ f.write(key) -+ f.write(cert) -+ -+ cert, key = make_cert_key('localhost', True) -+ with open('keycert3.pem', 'w') as f: -+ f.write(key) -+ f.write(cert) -+ -+ cert, key = make_cert_key('fakehostname', True) -+ with open('keycert4.pem', 'w') as f: -+ f.write(key) -+ f.write(cert) -+ -+ unmake_ca() -+ print("\n\nPlease change the values in test_ssl.py, test_parse_cert function related to notAfter,notBefore and serialNumber") -+ check_call(['openssl','x509','-in','keycert.pem','-dates','-serial','-noout']) -diff --git a/Lib/test/pycacert.pem b/Lib/test/pycacert.pem -new file mode 100644 ---- /dev/null -+++ b/Lib/test/pycacert.pem -@@ -0,0 +1,78 @@ -+Certificate: -+ Data: -+ Version: 3 (0x2) -+ Serial Number: 12723342612721443280 (0xb09264b1f2da21d0) -+ Signature Algorithm: sha1WithRSAEncryption -+ Issuer: C=XY, O=Python Software Foundation CA, CN=our-ca-server -+ Validity -+ Not Before: Jan 4 19:47:07 2013 GMT -+ Not After : Jan 2 19:47:07 2023 GMT -+ Subject: C=XY, O=Python Software Foundation CA, CN=our-ca-server -+ Subject Public Key Info: -+ Public Key Algorithm: rsaEncryption -+ Public-Key: (2048 bit) -+ Modulus: -+ 00:e7:de:e9:e3:0c:9f:00:b6:a1:fd:2b:5b:96:d2: -+ 6f:cc:e0:be:86:b9:20:5e:ec:03:7a:55:ab:ea:a4: -+ e9:f9:49:85:d2:66:d5:ed:c7:7a:ea:56:8e:2d:8f: -+ e7:42:e2:62:28:a9:9f:d6:1b:8e:eb:b5:b4:9c:9f: -+ 14:ab:df:e6:94:8b:76:1d:3e:6d:24:61:ed:0c:bf: -+ 00:8a:61:0c:df:5c:c8:36:73:16:00:cd:47:ba:6d: -+ a4:a4:74:88:83:23:0a:19:fc:09:a7:3c:4a:4b:d3: -+ e7:1d:2d:e4:ea:4c:54:21:f3:26:db:89:37:18:d4: -+ 02:bb:40:32:5f:a4:ff:2d:1c:f7:d4:bb:ec:8e:cf: -+ 5c:82:ac:e6:7c:08:6c:48:85:61:07:7f:25:e0:5c: -+ e0:bc:34:5f:e0:b9:04:47:75:c8:47:0b:8d:bc:d6: -+ c8:68:5f:33:83:62:d2:20:44:35:b1:ad:81:1a:8a: -+ cd:bc:35:b0:5c:8b:47:d6:18:e9:9c:18:97:cc:01: -+ 3c:29:cc:e8:1e:e4:e4:c1:b8:de:e7:c2:11:18:87: -+ 5a:93:34:d8:a6:25:f7:14:71:eb:e4:21:a2:d2:0f: -+ 2e:2e:d4:62:00:35:d3:d6:ef:5c:60:4b:4c:a9:14: -+ e2:dd:15:58:46:37:33:26:b7:e7:2e:5d:ed:42:e4: -+ c5:4d -+ Exponent: 65537 (0x10001) -+ X509v3 extensions: -+ X509v3 Subject Key Identifier: -+ BC:DD:62:D9:76:DA:1B:D2:54:6B:CF:E0:66:9B:1E:1E:7B:56:0C:0B -+ X509v3 Authority Key Identifier: -+ keyid:BC:DD:62:D9:76:DA:1B:D2:54:6B:CF:E0:66:9B:1E:1E:7B:56:0C:0B -+ -+ X509v3 Basic Constraints: -+ CA:TRUE -+ Signature Algorithm: sha1WithRSAEncryption -+ 7d:0a:f5:cb:8d:d3:5d:bd:99:8e:f8:2b:0f:ba:eb:c2:d9:a6: -+ 27:4f:2e:7b:2f:0e:64:d8:1c:35:50:4e:ee:fc:90:b9:8d:6d: -+ a8:c5:c6:06:b0:af:f3:2d:bf:3b:b8:42:07:dd:18:7d:6d:95: -+ 54:57:85:18:60:47:2f:eb:78:1b:f9:e8:17:fd:5a:0d:87:17: -+ 28:ac:4c:6a:e6:bc:29:f4:f4:55:70:29:42:de:85:ea:ab:6c: -+ 23:06:64:30:75:02:8e:53:bc:5e:01:33:37:cc:1e:cd:b8:a4: -+ fd:ca:e4:5f:65:3b:83:1c:86:f1:55:02:a0:3a:8f:db:91:b7: -+ 40:14:b4:e7:8d:d2:ee:73:ba:e3:e5:34:2d:bc:94:6f:4e:24: -+ 06:f7:5f:8b:0e:a7:8e:6b:de:5e:75:f4:32:9a:50:b1:44:33: -+ 9a:d0:05:e2:78:82:ff:db:da:8a:63:eb:a9:dd:d1:bf:a0:61: -+ ad:e3:9e:8a:24:5d:62:0e:e7:4c:91:7f:ef:df:34:36:3b:2f: -+ 5d:f5:84:b2:2f:c4:6d:93:96:1a:6f:30:28:f1:da:12:9a:64: -+ b4:40:33:1d:bd:de:2b:53:a8:ea:be:d6:bc:4e:96:f5:44:fb: -+ 32:18:ae:d5:1f:f6:69:af:b6:4e:7b:1d:58:ec:3b:a9:53:a3: -+ 5e:58:c8:9e -+-----BEGIN CERTIFICATE----- -+MIIDbTCCAlWgAwIBAgIJALCSZLHy2iHQMA0GCSqGSIb3DQEBBQUAME0xCzAJBgNV -+BAYTAlhZMSYwJAYDVQQKDB1QeXRob24gU29mdHdhcmUgRm91bmRhdGlvbiBDQTEW -+MBQGA1UEAwwNb3VyLWNhLXNlcnZlcjAeFw0xMzAxMDQxOTQ3MDdaFw0yMzAxMDIx -+OTQ3MDdaME0xCzAJBgNVBAYTAlhZMSYwJAYDVQQKDB1QeXRob24gU29mdHdhcmUg -+Rm91bmRhdGlvbiBDQTEWMBQGA1UEAwwNb3VyLWNhLXNlcnZlcjCCASIwDQYJKoZI -+hvcNAQEBBQADggEPADCCAQoCggEBAOfe6eMMnwC2of0rW5bSb8zgvoa5IF7sA3pV -+q+qk6flJhdJm1e3HeupWji2P50LiYiipn9Ybjuu1tJyfFKvf5pSLdh0+bSRh7Qy/ -+AIphDN9cyDZzFgDNR7ptpKR0iIMjChn8Cac8SkvT5x0t5OpMVCHzJtuJNxjUArtA -+Ml+k/y0c99S77I7PXIKs5nwIbEiFYQd/JeBc4Lw0X+C5BEd1yEcLjbzWyGhfM4Ni -+0iBENbGtgRqKzbw1sFyLR9YY6ZwYl8wBPCnM6B7k5MG43ufCERiHWpM02KYl9xRx -+6+QhotIPLi7UYgA109bvXGBLTKkU4t0VWEY3Mya35y5d7ULkxU0CAwEAAaNQME4w -+HQYDVR0OBBYEFLzdYtl22hvSVGvP4GabHh57VgwLMB8GA1UdIwQYMBaAFLzdYtl2 -+2hvSVGvP4GabHh57VgwLMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB -+AH0K9cuN0129mY74Kw+668LZpidPLnsvDmTYHDVQTu78kLmNbajFxgawr/Mtvzu4 -+QgfdGH1tlVRXhRhgRy/reBv56Bf9Wg2HFyisTGrmvCn09FVwKULeheqrbCMGZDB1 -+Ao5TvF4BMzfMHs24pP3K5F9lO4MchvFVAqA6j9uRt0AUtOeN0u5zuuPlNC28lG9O -+JAb3X4sOp45r3l519DKaULFEM5rQBeJ4gv/b2opj66nd0b+gYa3jnookXWIO50yR -+f+/fNDY7L131hLIvxG2TlhpvMCjx2hKaZLRAMx293itTqOq+1rxOlvVE+zIYrtUf -+9mmvtk57HVjsO6lTo15YyJ4= -+-----END CERTIFICATE----- -diff --git a/Lib/test/revocation.crl b/Lib/test/revocation.crl -new file mode 100644 ---- /dev/null -+++ b/Lib/test/revocation.crl -@@ -0,0 +1,11 @@ -+-----BEGIN X509 CRL----- -+MIIBpjCBjwIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJYWTEmMCQGA1UE -+CgwdUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24gQ0ExFjAUBgNVBAMMDW91ci1j -+YS1zZXJ2ZXIXDTEzMTEyMTE3MDg0N1oXDTIzMDkzMDE3MDg0N1qgDjAMMAoGA1Ud -+FAQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQCNJXC2mVKauEeN3LlQ3ZtM5gkH3ExH -++i4bmJjtJn497WwvvoIeUdrmVXgJQR93RtV37hZwN0SXMLlNmUZPH4rHhihayw4m -+unCzVj/OhCCY7/TPjKuJ1O/0XhaLBpBVjQN7R/1ujoRKbSia/CD3vcn7Fqxzw7LK -+fSRCKRGTj1CZiuxrphtFchwALXSiFDy9mr2ZKhImcyq1PydfgEzU78APpOkMQsIC -+UNJ/cf3c9emzf+dUtcMEcejQ3mynBo4eIGg1EW42bz4q4hSjzQlKcBV0muw5qXhc -+HOxH2iTFhQ7SrvVuK/dM14rYM4B5mSX3nRC1kNmXpS9j3wJDhuwmjHed -+-----END X509 CRL----- -diff --git a/Lib/test/sha256.pem b/Lib/test/sha256.pem ---- a/Lib/test/sha256.pem -+++ b/Lib/test/sha256.pem -@@ -1,128 +1,128 @@ - # Certificate chain for https://sha256.tbs-internet.com -- 0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=Certificats TBS X509/CN=ecom.tbs-x509.com -- i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA business -+ 0 s:/C=FR/postalCode=14000/ST=Calvados/L=CAEN/street=22 rue de Bretagne/O=TBS INTERNET/OU=0002 440443810/OU=sha-256 production/CN=sha256.tbs-internet.com -+ i:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC - -----BEGIN CERTIFICATE----- --MIIGTjCCBTagAwIBAgIQOh3d9dNDPq1cSdJmEiMpqDANBgkqhkiG9w0BAQUFADCB --yTELMAkGA1UEBhMCRlIxETAPBgNVBAgTCENhbHZhZG9zMQ0wCwYDVQQHEwRDYWVu --MRUwEwYDVQQKEwxUQlMgSU5URVJORVQxSDBGBgNVBAsTP1Rlcm1zIGFuZCBDb25k --aXRpb25zOiBodHRwOi8vd3d3LnRicy1pbnRlcm5ldC5jb20vQ0EvcmVwb3NpdG9y --eTEYMBYGA1UECxMPVEJTIElOVEVSTkVUIENBMR0wGwYDVQQDExRUQlMgWDUwOSBD --QSBidXNpbmVzczAeFw0xMTAxMjUwMDAwMDBaFw0xMzAyMDUyMzU5NTlaMIHHMQsw --CQYDVQQGEwJGUjEOMAwGA1UEERMFMTQwMDAxETAPBgNVBAgTCENhbHZhZG9zMQ0w --CwYDVQQHEwRDQUVOMRswGQYDVQQJExIyMiBydWUgZGUgQnJldGFnbmUxFTATBgNV --BAoTDFRCUyBJTlRFUk5FVDEXMBUGA1UECxMOMDAwMiA0NDA0NDM4MTAxHTAbBgNV --BAsTFENlcnRpZmljYXRzIFRCUyBYNTA5MRowGAYDVQQDExFlY29tLnRicy14NTA5 --LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKRrlHUnJ++1lpcg --jtYco7cdmRe+EEfTmwPfCdfV3G1QfsTSvY6FfMpm/83pqHfT+4ANwr18wD9ZrAEN --G16mf9VdCGK12+TP7DmqeZyGIqlFFoahQnmb8EarvE43/1UeQ2CV9XmzwZvpqeli --LfXsFonawrY3H6ZnMwS64St61Z+9gdyuZ/RbsoZBbT5KUjDEG844QRU4OT1IGeEI --eY5NM5RNIh6ZNhVtqeeCxMS7afONkHQrOco73RdSTRck/Hj96Ofl3MHNHryr+AMK --DGFk1kLCZGpPdXtkxXvaDeQoiYDlil26CWc+YK6xyDPMdsWvoG14ZLyCpzMXA7/7 --4YAQRH0CAwEAAaOCAjAwggIsMB8GA1UdIwQYMBaAFBoJBMz5CY+7HqDO1KQUf0vV --I1jNMB0GA1UdDgQWBBQgOU8HsWzbmD4WZP5Wtdw7jca2WDAOBgNVHQ8BAf8EBAMC --BaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw --TAYDVR0gBEUwQzBBBgsrBgEEAYDlNwIBATAyMDAGCCsGAQUFBwIBFiRodHRwczov --L3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL0NQUzEwdwYDVR0fBHAwbjA3oDWgM4Yx --aHR0cDovL2NybC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQWJ1c2luZXNzLmNy --bDAzoDGgL4YtaHR0cDovL2NybC50YnMteDUwOS5jb20vVEJTWDUwOUNBYnVzaW5l --c3MuY3JsMIGwBggrBgEFBQcBAQSBozCBoDA9BggrBgEFBQcwAoYxaHR0cDovL2Ny --dC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQWJ1c2luZXNzLmNydDA5BggrBgEF --BQcwAoYtaHR0cDovL2NydC50YnMteDUwOS5jb20vVEJTWDUwOUNBYnVzaW5lc3Mu --Y3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC50YnMteDUwOS5jb20wMwYDVR0R --BCwwKoIRZWNvbS50YnMteDUwOS5jb22CFXd3dy5lY29tLnRicy14NTA5LmNvbTAN --BgkqhkiG9w0BAQUFAAOCAQEArT4NHfbY87bGAw8lPV4DmHlmuDuVp/y7ltO3Ynse --3Rz8RxW2AzuO0Oy2F0Cu4yWKtMyEyMXyHqWtae7ElRbdTu5w5GwVBLJHClCzC8S9 --SpgMMQTx3Rgn8vjkHuU9VZQlulZyiPK7yunjc7c310S9FRZ7XxOwf8Nnx4WnB+No --WrfApzhhQl31w+RyrNxZe58hCfDDHmevRvwLjQ785ZoQXJDj2j3qAD4aI2yB8lB5 --oaE1jlCJzC7Kmz/Y9jzfmv/zAs1LQTm9ktevv4BTUFaGjv9jxnQ1xnS862ZiouLW --zZYIlYPf4F6JjXGiIQgQRglILUfq3ftJd9/ok9W9ZF8h8w== -+MIIGXDCCBUSgAwIBAgIRAKpVmHgg9nfCodAVwcP4siwwDQYJKoZIhvcNAQELBQAw -+gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl -+bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u -+ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv -+cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg -+Q0EgU0dDMB4XDTEyMDEwNDAwMDAwMFoXDTE0MDIxNzIzNTk1OVowgcsxCzAJBgNV -+BAYTAkZSMQ4wDAYDVQQREwUxNDAwMDERMA8GA1UECBMIQ2FsdmFkb3MxDTALBgNV -+BAcTBENBRU4xGzAZBgNVBAkTEjIyIHJ1ZSBkZSBCcmV0YWduZTEVMBMGA1UEChMM -+VEJTIElOVEVSTkVUMRcwFQYDVQQLEw4wMDAyIDQ0MDQ0MzgxMDEbMBkGA1UECxMS -+c2hhLTI1NiBwcm9kdWN0aW9uMSAwHgYDVQQDExdzaGEyNTYudGJzLWludGVybmV0 -+LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKQIX/zdJcyxty0m -+PM1XQSoSSifueS3AVcgqMsaIKS/u+rYzsv4hQ/qA6vLn5m5/ewUcZDj7zdi6rBVf -+PaVNXJ6YinLX0tkaW8TEjeVuZG5yksGZlhCt1CJ1Ho9XLiLaP4uJ7MCoNUntpJ+E -+LfrOdgsIj91kPmwjDJeztVcQCvKzhjVJA/KxdInc0JvOATn7rpaSmQI5bvIjufgo -+qVsTPwVFzuUYULXBk7KxRT7MiEqnd5HvviNh0285QC478zl3v0I0Fb5El4yD3p49 -+IthcRnxzMKc0UhU5ogi0SbONyBfm/mzONVfSxpM+MlyvZmJqrbuuLoEDzJD+t8PU -+xSuzgbcCAwEAAaOCAj4wggI6MB8GA1UdIwQYMBaAFAdEdoWTKLx/bXjSCuv6TEvf -+2YIfMB0GA1UdDgQWBBT/qTGYdaj+f61c2IRFL/B1eEsM8DAOBgNVHQ8BAf8EBAMC -+BaAwDAYDVR0TAQH/BAIwADA0BgNVHSUELTArBggrBgEFBQcDAQYIKwYBBQUHAwIG -+CisGAQQBgjcKAwMGCWCGSAGG+EIEATBLBgNVHSAERDBCMEAGCisGAQQB5TcCBAEw -+MjAwBggrBgEFBQcCARYkaHR0cHM6Ly93d3cudGJzLWludGVybmV0LmNvbS9DQS9D -+UFM0MG0GA1UdHwRmMGQwMqAwoC6GLGh0dHA6Ly9jcmwudGJzLWludGVybmV0LmNv -+bS9UQlNYNTA5Q0FTR0MuY3JsMC6gLKAqhihodHRwOi8vY3JsLnRicy14NTA5LmNv -+bS9UQlNYNTA5Q0FTR0MuY3JsMIGmBggrBgEFBQcBAQSBmTCBljA4BggrBgEFBQcw -+AoYsaHR0cDovL2NydC50YnMtaW50ZXJuZXQuY29tL1RCU1g1MDlDQVNHQy5jcnQw -+NAYIKwYBBQUHMAKGKGh0dHA6Ly9jcnQudGJzLXg1MDkuY29tL1RCU1g1MDlDQVNH -+Qy5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLnRicy14NTA5LmNvbTA/BgNV -+HREEODA2ghdzaGEyNTYudGJzLWludGVybmV0LmNvbYIbd3d3LnNoYTI1Ni50YnMt -+aW50ZXJuZXQuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQA0pOuL8QvAa5yksTbGShzX -+ABApagunUGoEydv4YJT1MXy9tTp7DrWaozZSlsqBxrYAXP1d9r2fuKbEniYHxaQ0 -+UYaf1VSIlDo1yuC8wE7wxbHDIpQ/E5KAyxiaJ8obtDhFstWAPAH+UoGXq0kj2teN -+21sFQ5dXgA95nldvVFsFhrRUNB6xXAcaj0VZFhttI0ZfQZmQwEI/P+N9Jr40OGun -+aa+Dn0TMeUH4U20YntfLbu2nDcJcYfyurm+8/0Tr4HznLnedXu9pCPYj0TaddrgT -+XO0oFiyy7qGaY6+qKh71yD64Y3ycCJ/HR9Wm39mjZYc9ezYwT4noP6r7Lk8YO7/q - -----END CERTIFICATE----- -- 1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA business -+ 1 s:/C=FR/ST=Calvados/L=Caen/O=TBS INTERNET/OU=Terms and Conditions: http://www.tbs-internet.com/CA/repository/OU=TBS INTERNET CA/CN=TBS X509 CA SGC - i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root - -----BEGIN CERTIFICATE----- --MIIFPzCCBCegAwIBAgIQDlBz/++iRSmLDeVRHT/hADANBgkqhkiG9w0BAQUFADBv -+MIIFVjCCBD6gAwIBAgIQXpDZ0ETJMV02WTx3GTnhhTANBgkqhkiG9w0BAQUFADBv - MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk - ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF --eHRlcm5hbCBDQSBSb290MB4XDTA1MTIwMTAwMDAwMFoXDTE5MDcwOTE4MTkyMlow --gckxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl -+eHRlcm5hbCBDQSBSb290MB4XDTA1MTIwMTAwMDAwMFoXDTE5MDYyNDE5MDYzMFow -+gcQxCzAJBgNVBAYTAkZSMREwDwYDVQQIEwhDYWx2YWRvczENMAsGA1UEBxMEQ2Fl - bjEVMBMGA1UEChMMVEJTIElOVEVSTkVUMUgwRgYDVQQLEz9UZXJtcyBhbmQgQ29u - ZGl0aW9uczogaHR0cDovL3d3dy50YnMtaW50ZXJuZXQuY29tL0NBL3JlcG9zaXRv --cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEdMBsGA1UEAxMUVEJTIFg1MDkg --Q0EgYnVzaW5lc3MwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDB1PAU --qudCcz3tmyGcf+u6EkZqonKKHrV4gZYbvVkIRojmmlhfi/jwvpHvo8bqSt/9Rj5S --jhCDW0pcbI+IPPtD1Jy+CHNSfnMqVDy6CKQ3p5maTzCMG6ZT+XjnvcND5v+FtaiB --xk1iCX6uvt0jeUtdZvYbyytsSDE6c3Y5//wRxOF8tM1JxibwO3pyER26jbbN2gQz --m/EkdGjLdJ4svPk23WDAvQ6G0/z2LcAaJB+XLfqRwfQpHQvfKa1uTi8PivC8qtip --rmNQMMPMjxSK2azX8cKjjTDJiUKaCb4VHlJDWKEsCFRpgJAoAuX8f7Yfs1M4esGo --sWb3PGspK3O22uIlAgMBAAGjggF6MIIBdjAdBgNVHQ4EFgQUGgkEzPkJj7seoM7U --pBR/S9UjWM0wDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwGAYD --VR0gBBEwDzANBgsrBgEEAYDlNwIBATB7BgNVHR8EdDByMDigNqA0hjJodHRwOi8v --Y3JsLmNvbW9kb2NhLmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LmNybDA2oDSg --MoYwaHR0cDovL2NybC5jb21vZG8ubmV0L0FkZFRydXN0RXh0ZXJuYWxDQVJvb3Qu --Y3JsMIGGBggrBgEFBQcBAQR6MHgwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29t --b2RvY2EuY29tL0FkZFRydXN0VVROU2VydmVyQ0EuY3J0MDkGCCsGAQUFBzAChi1o --dHRwOi8vY3J0LmNvbW9kby5uZXQvQWRkVHJ1c3RVVE5TZXJ2ZXJDQS5jcnQwEQYJ --YIZIAYb4QgEBBAQDAgIEMA0GCSqGSIb3DQEBBQUAA4IBAQA7mqrMgk/MrE6QnbNA --h4nRCn2ti4bg4w2C3lB6bSvRPnYwuNw9Jb8vuKkNFzRDxNJXqVDZdfFW5CVQJuyd --nfAx83+wk+spzvFaE1KhFYfN9G9pQfXUfvDRoIcJgPEKUXL1wRiOG+IjU3VVI8pg --IgqHkr7ylln5i5zCiFAPuIJmYUSFg/gxH5xkCNcjJqqrHrHatJr6Qrrke93joupw --oU1njfAcZtYp6fbiK6u2b1pJqwkVBE8RsfLnPhRj+SFbpvjv8Od7o/ieJhFIYQNU --k2jX2u8qZnAiNw93LZW9lpYjtuvMXq8QQppENNja5b53q7UwI+lU7ZGjZ7quuESp --J6/5 -+cnkxGDAWBgNVBAsTD1RCUyBJTlRFUk5FVCBDQTEYMBYGA1UEAxMPVEJTIFg1MDkg -+Q0EgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsgOkO3f7wzN6 -+rOjg45tR5vjBfzK7qmV9IBxb/QW9EEXxG+E7FNhZqQLtwGBKoSsHTnQqV75wWMk0 -+9tinWvftBkSpj5sTi/8cbzJfUvTSVYh3Qxv6AVVjMMH/ruLjE6y+4PoaPs8WoYAQ -+ts5R4Z1g8c/WnTepLst2x0/Wv7GmuoQi+gXvHU6YrBiu7XkeYhzc95QdviWSJRDk -+owhb5K43qhcvjRmBfO/paGlCliDGZp8mHwrI21mwobWpVjTxZRwYO3bd4+TGcI4G -+Ie5wmHwE8F7SK1tgSqbBacKjDa93j7txKkfz/Yd2n7TGqOXiHPsJpG655vrKtnXk -+9vs1zoDeJQIDAQABo4IBljCCAZIwHQYDVR0OBBYEFAdEdoWTKLx/bXjSCuv6TEvf -+2YIfMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMCAGA1UdJQQZ -+MBcGCisGAQQBgjcKAwMGCWCGSAGG+EIEATAYBgNVHSAEETAPMA0GCysGAQQBgOU3 -+AgQBMHsGA1UdHwR0MHIwOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0Fk -+ZFRydXN0RXh0ZXJuYWxDQVJvb3QuY3JsMDagNKAyhjBodHRwOi8vY3JsLmNvbW9k -+by5uZXQvQWRkVHJ1c3RFeHRlcm5hbENBUm9vdC5jcmwwgYAGCCsGAQUFBwEBBHQw -+cjA4BggrBgEFBQcwAoYsaHR0cDovL2NydC5jb21vZG9jYS5jb20vQWRkVHJ1c3RV -+VE5TR0NDQS5jcnQwNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuY29tb2RvLm5ldC9B -+ZGRUcnVzdFVUTlNHQ0NBLmNydDARBglghkgBhvhCAQEEBAMCAgQwDQYJKoZIhvcN -+AQEFBQADggEBAK2zEzs+jcIrVK9oDkdDZNvhuBYTdCfpxfFs+OAujW0bIfJAy232 -+euVsnJm6u/+OrqKudD2tad2BbejLLXhMZViaCmK7D9nrXHx4te5EP8rL19SUVqLY -+1pTnv5dhNgEgvA7n5lIzDSYs7yRLsr7HJsYPr6SeYSuZizyX1SNz7ooJ32/F3X98 -+RB0Mlc/E0OyOrkQ9/y5IrnpnaSora8CnUrV5XNOg+kyCz9edCyx4D5wXYcwZPVWz -+8aDqquESrezPyjtfi4WRO4s/VD3HLZvOxzMrWAVYCDG9FxaOhF0QGuuG1F7F3GKV -+v6prNyCl016kRl2j1UT+a7gLd8fA25A4C9E= - -----END CERTIFICATE----- - 2 s:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root -- i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -+ i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC - -----BEGIN CERTIFICATE----- --MIIETzCCAzegAwIBAgIQHM5EYpUZep1jUvnyI6m2mDANBgkqhkiG9w0BAQUFADCB --lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -+MIIEZjCCA06gAwIBAgIQUSYKkxzif5zDpV954HKugjANBgkqhkiG9w0BAQUFADCB -+kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug - Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho --dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt --SGFyZHdhcmUwHhcNMDUwNjA3MDgwOTEwWhcNMTkwNzA5MTgxOTIyWjBvMQswCQYD --VQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0 --IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5h --bCBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt/caM+by --AAQtOeBOW+0fvGwPzbX6I7bO3psRM5ekKUx9k5+9SryT7QMa44/P5W1QWtaXKZRa --gLBJetsulf24yr83OC0ePpFBrXBWx/BPP+gynnTKyJBU6cZfD3idmkA8Dqxhql4U --j56HoWpQ3NeaTq8Fs6ZxlJxxs1BgCscTnTgHhgKo6ahpJhiQq0ywTyOrOk+E2N/O --n+Fpb7vXQtdrROTHre5tQV9yWnEIN7N5ZaRZoJQ39wAvDcKSctrQOHLbFKhFxF0q --fbe01sTurM0TRLfJK91DACX6YblpalgjEbenM49WdVn1zSnXRrcKK2W200JvFbK4 --e/vv6V1T1TRaJwIDAQABo4G9MIG6MB8GA1UdIwQYMBaAFKFyXyYbKJhDlV0HN9WF --lp1L0sNFMB0GA1UdDgQWBBStvZh6NLQm9/rEJlTvA73gJMtUGjAOBgNVHQ8BAf8E --BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zARBglghkgBhvhCAQEEBAMCAQIwRAYDVR0f --BD0wOzA5oDegNYYzaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmly --c3QtSGFyZHdhcmUuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQByQhANOs4kClrwF8BW --onvUOGCSjRK52zYZgDXYNjDtmr5rJ6NyPFDNn+JxkLpjYetIFMTbSRe679Bt8m7a --gIAoQYFQtxMuyLnJegB2aEbQiIxh/tC21UcFF7ktdnDoTlA6w3pLuvunaI84Of3o --2YBrhzkTbCfaYk5JRlTpudW9DkUkHBsyx3nknPKnplkIGaK0jgn8E0n+SFabYaHk --I9LroYT/+JtLefh9lgBdAgVv0UPbzoGfuDsrk/Zh+UrgbLFpHoVnElhzbkh64Z0X --OGaJunQc68cCZu5HTn/aK7fBGMcVflRCXLVEQpU9PIAdGA8Ynvg684t8GMaKsRl1 --jIGZ -+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -+IFNHQzAeFw0wNTA2MDcwODA5MTBaFw0xOTA2MjQxOTA2MzBaMG8xCzAJBgNVBAYT -+AlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0 -+ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB -+IFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC39xoz5vIABC05 -+4E5b7R+8bA/Ntfojts7emxEzl6QpTH2Tn71KvJPtAxrjj8/lbVBa1pcplFqAsEl6 -+2y6V/bjKvzc4LR4+kUGtcFbH8E8/6DKedMrIkFTpxl8PeJ2aQDwOrGGqXhSPnoeh -+alDc15pOrwWzpnGUnHGzUGAKxxOdOAeGAqjpqGkmGJCrTLBPI6s6T4TY386f4Wlv -+u9dC12tE5Met7m1BX3JacQg3s3llpFmglDf3AC8NwpJy2tA4ctsUqEXEXSp9t7TW -+xO6szRNEt8kr3UMAJfphuWlqWCMRt6czj1Z1WfXNKddGtworZbbTQm8Vsrh7++/p -+XVPVNFonAgMBAAGjgdgwgdUwHwYDVR0jBBgwFoAUUzLRs89/+uDxoF2FTpLSnkUd -+tE8wHQYDVR0OBBYEFK29mHo0tCb3+sQmVO8DveAky1QaMA4GA1UdDwEB/wQEAwIB -+BjAPBgNVHRMBAf8EBTADAQH/MBEGCWCGSAGG+EIBAQQEAwIBAjAgBgNVHSUEGTAX -+BgorBgEEAYI3CgMDBglghkgBhvhCBAEwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDov -+L2NybC51c2VydHJ1c3QuY29tL1VUTi1EQVRBQ29ycFNHQy5jcmwwDQYJKoZIhvcN -+AQEFBQADggEBAMbuUxdoFLJRIh6QWA2U/b3xcOWGLcM2MY9USEbnLQg3vGwKYOEO -+rVE04BKT6b64q7gmtOmWPSiPrmQH/uAB7MXjkesYoPF1ftsK5p+R26+udd8jkWjd -+FwBaS/9kbHDrARrQkNnHptZt9hPk/7XJ0h4qy7ElQyZ42TCbTg0evmnv3+r+LbPM -++bDdtRTKkdSytaX7ARmjR3mfnYyVhzT4HziS2jamEfpr62vp3EV4FTkG101B5CHI -+3C+H0be/SGB1pWLLJN47YaApIKa+xWycxOkKaSLvkTr6Jq/RW0GnOuL4OAdCq8Fb -++M5tug8EPzI0rNwEKNdwMBQmBsTkm5jVz3g= - -----END CERTIFICATE----- -- 3 s:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -- i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware -+ 3 s:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC -+ i:/C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN - DATACorp SGC - -----BEGIN CERTIFICATE----- --MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB --lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -+MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB -+kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug - Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho --dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt --SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG --A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe --MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v --d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh --cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn --0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ --M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a --MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd --oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI --DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy --oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD --VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 --dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy --bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF --BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM --//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli --CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE --CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t --3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS --KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== -+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -+IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG -+EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD -+VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu -+dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN -+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 -+E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ -+D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK -+4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq -+lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW -+bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB -+o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT -+MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js -+LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr -+BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB -+AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -+Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj -+j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH -+KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv -+2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 -+mfnGV/TJVTl4uix5yaaIK/QI - -----END CERTIFICATE----- -diff --git a/Lib/test/ssl_cert.pem b/Lib/test/ssl_cert.pem -new file mode 100644 ---- /dev/null -+++ b/Lib/test/ssl_cert.pem -@@ -0,0 +1,15 @@ -+-----BEGIN CERTIFICATE----- -+MIICVDCCAb2gAwIBAgIJANfHOBkZr8JOMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV -+BAYTAlhZMRcwFQYDVQQHEw5DYXN0bGUgQW50aHJheDEjMCEGA1UEChMaUHl0aG9u -+IFNvZnR3YXJlIEZvdW5kYXRpb24xEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0xMDEw -+MDgyMzAxNTZaFw0yMDEwMDUyMzAxNTZaMF8xCzAJBgNVBAYTAlhZMRcwFQYDVQQH -+Ew5DYXN0bGUgQW50aHJheDEjMCEGA1UEChMaUHl0aG9uIFNvZnR3YXJlIEZvdW5k -+YXRpb24xEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -+gYkCgYEA21vT5isq7F68amYuuNpSFlKDPrMUCa4YWYqZRt2OZ+/3NKaZ2xAiSwr7 -+6MrQF70t5nLbSPpqE5+5VrS58SY+g/sXLiFd6AplH1wJZwh78DofbFYXUggktFMt -+pTyiX8jtP66bkcPkDADA089RI1TQR6Ca+n7HFa7c1fabVV6i3zkCAwEAAaMYMBYw -+FAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBBQUAA4GBAHPctQBEQ4wd -+BJ6+JcpIraopLn8BGhbjNWj40mmRqWB/NAWF6M5ne7KpGAu7tLeG4hb1zLaldK8G -+lxy2GPSRF6LFS48dpEj2HbMv2nvv6xxalDMJ9+DicWgAKTQ6bcX2j3GUkCR0g/T1 -+CRlNBAAlvhKzO7Clpf9l0YKBEfraJByX -+-----END CERTIFICATE----- -diff --git a/Lib/test/ssl_key.passwd.pem b/Lib/test/ssl_key.passwd.pem -new file mode 100644 ---- /dev/null -+++ b/Lib/test/ssl_key.passwd.pem -@@ -0,0 +1,18 @@ -+-----BEGIN RSA PRIVATE KEY----- -+Proc-Type: 4,ENCRYPTED -+DEK-Info: DES-EDE3-CBC,1A8D9D2A02EC698A -+ -+kJYbfZ8L0sfe9Oty3gw0aloNnY5E8fegRfQLZlNoxTl6jNt0nIwI8kDJ36CZgR9c -+u3FDJm/KqrfUoz8vW+qEnWhSG7QPX2wWGPHd4K94Yz/FgrRzZ0DoK7XxXq9gOtVA -+AVGQhnz32p+6WhfGsCr9ArXEwRZrTk/FvzEPaU5fHcoSkrNVAGX8IpSVkSDwEDQr -+Gv17+cfk99UV1OCza6yKHoFkTtrC+PZU71LomBabivS2Oc4B9hYuSR2hF01wTHP+ -+YlWNagZOOVtNz4oKK9x9eNQpmfQXQvPPTfusexKIbKfZrMvJoxcm1gfcZ0H/wK6P -+6wmXSG35qMOOztCZNtperjs1wzEBXznyK8QmLcAJBjkfarABJX9vBEzZV0OUKhy+ -+noORFwHTllphbmydLhu6ehLUZMHPhzAS5UN7srtpSN81eerDMy0RMUAwA7/PofX1 -+94Me85Q8jP0PC9ETdsJcPqLzAPETEYu0ELewKRcrdyWi+tlLFrpE5KT/s5ecbl9l -+7B61U4Kfd1PIXc/siINhU3A3bYK+845YyUArUOnKf1kEox7p1RpD7yFqVT04lRTo -+cibNKATBusXSuBrp2G6GNuhWEOSafWCKJQAzgCYIp6ZTV2khhMUGppc/2H3CF6cO -+zX0KtlPVZC7hLkB6HT8SxYUwF1zqWY7+/XPPdc37MeEZ87Q3UuZwqORLY+Z0hpgt -+L5JXBCoklZhCAaN2GqwFLXtGiRSRFGY7xXIhbDTlE65Wv1WGGgDLMKGE1gOz3yAo -+2jjG1+yAHJUdE69XTFHSqSkvaloA1W03LdMXZ9VuQJ/ySXCie6ABAQ== -+-----END RSA PRIVATE KEY----- -diff --git a/Lib/test/ssl_key.pem b/Lib/test/ssl_key.pem -new file mode 100644 ---- /dev/null -+++ b/Lib/test/ssl_key.pem -@@ -0,0 +1,16 @@ -+-----BEGIN PRIVATE KEY----- -+MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANtb0+YrKuxevGpm -+LrjaUhZSgz6zFAmuGFmKmUbdjmfv9zSmmdsQIksK++jK0Be9LeZy20j6ahOfuVa0 -+ufEmPoP7Fy4hXegKZR9cCWcIe/A6H2xWF1IIJLRTLaU8ol/I7T+um5HD5AwAwNPP -+USNU0Eegmvp+xxWu3NX2m1Veot85AgMBAAECgYA3ZdZ673X0oexFlq7AAmrutkHt -+CL7LvwrpOiaBjhyTxTeSNWzvtQBkIU8DOI0bIazA4UreAFffwtvEuPmonDb3F+Iq -+SMAu42XcGyVZEl+gHlTPU9XRX7nTOXVt+MlRRRxL6t9GkGfUAXI3XxJDXW3c0vBK -+UL9xqD8cORXOfE06rQJBAP8mEX1ERkR64Ptsoe4281vjTlNfIbs7NMPkUnrn9N/Y -+BLhjNIfQ3HFZG8BTMLfX7kCS9D593DW5tV4Z9BP/c6cCQQDcFzCcVArNh2JSywOQ -+ZfTfRbJg/Z5Lt9Fkngv1meeGNPgIMLN8Sg679pAOOWmzdMO3V706rNPzSVMME7E5 -+oPIfAkEA8pDddarP5tCvTTgUpmTFbakm0KoTZm2+FzHcnA4jRh+XNTjTOv98Y6Ik -+eO5d1ZnKXseWvkZncQgxfdnMqqpj5wJAcNq/RVne1DbYlwWchT2Si65MYmmJ8t+F -+0mcsULqjOnEMwf5e+ptq5LzwbyrHZYq5FNk7ocufPv/ZQrcSSC+cFwJBAKvOJByS -+x56qyGeZLOQlWS2JS3KJo59XuLFGqcbgN9Om9xFa41Yb4N9NvplFivsvZdw3m1Q/ -+SPIXQuT8RMPDVNQ= -+-----END PRIVATE KEY----- -diff --git a/Lib/test/ssl_servers.py b/Lib/test/ssl_servers.py -new file mode 100644 ---- /dev/null -+++ b/Lib/test/ssl_servers.py -@@ -0,0 +1,209 @@ -+import os -+import sys -+import ssl -+import pprint -+import urllib -+import urlparse -+# Rename HTTPServer to _HTTPServer so as to avoid confusion with HTTPSServer. -+from BaseHTTPServer import HTTPServer as _HTTPServer, BaseHTTPRequestHandler -+from SimpleHTTPServer import SimpleHTTPRequestHandler -+ -+from test import test_support as support -+threading = support.import_module("threading") -+ -+here = os.path.dirname(__file__) -+ -+HOST = support.HOST -+CERTFILE = os.path.join(here, 'keycert.pem') -+ -+# This one's based on HTTPServer, which is based on SocketServer -+ -+class HTTPSServer(_HTTPServer): -+ -+ def __init__(self, server_address, handler_class, context): -+ _HTTPServer.__init__(self, server_address, handler_class) -+ self.context = context -+ -+ def __str__(self): -+ return ('<%s %s:%s>' % -+ (self.__class__.__name__, -+ self.server_name, -+ self.server_port)) -+ -+ def get_request(self): -+ # override this to wrap socket with SSL -+ try: -+ sock, addr = self.socket.accept() -+ sslconn = self.context.wrap_socket(sock, server_side=True) -+ except OSError as e: -+ # socket errors are silenced by the caller, print them here -+ if support.verbose: -+ sys.stderr.write("Got an error:\n%s\n" % e) -+ raise -+ return sslconn, addr -+ -+class RootedHTTPRequestHandler(SimpleHTTPRequestHandler): -+ # need to override translate_path to get a known root, -+ # instead of using os.curdir, since the test could be -+ # run from anywhere -+ -+ server_version = "TestHTTPS/1.0" -+ root = here -+ # Avoid hanging when a request gets interrupted by the client -+ timeout = 5 -+ -+ def translate_path(self, path): -+ """Translate a /-separated PATH to the local filename syntax. -+ -+ Components that mean special things to the local file system -+ (e.g. drive or directory names) are ignored. (XXX They should -+ probably be diagnosed.) -+ -+ """ -+ # abandon query parameters -+ path = urlparse.urlparse(path)[2] -+ path = os.path.normpath(urllib.unquote(path)) -+ words = path.split('/') -+ words = filter(None, words) -+ path = self.root -+ for word in words: -+ drive, word = os.path.splitdrive(word) -+ head, word = os.path.split(word) -+ path = os.path.join(path, word) -+ return path -+ -+ def log_message(self, format, *args): -+ # we override this to suppress logging unless "verbose" -+ if support.verbose: -+ sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" % -+ (self.server.server_address, -+ self.server.server_port, -+ self.request.cipher(), -+ self.log_date_time_string(), -+ format%args)) -+ -+ -+class StatsRequestHandler(BaseHTTPRequestHandler): -+ """Example HTTP request handler which returns SSL statistics on GET -+ requests. -+ """ -+ -+ server_version = "StatsHTTPS/1.0" -+ -+ def do_GET(self, send_body=True): -+ """Serve a GET request.""" -+ sock = self.rfile.raw._sock -+ context = sock.context -+ stats = { -+ 'session_cache': context.session_stats(), -+ 'cipher': sock.cipher(), -+ 'compression': sock.compression(), -+ } -+ body = pprint.pformat(stats) -+ body = body.encode('utf-8') -+ self.send_response(200) -+ self.send_header("Content-type", "text/plain; charset=utf-8") -+ self.send_header("Content-Length", str(len(body))) -+ self.end_headers() -+ if send_body: -+ self.wfile.write(body) -+ -+ def do_HEAD(self): -+ """Serve a HEAD request.""" -+ self.do_GET(send_body=False) -+ -+ def log_request(self, format, *args): -+ if support.verbose: -+ BaseHTTPRequestHandler.log_request(self, format, *args) -+ -+ -+class HTTPSServerThread(threading.Thread): -+ -+ def __init__(self, context, host=HOST, handler_class=None): -+ self.flag = None -+ self.server = HTTPSServer((host, 0), -+ handler_class or RootedHTTPRequestHandler, -+ context) -+ self.port = self.server.server_port -+ threading.Thread.__init__(self) -+ self.daemon = True -+ -+ def __str__(self): -+ return "<%s %s>" % (self.__class__.__name__, self.server) -+ -+ def start(self, flag=None): -+ self.flag = flag -+ threading.Thread.start(self) -+ -+ def run(self): -+ if self.flag: -+ self.flag.set() -+ try: -+ self.server.serve_forever(0.05) -+ finally: -+ self.server.server_close() -+ -+ def stop(self): -+ self.server.shutdown() -+ -+ -+def make_https_server(case, context=None, certfile=CERTFILE, -+ host=HOST, handler_class=None): -+ if context is None: -+ context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) -+ # We assume the certfile contains both private key and certificate -+ context.load_cert_chain(certfile) -+ server = HTTPSServerThread(context, host, handler_class) -+ flag = threading.Event() -+ server.start(flag) -+ flag.wait() -+ def cleanup(): -+ if support.verbose: -+ sys.stdout.write('stopping HTTPS server\n') -+ server.stop() -+ if support.verbose: -+ sys.stdout.write('joining HTTPS thread\n') -+ server.join() -+ case.addCleanup(cleanup) -+ return server -+ -+ -+if __name__ == "__main__": -+ import argparse -+ parser = argparse.ArgumentParser( -+ description='Run a test HTTPS server. ' -+ 'By default, the current directory is served.') -+ parser.add_argument('-p', '--port', type=int, default=4433, -+ help='port to listen on (default: %(default)s)') -+ parser.add_argument('-q', '--quiet', dest='verbose', default=True, -+ action='store_false', help='be less verbose') -+ parser.add_argument('-s', '--stats', dest='use_stats_handler', default=False, -+ action='store_true', help='always return stats page') -+ parser.add_argument('--curve-name', dest='curve_name', type=str, -+ action='store', -+ help='curve name for EC-based Diffie-Hellman') -+ parser.add_argument('--ciphers', dest='ciphers', type=str, -+ help='allowed cipher list') -+ parser.add_argument('--dh', dest='dh_file', type=str, action='store', -+ help='PEM file containing DH parameters') -+ args = parser.parse_args() -+ -+ support.verbose = args.verbose -+ if args.use_stats_handler: -+ handler_class = StatsRequestHandler -+ else: -+ handler_class = RootedHTTPRequestHandler -+ handler_class.root = os.getcwd() -+ context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) -+ context.load_cert_chain(CERTFILE) -+ if args.curve_name: -+ context.set_ecdh_curve(args.curve_name) -+ if args.dh_file: -+ context.load_dh_params(args.dh_file) -+ if args.ciphers: -+ context.set_ciphers(args.ciphers) -+ -+ server = HTTPSServer(("", args.port), handler_class, context) -+ if args.verbose: -+ print("Listening on https://localhost:{0.port}".format(args)) -+ server.serve_forever(0.1) -diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py ---- a/Lib/test/test_ssl.py -+++ b/Lib/test/test_ssl.py -@@ -1,35 +1,78 @@ -+# -*- coding: utf-8 -*- - # Test the support for SSL and sockets - - import sys - import unittest --from test import test_support -+from test import test_support as support - import asyncore - import socket - import select - import time -+import datetime - import gc - import os - import errno - import pprint --import urllib, urlparse -+import tempfile -+import urllib - import traceback - import weakref -+import platform - import functools --import platform -+from contextlib import closing - --from BaseHTTPServer import HTTPServer --from SimpleHTTPServer import SimpleHTTPRequestHandler -+ssl = support.import_module("ssl") - --ssl = test_support.import_module("ssl") -+PROTOCOLS = sorted(ssl._PROTOCOL_NAMES) -+HOST = support.HOST - --HOST = test_support.HOST --CERTFILE = None --SVN_PYTHON_ORG_ROOT_CERT = None --NULLBYTECERT = None -+def data_file(*name): -+ return os.path.join(os.path.dirname(__file__), *name) -+ -+# The custom key and certificate files used in test_ssl are generated -+# using Lib/test/make_ssl_certs.py. -+# Other certificates are simply fetched from the Internet servers they -+# are meant to authenticate. -+ -+CERTFILE = data_file("keycert.pem") -+BYTES_CERTFILE = CERTFILE.encode(sys.getfilesystemencoding()) -+ONLYCERT = data_file("ssl_cert.pem") -+ONLYKEY = data_file("ssl_key.pem") -+BYTES_ONLYCERT = ONLYCERT.encode(sys.getfilesystemencoding()) -+BYTES_ONLYKEY = ONLYKEY.encode(sys.getfilesystemencoding()) -+CERTFILE_PROTECTED = data_file("keycert.passwd.pem") -+ONLYKEY_PROTECTED = data_file("ssl_key.passwd.pem") -+KEY_PASSWORD = "somepass" -+CAPATH = data_file("capath") -+BYTES_CAPATH = CAPATH.encode(sys.getfilesystemencoding()) -+CAFILE_NEURONIO = data_file("capath", "4e1295a3.0") -+CAFILE_CACERT = data_file("capath", "5ed36f99.0") -+ -+ -+# empty CRL -+CRLFILE = data_file("revocation.crl") -+ -+# Two keys and certs signed by the same CA (for SNI tests) -+SIGNED_CERTFILE = data_file("keycert3.pem") -+SIGNED_CERTFILE2 = data_file("keycert4.pem") -+SIGNING_CA = data_file("pycacert.pem") -+ -+SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem") -+ -+EMPTYCERT = data_file("nullcert.pem") -+BADCERT = data_file("badcert.pem") -+WRONGCERT = data_file("XXXnonexisting.pem") -+BADKEY = data_file("badkey.pem") -+NOKIACERT = data_file("nokia.pem") -+NULLBYTECERT = data_file("nullbytecert.pem") -+ -+DHFILE = data_file("dh512.pem") -+BYTES_DHFILE = DHFILE.encode(sys.getfilesystemencoding()) -+ - - def handle_error(prefix): - exc_format = ' '.join(traceback.format_exception(*sys.exc_info())) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(prefix + exc_format) - - -@@ -51,48 +94,76 @@ class BasicTests(unittest.TestCase): - pass - else: - raise -+def can_clear_options(): -+ # 0.9.8m or higher -+ return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15) -+ -+def no_sslv2_implies_sslv3_hello(): -+ # 0.9.7h or higher -+ return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15) -+ -+def have_verify_flags(): -+ # 0.9.8 or higher -+ return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15) -+ -+def utc_offset(): #NOTE: ignore issues like #1647654 -+ # local time = utc time + utc offset -+ if time.daylight and time.localtime().tm_isdst > 0: -+ return -time.altzone # seconds -+ return -time.timezone -+ -+def asn1time(cert_time): -+ # Some versions of OpenSSL ignore seconds, see #18207 -+ # 0.9.8.i -+ if ssl._OPENSSL_API_VERSION == (0, 9, 8, 9, 15): -+ fmt = "%b %d %H:%M:%S %Y GMT" -+ dt = datetime.datetime.strptime(cert_time, fmt) -+ dt = dt.replace(second=0) -+ cert_time = dt.strftime(fmt) -+ # %d adds leading zero but ASN1_TIME_print() uses leading space -+ if cert_time[4] == "0": -+ cert_time = cert_time[:4] + " " + cert_time[5:] -+ -+ return cert_time - - # Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2 - def skip_if_broken_ubuntu_ssl(func): - if hasattr(ssl, 'PROTOCOL_SSLv2'): -- # We need to access the lower-level wrapper in order to create an -- # implicit SSL context without trying to connect or listen. -- try: -- import _ssl -- except ImportError: -- # The returned function won't get executed, just ignore the error -- pass - @functools.wraps(func) - def f(*args, **kwargs): - try: -- s = socket.socket(socket.AF_INET) -- _ssl.sslwrap(s._sock, 0, None, None, -- ssl.CERT_NONE, ssl.PROTOCOL_SSLv2, None, None) -- except ssl.SSLError as e: -+ ssl.SSLContext(ssl.PROTOCOL_SSLv2) -+ except ssl.SSLError: - if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and -- platform.linux_distribution() == ('debian', 'squeeze/sid', '') -- and 'Invalid SSL protocol variant specified' in str(e)): -+ platform.linux_distribution() == ('debian', 'squeeze/sid', '')): - raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour") - return func(*args, **kwargs) - return f - else: - return func - -+needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test") -+ - - class BasicSocketTests(unittest.TestCase): - - def test_constants(self): -- #ssl.PROTOCOL_SSLv2 -- ssl.PROTOCOL_SSLv23 -- ssl.PROTOCOL_SSLv3 -- ssl.PROTOCOL_TLSv1 - ssl.CERT_NONE - ssl.CERT_OPTIONAL - ssl.CERT_REQUIRED -+ ssl.OP_CIPHER_SERVER_PREFERENCE -+ ssl.OP_SINGLE_DH_USE -+ if ssl.HAS_ECDH: -+ ssl.OP_SINGLE_ECDH_USE -+ if ssl.OPENSSL_VERSION_INFO >= (1, 0): -+ ssl.OP_NO_COMPRESSION -+ self.assertIn(ssl.HAS_SNI, {True, False}) -+ self.assertIn(ssl.HAS_ECDH, {True, False}) -+ - - def test_random(self): - v = ssl.RAND_status() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n RAND_status is %d (%s)\n" - % (v, (v and "sufficient randomness") or - "insufficient randomness")) -@@ -104,9 +175,19 @@ class BasicSocketTests(unittest.TestCase - # note that this uses an 'unofficial' function in _ssl.c, - # provided solely for this test, to exercise the certificate - # parsing code -- p = ssl._ssl._test_decode_cert(CERTFILE, False) -- if test_support.verbose: -+ p = ssl._ssl._test_decode_cert(CERTFILE) -+ if support.verbose: - sys.stdout.write("\n" + pprint.pformat(p) + "\n") -+ self.assertEqual(p['issuer'], -+ ((('countryName', 'XY'),), -+ (('localityName', 'Castle Anthrax'),), -+ (('organizationName', 'Python Software Foundation'),), -+ (('commonName', 'localhost'),)) -+ ) -+ # Note the next three asserts will fail if the keys are regenerated -+ self.assertEqual(p['notAfter'], asn1time('Oct 5 23:01:56 2020 GMT')) -+ self.assertEqual(p['notBefore'], asn1time('Oct 8 23:01:56 2010 GMT')) -+ self.assertEqual(p['serialNumber'], 'D7C7381919AFC24E') - self.assertEqual(p['subject'], - ((('countryName', 'XY'),), - (('localityName', 'Castle Anthrax'),), -@@ -117,16 +198,22 @@ class BasicSocketTests(unittest.TestCase - # Issue #13034: the subjectAltName in some certificates - # (notably projects.developer.nokia.com:443) wasn't parsed - p = ssl._ssl._test_decode_cert(NOKIACERT) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n" + pprint.pformat(p) + "\n") - self.assertEqual(p['subjectAltName'], - (('DNS', 'projects.developer.nokia.com'), - ('DNS', 'projects.forum.nokia.com')) - ) -+ # extra OCSP and AIA fields -+ self.assertEqual(p['OCSP'], ('http://ocsp.verisign.com',)) -+ self.assertEqual(p['caIssuers'], -+ ('http://SVRIntl-G3-aia.verisign.com/SVRIntlG3.cer',)) -+ self.assertEqual(p['crlDistributionPoints'], -+ ('http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl',)) - - def test_parse_cert_CVE_2013_4238(self): - p = ssl._ssl._test_decode_cert(NULLBYTECERT) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n" + pprint.pformat(p) + "\n") - subject = ((('countryName', 'US'),), - (('stateOrProvinceName', 'Oregon'),), -@@ -137,7 +224,7 @@ class BasicSocketTests(unittest.TestCase - (('emailAddress', 'python-dev@python.org'),)) - self.assertEqual(p['subject'], subject) - self.assertEqual(p['issuer'], subject) -- if ssl.OPENSSL_VERSION_INFO >= (0, 9, 8): -+ if ssl._OPENSSL_API_VERSION >= (0, 9, 8): - san = (('DNS', 'altnull.python.org\x00example.com'), - ('email', 'null@python.org\x00user@example.org'), - ('URI', 'http://null.python.org\x00http://example.org'), -@@ -192,24 +279,7 @@ class BasicSocketTests(unittest.TestCase - self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)), - (s, t)) - -- @test_support.requires_resource('network') -- def test_ciphers(self): -- remote = ("svn.python.org", 443) -- with test_support.transient_internet(remote[0]): -- s = ssl.wrap_socket(socket.socket(socket.AF_INET), -- cert_reqs=ssl.CERT_NONE, ciphers="ALL") -- s.connect(remote) -- s = ssl.wrap_socket(socket.socket(socket.AF_INET), -- cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT") -- s.connect(remote) -- # Error checking occurs when connecting, because the SSL context -- # isn't created before. -- s = ssl.wrap_socket(socket.socket(socket.AF_INET), -- cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx") -- with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"): -- s.connect(remote) -- -- @test_support.cpython_only -+ @support.cpython_only - def test_refcycle(self): - # Issue #7943: an SSL object doesn't create reference cycles with - # itself. -@@ -224,17 +294,319 @@ class BasicSocketTests(unittest.TestCase - self.assertEqual(wr(), None) - - def test_wrapped_unconnected(self): -- # The _delegate_methods in socket.py are correctly delegated to by an -- # unconnected SSLSocket, so they will raise a socket.error rather than -- # something unexpected like TypeError. -+ # Methods on an unconnected SSLSocket propagate the original -+ # socket.error raise by the underlying socket object. - s = socket.socket(socket.AF_INET) -- ss = ssl.wrap_socket(s) -- self.assertRaises(socket.error, ss.recv, 1) -- self.assertRaises(socket.error, ss.recv_into, bytearray(b'x')) -- self.assertRaises(socket.error, ss.recvfrom, 1) -- self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1) -- self.assertRaises(socket.error, ss.send, b'x') -- self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0)) -+ with closing(ssl.wrap_socket(s)) as ss: -+ self.assertRaises(socket.error, ss.recv, 1) -+ self.assertRaises(socket.error, ss.recv_into, bytearray(b'x')) -+ self.assertRaises(socket.error, ss.recvfrom, 1) -+ self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1) -+ self.assertRaises(socket.error, ss.send, b'x') -+ self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0)) -+ -+ def test_timeout(self): -+ # Issue #8524: when creating an SSL socket, the timeout of the -+ # original socket should be retained. -+ for timeout in (None, 0.0, 5.0): -+ s = socket.socket(socket.AF_INET) -+ s.settimeout(timeout) -+ with closing(ssl.wrap_socket(s)) as ss: -+ self.assertEqual(timeout, ss.gettimeout()) -+ -+ def test_errors(self): -+ sock = socket.socket() -+ self.assertRaisesRegexp(ValueError, -+ "certfile must be specified", -+ ssl.wrap_socket, sock, keyfile=CERTFILE) -+ self.assertRaisesRegexp(ValueError, -+ "certfile must be specified for server-side operations", -+ ssl.wrap_socket, sock, server_side=True) -+ self.assertRaisesRegexp(ValueError, -+ "certfile must be specified for server-side operations", -+ ssl.wrap_socket, sock, server_side=True, certfile="") -+ with closing(ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)) as s: -+ self.assertRaisesRegexp(ValueError, "can't connect in server-side mode", -+ s.connect, (HOST, 8080)) -+ with self.assertRaises(IOError) as cm: -+ with closing(socket.socket()) as sock: -+ ssl.wrap_socket(sock, certfile=WRONGCERT) -+ self.assertEqual(cm.exception.errno, errno.ENOENT) -+ with self.assertRaises(IOError) as cm: -+ with closing(socket.socket()) as sock: -+ ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT) -+ self.assertEqual(cm.exception.errno, errno.ENOENT) -+ with self.assertRaises(IOError) as cm: -+ with closing(socket.socket()) as sock: -+ ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT) -+ self.assertEqual(cm.exception.errno, errno.ENOENT) -+ -+ def test_match_hostname(self): -+ def ok(cert, hostname): -+ ssl.match_hostname(cert, hostname) -+ def fail(cert, hostname): -+ self.assertRaises(ssl.CertificateError, -+ ssl.match_hostname, cert, hostname) -+ -+ cert = {'subject': ((('commonName', 'example.com'),),)} -+ ok(cert, 'example.com') -+ ok(cert, 'ExAmple.cOm') -+ fail(cert, 'www.example.com') -+ fail(cert, '.example.com') -+ fail(cert, 'example.org') -+ fail(cert, 'exampleXcom') -+ -+ cert = {'subject': ((('commonName', '*.a.com'),),)} -+ ok(cert, 'foo.a.com') -+ fail(cert, 'bar.foo.a.com') -+ fail(cert, 'a.com') -+ fail(cert, 'Xa.com') -+ fail(cert, '.a.com') -+ -+ # only match one left-most wildcard -+ cert = {'subject': ((('commonName', 'f*.com'),),)} -+ ok(cert, 'foo.com') -+ ok(cert, 'f.com') -+ fail(cert, 'bar.com') -+ fail(cert, 'foo.a.com') -+ fail(cert, 'bar.foo.com') -+ -+ # NULL bytes are bad, CVE-2013-4073 -+ cert = {'subject': ((('commonName', -+ 'null.python.org\x00example.org'),),)} -+ ok(cert, 'null.python.org\x00example.org') # or raise an error? -+ fail(cert, 'example.org') -+ fail(cert, 'null.python.org') -+ -+ # error cases with wildcards -+ cert = {'subject': ((('commonName', '*.*.a.com'),),)} -+ fail(cert, 'bar.foo.a.com') -+ fail(cert, 'a.com') -+ fail(cert, 'Xa.com') -+ fail(cert, '.a.com') -+ -+ cert = {'subject': ((('commonName', 'a.*.com'),),)} -+ fail(cert, 'a.foo.com') -+ fail(cert, 'a..com') -+ fail(cert, 'a.com') -+ -+ # wildcard doesn't match IDNA prefix 'xn--' -+ idna = u'pĂ¼thon.python.org'.encode("idna").decode("ascii") -+ cert = {'subject': ((('commonName', idna),),)} -+ ok(cert, idna) -+ cert = {'subject': ((('commonName', 'x*.python.org'),),)} -+ fail(cert, idna) -+ cert = {'subject': ((('commonName', 'xn--p*.python.org'),),)} -+ fail(cert, idna) -+ -+ # wildcard in first fragment and IDNA A-labels in sequent fragments -+ # are supported. -+ idna = u'www*.pythön.org'.encode("idna").decode("ascii") -+ cert = {'subject': ((('commonName', idna),),)} -+ ok(cert, u'www.pythön.org'.encode("idna").decode("ascii")) -+ ok(cert, u'www1.pythön.org'.encode("idna").decode("ascii")) -+ fail(cert, u'ftp.pythön.org'.encode("idna").decode("ascii")) -+ fail(cert, u'pythön.org'.encode("idna").decode("ascii")) -+ -+ # Slightly fake real-world example -+ cert = {'notAfter': 'Jun 26 21:41:46 2011 GMT', -+ 'subject': ((('commonName', 'linuxfrz.org'),),), -+ 'subjectAltName': (('DNS', 'linuxfr.org'), -+ ('DNS', 'linuxfr.com'), -+ ('othername', ''))} -+ ok(cert, 'linuxfr.org') -+ ok(cert, 'linuxfr.com') -+ # Not a "DNS" entry -+ fail(cert, '') -+ # When there is a subjectAltName, commonName isn't used -+ fail(cert, 'linuxfrz.org') -+ -+ # A pristine real-world example -+ cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT', -+ 'subject': ((('countryName', 'US'),), -+ (('stateOrProvinceName', 'California'),), -+ (('localityName', 'Mountain View'),), -+ (('organizationName', 'Google Inc'),), -+ (('commonName', 'mail.google.com'),))} -+ ok(cert, 'mail.google.com') -+ fail(cert, 'gmail.com') -+ # Only commonName is considered -+ fail(cert, 'California') -+ -+ # Neither commonName nor subjectAltName -+ cert = {'notAfter': 'Dec 18 23:59:59 2011 GMT', -+ 'subject': ((('countryName', 'US'),), -+ (('stateOrProvinceName', 'California'),), -+ (('localityName', 'Mountain View'),), -+ (('organizationName', 'Google Inc'),))} -+ fail(cert, 'mail.google.com') -+ -+ # No DNS entry in subjectAltName but a commonName -+ cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT', -+ 'subject': ((('countryName', 'US'),), -+ (('stateOrProvinceName', 'California'),), -+ (('localityName', 'Mountain View'),), -+ (('commonName', 'mail.google.com'),)), -+ 'subjectAltName': (('othername', 'blabla'), )} -+ ok(cert, 'mail.google.com') -+ -+ # No DNS entry subjectAltName and no commonName -+ cert = {'notAfter': 'Dec 18 23:59:59 2099 GMT', -+ 'subject': ((('countryName', 'US'),), -+ (('stateOrProvinceName', 'California'),), -+ (('localityName', 'Mountain View'),), -+ (('organizationName', 'Google Inc'),)), -+ 'subjectAltName': (('othername', 'blabla'),)} -+ fail(cert, 'google.com') -+ -+ # Empty cert / no cert -+ self.assertRaises(ValueError, ssl.match_hostname, None, 'example.com') -+ self.assertRaises(ValueError, ssl.match_hostname, {}, 'example.com') -+ -+ # Issue #17980: avoid denials of service by refusing more than one -+ # wildcard per fragment. -+ cert = {'subject': ((('commonName', 'a*b.com'),),)} -+ ok(cert, 'axxb.com') -+ cert = {'subject': ((('commonName', 'a*b.co*'),),)} -+ fail(cert, 'axxb.com') -+ cert = {'subject': ((('commonName', 'a*b*.com'),),)} -+ with self.assertRaises(ssl.CertificateError) as cm: -+ ssl.match_hostname(cert, 'axxbxxc.com') -+ self.assertIn("too many wildcards", str(cm.exception)) -+ -+ def test_server_side(self): -+ # server_hostname doesn't work for server sockets -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ with closing(socket.socket()) as sock: -+ self.assertRaises(ValueError, ctx.wrap_socket, sock, True, -+ server_hostname="some.hostname") -+ -+ def test_unknown_channel_binding(self): -+ # should raise ValueError for unknown type -+ s = socket.socket(socket.AF_INET) -+ with closing(ssl.wrap_socket(s)) as ss: -+ with self.assertRaises(ValueError): -+ ss.get_channel_binding("unknown-type") -+ -+ @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES, -+ "'tls-unique' channel binding not available") -+ def test_tls_unique_channel_binding(self): -+ # unconnected should return None for known type -+ s = socket.socket(socket.AF_INET) -+ with closing(ssl.wrap_socket(s)) as ss: -+ self.assertIsNone(ss.get_channel_binding("tls-unique")) -+ # the same for server-side -+ s = socket.socket(socket.AF_INET) -+ with closing(ssl.wrap_socket(s, server_side=True, certfile=CERTFILE)) as ss: -+ self.assertIsNone(ss.get_channel_binding("tls-unique")) -+ -+ def test_get_default_verify_paths(self): -+ paths = ssl.get_default_verify_paths() -+ self.assertEqual(len(paths), 6) -+ self.assertIsInstance(paths, ssl.DefaultVerifyPaths) -+ -+ with support.EnvironmentVarGuard() as env: -+ env["SSL_CERT_DIR"] = CAPATH -+ env["SSL_CERT_FILE"] = CERTFILE -+ paths = ssl.get_default_verify_paths() -+ self.assertEqual(paths.cafile, CERTFILE) -+ self.assertEqual(paths.capath, CAPATH) -+ -+ @unittest.skipUnless(sys.platform == "win32", "Windows specific") -+ def test_enum_certificates(self): -+ self.assertTrue(ssl.enum_certificates("CA")) -+ self.assertTrue(ssl.enum_certificates("ROOT")) -+ -+ self.assertRaises(TypeError, ssl.enum_certificates) -+ self.assertRaises(WindowsError, ssl.enum_certificates, "") -+ -+ trust_oids = set() -+ for storename in ("CA", "ROOT"): -+ store = ssl.enum_certificates(storename) -+ self.assertIsInstance(store, list) -+ for element in store: -+ self.assertIsInstance(element, tuple) -+ self.assertEqual(len(element), 3) -+ cert, enc, trust = element -+ self.assertIsInstance(cert, bytes) -+ self.assertIn(enc, {"x509_asn", "pkcs_7_asn"}) -+ self.assertIsInstance(trust, (set, bool)) -+ if isinstance(trust, set): -+ trust_oids.update(trust) -+ -+ serverAuth = "1.3.6.1.5.5.7.3.1" -+ self.assertIn(serverAuth, trust_oids) -+ -+ @unittest.skipUnless(sys.platform == "win32", "Windows specific") -+ def test_enum_crls(self): -+ self.assertTrue(ssl.enum_crls("CA")) -+ self.assertRaises(TypeError, ssl.enum_crls) -+ self.assertRaises(WindowsError, ssl.enum_crls, "") -+ -+ crls = ssl.enum_crls("CA") -+ self.assertIsInstance(crls, list) -+ for element in crls: -+ self.assertIsInstance(element, tuple) -+ self.assertEqual(len(element), 2) -+ self.assertIsInstance(element[0], bytes) -+ self.assertIn(element[1], {"x509_asn", "pkcs_7_asn"}) -+ -+ -+ def test_asn1object(self): -+ expected = (129, 'serverAuth', 'TLS Web Server Authentication', -+ '1.3.6.1.5.5.7.3.1') -+ -+ val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1') -+ self.assertEqual(val, expected) -+ self.assertEqual(val.nid, 129) -+ self.assertEqual(val.shortname, 'serverAuth') -+ self.assertEqual(val.longname, 'TLS Web Server Authentication') -+ self.assertEqual(val.oid, '1.3.6.1.5.5.7.3.1') -+ self.assertIsInstance(val, ssl._ASN1Object) -+ self.assertRaises(ValueError, ssl._ASN1Object, 'serverAuth') -+ -+ val = ssl._ASN1Object.fromnid(129) -+ self.assertEqual(val, expected) -+ self.assertIsInstance(val, ssl._ASN1Object) -+ self.assertRaises(ValueError, ssl._ASN1Object.fromnid, -1) -+ with self.assertRaisesRegexp(ValueError, "unknown NID 100000"): -+ ssl._ASN1Object.fromnid(100000) -+ for i in range(1000): -+ try: -+ obj = ssl._ASN1Object.fromnid(i) -+ except ValueError: -+ pass -+ else: -+ self.assertIsInstance(obj.nid, int) -+ self.assertIsInstance(obj.shortname, str) -+ self.assertIsInstance(obj.longname, str) -+ self.assertIsInstance(obj.oid, (str, type(None))) -+ -+ val = ssl._ASN1Object.fromname('TLS Web Server Authentication') -+ self.assertEqual(val, expected) -+ self.assertIsInstance(val, ssl._ASN1Object) -+ self.assertEqual(ssl._ASN1Object.fromname('serverAuth'), expected) -+ self.assertEqual(ssl._ASN1Object.fromname('1.3.6.1.5.5.7.3.1'), -+ expected) -+ with self.assertRaisesRegexp(ValueError, "unknown object 'serverauth'"): -+ ssl._ASN1Object.fromname('serverauth') -+ -+ def test_purpose_enum(self): -+ val = ssl._ASN1Object('1.3.6.1.5.5.7.3.1') -+ self.assertIsInstance(ssl.Purpose.SERVER_AUTH, ssl._ASN1Object) -+ self.assertEqual(ssl.Purpose.SERVER_AUTH, val) -+ self.assertEqual(ssl.Purpose.SERVER_AUTH.nid, 129) -+ self.assertEqual(ssl.Purpose.SERVER_AUTH.shortname, 'serverAuth') -+ self.assertEqual(ssl.Purpose.SERVER_AUTH.oid, -+ '1.3.6.1.5.5.7.3.1') -+ -+ val = ssl._ASN1Object('1.3.6.1.5.5.7.3.2') -+ self.assertIsInstance(ssl.Purpose.CLIENT_AUTH, ssl._ASN1Object) -+ self.assertEqual(ssl.Purpose.CLIENT_AUTH, val) -+ self.assertEqual(ssl.Purpose.CLIENT_AUTH.nid, 130) -+ self.assertEqual(ssl.Purpose.CLIENT_AUTH.shortname, 'clientAuth') -+ self.assertEqual(ssl.Purpose.CLIENT_AUTH.oid, -+ '1.3.6.1.5.5.7.3.2') - - def test_unsupported_dtls(self): - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -@@ -242,29 +614,592 @@ class BasicSocketTests(unittest.TestCase - with self.assertRaises(NotImplementedError) as cx: - ssl.wrap_socket(s, cert_reqs=ssl.CERT_NONE) - self.assertEqual(str(cx.exception), "only stream sockets are supported") -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ with self.assertRaises(NotImplementedError) as cx: -+ ctx.wrap_socket(s) -+ self.assertEqual(str(cx.exception), "only stream sockets are supported") -+ -+ def cert_time_ok(self, timestring, timestamp): -+ self.assertEqual(ssl.cert_time_to_seconds(timestring), timestamp) -+ -+ def cert_time_fail(self, timestring): -+ with self.assertRaises(ValueError): -+ ssl.cert_time_to_seconds(timestring) -+ -+ @unittest.skipUnless(utc_offset(), -+ 'local time needs to be different from UTC') -+ def test_cert_time_to_seconds_timezone(self): -+ # Issue #19940: ssl.cert_time_to_seconds() returns wrong -+ # results if local timezone is not UTC -+ self.cert_time_ok("May 9 00:00:00 2007 GMT", 1178668800.0) -+ self.cert_time_ok("Jan 5 09:34:43 2018 GMT", 1515144883.0) -+ -+ def test_cert_time_to_seconds(self): -+ timestring = "Jan 5 09:34:43 2018 GMT" -+ ts = 1515144883.0 -+ self.cert_time_ok(timestring, ts) -+ # accept keyword parameter, assert its name -+ self.assertEqual(ssl.cert_time_to_seconds(cert_time=timestring), ts) -+ # accept both %e and %d (space or zero generated by strftime) -+ self.cert_time_ok("Jan 05 09:34:43 2018 GMT", ts) -+ # case-insensitive -+ self.cert_time_ok("JaN 5 09:34:43 2018 GmT", ts) -+ self.cert_time_fail("Jan 5 09:34 2018 GMT") # no seconds -+ self.cert_time_fail("Jan 5 09:34:43 2018") # no GMT -+ self.cert_time_fail("Jan 5 09:34:43 2018 UTC") # not GMT timezone -+ self.cert_time_fail("Jan 35 09:34:43 2018 GMT") # invalid day -+ self.cert_time_fail("Jon 5 09:34:43 2018 GMT") # invalid month -+ self.cert_time_fail("Jan 5 24:00:00 2018 GMT") # invalid hour -+ self.cert_time_fail("Jan 5 09:60:43 2018 GMT") # invalid minute -+ -+ newyear_ts = 1230768000.0 -+ # leap seconds -+ self.cert_time_ok("Dec 31 23:59:60 2008 GMT", newyear_ts) -+ # same timestamp -+ self.cert_time_ok("Jan 1 00:00:00 2009 GMT", newyear_ts) -+ -+ self.cert_time_ok("Jan 5 09:34:59 2018 GMT", 1515144899) -+ # allow 60th second (even if it is not a leap second) -+ self.cert_time_ok("Jan 5 09:34:60 2018 GMT", 1515144900) -+ # allow 2nd leap second for compatibility with time.strptime() -+ self.cert_time_ok("Jan 5 09:34:61 2018 GMT", 1515144901) -+ self.cert_time_fail("Jan 5 09:34:62 2018 GMT") # invalid seconds -+ -+ # no special treatement for the special value: -+ # 99991231235959Z (rfc 5280) -+ self.cert_time_ok("Dec 31 23:59:59 9999 GMT", 253402300799.0) -+ -+ @support.run_with_locale('LC_ALL', '') -+ def test_cert_time_to_seconds_locale(self): -+ # `cert_time_to_seconds()` should be locale independent -+ -+ def local_february_name(): -+ return time.strftime('%b', (1, 2, 3, 4, 5, 6, 0, 0, 0)) -+ -+ if local_february_name().lower() == 'feb': -+ self.skipTest("locale-specific month name needs to be " -+ "different from C locale") -+ -+ # locale-independent -+ self.cert_time_ok("Feb 9 00:00:00 2007 GMT", 1170979200.0) -+ self.cert_time_fail(local_february_name() + " 9 00:00:00 2007 GMT") -+ -+ -+class ContextTests(unittest.TestCase): -+ -+ @skip_if_broken_ubuntu_ssl -+ def test_constructor(self): -+ for protocol in PROTOCOLS: -+ ssl.SSLContext(protocol) -+ self.assertRaises(TypeError, ssl.SSLContext) -+ self.assertRaises(ValueError, ssl.SSLContext, -1) -+ self.assertRaises(ValueError, ssl.SSLContext, 42) -+ -+ @skip_if_broken_ubuntu_ssl -+ def test_protocol(self): -+ for proto in PROTOCOLS: -+ ctx = ssl.SSLContext(proto) -+ self.assertEqual(ctx.protocol, proto) -+ -+ def test_ciphers(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.set_ciphers("ALL") -+ ctx.set_ciphers("DEFAULT") -+ with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"): -+ ctx.set_ciphers("^$:,;?*'dorothyx") -+ -+ @skip_if_broken_ubuntu_ssl -+ def test_options(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ # OP_ALL | OP_NO_SSLv2 is the default value -+ self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2, -+ ctx.options) -+ ctx.options |= ssl.OP_NO_SSLv3 -+ self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3, -+ ctx.options) -+ if can_clear_options(): -+ ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1 -+ self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3, -+ ctx.options) -+ ctx.options = 0 -+ self.assertEqual(0, ctx.options) -+ else: -+ with self.assertRaises(ValueError): -+ ctx.options = 0 -+ -+ def test_verify_mode(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ # Default value -+ self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) -+ ctx.verify_mode = ssl.CERT_OPTIONAL -+ self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) -+ ctx.verify_mode = ssl.CERT_NONE -+ self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) -+ with self.assertRaises(TypeError): -+ ctx.verify_mode = None -+ with self.assertRaises(ValueError): -+ ctx.verify_mode = 42 -+ -+ @unittest.skipUnless(have_verify_flags(), -+ "verify_flags need OpenSSL > 0.9.8") -+ def test_verify_flags(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ # default value by OpenSSL -+ self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT) -+ ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF -+ self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_LEAF) -+ ctx.verify_flags = ssl.VERIFY_CRL_CHECK_CHAIN -+ self.assertEqual(ctx.verify_flags, ssl.VERIFY_CRL_CHECK_CHAIN) -+ ctx.verify_flags = ssl.VERIFY_DEFAULT -+ self.assertEqual(ctx.verify_flags, ssl.VERIFY_DEFAULT) -+ # supports any value -+ ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT -+ self.assertEqual(ctx.verify_flags, -+ ssl.VERIFY_CRL_CHECK_LEAF | ssl.VERIFY_X509_STRICT) -+ with self.assertRaises(TypeError): -+ ctx.verify_flags = None -+ -+ def test_load_cert_chain(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ # Combined key and cert in a single file -+ ctx.load_cert_chain(CERTFILE) -+ ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE) -+ self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE) -+ with self.assertRaises(IOError) as cm: -+ ctx.load_cert_chain(WRONGCERT) -+ self.assertEqual(cm.exception.errno, errno.ENOENT) -+ with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"): -+ ctx.load_cert_chain(BADCERT) -+ with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"): -+ ctx.load_cert_chain(EMPTYCERT) -+ # Separate key and cert -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_cert_chain(ONLYCERT, ONLYKEY) -+ ctx.load_cert_chain(certfile=ONLYCERT, keyfile=ONLYKEY) -+ ctx.load_cert_chain(certfile=BYTES_ONLYCERT, keyfile=BYTES_ONLYKEY) -+ with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"): -+ ctx.load_cert_chain(ONLYCERT) -+ with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"): -+ ctx.load_cert_chain(ONLYKEY) -+ with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"): -+ ctx.load_cert_chain(certfile=ONLYKEY, keyfile=ONLYCERT) -+ # Mismatching key and cert -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ with self.assertRaisesRegexp(ssl.SSLError, "key values mismatch"): -+ ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY) -+ # Password protected key and cert -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD) -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode()) -+ ctx.load_cert_chain(CERTFILE_PROTECTED, -+ password=bytearray(KEY_PASSWORD.encode())) -+ ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD) -+ ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, KEY_PASSWORD.encode()) -+ ctx.load_cert_chain(ONLYCERT, ONLYKEY_PROTECTED, -+ bytearray(KEY_PASSWORD.encode())) -+ with self.assertRaisesRegexp(TypeError, "should be a string"): -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=True) -+ with self.assertRaises(ssl.SSLError): -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password="badpass") -+ with self.assertRaisesRegexp(ValueError, "cannot be longer"): -+ # openssl has a fixed limit on the password buffer. -+ # PEM_BUFSIZE is generally set to 1kb. -+ # Return a string larger than this. -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=b'a' * 102400) -+ # Password callback -+ def getpass_unicode(): -+ return KEY_PASSWORD -+ def getpass_bytes(): -+ return KEY_PASSWORD.encode() -+ def getpass_bytearray(): -+ return bytearray(KEY_PASSWORD.encode()) -+ def getpass_badpass(): -+ return "badpass" -+ def getpass_huge(): -+ return b'a' * (1024 * 1024) -+ def getpass_bad_type(): -+ return 9 -+ def getpass_exception(): -+ raise Exception('getpass error') -+ class GetPassCallable: -+ def __call__(self): -+ return KEY_PASSWORD -+ def getpass(self): -+ return KEY_PASSWORD -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_unicode) -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytes) -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bytearray) -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=GetPassCallable()) -+ ctx.load_cert_chain(CERTFILE_PROTECTED, -+ password=GetPassCallable().getpass) -+ with self.assertRaises(ssl.SSLError): -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_badpass) -+ with self.assertRaisesRegexp(ValueError, "cannot be longer"): -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_huge) -+ with self.assertRaisesRegexp(TypeError, "must return a string"): -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_bad_type) -+ with self.assertRaisesRegexp(Exception, "getpass error"): -+ ctx.load_cert_chain(CERTFILE_PROTECTED, password=getpass_exception) -+ # Make sure the password function isn't called if it isn't needed -+ ctx.load_cert_chain(CERTFILE, password=getpass_exception) -+ -+ def test_load_verify_locations(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_verify_locations(CERTFILE) -+ ctx.load_verify_locations(cafile=CERTFILE, capath=None) -+ ctx.load_verify_locations(BYTES_CERTFILE) -+ ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None) -+ self.assertRaises(TypeError, ctx.load_verify_locations) -+ self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None) -+ with self.assertRaises(IOError) as cm: -+ ctx.load_verify_locations(WRONGCERT) -+ self.assertEqual(cm.exception.errno, errno.ENOENT) -+ with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"): -+ ctx.load_verify_locations(BADCERT) -+ ctx.load_verify_locations(CERTFILE, CAPATH) -+ ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH) -+ -+ # Issue #10989: crash if the second argument type is invalid -+ self.assertRaises(TypeError, ctx.load_verify_locations, None, True) -+ -+ def test_load_verify_cadata(self): -+ # test cadata -+ with open(CAFILE_CACERT) as f: -+ cacert_pem = f.read().decode("ascii") -+ cacert_der = ssl.PEM_cert_to_DER_cert(cacert_pem) -+ with open(CAFILE_NEURONIO) as f: -+ neuronio_pem = f.read().decode("ascii") -+ neuronio_der = ssl.PEM_cert_to_DER_cert(neuronio_pem) -+ -+ # test PEM -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 0) -+ ctx.load_verify_locations(cadata=cacert_pem) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 1) -+ ctx.load_verify_locations(cadata=neuronio_pem) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ # cert already in hash table -+ ctx.load_verify_locations(cadata=neuronio_pem) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ -+ # combined -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ combined = "\n".join((cacert_pem, neuronio_pem)) -+ ctx.load_verify_locations(cadata=combined) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ -+ # with junk around the certs -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ combined = ["head", cacert_pem, "other", neuronio_pem, "again", -+ neuronio_pem, "tail"] -+ ctx.load_verify_locations(cadata="\n".join(combined)) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ -+ # test DER -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_verify_locations(cadata=cacert_der) -+ ctx.load_verify_locations(cadata=neuronio_der) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ # cert already in hash table -+ ctx.load_verify_locations(cadata=cacert_der) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ -+ # combined -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ combined = b"".join((cacert_der, neuronio_der)) -+ ctx.load_verify_locations(cadata=combined) -+ self.assertEqual(ctx.cert_store_stats()["x509_ca"], 2) -+ -+ # error cases -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ self.assertRaises(TypeError, ctx.load_verify_locations, cadata=object) -+ -+ with self.assertRaisesRegexp(ssl.SSLError, "no start line"): -+ ctx.load_verify_locations(cadata=u"broken") -+ with self.assertRaisesRegexp(ssl.SSLError, "not enough data"): -+ ctx.load_verify_locations(cadata=b"broken") -+ -+ -+ def test_load_dh_params(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_dh_params(DHFILE) -+ if os.name != 'nt': -+ ctx.load_dh_params(BYTES_DHFILE) -+ self.assertRaises(TypeError, ctx.load_dh_params) -+ self.assertRaises(TypeError, ctx.load_dh_params, None) -+ with self.assertRaises(IOError) as cm: -+ ctx.load_dh_params(WRONGCERT) -+ self.assertEqual(cm.exception.errno, errno.ENOENT) -+ with self.assertRaises(ssl.SSLError) as cm: -+ ctx.load_dh_params(CERTFILE) -+ -+ @skip_if_broken_ubuntu_ssl -+ def test_session_stats(self): -+ for proto in PROTOCOLS: -+ ctx = ssl.SSLContext(proto) -+ self.assertEqual(ctx.session_stats(), { -+ 'number': 0, -+ 'connect': 0, -+ 'connect_good': 0, -+ 'connect_renegotiate': 0, -+ 'accept': 0, -+ 'accept_good': 0, -+ 'accept_renegotiate': 0, -+ 'hits': 0, -+ 'misses': 0, -+ 'timeouts': 0, -+ 'cache_full': 0, -+ }) -+ -+ def test_set_default_verify_paths(self): -+ # There's not much we can do to test that it acts as expected, -+ # so just check it doesn't crash or raise an exception. -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.set_default_verify_paths() -+ -+ @unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build") -+ def test_set_ecdh_curve(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.set_ecdh_curve("prime256v1") -+ ctx.set_ecdh_curve(b"prime256v1") -+ self.assertRaises(TypeError, ctx.set_ecdh_curve) -+ self.assertRaises(TypeError, ctx.set_ecdh_curve, None) -+ self.assertRaises(ValueError, ctx.set_ecdh_curve, "foo") -+ self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo") -+ -+ @needs_sni -+ def test_sni_callback(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ -+ # set_servername_callback expects a callable, or None -+ self.assertRaises(TypeError, ctx.set_servername_callback) -+ self.assertRaises(TypeError, ctx.set_servername_callback, 4) -+ self.assertRaises(TypeError, ctx.set_servername_callback, "") -+ self.assertRaises(TypeError, ctx.set_servername_callback, ctx) -+ -+ def dummycallback(sock, servername, ctx): -+ pass -+ ctx.set_servername_callback(None) -+ ctx.set_servername_callback(dummycallback) -+ -+ @needs_sni -+ def test_sni_callback_refcycle(self): -+ # Reference cycles through the servername callback are detected -+ # and cleared. -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ def dummycallback(sock, servername, ctx, cycle=ctx): -+ pass -+ ctx.set_servername_callback(dummycallback) -+ wr = weakref.ref(ctx) -+ del ctx, dummycallback -+ gc.collect() -+ self.assertIs(wr(), None) -+ -+ def test_cert_store_stats(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ self.assertEqual(ctx.cert_store_stats(), -+ {'x509_ca': 0, 'crl': 0, 'x509': 0}) -+ ctx.load_cert_chain(CERTFILE) -+ self.assertEqual(ctx.cert_store_stats(), -+ {'x509_ca': 0, 'crl': 0, 'x509': 0}) -+ ctx.load_verify_locations(CERTFILE) -+ self.assertEqual(ctx.cert_store_stats(), -+ {'x509_ca': 0, 'crl': 0, 'x509': 1}) -+ ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT) -+ self.assertEqual(ctx.cert_store_stats(), -+ {'x509_ca': 1, 'crl': 0, 'x509': 2}) -+ -+ def test_get_ca_certs(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ self.assertEqual(ctx.get_ca_certs(), []) -+ # CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE -+ ctx.load_verify_locations(CERTFILE) -+ self.assertEqual(ctx.get_ca_certs(), []) -+ # but SVN_PYTHON_ORG_ROOT_CERT is a CA cert -+ ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT) -+ self.assertEqual(ctx.get_ca_certs(), -+ [{'issuer': ((('organizationName', 'Root CA'),), -+ (('organizationalUnitName', 'http://www.cacert.org'),), -+ (('commonName', 'CA Cert Signing Authority'),), -+ (('emailAddress', 'support@cacert.org'),)), -+ 'notAfter': asn1time('Mar 29 12:29:49 2033 GMT'), -+ 'notBefore': asn1time('Mar 30 12:29:49 2003 GMT'), -+ 'serialNumber': '00', -+ 'crlDistributionPoints': ('https://www.cacert.org/revoke.crl',), -+ 'subject': ((('organizationName', 'Root CA'),), -+ (('organizationalUnitName', 'http://www.cacert.org'),), -+ (('commonName', 'CA Cert Signing Authority'),), -+ (('emailAddress', 'support@cacert.org'),)), -+ 'version': 3}]) -+ -+ with open(SVN_PYTHON_ORG_ROOT_CERT) as f: -+ pem = f.read() -+ der = ssl.PEM_cert_to_DER_cert(pem) -+ self.assertEqual(ctx.get_ca_certs(True), [der]) -+ -+ def test_load_default_certs(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_default_certs() -+ -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_default_certs(ssl.Purpose.SERVER_AUTH) -+ ctx.load_default_certs() -+ -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.load_default_certs(ssl.Purpose.CLIENT_AUTH) -+ -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ self.assertRaises(TypeError, ctx.load_default_certs, None) -+ self.assertRaises(TypeError, ctx.load_default_certs, 'SERVER_AUTH') -+ -+ def test_create_default_context(self): -+ ctx = ssl.create_default_context() -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) -+ self.assertTrue(ctx.check_hostname) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ self.assertEqual( -+ ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0), -+ getattr(ssl, "OP_NO_COMPRESSION", 0), -+ ) -+ -+ with open(SIGNING_CA) as f: -+ cadata = f.read().decode("ascii") -+ ctx = ssl.create_default_context(cafile=SIGNING_CA, capath=CAPATH, -+ cadata=cadata) -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ self.assertEqual( -+ ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0), -+ getattr(ssl, "OP_NO_COMPRESSION", 0), -+ ) -+ -+ ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ self.assertEqual( -+ ctx.options & getattr(ssl, "OP_NO_COMPRESSION", 0), -+ getattr(ssl, "OP_NO_COMPRESSION", 0), -+ ) -+ self.assertEqual( -+ ctx.options & getattr(ssl, "OP_SINGLE_DH_USE", 0), -+ getattr(ssl, "OP_SINGLE_DH_USE", 0), -+ ) -+ self.assertEqual( -+ ctx.options & getattr(ssl, "OP_SINGLE_ECDH_USE", 0), -+ getattr(ssl, "OP_SINGLE_ECDH_USE", 0), -+ ) -+ -+ def test__create_stdlib_context(self): -+ ctx = ssl._create_stdlib_context() -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) -+ self.assertFalse(ctx.check_hostname) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ -+ ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1) -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ -+ ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1, -+ cert_reqs=ssl.CERT_REQUIRED, -+ check_hostname=True) -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_TLSv1) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) -+ self.assertTrue(ctx.check_hostname) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ -+ ctx = ssl._create_stdlib_context(purpose=ssl.Purpose.CLIENT_AUTH) -+ self.assertEqual(ctx.protocol, ssl.PROTOCOL_SSLv23) -+ self.assertEqual(ctx.verify_mode, ssl.CERT_NONE) -+ self.assertEqual(ctx.options & ssl.OP_NO_SSLv2, ssl.OP_NO_SSLv2) -+ -+ def test_check_hostname(self): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ self.assertFalse(ctx.check_hostname) -+ -+ # Requires CERT_REQUIRED or CERT_OPTIONAL -+ with self.assertRaises(ValueError): -+ ctx.check_hostname = True -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ self.assertFalse(ctx.check_hostname) -+ ctx.check_hostname = True -+ self.assertTrue(ctx.check_hostname) -+ -+ ctx.verify_mode = ssl.CERT_OPTIONAL -+ ctx.check_hostname = True -+ self.assertTrue(ctx.check_hostname) -+ -+ # Cannot set CERT_NONE with check_hostname enabled -+ with self.assertRaises(ValueError): -+ ctx.verify_mode = ssl.CERT_NONE -+ ctx.check_hostname = False -+ self.assertFalse(ctx.check_hostname) -+ -+ -+class SSLErrorTests(unittest.TestCase): -+ -+ def test_str(self): -+ # The str() of a SSLError doesn't include the errno -+ e = ssl.SSLError(1, "foo") -+ self.assertEqual(str(e), "foo") -+ self.assertEqual(e.errno, 1) -+ # Same for a subclass -+ e = ssl.SSLZeroReturnError(1, "foo") -+ self.assertEqual(str(e), "foo") -+ self.assertEqual(e.errno, 1) -+ -+ def test_lib_reason(self): -+ # Test the library and reason attributes -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ with self.assertRaises(ssl.SSLError) as cm: -+ ctx.load_dh_params(CERTFILE) -+ self.assertEqual(cm.exception.library, 'PEM') -+ self.assertEqual(cm.exception.reason, 'NO_START_LINE') -+ s = str(cm.exception) -+ self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s) -+ -+ def test_subclass(self): -+ # Check that the appropriate SSLError subclass is raised -+ # (this only tests one of them) -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ with closing(socket.socket()) as s: -+ s.bind(("127.0.0.1", 0)) -+ s.listen(5) -+ c = socket.socket() -+ c.connect(s.getsockname()) -+ c.setblocking(False) -+ with closing(ctx.wrap_socket(c, False, do_handshake_on_connect=False)) as c: -+ with self.assertRaises(ssl.SSLWantReadError) as cm: -+ c.do_handshake() -+ s = str(cm.exception) -+ self.assertTrue(s.startswith("The operation did not complete (read)"), s) -+ # For compatibility -+ self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ) - - - class NetworkedTests(unittest.TestCase): - - def test_connect(self): -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - s = ssl.wrap_socket(socket.socket(socket.AF_INET), - cert_reqs=ssl.CERT_NONE) -- s.connect(("svn.python.org", 443)) -- c = s.getpeercert() -- if c: -- self.fail("Peer cert %s shouldn't be here!") -- s.close() -+ try: -+ s.connect(("svn.python.org", 443)) -+ self.assertEqual({}, s.getpeercert()) -+ finally: -+ s.close() - - # this should fail because we have no verification certs - s = ssl.wrap_socket(socket.socket(socket.AF_INET), - cert_reqs=ssl.CERT_REQUIRED) -- try: -- s.connect(("svn.python.org", 443)) -- except ssl.SSLError: -- pass -- finally: -- s.close() -+ self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed", -+ s.connect, ("svn.python.org", 443)) -+ s.close() - - # this should succeed because we specify the root cert - s = ssl.wrap_socket(socket.socket(socket.AF_INET), -@@ -272,12 +1207,13 @@ class NetworkedTests(unittest.TestCase): - ca_certs=SVN_PYTHON_ORG_ROOT_CERT) - try: - s.connect(("svn.python.org", 443)) -+ self.assertTrue(s.getpeercert()) - finally: - s.close() - - def test_connect_ex(self): - # Issue #11326: check connect_ex() implementation -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - s = ssl.wrap_socket(socket.socket(socket.AF_INET), - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=SVN_PYTHON_ORG_ROOT_CERT) -@@ -290,7 +1226,7 @@ class NetworkedTests(unittest.TestCase): - def test_non_blocking_connect_ex(self): - # Issue #11326: non-blocking connect_ex() should allow handshake - # to proceed after the socket gets ready. -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - s = ssl.wrap_socket(socket.socket(socket.AF_INET), - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=SVN_PYTHON_ORG_ROOT_CERT, -@@ -307,13 +1243,10 @@ class NetworkedTests(unittest.TestCase): - try: - s.do_handshake() - break -- except ssl.SSLError as err: -- if err.args[0] == ssl.SSL_ERROR_WANT_READ: -- select.select([s], [], [], 5.0) -- elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: -- select.select([], [s], [], 5.0) -- else: -- raise -+ except ssl.SSLWantReadError: -+ select.select([s], [], [], 5.0) -+ except ssl.SSLWantWriteError: -+ select.select([], [s], [], 5.0) - # SSL established - self.assertTrue(s.getpeercert()) - finally: -@@ -322,7 +1255,7 @@ class NetworkedTests(unittest.TestCase): - def test_timeout_connect_ex(self): - # Issue #12065: on a timeout, connect_ex() should return the original - # errno (mimicking the behaviour of non-SSL sockets). -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - s = ssl.wrap_socket(socket.socket(socket.AF_INET), - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=SVN_PYTHON_ORG_ROOT_CERT, -@@ -337,22 +1270,109 @@ class NetworkedTests(unittest.TestCase): - s.close() - - def test_connect_ex_error(self): -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - s = ssl.wrap_socket(socket.socket(socket.AF_INET), - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=SVN_PYTHON_ORG_ROOT_CERT) - try: -- self.assertEqual(errno.ECONNREFUSED, -- s.connect_ex(("svn.python.org", 444))) -+ rc = s.connect_ex(("svn.python.org", 444)) -+ # Issue #19919: Windows machines or VMs hosted on Windows -+ # machines sometimes return EWOULDBLOCK. -+ self.assertIn(rc, (errno.ECONNREFUSED, errno.EWOULDBLOCK)) - finally: - s.close() - -+ def test_connect_with_context(self): -+ with support.transient_internet("svn.python.org"): -+ # Same as test_connect, but with a separately created context -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET)) -+ s.connect(("svn.python.org", 443)) -+ try: -+ self.assertEqual({}, s.getpeercert()) -+ finally: -+ s.close() -+ # Same with a server hostname -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET), -+ server_hostname="svn.python.org") -+ if ssl.HAS_SNI: -+ s.connect(("svn.python.org", 443)) -+ s.close() -+ else: -+ self.assertRaises(ValueError, s.connect, ("svn.python.org", 443)) -+ # This should fail because we have no verification certs -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET)) -+ self.assertRaisesRegexp(ssl.SSLError, "certificate verify failed", -+ s.connect, ("svn.python.org", 443)) -+ s.close() -+ # This should succeed because we specify the root cert -+ ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT) -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET)) -+ s.connect(("svn.python.org", 443)) -+ try: -+ cert = s.getpeercert() -+ self.assertTrue(cert) -+ finally: -+ s.close() -+ -+ def test_connect_capath(self): -+ # Verify server certificates using the `capath` argument -+ # NOTE: the subject hashing algorithm has been changed between -+ # OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must -+ # contain both versions of each certificate (same content, different -+ # filename) for this test to be portable across OpenSSL releases. -+ with support.transient_internet("svn.python.org"): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ ctx.load_verify_locations(capath=CAPATH) -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET)) -+ s.connect(("svn.python.org", 443)) -+ try: -+ cert = s.getpeercert() -+ self.assertTrue(cert) -+ finally: -+ s.close() -+ # Same with a bytes `capath` argument -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ ctx.load_verify_locations(capath=BYTES_CAPATH) -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET)) -+ s.connect(("svn.python.org", 443)) -+ try: -+ cert = s.getpeercert() -+ self.assertTrue(cert) -+ finally: -+ s.close() -+ -+ def test_connect_cadata(self): -+ with open(CAFILE_CACERT) as f: -+ pem = f.read().decode('ascii') -+ der = ssl.PEM_cert_to_DER_cert(pem) -+ with support.transient_internet("svn.python.org"): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ ctx.load_verify_locations(cadata=pem) -+ with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s: -+ s.connect(("svn.python.org", 443)) -+ cert = s.getpeercert() -+ self.assertTrue(cert) -+ -+ # same with DER -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ ctx.load_verify_locations(cadata=der) -+ with closing(ctx.wrap_socket(socket.socket(socket.AF_INET))) as s: -+ s.connect(("svn.python.org", 443)) -+ cert = s.getpeercert() -+ self.assertTrue(cert) -+ - @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows") - def test_makefile_close(self): - # Issue #5238: creating a file-like object with makefile() shouldn't - # delay closing the underlying "real socket" (here tested with its - # file descriptor, hence skipping the test under Windows). -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - ss = ssl.wrap_socket(socket.socket(socket.AF_INET)) - ss.connect(("svn.python.org", 443)) - fd = ss.fileno() -@@ -368,7 +1388,7 @@ class NetworkedTests(unittest.TestCase): - self.assertEqual(e.exception.errno, errno.EBADF) - - def test_non_blocking_handshake(self): -- with test_support.transient_internet("svn.python.org"): -+ with support.transient_internet("svn.python.org"): - s = socket.socket(socket.AF_INET) - s.connect(("svn.python.org", 443)) - s.setblocking(False) -@@ -381,41 +1401,57 @@ class NetworkedTests(unittest.TestCase): - count += 1 - s.do_handshake() - break -- except ssl.SSLError, err: -- if err.args[0] == ssl.SSL_ERROR_WANT_READ: -- select.select([s], [], []) -- elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: -- select.select([], [s], []) -- else: -- raise -+ except ssl.SSLWantReadError: -+ select.select([s], [], []) -+ except ssl.SSLWantWriteError: -+ select.select([], [s], []) - s.close() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\nNeeded %d calls to do_handshake() to establish session.\n" % count) - - def test_get_server_certificate(self): -- with test_support.transient_internet("svn.python.org"): -- pem = ssl.get_server_certificate(("svn.python.org", 443), -- ssl.PROTOCOL_SSLv23) -- if not pem: -- self.fail("No server certificate on svn.python.org:443!") -+ def _test_get_server_certificate(host, port, cert=None): -+ with support.transient_internet(host): -+ pem = ssl.get_server_certificate((host, port)) -+ if not pem: -+ self.fail("No server certificate on %s:%s!" % (host, port)) - -- try: -- pem = ssl.get_server_certificate(("svn.python.org", 443), -- ssl.PROTOCOL_SSLv23, -- ca_certs=CERTFILE) -- except ssl.SSLError: -- #should fail -- pass -- else: -- self.fail("Got server certificate %s for svn.python.org!" % pem) -+ try: -+ pem = ssl.get_server_certificate((host, port), -+ ca_certs=CERTFILE) -+ except ssl.SSLError as x: -+ #should fail -+ if support.verbose: -+ sys.stdout.write("%s\n" % x) -+ else: -+ self.fail("Got server certificate %s for %s:%s!" % (pem, host, port)) - -- pem = ssl.get_server_certificate(("svn.python.org", 443), -- ssl.PROTOCOL_SSLv23, -- ca_certs=SVN_PYTHON_ORG_ROOT_CERT) -- if not pem: -- self.fail("No server certificate on svn.python.org:443!") -- if test_support.verbose: -- sys.stdout.write("\nVerified certificate for svn.python.org:443 is\n%s\n" % pem) -+ pem = ssl.get_server_certificate((host, port), -+ ca_certs=cert) -+ if not pem: -+ self.fail("No server certificate on %s:%s!" % (host, port)) -+ if support.verbose: -+ sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem)) -+ -+ _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT) -+ if support.IPV6_ENABLED: -+ _test_get_server_certificate('ipv6.google.com', 443) -+ -+ def test_ciphers(self): -+ remote = ("svn.python.org", 443) -+ with support.transient_internet(remote[0]): -+ with closing(ssl.wrap_socket(socket.socket(socket.AF_INET), -+ cert_reqs=ssl.CERT_NONE, ciphers="ALL")) as s: -+ s.connect(remote) -+ with closing(ssl.wrap_socket(socket.socket(socket.AF_INET), -+ cert_reqs=ssl.CERT_NONE, ciphers="DEFAULT")) as s: -+ s.connect(remote) -+ # Error checking can happen at instantiation or when connecting -+ with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"): -+ with closing(socket.socket(socket.AF_INET)) as sock: -+ s = ssl.wrap_socket(sock, -+ cert_reqs=ssl.CERT_NONE, ciphers="^$:,;?*'dorothyx") -+ s.connect(remote) - - def test_algorithms(self): - # Issue #8484: all algorithms should be available when verifying a -@@ -423,17 +1459,21 @@ class NetworkedTests(unittest.TestCase): - # SHA256 was added in OpenSSL 0.9.8 - if ssl.OPENSSL_VERSION_INFO < (0, 9, 8, 0, 15): - self.skipTest("SHA256 not available on %r" % ssl.OPENSSL_VERSION) -- self.skipTest("remote host needs SNI, only available on Python 3.2+") -- # NOTE: https://sha2.hboeck.de is another possible test host -+ # sha256.tbs-internet.com needs SNI to use the correct certificate -+ if not ssl.HAS_SNI: -+ self.skipTest("SNI needed for this test") -+ # https://sha2.hboeck.de/ was used until 2011-01-08 (no route to host) - remote = ("sha256.tbs-internet.com", 443) - sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem") -- with test_support.transient_internet("sha256.tbs-internet.com"): -- s = ssl.wrap_socket(socket.socket(socket.AF_INET), -- cert_reqs=ssl.CERT_REQUIRED, -- ca_certs=sha256_cert,) -+ with support.transient_internet("sha256.tbs-internet.com"): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ ctx.load_verify_locations(sha256_cert) -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET), -+ server_hostname="sha256.tbs-internet.com") - try: - s.connect(remote) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\nCipher with %r is %r\n" % - (remote, s.cipher())) - sys.stdout.write("Certificate is:\n%s\n" % -@@ -441,6 +1481,36 @@ class NetworkedTests(unittest.TestCase): - finally: - s.close() - -+ def test_get_ca_certs_capath(self): -+ # capath certs are loaded on request -+ with support.transient_internet("svn.python.org"): -+ ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ ctx.verify_mode = ssl.CERT_REQUIRED -+ ctx.load_verify_locations(capath=CAPATH) -+ self.assertEqual(ctx.get_ca_certs(), []) -+ s = ctx.wrap_socket(socket.socket(socket.AF_INET)) -+ s.connect(("svn.python.org", 443)) -+ try: -+ cert = s.getpeercert() -+ self.assertTrue(cert) -+ finally: -+ s.close() -+ self.assertEqual(len(ctx.get_ca_certs()), 1) -+ -+ @needs_sni -+ def test_context_setget(self): -+ # Check that the context of a connected socket can be replaced. -+ with support.transient_internet("svn.python.org"): -+ ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ s = socket.socket(socket.AF_INET) -+ with closing(ctx1.wrap_socket(s)) as ss: -+ ss.connect(("svn.python.org", 443)) -+ self.assertIs(ss.context, ctx1) -+ self.assertIs(ss._sslobj.context, ctx1) -+ ss.context = ctx2 -+ self.assertIs(ss.context, ctx2) -+ self.assertIs(ss._sslobj.context, ctx2) - - try: - import threading -@@ -449,6 +1519,8 @@ except ImportError: - else: - _have_threads = True - -+ from test.ssl_servers import make_https_server -+ - class ThreadedEchoServer(threading.Thread): - - class ConnectionHandler(threading.Thread): -@@ -457,48 +1529,51 @@ else: - with and without the SSL wrapper around the socket connection, so - that we can test the STARTTLS functionality.""" - -- def __init__(self, server, connsock): -+ def __init__(self, server, connsock, addr): - self.server = server - self.running = False - self.sock = connsock -+ self.addr = addr - self.sock.setblocking(1) - self.sslconn = None - threading.Thread.__init__(self) - self.daemon = True - -- def show_conn_details(self): -- if self.server.certreqs == ssl.CERT_REQUIRED: -- cert = self.sslconn.getpeercert() -- if test_support.verbose and self.server.chatty: -- sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n") -- cert_binary = self.sslconn.getpeercert(True) -- if test_support.verbose and self.server.chatty: -- sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n") -- cipher = self.sslconn.cipher() -- if test_support.verbose and self.server.chatty: -- sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n") -- - def wrap_conn(self): - try: -- self.sslconn = ssl.wrap_socket(self.sock, server_side=True, -- certfile=self.server.certificate, -- ssl_version=self.server.protocol, -- ca_certs=self.server.cacerts, -- cert_reqs=self.server.certreqs, -- ciphers=self.server.ciphers) -- except ssl.SSLError as e: -+ self.sslconn = self.server.context.wrap_socket( -+ self.sock, server_side=True) -+ self.server.selected_protocols.append(self.sslconn.selected_npn_protocol()) -+ except socket.error as e: -+ # We treat ConnectionResetError as though it were an -+ # SSLError - OpenSSL on Ubuntu abruptly closes the -+ # connection when asked to use an unsupported protocol. -+ # - # XXX Various errors can have happened here, for example - # a mismatching protocol version, an invalid certificate, - # or a low-level bug. This should be made more discriminating. -+ if not isinstance(e, ssl.SSLError) and e.errno != errno.ECONNRESET: -+ raise - self.server.conn_errors.append(e) - if self.server.chatty: -- handle_error("\n server: bad connection attempt from " + -- str(self.sock.getpeername()) + ":\n") -- self.close() -+ handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n") - self.running = False - self.server.stop() -+ self.close() - return False - else: -+ if self.server.context.verify_mode == ssl.CERT_REQUIRED: -+ cert = self.sslconn.getpeercert() -+ if support.verbose and self.server.chatty: -+ sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n") -+ cert_binary = self.sslconn.getpeercert(True) -+ if support.verbose and self.server.chatty: -+ sys.stdout.write(" cert binary is " + str(len(cert_binary)) + " bytes\n") -+ cipher = self.sslconn.cipher() -+ if support.verbose and self.server.chatty: -+ sys.stdout.write(" server: connection cipher is now " + str(cipher) + "\n") -+ sys.stdout.write(" server: selected protocol is now " -+ + str(self.sslconn.selected_npn_protocol()) + "\n") - return True - - def read(self): -@@ -517,48 +1592,53 @@ else: - if self.sslconn: - self.sslconn.close() - else: -- self.sock._sock.close() -+ self.sock.close() - - def run(self): - self.running = True - if not self.server.starttls_server: -- if isinstance(self.sock, ssl.SSLSocket): -- self.sslconn = self.sock -- elif not self.wrap_conn(): -+ if not self.wrap_conn(): - return -- self.show_conn_details() - while self.running: - try: - msg = self.read() -- if not msg: -+ stripped = msg.strip() -+ if not stripped: - # eof, so quit this handler - self.running = False - self.close() -- elif msg.strip() == 'over': -- if test_support.verbose and self.server.connectionchatty: -+ elif stripped == b'over': -+ if support.verbose and self.server.connectionchatty: - sys.stdout.write(" server: client closed connection\n") - self.close() - return -- elif self.server.starttls_server and msg.strip() == 'STARTTLS': -- if test_support.verbose and self.server.connectionchatty: -+ elif (self.server.starttls_server and -+ stripped == b'STARTTLS'): -+ if support.verbose and self.server.connectionchatty: - sys.stdout.write(" server: read STARTTLS from client, sending OK...\n") -- self.write("OK\n") -+ self.write(b"OK\n") - if not self.wrap_conn(): - return -- elif self.server.starttls_server and self.sslconn and msg.strip() == 'ENDTLS': -- if test_support.verbose and self.server.connectionchatty: -+ elif (self.server.starttls_server and self.sslconn -+ and stripped == b'ENDTLS'): -+ if support.verbose and self.server.connectionchatty: - sys.stdout.write(" server: read ENDTLS from client, sending OK...\n") -- self.write("OK\n") -- self.sslconn.unwrap() -+ self.write(b"OK\n") -+ self.sock = self.sslconn.unwrap() - self.sslconn = None -- if test_support.verbose and self.server.connectionchatty: -+ if support.verbose and self.server.connectionchatty: - sys.stdout.write(" server: connection is now unencrypted...\n") -+ elif stripped == b'CB tls-unique': -+ if support.verbose and self.server.connectionchatty: -+ sys.stdout.write(" server: read CB tls-unique from client, sending our CB data...\n") -+ data = self.sslconn.get_channel_binding("tls-unique") -+ self.write(repr(data).encode("us-ascii") + b"\n") - else: -- if (test_support.verbose and -+ if (support.verbose and - self.server.connectionchatty): - ctype = (self.sslconn and "encrypted") or "unencrypted" -- sys.stdout.write(" server: read %s (%s), sending back %s (%s)...\n" -- % (repr(msg), ctype, repr(msg.lower()), ctype)) -+ sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n" -+ % (msg, ctype, msg.lower(), ctype)) - self.write(msg.lower()) - except ssl.SSLError: - if self.server.chatty: -@@ -569,36 +1649,34 @@ else: - # harness, we want to stop the server - self.server.stop() - -- def __init__(self, certificate, ssl_version=None, -+ def __init__(self, certificate=None, ssl_version=None, - certreqs=None, cacerts=None, - chatty=True, connectionchatty=False, starttls_server=False, -- wrap_accepting_socket=False, ciphers=None): -- -- if ssl_version is None: -- ssl_version = ssl.PROTOCOL_TLSv1 -- if certreqs is None: -- certreqs = ssl.CERT_NONE -- self.certificate = certificate -- self.protocol = ssl_version -- self.certreqs = certreqs -- self.cacerts = cacerts -- self.ciphers = ciphers -+ npn_protocols=None, ciphers=None, context=None): -+ if context: -+ self.context = context -+ else: -+ self.context = ssl.SSLContext(ssl_version -+ if ssl_version is not None -+ else ssl.PROTOCOL_TLSv1) -+ self.context.verify_mode = (certreqs if certreqs is not None -+ else ssl.CERT_NONE) -+ if cacerts: -+ self.context.load_verify_locations(cacerts) -+ if certificate: -+ self.context.load_cert_chain(certificate) -+ if npn_protocols: -+ self.context.set_npn_protocols(npn_protocols) -+ if ciphers: -+ self.context.set_ciphers(ciphers) - self.chatty = chatty - self.connectionchatty = connectionchatty - self.starttls_server = starttls_server - self.sock = socket.socket() -+ self.port = support.bind_port(self.sock) - self.flag = None -- if wrap_accepting_socket: -- self.sock = ssl.wrap_socket(self.sock, server_side=True, -- certfile=self.certificate, -- cert_reqs = self.certreqs, -- ca_certs = self.cacerts, -- ssl_version = self.protocol, -- ciphers = self.ciphers) -- if test_support.verbose and self.chatty: -- sys.stdout.write(' server: wrapped server socket as %s\n' % str(self.sock)) -- self.port = test_support.bind_port(self.sock) - self.active = False -+ self.selected_protocols = [] - self.conn_errors = [] - threading.Thread.__init__(self) - self.daemon = True -@@ -626,10 +1704,10 @@ else: - while self.active: - try: - newconn, connaddr = self.sock.accept() -- if test_support.verbose and self.chatty: -+ if support.verbose and self.chatty: - sys.stdout.write(' server: new connection from ' -- + str(connaddr) + '\n') -- handler = self.ConnectionHandler(self, newconn) -+ + repr(connaddr) + '\n') -+ handler = self.ConnectionHandler(self, newconn, connaddr) - handler.start() - handler.join() - except socket.timeout: -@@ -648,11 +1726,12 @@ else: - class ConnectionHandler(asyncore.dispatcher_with_send): - - def __init__(self, conn, certfile): -- asyncore.dispatcher_with_send.__init__(self, conn) - self.socket = ssl.wrap_socket(conn, server_side=True, - certfile=certfile, - do_handshake_on_connect=False) -+ asyncore.dispatcher_with_send.__init__(self, self.socket) - self._ssl_accepting = True -+ self._do_ssl_handshake() - - def readable(self): - if isinstance(self.socket, ssl.SSLSocket): -@@ -663,12 +1742,11 @@ else: - def _do_ssl_handshake(self): - try: - self.socket.do_handshake() -- except ssl.SSLError, err: -- if err.args[0] in (ssl.SSL_ERROR_WANT_READ, -- ssl.SSL_ERROR_WANT_WRITE): -- return -- elif err.args[0] == ssl.SSL_ERROR_EOF: -- return self.handle_close() -+ except (ssl.SSLWantReadError, ssl.SSLWantWriteError): -+ return -+ except ssl.SSLEOFError: -+ return self.handle_close() -+ except ssl.SSLError: - raise - except socket.error, err: - if err.args[0] == errno.ECONNABORTED: -@@ -681,12 +1759,16 @@ else: - self._do_ssl_handshake() - else: - data = self.recv(1024) -- if data and data.strip() != 'over': -+ if support.verbose: -+ sys.stdout.write(" server: read %s from client\n" % repr(data)) -+ if not data: -+ self.close() -+ else: - self.send(data.lower()) - - def handle_close(self): - self.close() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(" server: closed connection %s\n" % self.socket) - - def handle_error(self): -@@ -694,14 +1776,14 @@ else: - - def __init__(self, certfile): - self.certfile = certfile -- asyncore.dispatcher.__init__(self) -- self.create_socket(socket.AF_INET, socket.SOCK_STREAM) -- self.port = test_support.bind_port(self.socket) -+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -+ self.port = support.bind_port(sock, '') -+ asyncore.dispatcher.__init__(self, sock) - self.listen(5) - - def handle_accept(self): - sock_obj, addr = self.accept() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(" server: new connection from %s:%s\n" %addr) - self.ConnectionHandler(sock_obj, self.certfile) - -@@ -725,13 +1807,13 @@ else: - return self - - def __exit__(self, *args): -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(" cleanup: stopping server.\n") - self.stop() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(" cleanup: joining server thread.\n") - self.join() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(" cleanup: successfully joined.\n") - - def start(self, flag=None): -@@ -743,103 +1825,15 @@ else: - if self.flag: - self.flag.set() - while self.active: -- asyncore.loop(0.05) -+ try: -+ asyncore.loop(1) -+ except: -+ pass - - def stop(self): - self.active = False - self.server.close() - -- class SocketServerHTTPSServer(threading.Thread): -- -- class HTTPSServer(HTTPServer): -- -- def __init__(self, server_address, RequestHandlerClass, certfile): -- HTTPServer.__init__(self, server_address, RequestHandlerClass) -- # we assume the certfile contains both private key and certificate -- self.certfile = certfile -- self.allow_reuse_address = True -- -- def __str__(self): -- return ('<%s %s:%s>' % -- (self.__class__.__name__, -- self.server_name, -- self.server_port)) -- -- def get_request(self): -- # override this to wrap socket with SSL -- sock, addr = self.socket.accept() -- sslconn = ssl.wrap_socket(sock, server_side=True, -- certfile=self.certfile) -- return sslconn, addr -- -- class RootedHTTPRequestHandler(SimpleHTTPRequestHandler): -- # need to override translate_path to get a known root, -- # instead of using os.curdir, since the test could be -- # run from anywhere -- -- server_version = "TestHTTPS/1.0" -- -- root = None -- -- def translate_path(self, path): -- """Translate a /-separated PATH to the local filename syntax. -- -- Components that mean special things to the local file system -- (e.g. drive or directory names) are ignored. (XXX They should -- probably be diagnosed.) -- -- """ -- # abandon query parameters -- path = urlparse.urlparse(path)[2] -- path = os.path.normpath(urllib.unquote(path)) -- words = path.split('/') -- words = filter(None, words) -- path = self.root -- for word in words: -- drive, word = os.path.splitdrive(word) -- head, word = os.path.split(word) -- if word in self.root: continue -- path = os.path.join(path, word) -- return path -- -- def log_message(self, format, *args): -- -- # we override this to suppress logging unless "verbose" -- -- if test_support.verbose: -- sys.stdout.write(" server (%s:%d %s):\n [%s] %s\n" % -- (self.server.server_address, -- self.server.server_port, -- self.request.cipher(), -- self.log_date_time_string(), -- format%args)) -- -- -- def __init__(self, certfile): -- self.flag = None -- self.RootedHTTPRequestHandler.root = os.path.split(CERTFILE)[0] -- self.server = self.HTTPSServer( -- (HOST, 0), self.RootedHTTPRequestHandler, certfile) -- self.port = self.server.server_port -- threading.Thread.__init__(self) -- self.daemon = True -- -- def __str__(self): -- return "<%s %s>" % (self.__class__.__name__, self.server) -- -- def start(self, flag=None): -- self.flag = flag -- threading.Thread.start(self) -- -- def run(self): -- if self.flag: -- self.flag.set() -- self.server.serve_forever(0.05) -- -- def stop(self): -- self.server.shutdown() -- -- - def bad_cert_test(certfile): - """ - Launch a server with CERT_REQUIRED, and check that trying to -@@ -847,74 +1841,74 @@ else: - """ - server = ThreadedEchoServer(CERTFILE, - certreqs=ssl.CERT_REQUIRED, -- cacerts=CERTFILE, chatty=False) -+ cacerts=CERTFILE, chatty=False, -+ connectionchatty=False) - with server: - try: -- s = ssl.wrap_socket(socket.socket(), -- certfile=certfile, -- ssl_version=ssl.PROTOCOL_TLSv1) -- s.connect((HOST, server.port)) -- except ssl.SSLError, x: -- if test_support.verbose: -- sys.stdout.write("\nSSLError is %s\n" % x[1]) -- except socket.error, x: -- if test_support.verbose: -- sys.stdout.write("\nsocket.error is %s\n" % x[1]) -+ with closing(socket.socket()) as sock: -+ s = ssl.wrap_socket(sock, -+ certfile=certfile, -+ ssl_version=ssl.PROTOCOL_TLSv1) -+ s.connect((HOST, server.port)) -+ except ssl.SSLError as x: -+ if support.verbose: -+ sys.stdout.write("\nSSLError is %s\n" % x.args[1]) -+ except OSError as x: -+ if support.verbose: -+ sys.stdout.write("\nOSError is %s\n" % x.args[1]) -+ except OSError as x: -+ if x.errno != errno.ENOENT: -+ raise -+ if support.verbose: -+ sys.stdout.write("\OSError is %s\n" % str(x)) - else: - raise AssertionError("Use of invalid cert should have failed!") - -- def server_params_test(certfile, protocol, certreqs, cacertsfile, -- client_certfile, client_protocol=None, indata="FOO\n", -- ciphers=None, chatty=True, connectionchatty=False, -- wrap_accepting_socket=False): -+ def server_params_test(client_context, server_context, indata=b"FOO\n", -+ chatty=True, connectionchatty=False, sni_name=None): - """ - Launch a server, connect a client to it and try various reads - and writes. - """ -- server = ThreadedEchoServer(certfile, -- certreqs=certreqs, -- ssl_version=protocol, -- cacerts=cacertsfile, -- ciphers=ciphers, -+ stats = {} -+ server = ThreadedEchoServer(context=server_context, - chatty=chatty, -- connectionchatty=connectionchatty, -- wrap_accepting_socket=wrap_accepting_socket) -+ connectionchatty=False) - with server: -- # try to connect -- if client_protocol is None: -- client_protocol = protocol -- s = ssl.wrap_socket(socket.socket(), -- certfile=client_certfile, -- ca_certs=cacertsfile, -- ciphers=ciphers, -- cert_reqs=certreqs, -- ssl_version=client_protocol) -- s.connect((HOST, server.port)) -- for arg in [indata, bytearray(indata), memoryview(indata)]: -+ with closing(client_context.wrap_socket(socket.socket(), -+ server_hostname=sni_name)) as s: -+ s.connect((HOST, server.port)) -+ for arg in [indata, bytearray(indata), memoryview(indata)]: -+ if connectionchatty: -+ if support.verbose: -+ sys.stdout.write( -+ " client: sending %r...\n" % indata) -+ s.write(arg) -+ outdata = s.read() -+ if connectionchatty: -+ if support.verbose: -+ sys.stdout.write(" client: read %r\n" % outdata) -+ if outdata != indata.lower(): -+ raise AssertionError( -+ "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n" -+ % (outdata[:20], len(outdata), -+ indata[:20].lower(), len(indata))) -+ s.write(b"over\n") - if connectionchatty: -- if test_support.verbose: -- sys.stdout.write( -- " client: sending %s...\n" % (repr(arg))) -- s.write(arg) -- outdata = s.read() -- if connectionchatty: -- if test_support.verbose: -- sys.stdout.write(" client: read %s\n" % repr(outdata)) -- if outdata != indata.lower(): -- raise AssertionError( -- "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n" -- % (outdata[:min(len(outdata),20)], len(outdata), -- indata[:min(len(indata),20)].lower(), len(indata))) -- s.write("over\n") -- if connectionchatty: -- if test_support.verbose: -- sys.stdout.write(" client: closing connection.\n") -- s.close() -+ if support.verbose: -+ sys.stdout.write(" client: closing connection.\n") -+ stats.update({ -+ 'compression': s.compression(), -+ 'cipher': s.cipher(), -+ 'peercert': s.getpeercert(), -+ 'client_npn_protocol': s.selected_npn_protocol() -+ }) -+ s.close() -+ stats['server_npn_protocols'] = server.selected_protocols -+ return stats - -- def try_protocol_combo(server_protocol, -- client_protocol, -- expect_success, -- certsreqs=None): -+ def try_protocol_combo(server_protocol, client_protocol, expect_success, -+ certsreqs=None, server_options=0, client_options=0): - if certsreqs is None: - certsreqs = ssl.CERT_NONE - certtype = { -@@ -922,19 +1916,30 @@ else: - ssl.CERT_OPTIONAL: "CERT_OPTIONAL", - ssl.CERT_REQUIRED: "CERT_REQUIRED", - }[certsreqs] -- if test_support.verbose: -+ if support.verbose: - formatstr = (expect_success and " %s->%s %s\n") or " {%s->%s} %s\n" - sys.stdout.write(formatstr % - (ssl.get_protocol_name(client_protocol), - ssl.get_protocol_name(server_protocol), - certtype)) -+ client_context = ssl.SSLContext(client_protocol) -+ client_context.options |= client_options -+ server_context = ssl.SSLContext(server_protocol) -+ server_context.options |= server_options -+ -+ # NOTE: we must enable "ALL" ciphers on the client, otherwise an -+ # SSLv23 client will send an SSLv3 hello (rather than SSLv2) -+ # starting from OpenSSL 1.0.0 (see issue #8322). -+ if client_context.protocol == ssl.PROTOCOL_SSLv23: -+ client_context.set_ciphers("ALL") -+ -+ for ctx in (client_context, server_context): -+ ctx.verify_mode = certsreqs -+ ctx.load_cert_chain(CERTFILE) -+ ctx.load_verify_locations(CERTFILE) - try: -- # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client -- # will send an SSLv3 hello (rather than SSLv2) starting from -- # OpenSSL 1.0.0 (see issue #8322). -- server_params_test(CERTFILE, server_protocol, certsreqs, -- CERTFILE, CERTFILE, client_protocol, -- ciphers="ALL", chatty=False) -+ server_params_test(client_context, server_context, -+ chatty=False, connectionchatty=False) - # Protocol mismatch can result in either an SSLError, or a - # "Connection reset by peer" error. - except ssl.SSLError: -@@ -953,75 +1958,38 @@ else: - - class ThreadedTests(unittest.TestCase): - -- def test_rude_shutdown(self): -- """A brutal shutdown of an SSL server should raise an IOError -- in the client when attempting handshake. -- """ -- listener_ready = threading.Event() -- listener_gone = threading.Event() -- -- s = socket.socket() -- port = test_support.bind_port(s, HOST) -- -- # `listener` runs in a thread. It sits in an accept() until -- # the main thread connects. Then it rudely closes the socket, -- # and sets Event `listener_gone` to let the main thread know -- # the socket is gone. -- def listener(): -- s.listen(5) -- listener_ready.set() -- s.accept() -- s.close() -- listener_gone.set() -- -- def connector(): -- listener_ready.wait() -- c = socket.socket() -- c.connect((HOST, port)) -- listener_gone.wait() -- try: -- ssl_sock = ssl.wrap_socket(c) -- except IOError: -- pass -- else: -- self.fail('connecting to closed SSL socket should have failed') -- -- t = threading.Thread(target=listener) -- t.start() -- try: -- connector() -- finally: -- t.join() -- - @skip_if_broken_ubuntu_ssl - def test_echo(self): - """Basic test of an SSL client connecting to a server""" -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") -- server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE, -- CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1, -- chatty=True, connectionchatty=True) -+ for protocol in PROTOCOLS: -+ context = ssl.SSLContext(protocol) -+ context.load_cert_chain(CERTFILE) -+ server_params_test(context, context, -+ chatty=True, connectionchatty=True) - - def test_getpeercert(self): -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") -- s2 = socket.socket() -- server = ThreadedEchoServer(CERTFILE, -- certreqs=ssl.CERT_NONE, -- ssl_version=ssl.PROTOCOL_SSLv23, -- cacerts=CERTFILE, -- chatty=False) -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.load_verify_locations(CERTFILE) -+ context.load_cert_chain(CERTFILE) -+ server = ThreadedEchoServer(context=context, chatty=False) - with server: -- s = ssl.wrap_socket(socket.socket(), -- certfile=CERTFILE, -- ca_certs=CERTFILE, -- cert_reqs=ssl.CERT_REQUIRED, -- ssl_version=ssl.PROTOCOL_SSLv23) -+ s = context.wrap_socket(socket.socket(), -+ do_handshake_on_connect=False) - s.connect((HOST, server.port)) -+ # getpeercert() raise ValueError while the handshake isn't -+ # done. -+ with self.assertRaises(ValueError): -+ s.getpeercert() -+ s.do_handshake() - cert = s.getpeercert() - self.assertTrue(cert, "Can't get peer certificate.") - cipher = s.cipher() -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write(pprint.pformat(cert) + '\n') - sys.stdout.write("Connection cipher is " + str(cipher) + '.\n') - if 'subject' not in cert: -@@ -1032,8 +2000,94 @@ else: - self.fail( - "Missing or invalid 'organizationName' field in certificate subject; " - "should be 'Python Software Foundation'.") -+ self.assertIn('notBefore', cert) -+ self.assertIn('notAfter', cert) -+ before = ssl.cert_time_to_seconds(cert['notBefore']) -+ after = ssl.cert_time_to_seconds(cert['notAfter']) -+ self.assertLess(before, after) - s.close() - -+ @unittest.skipUnless(have_verify_flags(), -+ "verify_flags need OpenSSL > 0.9.8") -+ def test_crl_check(self): -+ if support.verbose: -+ sys.stdout.write("\n") -+ -+ server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ server_context.load_cert_chain(SIGNED_CERTFILE) -+ -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.load_verify_locations(SIGNING_CA) -+ self.assertEqual(context.verify_flags, ssl.VERIFY_DEFAULT) -+ -+ # VERIFY_DEFAULT should pass -+ server = ThreadedEchoServer(context=server_context, chatty=True) -+ with server: -+ with closing(context.wrap_socket(socket.socket())) as s: -+ s.connect((HOST, server.port)) -+ cert = s.getpeercert() -+ self.assertTrue(cert, "Can't get peer certificate.") -+ -+ # VERIFY_CRL_CHECK_LEAF without a loaded CRL file fails -+ context.verify_flags |= ssl.VERIFY_CRL_CHECK_LEAF -+ -+ server = ThreadedEchoServer(context=server_context, chatty=True) -+ with server: -+ with closing(context.wrap_socket(socket.socket())) as s: -+ with self.assertRaisesRegexp(ssl.SSLError, -+ "certificate verify failed"): -+ s.connect((HOST, server.port)) -+ -+ # now load a CRL file. The CRL file is signed by the CA. -+ context.load_verify_locations(CRLFILE) -+ -+ server = ThreadedEchoServer(context=server_context, chatty=True) -+ with server: -+ with closing(context.wrap_socket(socket.socket())) as s: -+ s.connect((HOST, server.port)) -+ cert = s.getpeercert() -+ self.assertTrue(cert, "Can't get peer certificate.") -+ -+ @needs_sni -+ def test_check_hostname(self): -+ if support.verbose: -+ sys.stdout.write("\n") -+ -+ server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ server_context.load_cert_chain(SIGNED_CERTFILE) -+ -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.check_hostname = True -+ context.load_verify_locations(SIGNING_CA) -+ -+ # correct hostname should verify -+ server = ThreadedEchoServer(context=server_context, chatty=True) -+ with server: -+ with closing(context.wrap_socket(socket.socket(), -+ server_hostname="localhost")) as s: -+ s.connect((HOST, server.port)) -+ cert = s.getpeercert() -+ self.assertTrue(cert, "Can't get peer certificate.") -+ -+ # incorrect hostname should raise an exception -+ server = ThreadedEchoServer(context=server_context, chatty=True) -+ with server: -+ with closing(context.wrap_socket(socket.socket(), -+ server_hostname="invalid")) as s: -+ with self.assertRaisesRegexp(ssl.CertificateError, -+ "hostname 'invalid' doesn't match u?'localhost'"): -+ s.connect((HOST, server.port)) -+ -+ # missing server_hostname arg should cause an exception, too -+ server = ThreadedEchoServer(context=server_context, chatty=True) -+ with server: -+ with closing(socket.socket()) as s: -+ with self.assertRaisesRegexp(ValueError, -+ "check_hostname requires server_hostname"): -+ context.wrap_socket(s) -+ - def test_empty_cert(self): - """Connecting with an empty cert file""" - bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir, -@@ -1051,25 +2105,84 @@ else: - bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir, - "badkey.pem")) - -+ def test_rude_shutdown(self): -+ """A brutal shutdown of an SSL server should raise an OSError -+ in the client when attempting handshake. -+ """ -+ listener_ready = threading.Event() -+ listener_gone = threading.Event() -+ -+ s = socket.socket() -+ port = support.bind_port(s, HOST) -+ -+ # `listener` runs in a thread. It sits in an accept() until -+ # the main thread connects. Then it rudely closes the socket, -+ # and sets Event `listener_gone` to let the main thread know -+ # the socket is gone. -+ def listener(): -+ s.listen(5) -+ listener_ready.set() -+ newsock, addr = s.accept() -+ newsock.close() -+ s.close() -+ listener_gone.set() -+ -+ def connector(): -+ listener_ready.wait() -+ with closing(socket.socket()) as c: -+ c.connect((HOST, port)) -+ listener_gone.wait() -+ try: -+ ssl_sock = ssl.wrap_socket(c) -+ except ssl.SSLError: -+ pass -+ else: -+ self.fail('connecting to closed SSL socket should have failed') -+ -+ t = threading.Thread(target=listener) -+ t.start() -+ try: -+ connector() -+ finally: -+ t.join() -+ - @skip_if_broken_ubuntu_ssl -+ @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'), -+ "OpenSSL is compiled without SSLv2 support") - def test_protocol_sslv2(self): - """Connecting to an SSLv2 server with various client options""" -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") -- if not hasattr(ssl, 'PROTOCOL_SSLv2'): -- self.skipTest("PROTOCOL_SSLv2 needed") - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED) -- try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False) -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False) -+ # SSLv23 client with specific SSL options -+ if no_sslv2_implies_sslv3_hello(): -+ # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_SSLv2) -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_SSLv3) -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_TLSv1) - - @skip_if_broken_ubuntu_ssl - def test_protocol_sslv23(self): - """Connecting to an SSLv23 server with various client options""" -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") -+ if hasattr(ssl, 'PROTOCOL_SSLv2'): -+ try: -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True) -+ except socket.error as x: -+ # this fails on some older versions of OpenSSL (0.9.7l, for instance) -+ if support.verbose: -+ sys.stdout.write( -+ " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n" -+ % str(x)) - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True) - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True) - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True) -@@ -1082,22 +2195,38 @@ else: - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED) - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) - -+ # Server with specific SSL options -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, -+ server_options=ssl.OP_NO_SSLv3) -+ # Will choose TLSv1 -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, -+ server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3) -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False, -+ server_options=ssl.OP_NO_TLSv1) -+ -+ - @skip_if_broken_ubuntu_ssl - def test_protocol_sslv3(self): - """Connecting to an SSLv3 server with various client options""" -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True) - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) - if hasattr(ssl, 'PROTOCOL_SSLv2'): - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False) -+ try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_SSLv3) - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False) -+ if no_sslv2_implies_sslv3_hello(): -+ # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs -+ try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True, -+ client_options=ssl.OP_NO_SSLv2) - - @skip_if_broken_ubuntu_ssl - def test_protocol_tlsv1(self): - """Connecting to a TLSv1 server with various client options""" -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True) - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) -@@ -1105,10 +2234,55 @@ else: - if hasattr(ssl, 'PROTOCOL_SSLv2'): - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False) - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_TLSv1) -+ -+ @skip_if_broken_ubuntu_ssl -+ @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"), -+ "TLS version 1.1 not supported.") -+ def test_protocol_tlsv1_1(self): -+ """Connecting to a TLSv1.1 server with various client options. -+ Testing against older TLS versions.""" -+ if support.verbose: -+ sys.stdout.write("\n") -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True) -+ if hasattr(ssl, 'PROTOCOL_SSLv2'): -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_TLSv1_1) -+ -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False) -+ -+ -+ @skip_if_broken_ubuntu_ssl -+ @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"), -+ "TLS version 1.2 not supported.") -+ def test_protocol_tlsv1_2(self): -+ """Connecting to a TLSv1.2 server with various client options. -+ Testing against older TLS versions.""" -+ if support.verbose: -+ sys.stdout.write("\n") -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True, -+ server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2, -+ client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,) -+ if hasattr(ssl, 'PROTOCOL_SSLv2'): -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_TLSv1_2) -+ -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False) - - def test_starttls(self): - """Switching from clear text to encrypted and back again.""" -- msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6") -+ msgs = (b"msg 1", b"MSG 2", b"STARTTLS", b"MSG 3", b"msg 4", b"ENDTLS", b"msg 5", b"msg 6") - - server = ThreadedEchoServer(CERTFILE, - ssl_version=ssl.PROTOCOL_TLSv1, -@@ -1120,119 +2294,109 @@ else: - s = socket.socket() - s.setblocking(1) - s.connect((HOST, server.port)) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") - for indata in msgs: -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write( -- " client: sending %s...\n" % repr(indata)) -+ " client: sending %r...\n" % indata) - if wrapped: - conn.write(indata) - outdata = conn.read() - else: - s.send(indata) - outdata = s.recv(1024) -- if (indata == "STARTTLS" and -- outdata.strip().lower().startswith("ok")): -+ msg = outdata.strip().lower() -+ if indata == b"STARTTLS" and msg.startswith(b"ok"): - # STARTTLS ok, switch to secure mode -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write( -- " client: read %s from server, starting TLS...\n" -- % repr(outdata)) -+ " client: read %r from server, starting TLS...\n" -+ % msg) - conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1) - wrapped = True -- elif (indata == "ENDTLS" and -- outdata.strip().lower().startswith("ok")): -+ elif indata == b"ENDTLS" and msg.startswith(b"ok"): - # ENDTLS ok, switch back to clear text -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write( -- " client: read %s from server, ending TLS...\n" -- % repr(outdata)) -+ " client: read %r from server, ending TLS...\n" -+ % msg) - s = conn.unwrap() - wrapped = False - else: -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write( -- " client: read %s from server\n" % repr(outdata)) -- if test_support.verbose: -+ " client: read %r from server\n" % msg) -+ if support.verbose: - sys.stdout.write(" client: closing connection.\n") - if wrapped: -- conn.write("over\n") -+ conn.write(b"over\n") - else: -- s.send("over\n") -- s.close() -+ s.send(b"over\n") -+ if wrapped: -+ conn.close() -+ else: -+ s.close() - - def test_socketserver(self): - """Using a SocketServer to create and manage SSL connections.""" -- server = SocketServerHTTPSServer(CERTFILE) -- flag = threading.Event() -- server.start(flag) -- # wait for it to start -- flag.wait() -+ server = make_https_server(self, certfile=CERTFILE) - # try to connect -+ if support.verbose: -+ sys.stdout.write('\n') -+ with open(CERTFILE, 'rb') as f: -+ d1 = f.read() -+ d2 = '' -+ # now fetch the same data from the HTTPS server -+ url = 'https://%s:%d/%s' % ( -+ HOST, server.port, os.path.split(CERTFILE)[1]) -+ f = urllib.urlopen(url) - try: -- if test_support.verbose: -- sys.stdout.write('\n') -- with open(CERTFILE, 'rb') as f: -- d1 = f.read() -- d2 = '' -- # now fetch the same data from the HTTPS server -- url = 'https://127.0.0.1:%d/%s' % ( -- server.port, os.path.split(CERTFILE)[1]) -- with test_support.check_py3k_warnings(): -- f = urllib.urlopen(url) - dlen = f.info().getheader("content-length") - if dlen and (int(dlen) > 0): - d2 = f.read(int(dlen)) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write( - " client: read %d bytes from remote server '%s'\n" - % (len(d2), server)) -+ finally: - f.close() -- self.assertEqual(d1, d2) -- finally: -- server.stop() -- server.join() -- -- def test_wrapped_accept(self): -- """Check the accept() method on SSL sockets.""" -- if test_support.verbose: -- sys.stdout.write("\n") -- server_params_test(CERTFILE, ssl.PROTOCOL_SSLv23, ssl.CERT_REQUIRED, -- CERTFILE, CERTFILE, ssl.PROTOCOL_SSLv23, -- chatty=True, connectionchatty=True, -- wrap_accepting_socket=True) -+ self.assertEqual(d1, d2) - - def test_asyncore_server(self): - """Check the example asyncore integration.""" - indata = "TEST MESSAGE of mixed case\n" - -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") -+ -+ indata = b"FOO\n" - server = AsyncoreEchoServer(CERTFILE) - with server: - s = ssl.wrap_socket(socket.socket()) - s.connect(('127.0.0.1', server.port)) -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write( -- " client: sending %s...\n" % (repr(indata))) -+ " client: sending %r...\n" % indata) - s.write(indata) - outdata = s.read() -- if test_support.verbose: -- sys.stdout.write(" client: read %s\n" % repr(outdata)) -+ if support.verbose: -+ sys.stdout.write(" client: read %r\n" % outdata) - if outdata != indata.lower(): - self.fail( -- "bad data <<%s>> (%d) received; expected <<%s>> (%d)\n" -- % (outdata[:min(len(outdata),20)], len(outdata), -- indata[:min(len(indata),20)].lower(), len(indata))) -- s.write("over\n") -- if test_support.verbose: -+ "bad data <<%r>> (%d) received; expected <<%r>> (%d)\n" -+ % (outdata[:20], len(outdata), -+ indata[:20].lower(), len(indata))) -+ s.write(b"over\n") -+ if support.verbose: - sys.stdout.write(" client: closing connection.\n") - s.close() -+ if support.verbose: -+ sys.stdout.write(" client: connection closed.\n") - - def test_recv_send(self): - """Test recv(), send() and friends.""" -- if test_support.verbose: -+ if support.verbose: - sys.stdout.write("\n") - - server = ThreadedEchoServer(CERTFILE, -@@ -1251,12 +2415,12 @@ else: - s.connect((HOST, server.port)) - # helper methods for standardising recv* method signatures - def _recv_into(): -- b = bytearray("\0"*100) -+ b = bytearray(b"\0"*100) - count = s.recv_into(b) - return b[:count] - - def _recvfrom_into(): -- b = bytearray("\0"*100) -+ b = bytearray(b"\0"*100) - count, addr = s.recvfrom_into(b) - return b[:count] - -@@ -1275,73 +2439,73 @@ else: - data_prefix = u"PREFIX_" - - for meth_name, send_meth, expect_success, args in send_methods: -- indata = data_prefix + meth_name -+ indata = (data_prefix + meth_name).encode('ascii') - try: -- send_meth(indata.encode('ASCII', 'strict'), *args) -+ send_meth(indata, *args) - outdata = s.read() -- outdata = outdata.decode('ASCII', 'strict') - if outdata != indata.lower(): - self.fail( -- "While sending with <<%s>> bad data " -- "<<%r>> (%d) received; " -- "expected <<%r>> (%d)\n" % ( -- meth_name, outdata[:20], len(outdata), -- indata[:20], len(indata) -+ "While sending with <<{name:s}>> bad data " -+ "<<{outdata:r}>> ({nout:d}) received; " -+ "expected <<{indata:r}>> ({nin:d})\n".format( -+ name=meth_name, outdata=outdata[:20], -+ nout=len(outdata), -+ indata=indata[:20], nin=len(indata) - ) - ) - except ValueError as e: - if expect_success: - self.fail( -- "Failed to send with method <<%s>>; " -- "expected to succeed.\n" % (meth_name,) -+ "Failed to send with method <<{name:s}>>; " -+ "expected to succeed.\n".format(name=meth_name) - ) - if not str(e).startswith(meth_name): - self.fail( -- "Method <<%s>> failed with unexpected " -- "exception message: %s\n" % ( -- meth_name, e -+ "Method <<{name:s}>> failed with unexpected " -+ "exception message: {exp:s}\n".format( -+ name=meth_name, exp=e - ) - ) - - for meth_name, recv_meth, expect_success, args in recv_methods: -- indata = data_prefix + meth_name -+ indata = (data_prefix + meth_name).encode('ascii') - try: -- s.send(indata.encode('ASCII', 'strict')) -+ s.send(indata) - outdata = recv_meth(*args) -- outdata = outdata.decode('ASCII', 'strict') - if outdata != indata.lower(): - self.fail( -- "While receiving with <<%s>> bad data " -- "<<%r>> (%d) received; " -- "expected <<%r>> (%d)\n" % ( -- meth_name, outdata[:20], len(outdata), -- indata[:20], len(indata) -+ "While receiving with <<{name:s}>> bad data " -+ "<<{outdata:r}>> ({nout:d}) received; " -+ "expected <<{indata:r}>> ({nin:d})\n".format( -+ name=meth_name, outdata=outdata[:20], -+ nout=len(outdata), -+ indata=indata[:20], nin=len(indata) - ) - ) - except ValueError as e: - if expect_success: - self.fail( -- "Failed to receive with method <<%s>>; " -- "expected to succeed.\n" % (meth_name,) -+ "Failed to receive with method <<{name:s}>>; " -+ "expected to succeed.\n".format(name=meth_name) - ) - if not str(e).startswith(meth_name): - self.fail( -- "Method <<%s>> failed with unexpected " -- "exception message: %s\n" % ( -- meth_name, e -+ "Method <<{name:s}>> failed with unexpected " -+ "exception message: {exp:s}\n".format( -+ name=meth_name, exp=e - ) - ) - # consume data - s.read() - -- s.write("over\n".encode("ASCII", "strict")) -+ s.write(b"over\n") - s.close() - - def test_handshake_timeout(self): - # Issue #5103: SSL handshake must respect the socket timeout - server = socket.socket(socket.AF_INET) - host = "127.0.0.1" -- port = test_support.bind_port(server) -+ port = support.bind_port(server) - started = threading.Event() - finish = False - -@@ -1355,6 +2519,8 @@ else: - # Let the socket hang around rather than having - # it closed by garbage collection. - conns.append(server.accept()[0]) -+ for sock in conns: -+ sock.close() - - t = threading.Thread(target=serve) - t.start() -@@ -1372,8 +2538,8 @@ else: - c.close() - try: - c = socket.socket(socket.AF_INET) -+ c = ssl.wrap_socket(c) - c.settimeout(0.2) -- c = ssl.wrap_socket(c) - # Will attempt handshake and time out - self.assertRaisesRegexp(ssl.SSLError, "timed out", - c.connect, (host, port)) -@@ -1384,59 +2550,384 @@ else: - t.join() - server.close() - -+ def test_server_accept(self): -+ # Issue #16357: accept() on a SSLSocket created through -+ # SSLContext.wrap_socket(). -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.load_verify_locations(CERTFILE) -+ context.load_cert_chain(CERTFILE) -+ server = socket.socket(socket.AF_INET) -+ host = "127.0.0.1" -+ port = support.bind_port(server) -+ server = context.wrap_socket(server, server_side=True) -+ -+ evt = threading.Event() -+ remote = [None] -+ peer = [None] -+ def serve(): -+ server.listen(5) -+ # Block on the accept and wait on the connection to close. -+ evt.set() -+ remote[0], peer[0] = server.accept() -+ remote[0].recv(1) -+ -+ t = threading.Thread(target=serve) -+ t.start() -+ # Client wait until server setup and perform a connect. -+ evt.wait() -+ client = context.wrap_socket(socket.socket()) -+ client.connect((host, port)) -+ client_addr = client.getsockname() -+ client.close() -+ t.join() -+ remote[0].close() -+ server.close() -+ # Sanity checks. -+ self.assertIsInstance(remote[0], ssl.SSLSocket) -+ self.assertEqual(peer[0], client_addr) -+ -+ def test_getpeercert_enotconn(self): -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ with closing(context.wrap_socket(socket.socket())) as sock: -+ with self.assertRaises(socket.error) as cm: -+ sock.getpeercert() -+ self.assertEqual(cm.exception.errno, errno.ENOTCONN) -+ -+ def test_do_handshake_enotconn(self): -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ with closing(context.wrap_socket(socket.socket())) as sock: -+ with self.assertRaises(socket.error) as cm: -+ sock.do_handshake() -+ self.assertEqual(cm.exception.errno, errno.ENOTCONN) -+ - def test_default_ciphers(self): -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ try: -+ # Force a set of weak ciphers on our client context -+ context.set_ciphers("DES") -+ except ssl.SSLError: -+ self.skipTest("no DES cipher available") - with ThreadedEchoServer(CERTFILE, - ssl_version=ssl.PROTOCOL_SSLv23, - chatty=False) as server: -- sock = socket.socket() -- try: -- # Force a set of weak ciphers on our client socket -- try: -- s = ssl.wrap_socket(sock, -- ssl_version=ssl.PROTOCOL_SSLv23, -- ciphers="DES") -- except ssl.SSLError: -- self.skipTest("no DES cipher available") -- with self.assertRaises((OSError, ssl.SSLError)): -+ with closing(context.wrap_socket(socket.socket())) as s: -+ with self.assertRaises(ssl.SSLError): - s.connect((HOST, server.port)) -- finally: -- sock.close() - self.assertIn("no shared cipher", str(server.conn_errors[0])) - -+ @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL") -+ def test_default_ecdh_curve(self): -+ # Issue #21015: elliptic curve-based Diffie Hellman key exchange -+ # should be enabled by default on SSL contexts. -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ context.load_cert_chain(CERTFILE) -+ # Prior to OpenSSL 1.0.0, ECDH ciphers have to be enabled -+ # explicitly using the 'ECCdraft' cipher alias. Otherwise, -+ # our default cipher list should prefer ECDH-based ciphers -+ # automatically. -+ if ssl.OPENSSL_VERSION_INFO < (1, 0, 0): -+ context.set_ciphers("ECCdraft:ECDH") -+ with ThreadedEchoServer(context=context) as server: -+ with closing(context.wrap_socket(socket.socket())) as s: -+ s.connect((HOST, server.port)) -+ self.assertIn("ECDH", s.cipher()[0]) -+ -+ @unittest.skipUnless("tls-unique" in ssl.CHANNEL_BINDING_TYPES, -+ "'tls-unique' channel binding not available") -+ def test_tls_unique_channel_binding(self): -+ """Test tls-unique channel binding.""" -+ if support.verbose: -+ sys.stdout.write("\n") -+ -+ server = ThreadedEchoServer(CERTFILE, -+ certreqs=ssl.CERT_NONE, -+ ssl_version=ssl.PROTOCOL_TLSv1, -+ cacerts=CERTFILE, -+ chatty=True, -+ connectionchatty=False) -+ with server: -+ s = ssl.wrap_socket(socket.socket(), -+ server_side=False, -+ certfile=CERTFILE, -+ ca_certs=CERTFILE, -+ cert_reqs=ssl.CERT_NONE, -+ ssl_version=ssl.PROTOCOL_TLSv1) -+ s.connect((HOST, server.port)) -+ # get the data -+ cb_data = s.get_channel_binding("tls-unique") -+ if support.verbose: -+ sys.stdout.write(" got channel binding data: {0!r}\n" -+ .format(cb_data)) -+ -+ # check if it is sane -+ self.assertIsNotNone(cb_data) -+ self.assertEqual(len(cb_data), 12) # True for TLSv1 -+ -+ # and compare with the peers version -+ s.write(b"CB tls-unique\n") -+ peer_data_repr = s.read().strip() -+ self.assertEqual(peer_data_repr, -+ repr(cb_data).encode("us-ascii")) -+ s.close() -+ -+ # now, again -+ s = ssl.wrap_socket(socket.socket(), -+ server_side=False, -+ certfile=CERTFILE, -+ ca_certs=CERTFILE, -+ cert_reqs=ssl.CERT_NONE, -+ ssl_version=ssl.PROTOCOL_TLSv1) -+ s.connect((HOST, server.port)) -+ new_cb_data = s.get_channel_binding("tls-unique") -+ if support.verbose: -+ sys.stdout.write(" got another channel binding data: {0!r}\n" -+ .format(new_cb_data)) -+ # is it really unique -+ self.assertNotEqual(cb_data, new_cb_data) -+ self.assertIsNotNone(cb_data) -+ self.assertEqual(len(cb_data), 12) # True for TLSv1 -+ s.write(b"CB tls-unique\n") -+ peer_data_repr = s.read().strip() -+ self.assertEqual(peer_data_repr, -+ repr(new_cb_data).encode("us-ascii")) -+ s.close() -+ -+ def test_compression(self): -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.load_cert_chain(CERTFILE) -+ stats = server_params_test(context, context, -+ chatty=True, connectionchatty=True) -+ if support.verbose: -+ sys.stdout.write(" got compression: {!r}\n".format(stats['compression'])) -+ self.assertIn(stats['compression'], { None, 'ZLIB', 'RLE' }) -+ -+ @unittest.skipUnless(hasattr(ssl, 'OP_NO_COMPRESSION'), -+ "ssl.OP_NO_COMPRESSION needed for this test") -+ def test_compression_disabled(self): -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.load_cert_chain(CERTFILE) -+ context.options |= ssl.OP_NO_COMPRESSION -+ stats = server_params_test(context, context, -+ chatty=True, connectionchatty=True) -+ self.assertIs(stats['compression'], None) -+ -+ def test_dh_params(self): -+ # Check we can get a connection with ephemeral Diffie-Hellman -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.load_cert_chain(CERTFILE) -+ context.load_dh_params(DHFILE) -+ context.set_ciphers("kEDH") -+ stats = server_params_test(context, context, -+ chatty=True, connectionchatty=True) -+ cipher = stats["cipher"][0] -+ parts = cipher.split("-") -+ if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts: -+ self.fail("Non-DH cipher: " + cipher[0]) -+ -+ def test_selected_npn_protocol(self): -+ # selected_npn_protocol() is None unless NPN is used -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.load_cert_chain(CERTFILE) -+ stats = server_params_test(context, context, -+ chatty=True, connectionchatty=True) -+ self.assertIs(stats['client_npn_protocol'], None) -+ -+ @unittest.skipUnless(ssl.HAS_NPN, "NPN support needed for this test") -+ def test_npn_protocols(self): -+ server_protocols = ['http/1.1', 'spdy/2'] -+ protocol_tests = [ -+ (['http/1.1', 'spdy/2'], 'http/1.1'), -+ (['spdy/2', 'http/1.1'], 'http/1.1'), -+ (['spdy/2', 'test'], 'spdy/2'), -+ (['abc', 'def'], 'abc') -+ ] -+ for client_protocols, expected in protocol_tests: -+ server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ server_context.load_cert_chain(CERTFILE) -+ server_context.set_npn_protocols(server_protocols) -+ client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ client_context.load_cert_chain(CERTFILE) -+ client_context.set_npn_protocols(client_protocols) -+ stats = server_params_test(client_context, server_context, -+ chatty=True, connectionchatty=True) -+ -+ msg = "failed trying %s (s) and %s (c).\n" \ -+ "was expecting %s, but got %%s from the %%s" \ -+ % (str(server_protocols), str(client_protocols), -+ str(expected)) -+ client_result = stats['client_npn_protocol'] -+ self.assertEqual(client_result, expected, msg % (client_result, "client")) -+ server_result = stats['server_npn_protocols'][-1] \ -+ if len(stats['server_npn_protocols']) else 'nothing' -+ self.assertEqual(server_result, expected, msg % (server_result, "server")) -+ -+ def sni_contexts(self): -+ server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ server_context.load_cert_chain(SIGNED_CERTFILE) -+ other_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ other_context.load_cert_chain(SIGNED_CERTFILE2) -+ client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ client_context.verify_mode = ssl.CERT_REQUIRED -+ client_context.load_verify_locations(SIGNING_CA) -+ return server_context, other_context, client_context -+ -+ def check_common_name(self, stats, name): -+ cert = stats['peercert'] -+ self.assertIn((('commonName', name),), cert['subject']) -+ -+ @needs_sni -+ def test_sni_callback(self): -+ calls = [] -+ server_context, other_context, client_context = self.sni_contexts() -+ -+ def servername_cb(ssl_sock, server_name, initial_context): -+ calls.append((server_name, initial_context)) -+ if server_name is not None: -+ ssl_sock.context = other_context -+ server_context.set_servername_callback(servername_cb) -+ -+ stats = server_params_test(client_context, server_context, -+ chatty=True, -+ sni_name='supermessage') -+ # The hostname was fetched properly, and the certificate was -+ # changed for the connection. -+ self.assertEqual(calls, [("supermessage", server_context)]) -+ # CERTFILE4 was selected -+ self.check_common_name(stats, 'fakehostname') -+ -+ calls = [] -+ # The callback is called with server_name=None -+ stats = server_params_test(client_context, server_context, -+ chatty=True, -+ sni_name=None) -+ self.assertEqual(calls, [(None, server_context)]) -+ self.check_common_name(stats, 'localhost') -+ -+ # Check disabling the callback -+ calls = [] -+ server_context.set_servername_callback(None) -+ -+ stats = server_params_test(client_context, server_context, -+ chatty=True, -+ sni_name='notfunny') -+ # Certificate didn't change -+ self.check_common_name(stats, 'localhost') -+ self.assertEqual(calls, []) -+ -+ @needs_sni -+ def test_sni_callback_alert(self): -+ # Returning a TLS alert is reflected to the connecting client -+ server_context, other_context, client_context = self.sni_contexts() -+ -+ def cb_returning_alert(ssl_sock, server_name, initial_context): -+ return ssl.ALERT_DESCRIPTION_ACCESS_DENIED -+ server_context.set_servername_callback(cb_returning_alert) -+ -+ with self.assertRaises(ssl.SSLError) as cm: -+ stats = server_params_test(client_context, server_context, -+ chatty=False, -+ sni_name='supermessage') -+ self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_ACCESS_DENIED') -+ -+ @needs_sni -+ def test_sni_callback_raising(self): -+ # Raising fails the connection with a TLS handshake failure alert. -+ server_context, other_context, client_context = self.sni_contexts() -+ -+ def cb_raising(ssl_sock, server_name, initial_context): -+ 1/0 -+ server_context.set_servername_callback(cb_raising) -+ -+ with self.assertRaises(ssl.SSLError) as cm, \ -+ support.captured_stderr() as stderr: -+ stats = server_params_test(client_context, server_context, -+ chatty=False, -+ sni_name='supermessage') -+ self.assertEqual(cm.exception.reason, 'SSLV3_ALERT_HANDSHAKE_FAILURE') -+ self.assertIn("ZeroDivisionError", stderr.getvalue()) -+ -+ @needs_sni -+ def test_sni_callback_wrong_return_type(self): -+ # Returning the wrong return type terminates the TLS connection -+ # with an internal error alert. -+ server_context, other_context, client_context = self.sni_contexts() -+ -+ def cb_wrong_return_type(ssl_sock, server_name, initial_context): -+ return "foo" -+ server_context.set_servername_callback(cb_wrong_return_type) -+ -+ with self.assertRaises(ssl.SSLError) as cm, \ -+ support.captured_stderr() as stderr: -+ stats = server_params_test(client_context, server_context, -+ chatty=False, -+ sni_name='supermessage') -+ self.assertEqual(cm.exception.reason, 'TLSV1_ALERT_INTERNAL_ERROR') -+ self.assertIn("TypeError", stderr.getvalue()) -+ -+ def test_read_write_after_close_raises_valuerror(self): -+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.load_verify_locations(CERTFILE) -+ context.load_cert_chain(CERTFILE) -+ server = ThreadedEchoServer(context=context, chatty=False) -+ -+ with server: -+ s = context.wrap_socket(socket.socket()) -+ s.connect((HOST, server.port)) -+ s.close() -+ -+ self.assertRaises(ValueError, s.read, 1024) -+ self.assertRaises(ValueError, s.write, b'hello') -+ - - def test_main(verbose=False): -- global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, NOKIACERT, NULLBYTECERT -- CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, -- "keycert.pem") -- SVN_PYTHON_ORG_ROOT_CERT = os.path.join( -- os.path.dirname(__file__) or os.curdir, -- "https_svn_python_org_root.pem") -- NOKIACERT = os.path.join(os.path.dirname(__file__) or os.curdir, -- "nokia.pem") -- NULLBYTECERT = os.path.join(os.path.dirname(__file__) or os.curdir, -- "nullbytecert.pem") -+ if support.verbose: -+ plats = { -+ 'Linux': platform.linux_distribution, -+ 'Mac': platform.mac_ver, -+ 'Windows': platform.win32_ver, -+ } -+ for name, func in plats.items(): -+ plat = func() -+ if plat and plat[0]: -+ plat = '%s %r' % (name, plat) -+ break -+ else: -+ plat = repr(platform.platform()) -+ print("test_ssl: testing with %r %r" % -+ (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO)) -+ print(" under %s" % plat) -+ print(" HAS_SNI = %r" % ssl.HAS_SNI) -+ print(" OP_ALL = 0x%8x" % ssl.OP_ALL) -+ try: -+ print(" OP_NO_TLSv1_1 = 0x%8x" % ssl.OP_NO_TLSv1_1) -+ except AttributeError: -+ pass - -- if (not os.path.exists(CERTFILE) or -- not os.path.exists(SVN_PYTHON_ORG_ROOT_CERT) or -- not os.path.exists(NOKIACERT) or -- not os.path.exists(NULLBYTECERT)): -- raise test_support.TestFailed("Can't read certificate files!") -+ for filename in [ -+ CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE, -+ ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY, -+ SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA, -+ BADCERT, BADKEY, EMPTYCERT]: -+ if not os.path.exists(filename): -+ raise support.TestFailed("Can't read certificate file %r" % filename) - -- tests = [BasicTests, BasicSocketTests] -+ tests = [ContextTests, BasicSocketTests, SSLErrorTests] - -- if test_support.is_resource_enabled('network'): -+ if support.is_resource_enabled('network'): - tests.append(NetworkedTests) - - if _have_threads: -- thread_info = test_support.threading_setup() -- if thread_info and test_support.is_resource_enabled('network'): -+ thread_info = support.threading_setup() -+ if thread_info: - tests.append(ThreadedTests) - - try: -- test_support.run_unittest(*tests) -+ support.run_unittest(*tests) - finally: - if _have_threads: -- test_support.threading_cleanup(*thread_info) -+ support.threading_cleanup(*thread_info) - - if __name__ == "__main__": - test_main() -diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py ---- a/Lib/test/test_support.py -+++ b/Lib/test/test_support.py -@@ -39,7 +39,7 @@ except ImportError: - "threading_cleanup", "reap_children", "cpython_only", - "check_impl_detail", "get_attribute", "py3k_bytes", - "import_fresh_module", "threading_cleanup", "reap_children", -- "strip_python_stderr"] -+ "strip_python_stderr", "IPV6_ENABLED"] - - class Error(Exception): - """Base class for regression test exceptions.""" -@@ -465,6 +465,23 @@ def bind_port(sock, host=HOST): - port = sock.getsockname()[1] - return port - -+def _is_ipv6_enabled(): -+ """Check whether IPv6 is enabled on this host.""" -+ if socket.has_ipv6: -+ sock = None -+ try: -+ sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) -+ sock.bind((HOSTv6, 0)) -+ return True -+ except OSError: -+ pass -+ finally: -+ if sock: -+ sock.close() -+ return False -+ -+IPV6_ENABLED = _is_ipv6_enabled() -+ - FUZZ = 1e-6 - - def fcmp(x, y): # fuzzy comparison function -diff --git a/Makefile.pre.in b/Makefile.pre.in ---- a/Makefile.pre.in -+++ b/Makefile.pre.in -@@ -930,8 +930,8 @@ PLATMACDIRS= plat-mac plat-mac/Carbon pl - plat-mac/lib-scriptpackages/Terminal - PLATMACPATH=:plat-mac:plat-mac/lib-scriptpackages - LIBSUBDIRS= lib-tk lib-tk/test lib-tk/test/test_tkinter \ -- lib-tk/test/test_ttk site-packages test test/audiodata test/data \ -- test/cjkencodings test/decimaltestdata test/xmltestdata \ -+ lib-tk/test/test_ttk site-packages test test/audiodata test/capath \ -+ test/data test/cjkencodings test/decimaltestdata test/xmltestdata \ - test/imghdrdata \ - test/subprocessdata \ - test/tracedmodules \ -diff --git a/Modules/_ssl.c b/Modules/_ssl.c ---- a/Modules/_ssl.c -+++ b/Modules/_ssl.c -@@ -14,22 +14,28 @@ - http://bugs.python.org/issue8108#msg102867 ? - */ - -+#define PY_SSIZE_T_CLEAN - #include "Python.h" - - #ifdef WITH_THREAD - #include "pythread.h" - - -+#define PySSL_BEGIN_ALLOW_THREADS_S(save) \ -+ do { if (_ssl_locks_count>0) { (save) = PyEval_SaveThread(); } } while (0) -+#define PySSL_END_ALLOW_THREADS_S(save) \ -+ do { if (_ssl_locks_count>0) { PyEval_RestoreThread(save); } } while (0) - #define PySSL_BEGIN_ALLOW_THREADS { \ - PyThreadState *_save = NULL; \ -- if (_ssl_locks_count>0) {_save = PyEval_SaveThread();} --#define PySSL_BLOCK_THREADS if (_ssl_locks_count>0){PyEval_RestoreThread(_save)}; --#define PySSL_UNBLOCK_THREADS if (_ssl_locks_count>0){_save = PyEval_SaveThread()}; --#define PySSL_END_ALLOW_THREADS if (_ssl_locks_count>0){PyEval_RestoreThread(_save);} \ -- } -+ PySSL_BEGIN_ALLOW_THREADS_S(_save); -+#define PySSL_BLOCK_THREADS PySSL_END_ALLOW_THREADS_S(_save); -+#define PySSL_UNBLOCK_THREADS PySSL_BEGIN_ALLOW_THREADS_S(_save); -+#define PySSL_END_ALLOW_THREADS PySSL_END_ALLOW_THREADS_S(_save); } - - #else /* no WITH_THREAD */ - -+#define PySSL_BEGIN_ALLOW_THREADS_S(save) -+#define PySSL_END_ALLOW_THREADS_S(save) - #define PySSL_BEGIN_ALLOW_THREADS - #define PySSL_BLOCK_THREADS - #define PySSL_UNBLOCK_THREADS -@@ -37,6 +43,68 @@ - - #endif - -+/* Include symbols from _socket module */ -+#include "socketmodule.h" -+ -+#if defined(HAVE_POLL_H) -+#include -+#elif defined(HAVE_SYS_POLL_H) -+#include -+#endif -+ -+/* Include OpenSSL header files */ -+#include "openssl/rsa.h" -+#include "openssl/crypto.h" -+#include "openssl/x509.h" -+#include "openssl/x509v3.h" -+#include "openssl/pem.h" -+#include "openssl/ssl.h" -+#include "openssl/err.h" -+#include "openssl/rand.h" -+ -+/* SSL error object */ -+static PyObject *PySSLErrorObject; -+static PyObject *PySSLZeroReturnErrorObject; -+static PyObject *PySSLWantReadErrorObject; -+static PyObject *PySSLWantWriteErrorObject; -+static PyObject *PySSLSyscallErrorObject; -+static PyObject *PySSLEOFErrorObject; -+ -+/* Error mappings */ -+static PyObject *err_codes_to_names; -+static PyObject *err_names_to_codes; -+static PyObject *lib_codes_to_names; -+ -+struct py_ssl_error_code { -+ const char *mnemonic; -+ int library, reason; -+}; -+struct py_ssl_library_code { -+ const char *library; -+ int code; -+}; -+ -+/* Include generated data (error codes) */ -+#include "_ssl_data.h" -+ -+/* Openssl comes with TLSv1.1 and TLSv1.2 between 1.0.0h and 1.0.1 -+ http://www.openssl.org/news/changelog.html -+ */ -+#if OPENSSL_VERSION_NUMBER >= 0x10001000L -+# define HAVE_TLSv1_2 1 -+#else -+# define HAVE_TLSv1_2 0 -+#endif -+ -+/* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f -+ * This includes the SSL_set_SSL_CTX() function. -+ */ -+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME -+# define HAVE_SNI 1 -+#else -+# define HAVE_SNI 0 -+#endif -+ - enum py_ssl_error { - /* these mirror ssl.h */ - PY_SSL_ERROR_NONE, -@@ -49,6 +117,7 @@ enum py_ssl_error { - PY_SSL_ERROR_WANT_CONNECT, - /* start of non ssl.h errorcodes */ - PY_SSL_ERROR_EOF, /* special case of SSL_ERROR_SYSCALL */ -+ PY_SSL_ERROR_NO_SOCKET, /* socket has been GC'd */ - PY_SSL_ERROR_INVALID_ERROR_CODE - }; - -@@ -64,36 +133,18 @@ enum py_ssl_cert_requirements { - }; - - enum py_ssl_version { --#ifndef OPENSSL_NO_SSL2 - PY_SSL_VERSION_SSL2, --#endif - PY_SSL_VERSION_SSL3=1, - PY_SSL_VERSION_SSL23, -+#if HAVE_TLSv1_2 -+ PY_SSL_VERSION_TLS1, -+ PY_SSL_VERSION_TLS1_1, -+ PY_SSL_VERSION_TLS1_2 -+#else - PY_SSL_VERSION_TLS1 -+#endif - }; - --/* Include symbols from _socket module */ --#include "socketmodule.h" -- --#if defined(HAVE_POLL_H) --#include --#elif defined(HAVE_SYS_POLL_H) --#include --#endif -- --/* Include OpenSSL header files */ --#include "openssl/rsa.h" --#include "openssl/crypto.h" --#include "openssl/x509.h" --#include "openssl/x509v3.h" --#include "openssl/pem.h" --#include "openssl/ssl.h" --#include "openssl/err.h" --#include "openssl/rand.h" -- --/* SSL error object */ --static PyObject *PySSLErrorObject; -- - #ifdef WITH_THREAD - - /* serves as a flag to see whether we've initialized the SSL thread support. */ -@@ -114,27 +165,79 @@ static unsigned int _ssl_locks_count = 0 - # undef HAVE_OPENSSL_RAND - #endif - -+/* SSL_CTX_clear_options() and SSL_clear_options() were first added in -+ * OpenSSL 0.9.8m but do not appear in some 0.9.9-dev versions such the -+ * 0.9.9 from "May 2008" that NetBSD 5.0 uses. */ -+#if OPENSSL_VERSION_NUMBER >= 0x009080dfL && OPENSSL_VERSION_NUMBER != 0x00909000L -+# define HAVE_SSL_CTX_CLEAR_OPTIONS -+#else -+# undef HAVE_SSL_CTX_CLEAR_OPTIONS -+#endif -+ -+/* In case of 'tls-unique' it will be 12 bytes for TLS, 36 bytes for -+ * older SSL, but let's be safe */ -+#define PySSL_CB_MAXLEN 128 -+ -+/* SSL_get_finished got added to OpenSSL in 0.9.5 */ -+#if OPENSSL_VERSION_NUMBER >= 0x0090500fL -+# define HAVE_OPENSSL_FINISHED 1 -+#else -+# define HAVE_OPENSSL_FINISHED 0 -+#endif -+ -+/* ECDH support got added to OpenSSL in 0.9.8 */ -+#if OPENSSL_VERSION_NUMBER < 0x0090800fL && !defined(OPENSSL_NO_ECDH) -+# define OPENSSL_NO_ECDH -+#endif -+ -+/* compression support got added to OpenSSL in 0.9.8 */ -+#if OPENSSL_VERSION_NUMBER < 0x0090800fL && !defined(OPENSSL_NO_COMP) -+# define OPENSSL_NO_COMP -+#endif -+ -+/* X509_VERIFY_PARAM got added to OpenSSL in 0.9.8 */ -+#if OPENSSL_VERSION_NUMBER >= 0x0090800fL -+# define HAVE_OPENSSL_VERIFY_PARAM -+#endif -+ -+ - typedef struct { - PyObject_HEAD -- PySocketSockObject *Socket; /* Socket on which we're layered */ -- SSL_CTX* ctx; -- SSL* ssl; -- X509* peer_cert; -- char server[X509_NAME_MAXLEN]; -- char issuer[X509_NAME_MAXLEN]; -- int shutdown_seen_zero; -- --} PySSLObject; -- --static PyTypeObject PySSL_Type; --static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args); --static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args); -+ SSL_CTX *ctx; -+#ifdef OPENSSL_NPN_NEGOTIATED -+ char *npn_protocols; -+ int npn_protocols_len; -+#endif -+#ifndef OPENSSL_NO_TLSEXT -+ PyObject *set_hostname; -+#endif -+ int check_hostname; -+} PySSLContext; -+ -+typedef struct { -+ PyObject_HEAD -+ PySocketSockObject *Socket; -+ PyObject *ssl_sock; -+ SSL *ssl; -+ PySSLContext *ctx; /* weakref to SSL context */ -+ X509 *peer_cert; -+ char shutdown_seen_zero; -+ char handshake_done; -+ enum py_ssl_server_or_client socket_type; -+} PySSLSocket; -+ -+static PyTypeObject PySSLContext_Type; -+static PyTypeObject PySSLSocket_Type; -+ -+static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args); -+static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args); - static int check_socket_and_wait_for_timeout(PySocketSockObject *s, - int writing); --static PyObject *PySSL_peercert(PySSLObject *self, PyObject *args); --static PyObject *PySSL_cipher(PySSLObject *self); -- --#define PySSLObject_Check(v) (Py_TYPE(v) == &PySSL_Type) -+static PyObject *PySSL_peercert(PySSLSocket *self, PyObject *args); -+static PyObject *PySSL_cipher(PySSLSocket *self); -+ -+#define PySSLContext_Check(v) (Py_TYPE(v) == &PySSLContext_Type) -+#define PySSLSocket_Check(v) (Py_TYPE(v) == &PySSLSocket_Type) - - typedef enum { - SOCKET_IS_NONBLOCKING, -@@ -151,36 +254,140 @@ typedef enum { - #define ERRSTR1(x,y,z) (x ":" y ": " z) - #define ERRSTR(x) ERRSTR1("_ssl.c", STRINGIFY2(__LINE__), x) - --/* XXX It might be helpful to augment the error message generated -- below with the name of the SSL function that generated the error. -- I expect it's obvious most of the time. --*/ -+ -+/* -+ * SSL errors. -+ */ -+ -+PyDoc_STRVAR(SSLError_doc, -+"An error occurred in the SSL implementation."); -+ -+PyDoc_STRVAR(SSLZeroReturnError_doc, -+"SSL/TLS session closed cleanly."); -+ -+PyDoc_STRVAR(SSLWantReadError_doc, -+"Non-blocking SSL socket needs to read more data\n" -+"before the requested operation can be completed."); -+ -+PyDoc_STRVAR(SSLWantWriteError_doc, -+"Non-blocking SSL socket needs to write more data\n" -+"before the requested operation can be completed."); -+ -+PyDoc_STRVAR(SSLSyscallError_doc, -+"System error when attempting SSL operation."); -+ -+PyDoc_STRVAR(SSLEOFError_doc, -+"SSL/TLS connection terminated abruptly."); -+ - - static PyObject * --PySSL_SetError(PySSLObject *obj, int ret, char *filename, int lineno) -+SSLError_str(PyEnvironmentErrorObject *self) - { -- PyObject *v; -- char buf[2048]; -- char *errstr; -+ if (self->strerror != NULL) { -+ Py_INCREF(self->strerror); -+ return self->strerror; -+ } -+ else -+ return PyObject_Str(self->args); -+} -+ -+static void -+fill_and_set_sslerror(PyObject *type, int ssl_errno, const char *errstr, -+ int lineno, unsigned long errcode) -+{ -+ PyObject *err_value = NULL, *reason_obj = NULL, *lib_obj = NULL; -+ PyObject *init_value, *msg, *key; -+ -+ if (errcode != 0) { -+ int lib, reason; -+ -+ lib = ERR_GET_LIB(errcode); -+ reason = ERR_GET_REASON(errcode); -+ key = Py_BuildValue("ii", lib, reason); -+ if (key == NULL) -+ goto fail; -+ reason_obj = PyDict_GetItem(err_codes_to_names, key); -+ Py_DECREF(key); -+ if (reason_obj == NULL) { -+ /* XXX if reason < 100, it might reflect a library number (!!) */ -+ PyErr_Clear(); -+ } -+ key = PyLong_FromLong(lib); -+ if (key == NULL) -+ goto fail; -+ lib_obj = PyDict_GetItem(lib_codes_to_names, key); -+ Py_DECREF(key); -+ if (lib_obj == NULL) { -+ PyErr_Clear(); -+ } -+ if (errstr == NULL) -+ errstr = ERR_reason_error_string(errcode); -+ } -+ if (errstr == NULL) -+ errstr = "unknown error"; -+ -+ if (reason_obj && lib_obj) -+ msg = PyUnicode_FromFormat("[%S: %S] %s (_ssl.c:%d)", -+ lib_obj, reason_obj, errstr, lineno); -+ else if (lib_obj) -+ msg = PyUnicode_FromFormat("[%S] %s (_ssl.c:%d)", -+ lib_obj, errstr, lineno); -+ else -+ msg = PyUnicode_FromFormat("%s (_ssl.c:%d)", errstr, lineno); -+ if (msg == NULL) -+ goto fail; -+ -+ init_value = Py_BuildValue("iN", ssl_errno, msg); -+ if (init_value == NULL) -+ goto fail; -+ -+ err_value = PyObject_CallObject(type, init_value); -+ Py_DECREF(init_value); -+ if (err_value == NULL) -+ goto fail; -+ -+ if (reason_obj == NULL) -+ reason_obj = Py_None; -+ if (PyObject_SetAttrString(err_value, "reason", reason_obj)) -+ goto fail; -+ if (lib_obj == NULL) -+ lib_obj = Py_None; -+ if (PyObject_SetAttrString(err_value, "library", lib_obj)) -+ goto fail; -+ PyErr_SetObject(type, err_value); -+fail: -+ Py_XDECREF(err_value); -+} -+ -+static PyObject * -+PySSL_SetError(PySSLSocket *obj, int ret, char *filename, int lineno) -+{ -+ PyObject *type = PySSLErrorObject; -+ char *errstr = NULL; - int err; - enum py_ssl_error p = PY_SSL_ERROR_NONE; -+ unsigned long e = 0; - - assert(ret <= 0); -+ e = ERR_peek_last_error(); - - if (obj->ssl != NULL) { - err = SSL_get_error(obj->ssl, ret); - - switch (err) { - case SSL_ERROR_ZERO_RETURN: -- errstr = "TLS/SSL connection has been closed"; -+ errstr = "TLS/SSL connection has been closed (EOF)"; -+ type = PySSLZeroReturnErrorObject; - p = PY_SSL_ERROR_ZERO_RETURN; - break; - case SSL_ERROR_WANT_READ: - errstr = "The operation did not complete (read)"; -+ type = PySSLWantReadErrorObject; - p = PY_SSL_ERROR_WANT_READ; - break; - case SSL_ERROR_WANT_WRITE: - p = PY_SSL_ERROR_WANT_WRITE; -+ type = PySSLWantWriteErrorObject; - errstr = "The operation did not complete (write)"; - break; - case SSL_ERROR_WANT_X509_LOOKUP: -@@ -193,213 +400,109 @@ PySSL_SetError(PySSLObject *obj, int ret - break; - case SSL_ERROR_SYSCALL: - { -- unsigned long e = ERR_get_error(); - if (e == 0) { -- if (ret == 0 || !obj->Socket) { -+ PySocketSockObject *s = obj->Socket; -+ if (ret == 0) { - p = PY_SSL_ERROR_EOF; -+ type = PySSLEOFErrorObject; - errstr = "EOF occurred in violation of protocol"; - } else if (ret == -1) { - /* underlying BIO reported an I/O error */ -+ Py_INCREF(s); - ERR_clear_error(); -- return obj->Socket->errorhandler(); -+ s->errorhandler(); -+ Py_DECREF(s); -+ return NULL; - } else { /* possible? */ - p = PY_SSL_ERROR_SYSCALL; -+ type = PySSLSyscallErrorObject; - errstr = "Some I/O error occurred"; - } - } else { - p = PY_SSL_ERROR_SYSCALL; -- /* XXX Protected by global interpreter lock */ -- errstr = ERR_error_string(e, NULL); - } - break; - } - case SSL_ERROR_SSL: - { -- unsigned long e = ERR_get_error(); - p = PY_SSL_ERROR_SSL; -- if (e != 0) -- /* XXX Protected by global interpreter lock */ -- errstr = ERR_error_string(e, NULL); -- else { /* possible? */ -+ if (e == 0) -+ /* possible? */ - errstr = "A failure in the SSL library occurred"; -- } - break; - } - default: - p = PY_SSL_ERROR_INVALID_ERROR_CODE; - errstr = "Invalid error code"; - } -- } else { -- errstr = ERR_error_string(ERR_peek_last_error(), NULL); - } -- PyOS_snprintf(buf, sizeof(buf), "_ssl.c:%d: %s", lineno, errstr); -+ fill_and_set_sslerror(type, p, errstr, lineno, e); - ERR_clear_error(); -- v = Py_BuildValue("(is)", p, buf); -- if (v != NULL) { -- PyErr_SetObject(PySSLErrorObject, v); -- Py_DECREF(v); -- } - return NULL; - } - - static PyObject * - _setSSLError (char *errstr, int errcode, char *filename, int lineno) { - -- char buf[2048]; -- PyObject *v; -- -- if (errstr == NULL) { -+ if (errstr == NULL) - errcode = ERR_peek_last_error(); -- errstr = ERR_error_string(errcode, NULL); -- } -- PyOS_snprintf(buf, sizeof(buf), "_ssl.c:%d: %s", lineno, errstr); -+ else -+ errcode = 0; -+ fill_and_set_sslerror(PySSLErrorObject, errcode, errstr, lineno, errcode); - ERR_clear_error(); -- v = Py_BuildValue("(is)", errcode, buf); -- if (v != NULL) { -- PyErr_SetObject(PySSLErrorObject, v); -- Py_DECREF(v); -- } - return NULL; - } - --static PySSLObject * --newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file, -+/* -+ * SSL objects -+ */ -+ -+static PySSLSocket * -+newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, - enum py_ssl_server_or_client socket_type, -- enum py_ssl_cert_requirements certreq, -- enum py_ssl_version proto_version, -- char *cacerts_file, char *ciphers) -+ char *server_hostname, PyObject *ssl_sock) - { -- PySSLObject *self; -- char *errstr = NULL; -- int ret; -- int verification_mode; -- long options; -- -- self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */ -+ PySSLSocket *self; -+ SSL_CTX *ctx = sslctx->ctx; -+ long mode; -+ -+ self = PyObject_New(PySSLSocket, &PySSLSocket_Type); - if (self == NULL) - return NULL; -- memset(self->server, '\0', sizeof(char) * X509_NAME_MAXLEN); -- memset(self->issuer, '\0', sizeof(char) * X509_NAME_MAXLEN); -+ - self->peer_cert = NULL; - self->ssl = NULL; -- self->ctx = NULL; - self->Socket = NULL; -+ self->ssl_sock = NULL; -+ self->ctx = sslctx; - self->shutdown_seen_zero = 0; -+ self->handshake_done = 0; -+ Py_INCREF(sslctx); - - /* Make sure the SSL error state is initialized */ - (void) ERR_get_state(); - ERR_clear_error(); - -- if ((key_file && !cert_file) || (!key_file && cert_file)) { -- errstr = ERRSTR("Both the key & certificate files " -- "must be specified"); -- goto fail; -- } -- -- if ((socket_type == PY_SSL_SERVER) && -- ((key_file == NULL) || (cert_file == NULL))) { -- errstr = ERRSTR("Both the key & certificate files " -- "must be specified for server-side operation"); -- goto fail; -- } -- - PySSL_BEGIN_ALLOW_THREADS -- if (proto_version == PY_SSL_VERSION_TLS1) -- self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ -- else if (proto_version == PY_SSL_VERSION_SSL3) -- self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ --#ifndef OPENSSL_NO_SSL2 -- else if (proto_version == PY_SSL_VERSION_SSL2) -- self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ -+ self->ssl = SSL_new(ctx); -+ PySSL_END_ALLOW_THREADS -+ SSL_set_app_data(self->ssl,self); -+ SSL_set_fd(self->ssl, Py_SAFE_DOWNCAST(sock->sock_fd, SOCKET_T, int)); -+ mode = SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; -+#ifdef SSL_MODE_AUTO_RETRY -+ mode |= SSL_MODE_AUTO_RETRY; - #endif -- else if (proto_version == PY_SSL_VERSION_SSL23) -- self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ -- PySSL_END_ALLOW_THREADS -- -- if (self->ctx == NULL) { -- errstr = ERRSTR("Invalid SSL protocol variant specified."); -- goto fail; -- } -- -- if (ciphers != NULL) { -- ret = SSL_CTX_set_cipher_list(self->ctx, ciphers); -- if (ret == 0) { -- errstr = ERRSTR("No cipher can be selected."); -- goto fail; -- } -- } -- -- if (certreq != PY_SSL_CERT_NONE) { -- if (cacerts_file == NULL) { -- errstr = ERRSTR("No root certificates specified for " -- "verification of other-side certificates."); -- goto fail; -- } else { -- PySSL_BEGIN_ALLOW_THREADS -- ret = SSL_CTX_load_verify_locations(self->ctx, -- cacerts_file, -- NULL); -- PySSL_END_ALLOW_THREADS -- if (ret != 1) { -- _setSSLError(NULL, 0, __FILE__, __LINE__); -- goto fail; -- } -- } -- } -- if (key_file) { -- PySSL_BEGIN_ALLOW_THREADS -- ret = SSL_CTX_use_PrivateKey_file(self->ctx, key_file, -- SSL_FILETYPE_PEM); -- PySSL_END_ALLOW_THREADS -- if (ret != 1) { -- _setSSLError(NULL, ret, __FILE__, __LINE__); -- goto fail; -- } -- -- PySSL_BEGIN_ALLOW_THREADS -- ret = SSL_CTX_use_certificate_chain_file(self->ctx, -- cert_file); -- PySSL_END_ALLOW_THREADS -- if (ret != 1) { -- /* -- fprintf(stderr, "ret is %d, errcode is %lu, %lu, with file \"%s\"\n", -- ret, ERR_peek_error(), ERR_peek_last_error(), cert_file); -- */ -- if (ERR_peek_last_error() != 0) { -- _setSSLError(NULL, ret, __FILE__, __LINE__); -- goto fail; -- } -- } -- } -- -- /* ssl compatibility */ -- options = SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; -- if (proto_version != PY_SSL_VERSION_SSL2) -- options |= SSL_OP_NO_SSLv2; -- SSL_CTX_set_options(self->ctx, options); -- -- verification_mode = SSL_VERIFY_NONE; -- if (certreq == PY_SSL_CERT_OPTIONAL) -- verification_mode = SSL_VERIFY_PEER; -- else if (certreq == PY_SSL_CERT_REQUIRED) -- verification_mode = (SSL_VERIFY_PEER | -- SSL_VERIFY_FAIL_IF_NO_PEER_CERT); -- SSL_CTX_set_verify(self->ctx, verification_mode, -- NULL); /* set verify lvl */ -- -- PySSL_BEGIN_ALLOW_THREADS -- self->ssl = SSL_new(self->ctx); /* New ssl struct */ -- PySSL_END_ALLOW_THREADS -- SSL_set_fd(self->ssl, Sock->sock_fd); /* Set the socket for SSL */ --#ifdef SSL_MODE_AUTO_RETRY -- SSL_set_mode(self->ssl, SSL_MODE_AUTO_RETRY); -+ SSL_set_mode(self->ssl, mode); -+ -+#if HAVE_SNI -+ if (server_hostname != NULL) -+ SSL_set_tlsext_host_name(self->ssl, server_hostname); - #endif - - /* If the socket is in non-blocking mode or timeout mode, set the BIO - * to non-blocking mode (blocking is the default) - */ -- if (Sock->sock_timeout >= 0.0) { -- /* Set both the read and write BIO's to non-blocking mode */ -+ if (sock->sock_timeout >= 0.0) { - BIO_set_nbio(SSL_get_rbio(self->ssl), 1); - BIO_set_nbio(SSL_get_wbio(self->ssl), 1); - } -@@ -411,65 +514,31 @@ newPySSLObject(PySocketSockObject *Sock, - SSL_set_accept_state(self->ssl); - PySSL_END_ALLOW_THREADS - -- self->Socket = Sock; -+ self->socket_type = socket_type; -+ self->Socket = sock; - Py_INCREF(self->Socket); -+ self->ssl_sock = PyWeakref_NewRef(ssl_sock, NULL); -+ if (self->ssl_sock == NULL) { -+ Py_DECREF(self); -+ return NULL; -+ } - return self; -- fail: -- if (errstr) -- PyErr_SetString(PySSLErrorObject, errstr); -- Py_DECREF(self); -- return NULL; - } - --static PyObject * --PySSL_sslwrap(PyObject *self, PyObject *args) --{ -- PySocketSockObject *Sock; -- int server_side = 0; -- int verification_mode = PY_SSL_CERT_NONE; -- int protocol = PY_SSL_VERSION_SSL23; -- char *key_file = NULL; -- char *cert_file = NULL; -- char *cacerts_file = NULL; -- char *ciphers = NULL; -- -- if (!PyArg_ParseTuple(args, "O!i|zziizz:sslwrap", -- PySocketModule.Sock_Type, -- &Sock, -- &server_side, -- &key_file, &cert_file, -- &verification_mode, &protocol, -- &cacerts_file, &ciphers)) -- return NULL; -- -- /* -- fprintf(stderr, -- "server_side is %d, keyfile %p, certfile %p, verify_mode %d, " -- "protocol %d, certs %p\n", -- server_side, key_file, cert_file, verification_mode, -- protocol, cacerts_file); -- */ -- -- return (PyObject *) newPySSLObject(Sock, key_file, cert_file, -- server_side, verification_mode, -- protocol, cacerts_file, -- ciphers); --} -- --PyDoc_STRVAR(ssl_doc, --"sslwrap(socket, server_side, [keyfile, certfile, certs_mode, protocol,\n" --" cacertsfile, ciphers]) -> sslobject"); - - /* SSL object methods */ - --static PyObject *PySSL_SSLdo_handshake(PySSLObject *self) -+static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self) - { - int ret; - int err; - int sockstate, nonblocking; -+ PySocketSockObject *sock = self->Socket; -+ -+ Py_INCREF(sock); - - /* just in case the blocking state of the socket has been changed */ -- nonblocking = (self->Socket->sock_timeout >= 0.0); -+ nonblocking = (sock->sock_timeout >= 0.0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - -@@ -480,60 +549,48 @@ static PyObject *PySSL_SSLdo_handshake(P - ret = SSL_do_handshake(self->ssl); - err = SSL_get_error(self->ssl, ret); - PySSL_END_ALLOW_THREADS -- if(PyErr_CheckSignals()) { -- return NULL; -- } -+ if (PyErr_CheckSignals()) -+ goto error; - if (err == SSL_ERROR_WANT_READ) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); -+ sockstate = check_socket_and_wait_for_timeout(sock, 0); - } else if (err == SSL_ERROR_WANT_WRITE) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); -+ sockstate = check_socket_and_wait_for_timeout(sock, 1); - } else { - sockstate = SOCKET_OPERATION_OK; - } - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySSLErrorObject, - ERRSTR("The handshake operation timed out")); -- return NULL; -+ goto error; - } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { - PyErr_SetString(PySSLErrorObject, - ERRSTR("Underlying socket has been closed.")); -- return NULL; -+ goto error; - } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, - ERRSTR("Underlying socket too large for select().")); -- return NULL; -+ goto error; - } else if (sockstate == SOCKET_IS_NONBLOCKING) { - break; - } - } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); -+ Py_DECREF(sock); - if (ret < 1) - return PySSL_SetError(self, ret, __FILE__, __LINE__); - - if (self->peer_cert) - X509_free (self->peer_cert); - PySSL_BEGIN_ALLOW_THREADS -- if ((self->peer_cert = SSL_get_peer_certificate(self->ssl))) { -- X509_NAME_oneline(X509_get_subject_name(self->peer_cert), -- self->server, X509_NAME_MAXLEN); -- X509_NAME_oneline(X509_get_issuer_name(self->peer_cert), -- self->issuer, X509_NAME_MAXLEN); -- } -+ self->peer_cert = SSL_get_peer_certificate(self->ssl); - PySSL_END_ALLOW_THREADS -+ self->handshake_done = 1; - - Py_INCREF(Py_None); - return Py_None; --} -- --static PyObject * --PySSL_server(PySSLObject *self) --{ -- return PyString_FromString(self->server); --} -- --static PyObject * --PySSL_issuer(PySSLObject *self) --{ -- return PyString_FromString(self->issuer); -+ -+error: -+ Py_DECREF(sock); -+ return NULL; - } - - static PyObject * -@@ -639,8 +696,8 @@ static PyObject * - /* - fprintf(stderr, "RDN level %d, attribute %s: %s\n", - entry->set, -- PyString_AS_STRING(PyTuple_GET_ITEM(attr, 0)), -- PyString_AS_STRING(PyTuple_GET_ITEM(attr, 1))); -+ PyBytes_AS_STRING(PyTuple_GET_ITEM(attr, 0)), -+ PyBytes_AS_STRING(PyTuple_GET_ITEM(attr, 1))); - */ - if (attr == NULL) - goto fail1; -@@ -727,21 +784,24 @@ static PyObject * - /* now decode the altName */ - ext = X509_get_ext(certificate, i); - if(!(method = X509V3_EXT_get(ext))) { -- PyErr_SetString(PySSLErrorObject, -- ERRSTR("No method for internalizing subjectAltName!")); -+ PyErr_SetString -+ (PySSLErrorObject, -+ ERRSTR("No method for internalizing subjectAltName!")); - goto fail; - } - - p = ext->value->data; - if (method->it) -- names = (GENERAL_NAMES*) (ASN1_item_d2i(NULL, -- &p, -- ext->value->length, -- ASN1_ITEM_ptr(method->it))); -+ names = (GENERAL_NAMES*) -+ (ASN1_item_d2i(NULL, -+ &p, -+ ext->value->length, -+ ASN1_ITEM_ptr(method->it))); - else -- names = (GENERAL_NAMES*) (method->d2i(NULL, -- &p, -- ext->value->length)); -+ names = (GENERAL_NAMES*) -+ (method->d2i(NULL, -+ &p, -+ ext->value->length)); - - for(j = 0; j < sk_GENERAL_NAME_num(names); j++) { - /* get a rendering of each name in the set of names */ -@@ -888,7 +948,127 @@ static PyObject * - } - - static PyObject * --_decode_certificate (X509 *certificate, int verbose) { -+_get_aia_uri(X509 *certificate, int nid) { -+ PyObject *lst = NULL, *ostr = NULL; -+ int i, result; -+ AUTHORITY_INFO_ACCESS *info; -+ -+ info = X509_get_ext_d2i(certificate, NID_info_access, NULL, NULL); -+ if ((info == NULL) || (sk_ACCESS_DESCRIPTION_num(info) == 0)) { -+ return Py_None; -+ } -+ -+ if ((lst = PyList_New(0)) == NULL) { -+ goto fail; -+ } -+ -+ for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { -+ ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); -+ ASN1_IA5STRING *uri; -+ -+ if ((OBJ_obj2nid(ad->method) != nid) || -+ (ad->location->type != GEN_URI)) { -+ continue; -+ } -+ uri = ad->location->d.uniformResourceIdentifier; -+ ostr = PyUnicode_FromStringAndSize((char *)uri->data, -+ uri->length); -+ if (ostr == NULL) { -+ goto fail; -+ } -+ result = PyList_Append(lst, ostr); -+ Py_DECREF(ostr); -+ if (result < 0) { -+ goto fail; -+ } -+ } -+ AUTHORITY_INFO_ACCESS_free(info); -+ -+ /* convert to tuple or None */ -+ if (PyList_Size(lst) == 0) { -+ Py_DECREF(lst); -+ return Py_None; -+ } else { -+ PyObject *tup; -+ tup = PyList_AsTuple(lst); -+ Py_DECREF(lst); -+ return tup; -+ } -+ -+ fail: -+ AUTHORITY_INFO_ACCESS_free(info); -+ Py_XDECREF(lst); -+ return NULL; -+} -+ -+static PyObject * -+_get_crl_dp(X509 *certificate) { -+ STACK_OF(DIST_POINT) *dps; -+ int i, j, result; -+ PyObject *lst; -+ -+#if OPENSSL_VERSION_NUMBER < 0x10001000L -+ dps = X509_get_ext_d2i(certificate, NID_crl_distribution_points, -+ NULL, NULL); -+#else -+ /* Calls x509v3_cache_extensions and sets up crldp */ -+ X509_check_ca(certificate); -+ dps = certificate->crldp; -+#endif -+ -+ if (dps == NULL) { -+ return Py_None; -+ } -+ -+ if ((lst = PyList_New(0)) == NULL) { -+ return NULL; -+ } -+ -+ for (i=0; i < sk_DIST_POINT_num(dps); i++) { -+ DIST_POINT *dp; -+ STACK_OF(GENERAL_NAME) *gns; -+ -+ dp = sk_DIST_POINT_value(dps, i); -+ gns = dp->distpoint->name.fullname; -+ -+ for (j=0; j < sk_GENERAL_NAME_num(gns); j++) { -+ GENERAL_NAME *gn; -+ ASN1_IA5STRING *uri; -+ PyObject *ouri; -+ -+ gn = sk_GENERAL_NAME_value(gns, j); -+ if (gn->type != GEN_URI) { -+ continue; -+ } -+ uri = gn->d.uniformResourceIdentifier; -+ ouri = PyUnicode_FromStringAndSize((char *)uri->data, -+ uri->length); -+ if (ouri == NULL) { -+ Py_DECREF(lst); -+ return NULL; -+ } -+ result = PyList_Append(lst, ouri); -+ Py_DECREF(ouri); -+ if (result < 0) { -+ Py_DECREF(lst); -+ return NULL; -+ } -+ } -+ } -+ /* convert to tuple or None */ -+ if (PyList_Size(lst) == 0) { -+ Py_DECREF(lst); -+ return Py_None; -+ } else { -+ PyObject *tup; -+ tup = PyList_AsTuple(lst); -+ Py_DECREF(lst); -+ return tup; -+ } -+} -+ -+static PyObject * -+_decode_certificate(X509 *certificate) { - - PyObject *retval = NULL; - BIO *biobuf = NULL; -@@ -897,9 +1077,10 @@ static PyObject * - PyObject *issuer; - PyObject *version; - PyObject *sn_obj; -+ PyObject *obj; - ASN1_INTEGER *serialNumber; - char buf[2048]; -- int len; -+ int len, result; - ASN1_TIME *notBefore, *notAfter; - PyObject *pnotBefore, *pnotAfter; - -@@ -917,65 +1098,62 @@ static PyObject * - } - Py_DECREF(peer); - -- if (verbose) { -- issuer = _create_tuple_for_X509_NAME( -- X509_get_issuer_name(certificate)); -- if (issuer == NULL) -- goto fail0; -- if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) { -- Py_DECREF(issuer); -- goto fail0; -- } -+ issuer = _create_tuple_for_X509_NAME( -+ X509_get_issuer_name(certificate)); -+ if (issuer == NULL) -+ goto fail0; -+ if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) { - Py_DECREF(issuer); -- -- version = PyInt_FromLong(X509_get_version(certificate) + 1); -- if (PyDict_SetItemString(retval, "version", version) < 0) { -- Py_DECREF(version); -- goto fail0; -- } -+ goto fail0; -+ } -+ Py_DECREF(issuer); -+ -+ version = PyLong_FromLong(X509_get_version(certificate) + 1); -+ if (version == NULL) -+ goto fail0; -+ if (PyDict_SetItemString(retval, "version", version) < 0) { - Py_DECREF(version); -+ goto fail0; - } -+ Py_DECREF(version); - - /* get a memory buffer */ - biobuf = BIO_new(BIO_s_mem()); - -- if (verbose) { -- -- (void) BIO_reset(biobuf); -- serialNumber = X509_get_serialNumber(certificate); -- /* should not exceed 20 octets, 160 bits, so buf is big enough */ -- i2a_ASN1_INTEGER(biobuf, serialNumber); -- len = BIO_gets(biobuf, buf, sizeof(buf)-1); -- if (len < 0) { -- _setSSLError(NULL, 0, __FILE__, __LINE__); -- goto fail1; -- } -- sn_obj = PyString_FromStringAndSize(buf, len); -- if (sn_obj == NULL) -- goto fail1; -- if (PyDict_SetItemString(retval, "serialNumber", sn_obj) < 0) { -- Py_DECREF(sn_obj); -- goto fail1; -- } -+ (void) BIO_reset(biobuf); -+ serialNumber = X509_get_serialNumber(certificate); -+ /* should not exceed 20 octets, 160 bits, so buf is big enough */ -+ i2a_ASN1_INTEGER(biobuf, serialNumber); -+ len = BIO_gets(biobuf, buf, sizeof(buf)-1); -+ if (len < 0) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ goto fail1; -+ } -+ sn_obj = PyUnicode_FromStringAndSize(buf, len); -+ if (sn_obj == NULL) -+ goto fail1; -+ if (PyDict_SetItemString(retval, "serialNumber", sn_obj) < 0) { - Py_DECREF(sn_obj); -- -- (void) BIO_reset(biobuf); -- notBefore = X509_get_notBefore(certificate); -- ASN1_TIME_print(biobuf, notBefore); -- len = BIO_gets(biobuf, buf, sizeof(buf)-1); -- if (len < 0) { -- _setSSLError(NULL, 0, __FILE__, __LINE__); -- goto fail1; -- } -- pnotBefore = PyString_FromStringAndSize(buf, len); -- if (pnotBefore == NULL) -- goto fail1; -- if (PyDict_SetItemString(retval, "notBefore", pnotBefore) < 0) { -- Py_DECREF(pnotBefore); -- goto fail1; -- } -+ goto fail1; -+ } -+ Py_DECREF(sn_obj); -+ -+ (void) BIO_reset(biobuf); -+ notBefore = X509_get_notBefore(certificate); -+ ASN1_TIME_print(biobuf, notBefore); -+ len = BIO_gets(biobuf, buf, sizeof(buf)-1); -+ if (len < 0) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ goto fail1; -+ } -+ pnotBefore = PyUnicode_FromStringAndSize(buf, len); -+ if (pnotBefore == NULL) -+ goto fail1; -+ if (PyDict_SetItemString(retval, "notBefore", pnotBefore) < 0) { - Py_DECREF(pnotBefore); -+ goto fail1; - } -+ Py_DECREF(pnotBefore); - - (void) BIO_reset(biobuf); - notAfter = X509_get_notAfter(certificate); -@@ -1008,6 +1186,41 @@ static PyObject * - Py_DECREF(peer_alt_names); - } - -+ /* Authority Information Access: OCSP URIs */ -+ obj = _get_aia_uri(certificate, NID_ad_OCSP); -+ if (obj == NULL) { -+ goto fail1; -+ } else if (obj != Py_None) { -+ result = PyDict_SetItemString(retval, "OCSP", obj); -+ Py_DECREF(obj); -+ if (result < 0) { -+ goto fail1; -+ } -+ } -+ -+ obj = _get_aia_uri(certificate, NID_ad_ca_issuers); -+ if (obj == NULL) { -+ goto fail1; -+ } else if (obj != Py_None) { -+ result = PyDict_SetItemString(retval, "caIssuers", obj); -+ Py_DECREF(obj); -+ if (result < 0) { -+ goto fail1; -+ } -+ } -+ -+ /* CDP (CRL distribution points) */ -+ obj = _get_crl_dp(certificate); -+ if (obj == NULL) { -+ goto fail1; -+ } else if (obj != Py_None) { -+ result = PyDict_SetItemString(retval, "crlDistributionPoints", obj); -+ Py_DECREF(obj); -+ if (result < 0) { -+ goto fail1; -+ } -+ } -+ - BIO_free(biobuf); - return retval; - -@@ -1019,6 +1232,24 @@ static PyObject * - return NULL; - } - -+static PyObject * -+_certificate_to_der(X509 *certificate) -+{ -+ unsigned char *bytes_buf = NULL; -+ int len; -+ PyObject *retval; -+ -+ bytes_buf = NULL; -+ len = i2d_X509(certificate, &bytes_buf); -+ if (len < 0) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ return NULL; -+ } -+ /* this is actually an immutable bytes sequence */ -+ retval = PyBytes_FromStringAndSize((const char *) bytes_buf, len); -+ OPENSSL_free(bytes_buf); -+ return retval; -+} - - static PyObject * - PySSL_test_decode_certificate (PyObject *mod, PyObject *args) { -@@ -1027,28 +1258,30 @@ PySSL_test_decode_certificate (PyObject - char *filename = NULL; - X509 *x=NULL; - BIO *cert; -- int verbose = 1; -- -- if (!PyArg_ParseTuple(args, "s|i:test_decode_certificate", &filename, &verbose)) -+ -+ if (!PyArg_ParseTuple(args, "s:test_decode_certificate", &filename)) - return NULL; - - if ((cert=BIO_new(BIO_s_file())) == NULL) { -- PyErr_SetString(PySSLErrorObject, "Can't malloc memory to read file"); -+ PyErr_SetString(PySSLErrorObject, -+ "Can't malloc memory to read file"); - goto fail0; - } - - if (BIO_read_filename(cert,filename) <= 0) { -- PyErr_SetString(PySSLErrorObject, "Can't open file"); -+ PyErr_SetString(PySSLErrorObject, -+ "Can't open file"); - goto fail0; - } - - x = PEM_read_bio_X509_AUX(cert,NULL, NULL, NULL); - if (x == NULL) { -- PyErr_SetString(PySSLErrorObject, "Error decoding PEM-encoded file"); -+ PyErr_SetString(PySSLErrorObject, -+ "Error decoding PEM-encoded file"); - goto fail0; - } - -- retval = _decode_certificate(x, verbose); -+ retval = _decode_certificate(x); - X509_free(x); - - fail0: -@@ -1059,10 +1292,8 @@ PySSL_test_decode_certificate (PyObject - - - static PyObject * --PySSL_peercert(PySSLObject *self, PyObject *args) -+PySSL_peercert(PySSLSocket *self, PyObject *args) - { -- PyObject *retval = NULL; -- int len; - int verification; - PyObject *binary_mode = Py_None; - int b; -@@ -1070,6 +1301,11 @@ PySSL_peercert(PySSLObject *self, PyObje - if (!PyArg_ParseTuple(args, "|O:peer_certificate", &binary_mode)) - return NULL; - -+ if (!self->handshake_done) { -+ PyErr_SetString(PyExc_ValueError, -+ "handshake not done yet"); -+ return NULL; -+ } - if (!self->peer_cert) - Py_RETURN_NONE; - -@@ -1078,26 +1314,13 @@ PySSL_peercert(PySSLObject *self, PyObje - return NULL; - if (b) { - /* return cert in DER-encoded format */ -- -- unsigned char *bytes_buf = NULL; -- -- bytes_buf = NULL; -- len = i2d_X509(self->peer_cert, &bytes_buf); -- if (len < 0) { -- PySSL_SetError(self, len, __FILE__, __LINE__); -- return NULL; -- } -- retval = PyString_FromStringAndSize((const char *) bytes_buf, len); -- OPENSSL_free(bytes_buf); -- return retval; -- -+ return _certificate_to_der(self->peer_cert); - } else { -- -- verification = SSL_CTX_get_verify_mode(self->ctx); -+ verification = SSL_CTX_get_verify_mode(SSL_get_SSL_CTX(self->ssl)); - if ((verification & SSL_VERIFY_PEER) == 0) - return PyDict_New(); - else -- return _decode_certificate (self->peer_cert, 0); -+ return _decode_certificate(self->peer_cert); - } - } - -@@ -1113,7 +1336,7 @@ If the optional argument is True, return - peer certificate, or None if no certificate was provided. This will\n\ - return the certificate even if it wasn't validated."); - --static PyObject *PySSL_cipher (PySSLObject *self) { -+static PyObject *PySSL_cipher (PySSLSocket *self) { - - PyObject *retval, *v; - const SSL_CIPHER *current; -@@ -1140,7 +1363,7 @@ static PyObject *PySSL_cipher (PySSLObje - goto fail0; - PyTuple_SET_ITEM(retval, 0, v); - } -- cipher_protocol = SSL_CIPHER_get_version(current); -+ cipher_protocol = (char *) SSL_CIPHER_get_version(current); - if (cipher_protocol == NULL) { - Py_INCREF(Py_None); - PyTuple_SET_ITEM(retval, 1, Py_None); -@@ -1161,15 +1384,85 @@ static PyObject *PySSL_cipher (PySSLObje - return NULL; - } - --static void PySSL_dealloc(PySSLObject *self) -+#ifdef OPENSSL_NPN_NEGOTIATED -+static PyObject *PySSL_selected_npn_protocol(PySSLSocket *self) { -+ const unsigned char *out; -+ unsigned int outlen; -+ -+ SSL_get0_next_proto_negotiated(self->ssl, -+ &out, &outlen); -+ -+ if (out == NULL) -+ Py_RETURN_NONE; -+ return PyUnicode_FromStringAndSize((char *) out, outlen); -+} -+#endif -+ -+static PyObject *PySSL_compression(PySSLSocket *self) { -+#ifdef OPENSSL_NO_COMP -+ Py_RETURN_NONE; -+#else -+ const COMP_METHOD *comp_method; -+ const char *short_name; -+ -+ if (self->ssl == NULL) -+ Py_RETURN_NONE; -+ comp_method = SSL_get_current_compression(self->ssl); -+ if (comp_method == NULL || comp_method->type == NID_undef) -+ Py_RETURN_NONE; -+ short_name = OBJ_nid2sn(comp_method->type); -+ if (short_name == NULL) -+ Py_RETURN_NONE; -+ return PyBytes_FromString(short_name); -+#endif -+} -+ -+static PySSLContext *PySSL_get_context(PySSLSocket *self, void *closure) { -+ Py_INCREF(self->ctx); -+ return self->ctx; -+} -+ -+static int PySSL_set_context(PySSLSocket *self, PyObject *value, -+ void *closure) { -+ -+ if (PyObject_TypeCheck(value, &PySSLContext_Type)) { -+#if !HAVE_SNI -+ PyErr_SetString(PyExc_NotImplementedError, "setting a socket's " -+ "context is not supported by your OpenSSL library"); -+ return -1; -+#else -+ Py_INCREF(value); -+ Py_DECREF(self->ctx); -+ self->ctx = (PySSLContext *) value; -+ SSL_set_SSL_CTX(self->ssl, self->ctx->ctx); -+#endif -+ } else { -+ PyErr_SetString(PyExc_TypeError, "The value must be a SSLContext"); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+PyDoc_STRVAR(PySSL_set_context_doc, -+"_setter_context(ctx)\n\ -+\ -+This changes the context associated with the SSLSocket. This is typically\n\ -+used from within a callback function set by the set_servername_callback\n\ -+on the SSLContext to change the certificate information associated with the\n\ -+SSLSocket before the cryptographic exchange handshake messages\n"); -+ -+ -+ -+static void PySSL_dealloc(PySSLSocket *self) - { - if (self->peer_cert) /* Possible not to have one? */ - X509_free (self->peer_cert); - if (self->ssl) - SSL_free(self->ssl); -- if (self->ctx) -- SSL_CTX_free(self->ctx); - Py_XDECREF(self->Socket); -+ Py_XDECREF(self->ssl_sock); -+ Py_XDECREF(self->ctx); - PyObject_Del(self); - } - -@@ -1241,16 +1534,21 @@ normal_return: - return rc == 0 ? SOCKET_HAS_TIMED_OUT : SOCKET_OPERATION_OK; - } - --static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args) -+static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args) - { - Py_buffer buf; - int len; - int sockstate; - int err; - int nonblocking; -- -- if (!PyArg_ParseTuple(args, "s*:write", &buf)) -+ PySocketSockObject *sock = self->Socket; -+ -+ Py_INCREF(sock); -+ -+ if (!PyArg_ParseTuple(args, "s*:write", &buf)) { -+ Py_DECREF(sock); - return NULL; -+ } - - if (buf.len > INT_MAX) { - PyErr_Format(PyExc_OverflowError, -@@ -1259,11 +1557,11 @@ static PyObject *PySSL_SSLwrite(PySSLObj - } - - /* just in case the blocking state of the socket has been changed */ -- nonblocking = (self->Socket->sock_timeout >= 0.0); -+ nonblocking = (sock->sock_timeout >= 0.0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); -+ sockstate = check_socket_and_wait_for_timeout(sock, 1); - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySSLErrorObject, - "The write operation timed out"); -@@ -1286,9 +1584,9 @@ static PyObject *PySSL_SSLwrite(PySSLObj - goto error; - } - if (err == SSL_ERROR_WANT_READ) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); -+ sockstate = check_socket_and_wait_for_timeout(sock, 0); - } else if (err == SSL_ERROR_WANT_WRITE) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); -+ sockstate = check_socket_and_wait_for_timeout(sock, 1); - } else { - sockstate = SOCKET_OPERATION_OK; - } -@@ -1305,6 +1603,7 @@ static PyObject *PySSL_SSLwrite(PySSLObj - } - } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); - -+ Py_DECREF(sock); - PyBuffer_Release(&buf); - if (len > 0) - return PyInt_FromLong(len); -@@ -1312,6 +1611,7 @@ static PyObject *PySSL_SSLwrite(PySSLObj - return PySSL_SetError(self, len, __FILE__, __LINE__); - - error: -+ Py_DECREF(sock); - PyBuffer_Release(&buf); - return NULL; - } -@@ -1322,7 +1622,7 @@ PyDoc_STRVAR(PySSL_SSLwrite_doc, - Writes the string s into the SSL object. Returns the number\n\ - of bytes written."); - --static PyObject *PySSL_SSLpending(PySSLObject *self) -+static PyObject *PySSL_SSLpending(PySSLSocket *self) - { - int count = 0; - -@@ -1341,23 +1641,46 @@ PyDoc_STRVAR(PySSL_SSLpending_doc, - Returns the number of already decrypted bytes available for read,\n\ - pending on the connection.\n"); - --static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args) -+static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args) - { -- PyObject *buf; -- int count = 0; -- int len = 1024; -+ PyObject *dest = NULL; -+ Py_buffer buf; -+ char *mem; -+ int len, count; -+ int buf_passed = 0; - int sockstate; - int err; - int nonblocking; -- -- if (!PyArg_ParseTuple(args, "|i:read", &len)) -- return NULL; -- -- if (!(buf = PyString_FromStringAndSize((char *) 0, len))) -- return NULL; -+ PySocketSockObject *sock = self->Socket; -+ -+ Py_INCREF(sock); -+ -+ buf.obj = NULL; -+ buf.buf = NULL; -+ if (!PyArg_ParseTuple(args, "i|w*:read", &len, &buf)) -+ goto error; -+ -+ if ((buf.buf == NULL) && (buf.obj == NULL)) { -+ dest = PyBytes_FromStringAndSize(NULL, len); -+ if (dest == NULL) -+ goto error; -+ mem = PyBytes_AS_STRING(dest); -+ } -+ else { -+ buf_passed = 1; -+ mem = buf.buf; -+ if (len <= 0 || len > buf.len) { -+ len = (int) buf.len; -+ if (buf.len != len) { -+ PyErr_SetString(PyExc_OverflowError, -+ "maximum length can't fit in a C 'int'"); -+ goto error; -+ } -+ } -+ } - - /* just in case the blocking state of the socket has been changed */ -- nonblocking = (self->Socket->sock_timeout >= 0.0); -+ nonblocking = (sock->sock_timeout >= 0.0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - -@@ -1367,70 +1690,71 @@ static PyObject *PySSL_SSLread(PySSLObje - PySSL_END_ALLOW_THREADS - - if (!count) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); -+ sockstate = check_socket_and_wait_for_timeout(sock, 0); - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySSLErrorObject, - "The read operation timed out"); -- Py_DECREF(buf); -- return NULL; -+ goto error; - } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket too large for select()."); -- Py_DECREF(buf); -- return NULL; -+ goto error; - } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { -- if (SSL_get_shutdown(self->ssl) != -- SSL_RECEIVED_SHUTDOWN) -- { -- Py_DECREF(buf); -- PyErr_SetString(PySSLErrorObject, -- "Socket closed without SSL shutdown handshake"); -- return NULL; -- } else { -- /* should contain a zero-length string */ -- _PyString_Resize(&buf, 0); -- return buf; -- } -+ count = 0; -+ goto done; - } - } - do { - PySSL_BEGIN_ALLOW_THREADS -- count = SSL_read(self->ssl, PyString_AsString(buf), len); -+ count = SSL_read(self->ssl, mem, len); - err = SSL_get_error(self->ssl, count); - PySSL_END_ALLOW_THREADS -- if(PyErr_CheckSignals()) { -- Py_DECREF(buf); -- return NULL; -- } -+ if (PyErr_CheckSignals()) -+ goto error; - if (err == SSL_ERROR_WANT_READ) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); -+ sockstate = check_socket_and_wait_for_timeout(sock, 0); - } else if (err == SSL_ERROR_WANT_WRITE) { -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); -+ sockstate = check_socket_and_wait_for_timeout(sock, 1); - } else if ((err == SSL_ERROR_ZERO_RETURN) && - (SSL_get_shutdown(self->ssl) == - SSL_RECEIVED_SHUTDOWN)) - { -- _PyString_Resize(&buf, 0); -- return buf; -+ count = 0; -+ goto done; - } else { - sockstate = SOCKET_OPERATION_OK; - } - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySSLErrorObject, - "The read operation timed out"); -- Py_DECREF(buf); -- return NULL; -+ goto error; - } else if (sockstate == SOCKET_IS_NONBLOCKING) { - break; - } - } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); - if (count <= 0) { -- Py_DECREF(buf); -- return PySSL_SetError(self, count, __FILE__, __LINE__); -+ PySSL_SetError(self, count, __FILE__, __LINE__); -+ goto error; - } -- if (count != len) -- _PyString_Resize(&buf, count); -- return buf; -+ -+done: -+ Py_DECREF(sock); -+ if (!buf_passed) { -+ _PyBytes_Resize(&dest, count); -+ return dest; -+ } -+ else { -+ PyBuffer_Release(&buf); -+ return PyLong_FromLong(count); -+ } -+ -+error: -+ Py_DECREF(sock); -+ if (!buf_passed) -+ Py_XDECREF(dest); -+ else -+ PyBuffer_Release(&buf); -+ return NULL; - } - - PyDoc_STRVAR(PySSL_SSLread_doc, -@@ -1438,20 +1762,22 @@ PyDoc_STRVAR(PySSL_SSLread_doc, - \n\ - Read up to len bytes from the SSL socket."); - --static PyObject *PySSL_SSLshutdown(PySSLObject *self) -+static PyObject *PySSL_SSLshutdown(PySSLSocket *self) - { - int err, ssl_err, sockstate, nonblocking; - int zeros = 0; -+ PySocketSockObject *sock = self->Socket; - - /* Guard against closed socket */ -- if (self->Socket->sock_fd < 0) { -- PyErr_SetString(PySSLErrorObject, -- "Underlying socket has been closed."); -+ if (sock->sock_fd < 0) { -+ _setSSLError("Underlying socket connection gone", -+ PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); - return NULL; - } -+ Py_INCREF(sock); - - /* Just in case the blocking state of the socket has been changed */ -- nonblocking = (self->Socket->sock_timeout >= 0.0); -+ nonblocking = (sock->sock_timeout >= 0.0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - -@@ -1486,9 +1812,9 @@ static PyObject *PySSL_SSLshutdown(PySSL - /* Possibly retry shutdown until timeout or failure */ - ssl_err = SSL_get_error(self->ssl, err); - if (ssl_err == SSL_ERROR_WANT_READ) -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); -+ sockstate = check_socket_and_wait_for_timeout(sock, 0); - else if (ssl_err == SSL_ERROR_WANT_WRITE) -- sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); -+ sockstate = check_socket_and_wait_for_timeout(sock, 1); - else - break; - if (sockstate == SOCKET_HAS_TIMED_OUT) { -@@ -1498,24 +1824,29 @@ static PyObject *PySSL_SSLshutdown(PySSL - else - PyErr_SetString(PySSLErrorObject, - "The write operation timed out"); -- return NULL; -+ goto error; - } - else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket too large for select()."); -- return NULL; -+ goto error; - } - else if (sockstate != SOCKET_OPERATION_OK) - /* Retain the SSL error code */ - break; - } - -- if (err < 0) -+ if (err < 0) { -+ Py_DECREF(sock); - return PySSL_SetError(self, err, __FILE__, __LINE__); -- else { -- Py_INCREF(self->Socket); -- return (PyObject *) (self->Socket); - } -+ else -+ /* It's already INCREF'ed */ -+ return (PyObject *) sock; -+ -+error: -+ Py_DECREF(sock); -+ return NULL; - } - - PyDoc_STRVAR(PySSL_SSLshutdown_doc, -@@ -1524,6 +1855,47 @@ PyDoc_STRVAR(PySSL_SSLshutdown_doc, - Does the SSL shutdown handshake with the remote end, and returns\n\ - the underlying socket object."); - -+#if HAVE_OPENSSL_FINISHED -+static PyObject * -+PySSL_tls_unique_cb(PySSLSocket *self) -+{ -+ PyObject *retval = NULL; -+ char buf[PySSL_CB_MAXLEN]; -+ size_t len; -+ -+ if (SSL_session_reused(self->ssl) ^ !self->socket_type) { -+ /* if session is resumed XOR we are the client */ -+ len = SSL_get_finished(self->ssl, buf, PySSL_CB_MAXLEN); -+ } -+ else { -+ /* if a new session XOR we are the server */ -+ len = SSL_get_peer_finished(self->ssl, buf, PySSL_CB_MAXLEN); -+ } -+ -+ /* It cannot be negative in current OpenSSL version as of July 2011 */ -+ if (len == 0) -+ Py_RETURN_NONE; -+ -+ retval = PyBytes_FromStringAndSize(buf, len); -+ -+ return retval; -+} -+ -+PyDoc_STRVAR(PySSL_tls_unique_cb_doc, -+"tls_unique_cb() -> bytes\n\ -+\n\ -+Returns the 'tls-unique' channel binding data, as defined by RFC 5929.\n\ -+\n\ -+If the TLS handshake is not yet complete, None is returned"); -+ -+#endif /* HAVE_OPENSSL_FINISHED */ -+ -+static PyGetSetDef ssl_getsetlist[] = { -+ {"context", (getter) PySSL_get_context, -+ (setter) PySSL_set_context, PySSL_set_context_doc}, -+ {NULL}, /* sentinel */ -+}; -+ - static PyMethodDef PySSLMethods[] = { - {"do_handshake", (PyCFunction)PySSL_SSLdo_handshake, METH_NOARGS}, - {"write", (PyCFunction)PySSL_SSLwrite, METH_VARARGS, -@@ -1532,39 +1904,1307 @@ static PyMethodDef PySSLMethods[] = { - PySSL_SSLread_doc}, - {"pending", (PyCFunction)PySSL_SSLpending, METH_NOARGS, - PySSL_SSLpending_doc}, -- {"server", (PyCFunction)PySSL_server, METH_NOARGS}, -- {"issuer", (PyCFunction)PySSL_issuer, METH_NOARGS}, - {"peer_certificate", (PyCFunction)PySSL_peercert, METH_VARARGS, - PySSL_peercert_doc}, - {"cipher", (PyCFunction)PySSL_cipher, METH_NOARGS}, -+#ifdef OPENSSL_NPN_NEGOTIATED -+ {"selected_npn_protocol", (PyCFunction)PySSL_selected_npn_protocol, METH_NOARGS}, -+#endif -+ {"compression", (PyCFunction)PySSL_compression, METH_NOARGS}, - {"shutdown", (PyCFunction)PySSL_SSLshutdown, METH_NOARGS, - PySSL_SSLshutdown_doc}, -+#if HAVE_OPENSSL_FINISHED -+ {"tls_unique_cb", (PyCFunction)PySSL_tls_unique_cb, METH_NOARGS, -+ PySSL_tls_unique_cb_doc}, -+#endif - {NULL, NULL} - }; - --static PyObject *PySSL_getattr(PySSLObject *self, char *name) --{ -- return Py_FindMethod(PySSLMethods, (PyObject *)self, name); --} -- --static PyTypeObject PySSL_Type = { -+static PyTypeObject PySSLSocket_Type = { - PyVarObject_HEAD_INIT(NULL, 0) -- "ssl.SSLContext", /*tp_name*/ -- sizeof(PySSLObject), /*tp_basicsize*/ -+ "_ssl._SSLSocket", /*tp_name*/ -+ sizeof(PySSLSocket), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PySSL_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ -- (getattrfunc)PySSL_getattr, /*tp_getattr*/ -+ 0, /*tp_getattr*/ - 0, /*tp_setattr*/ -- 0, /*tp_compare*/ -+ 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ -+ 0, /*tp_call*/ -+ 0, /*tp_str*/ -+ 0, /*tp_getattro*/ -+ 0, /*tp_setattro*/ -+ 0, /*tp_as_buffer*/ -+ Py_TPFLAGS_DEFAULT, /*tp_flags*/ -+ 0, /*tp_doc*/ -+ 0, /*tp_traverse*/ -+ 0, /*tp_clear*/ -+ 0, /*tp_richcompare*/ -+ 0, /*tp_weaklistoffset*/ -+ 0, /*tp_iter*/ -+ 0, /*tp_iternext*/ -+ PySSLMethods, /*tp_methods*/ -+ 0, /*tp_members*/ -+ ssl_getsetlist, /*tp_getset*/ - }; - -+ -+/* -+ * _SSLContext objects -+ */ -+ -+static PyObject * -+context_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"protocol", NULL}; -+ PySSLContext *self; -+ int proto_version = PY_SSL_VERSION_SSL23; -+ long options; -+ SSL_CTX *ctx = NULL; -+ -+ if (!PyArg_ParseTupleAndKeywords( -+ args, kwds, "i:_SSLContext", kwlist, -+ &proto_version)) -+ return NULL; -+ -+ PySSL_BEGIN_ALLOW_THREADS -+ if (proto_version == PY_SSL_VERSION_TLS1) -+ ctx = SSL_CTX_new(TLSv1_method()); -+#if HAVE_TLSv1_2 -+ else if (proto_version == PY_SSL_VERSION_TLS1_1) -+ ctx = SSL_CTX_new(TLSv1_1_method()); -+ else if (proto_version == PY_SSL_VERSION_TLS1_2) -+ ctx = SSL_CTX_new(TLSv1_2_method()); -+#endif -+ else if (proto_version == PY_SSL_VERSION_SSL3) -+ ctx = SSL_CTX_new(SSLv3_method()); -+#ifndef OPENSSL_NO_SSL2 -+ else if (proto_version == PY_SSL_VERSION_SSL2) -+ ctx = SSL_CTX_new(SSLv2_method()); -+#endif -+ else if (proto_version == PY_SSL_VERSION_SSL23) -+ ctx = SSL_CTX_new(SSLv23_method()); -+ else -+ proto_version = -1; -+ PySSL_END_ALLOW_THREADS -+ -+ if (proto_version == -1) { -+ PyErr_SetString(PyExc_ValueError, -+ "invalid protocol version"); -+ return NULL; -+ } -+ if (ctx == NULL) { -+ PyErr_SetString(PySSLErrorObject, -+ "failed to allocate SSL context"); -+ return NULL; -+ } -+ -+ assert(type != NULL && type->tp_alloc != NULL); -+ self = (PySSLContext *) type->tp_alloc(type, 0); -+ if (self == NULL) { -+ SSL_CTX_free(ctx); -+ return NULL; -+ } -+ self->ctx = ctx; -+#ifdef OPENSSL_NPN_NEGOTIATED -+ self->npn_protocols = NULL; -+#endif -+#ifndef OPENSSL_NO_TLSEXT -+ self->set_hostname = NULL; -+#endif -+ /* Don't check host name by default */ -+ self->check_hostname = 0; -+ /* Defaults */ -+ SSL_CTX_set_verify(self->ctx, SSL_VERIFY_NONE, NULL); -+ options = SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; -+ -+ -+ SSL_CTX_set_options(self->ctx, options); -+ -+#ifndef OPENSSL_NO_ECDH -+ /* Allow automatic ECDH curve selection (on OpenSSL 1.0.2+), or use -+ prime256v1 by default. This is Apache mod_ssl's initialization -+ policy, so we should be safe. */ -+#if defined(SSL_CTX_set_ecdh_auto) -+ SSL_CTX_set_ecdh_auto(self->ctx, 1); -+#else -+ { -+ EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); -+ SSL_CTX_set_tmp_ecdh(self->ctx, key); -+ EC_KEY_free(key); -+ } -+#endif -+#endif -+ -+#define SID_CTX "Python" -+ SSL_CTX_set_session_id_context(self->ctx, (const unsigned char *) SID_CTX, -+ sizeof(SID_CTX)); -+#undef SID_CTX -+ -+ return (PyObject *)self; -+} -+ -+static int -+context_traverse(PySSLContext *self, visitproc visit, void *arg) -+{ -+#ifndef OPENSSL_NO_TLSEXT -+ Py_VISIT(self->set_hostname); -+#endif -+ return 0; -+} -+ -+static int -+context_clear(PySSLContext *self) -+{ -+#ifndef OPENSSL_NO_TLSEXT -+ Py_CLEAR(self->set_hostname); -+#endif -+ return 0; -+} -+ -+static void -+context_dealloc(PySSLContext *self) -+{ -+ context_clear(self); -+ SSL_CTX_free(self->ctx); -+#ifdef OPENSSL_NPN_NEGOTIATED -+ PyMem_Free(self->npn_protocols); -+#endif -+ Py_TYPE(self)->tp_free(self); -+} -+ -+static PyObject * -+set_ciphers(PySSLContext *self, PyObject *args) -+{ -+ int ret; -+ const char *cipherlist; -+ -+ if (!PyArg_ParseTuple(args, "s:set_ciphers", &cipherlist)) -+ return NULL; -+ ret = SSL_CTX_set_cipher_list(self->ctx, cipherlist); -+ if (ret == 0) { -+ /* Clearing the error queue is necessary on some OpenSSL versions, -+ otherwise the error will be reported again when another SSL call -+ is done. */ -+ ERR_clear_error(); -+ PyErr_SetString(PySSLErrorObject, -+ "No cipher can be selected."); -+ return NULL; -+ } -+ Py_RETURN_NONE; -+} -+ -+#ifdef OPENSSL_NPN_NEGOTIATED -+/* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */ -+static int -+_advertiseNPN_cb(SSL *s, -+ const unsigned char **data, unsigned int *len, -+ void *args) -+{ -+ PySSLContext *ssl_ctx = (PySSLContext *) args; -+ -+ if (ssl_ctx->npn_protocols == NULL) { -+ *data = (unsigned char *) ""; -+ *len = 0; -+ } else { -+ *data = (unsigned char *) ssl_ctx->npn_protocols; -+ *len = ssl_ctx->npn_protocols_len; -+ } -+ -+ return SSL_TLSEXT_ERR_OK; -+} -+/* this callback gets passed to SSL_CTX_set_next_proto_select_cb */ -+static int -+_selectNPN_cb(SSL *s, -+ unsigned char **out, unsigned char *outlen, -+ const unsigned char *server, unsigned int server_len, -+ void *args) -+{ -+ PySSLContext *ssl_ctx = (PySSLContext *) args; -+ -+ unsigned char *client = (unsigned char *) ssl_ctx->npn_protocols; -+ int client_len; -+ -+ if (client == NULL) { -+ client = (unsigned char *) ""; -+ client_len = 0; -+ } else { -+ client_len = ssl_ctx->npn_protocols_len; -+ } -+ -+ SSL_select_next_proto(out, outlen, -+ server, server_len, -+ client, client_len); -+ -+ return SSL_TLSEXT_ERR_OK; -+} -+#endif -+ -+static PyObject * -+_set_npn_protocols(PySSLContext *self, PyObject *args) -+{ -+#ifdef OPENSSL_NPN_NEGOTIATED -+ Py_buffer protos; -+ -+ if (!PyArg_ParseTuple(args, "s*:set_npn_protocols", &protos)) -+ return NULL; -+ -+ if (self->npn_protocols != NULL) { -+ PyMem_Free(self->npn_protocols); -+ } -+ -+ self->npn_protocols = PyMem_Malloc(protos.len); -+ if (self->npn_protocols == NULL) { -+ PyBuffer_Release(&protos); -+ return PyErr_NoMemory(); -+ } -+ memcpy(self->npn_protocols, protos.buf, protos.len); -+ self->npn_protocols_len = (int) protos.len; -+ -+ /* set both server and client callbacks, because the context can -+ * be used to create both types of sockets */ -+ SSL_CTX_set_next_protos_advertised_cb(self->ctx, -+ _advertiseNPN_cb, -+ self); -+ SSL_CTX_set_next_proto_select_cb(self->ctx, -+ _selectNPN_cb, -+ self); -+ -+ PyBuffer_Release(&protos); -+ Py_RETURN_NONE; -+#else -+ PyErr_SetString(PyExc_NotImplementedError, -+ "The NPN extension requires OpenSSL 1.0.1 or later."); -+ return NULL; -+#endif -+} -+ -+static PyObject * -+get_verify_mode(PySSLContext *self, void *c) -+{ -+ switch (SSL_CTX_get_verify_mode(self->ctx)) { -+ case SSL_VERIFY_NONE: -+ return PyLong_FromLong(PY_SSL_CERT_NONE); -+ case SSL_VERIFY_PEER: -+ return PyLong_FromLong(PY_SSL_CERT_OPTIONAL); -+ case SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT: -+ return PyLong_FromLong(PY_SSL_CERT_REQUIRED); -+ } -+ PyErr_SetString(PySSLErrorObject, -+ "invalid return value from SSL_CTX_get_verify_mode"); -+ return NULL; -+} -+ -+static int -+set_verify_mode(PySSLContext *self, PyObject *arg, void *c) -+{ -+ int n, mode; -+ if (!PyArg_Parse(arg, "i", &n)) -+ return -1; -+ if (n == PY_SSL_CERT_NONE) -+ mode = SSL_VERIFY_NONE; -+ else if (n == PY_SSL_CERT_OPTIONAL) -+ mode = SSL_VERIFY_PEER; -+ else if (n == PY_SSL_CERT_REQUIRED) -+ mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; -+ else { -+ PyErr_SetString(PyExc_ValueError, -+ "invalid value for verify_mode"); -+ return -1; -+ } -+ if (mode == SSL_VERIFY_NONE && self->check_hostname) { -+ PyErr_SetString(PyExc_ValueError, -+ "Cannot set verify_mode to CERT_NONE when " -+ "check_hostname is enabled."); -+ return -1; -+ } -+ SSL_CTX_set_verify(self->ctx, mode, NULL); -+ return 0; -+} -+ -+#ifdef HAVE_OPENSSL_VERIFY_PARAM -+static PyObject * -+get_verify_flags(PySSLContext *self, void *c) -+{ -+ X509_STORE *store; -+ unsigned long flags; -+ -+ store = SSL_CTX_get_cert_store(self->ctx); -+ flags = X509_VERIFY_PARAM_get_flags(store->param); -+ return PyLong_FromUnsignedLong(flags); -+} -+ -+static int -+set_verify_flags(PySSLContext *self, PyObject *arg, void *c) -+{ -+ X509_STORE *store; -+ unsigned long new_flags, flags, set, clear; -+ -+ if (!PyArg_Parse(arg, "k", &new_flags)) -+ return -1; -+ store = SSL_CTX_get_cert_store(self->ctx); -+ flags = X509_VERIFY_PARAM_get_flags(store->param); -+ clear = flags & ~new_flags; -+ set = ~flags & new_flags; -+ if (clear) { -+ if (!X509_VERIFY_PARAM_clear_flags(store->param, clear)) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ return -1; -+ } -+ } -+ if (set) { -+ if (!X509_VERIFY_PARAM_set_flags(store->param, set)) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ return -1; -+ } -+ } -+ return 0; -+} -+#endif -+ -+static PyObject * -+get_options(PySSLContext *self, void *c) -+{ -+ return PyLong_FromLong(SSL_CTX_get_options(self->ctx)); -+} -+ -+static int -+set_options(PySSLContext *self, PyObject *arg, void *c) -+{ -+ long new_opts, opts, set, clear; -+ if (!PyArg_Parse(arg, "l", &new_opts)) -+ return -1; -+ opts = SSL_CTX_get_options(self->ctx); -+ clear = opts & ~new_opts; -+ set = ~opts & new_opts; -+ if (clear) { -+#ifdef HAVE_SSL_CTX_CLEAR_OPTIONS -+ SSL_CTX_clear_options(self->ctx, clear); -+#else -+ PyErr_SetString(PyExc_ValueError, -+ "can't clear options before OpenSSL 0.9.8m"); -+ return -1; -+#endif -+ } -+ if (set) -+ SSL_CTX_set_options(self->ctx, set); -+ return 0; -+} -+ -+static PyObject * -+get_check_hostname(PySSLContext *self, void *c) -+{ -+ return PyBool_FromLong(self->check_hostname); -+} -+ -+static int -+set_check_hostname(PySSLContext *self, PyObject *arg, void *c) -+{ -+ PyObject *py_check_hostname; -+ int check_hostname; -+ if (!PyArg_Parse(arg, "O", &py_check_hostname)) -+ return -1; -+ -+ check_hostname = PyObject_IsTrue(py_check_hostname); -+ if (check_hostname < 0) -+ return -1; -+ if (check_hostname && -+ SSL_CTX_get_verify_mode(self->ctx) == SSL_VERIFY_NONE) { -+ PyErr_SetString(PyExc_ValueError, -+ "check_hostname needs a SSL context with either " -+ "CERT_OPTIONAL or CERT_REQUIRED"); -+ return -1; -+ } -+ self->check_hostname = check_hostname; -+ return 0; -+} -+ -+ -+typedef struct { -+ PyThreadState *thread_state; -+ PyObject *callable; -+ char *password; -+ int size; -+ int error; -+} _PySSLPasswordInfo; -+ -+static int -+_pwinfo_set(_PySSLPasswordInfo *pw_info, PyObject* password, -+ const char *bad_type_error) -+{ -+ /* Set the password and size fields of a _PySSLPasswordInfo struct -+ from a unicode, bytes, or byte array object. -+ The password field will be dynamically allocated and must be freed -+ by the caller */ -+ PyObject *password_bytes = NULL; -+ const char *data = NULL; -+ Py_ssize_t size; -+ -+ if (PyUnicode_Check(password)) { -+ password_bytes = PyUnicode_AsEncodedString(password, NULL, NULL); -+ if (!password_bytes) { -+ goto error; -+ } -+ data = PyBytes_AS_STRING(password_bytes); -+ size = PyBytes_GET_SIZE(password_bytes); -+ } else if (PyBytes_Check(password)) { -+ data = PyBytes_AS_STRING(password); -+ size = PyBytes_GET_SIZE(password); -+ } else if (PyByteArray_Check(password)) { -+ data = PyByteArray_AS_STRING(password); -+ size = PyByteArray_GET_SIZE(password); -+ } else { -+ PyErr_SetString(PyExc_TypeError, bad_type_error); -+ goto error; -+ } -+ -+ if (size > (Py_ssize_t)INT_MAX) { -+ PyErr_Format(PyExc_ValueError, -+ "password cannot be longer than %d bytes", INT_MAX); -+ goto error; -+ } -+ -+ PyMem_Free(pw_info->password); -+ pw_info->password = PyMem_Malloc(size); -+ if (!pw_info->password) { -+ PyErr_SetString(PyExc_MemoryError, -+ "unable to allocate password buffer"); -+ goto error; -+ } -+ memcpy(pw_info->password, data, size); -+ pw_info->size = (int)size; -+ -+ Py_XDECREF(password_bytes); -+ return 1; -+ -+error: -+ Py_XDECREF(password_bytes); -+ return 0; -+} -+ -+static int -+_password_callback(char *buf, int size, int rwflag, void *userdata) -+{ -+ _PySSLPasswordInfo *pw_info = (_PySSLPasswordInfo*) userdata; -+ PyObject *fn_ret = NULL; -+ -+ PySSL_END_ALLOW_THREADS_S(pw_info->thread_state); -+ -+ if (pw_info->callable) { -+ fn_ret = PyObject_CallFunctionObjArgs(pw_info->callable, NULL); -+ if (!fn_ret) { -+ /* TODO: It would be nice to move _ctypes_add_traceback() into the -+ core python API, so we could use it to add a frame here */ -+ goto error; -+ } -+ -+ if (!_pwinfo_set(pw_info, fn_ret, -+ "password callback must return a string")) { -+ goto error; -+ } -+ Py_CLEAR(fn_ret); -+ } -+ -+ if (pw_info->size > size) { -+ PyErr_Format(PyExc_ValueError, -+ "password cannot be longer than %d bytes", size); -+ goto error; -+ } -+ -+ PySSL_BEGIN_ALLOW_THREADS_S(pw_info->thread_state); -+ memcpy(buf, pw_info->password, pw_info->size); -+ return pw_info->size; -+ -+error: -+ Py_XDECREF(fn_ret); -+ PySSL_BEGIN_ALLOW_THREADS_S(pw_info->thread_state); -+ pw_info->error = 1; -+ return -1; -+} -+ -+static PyObject * -+load_cert_chain(PySSLContext *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"certfile", "keyfile", "password", NULL}; -+ PyObject *password = NULL; -+ char *certfile_bytes = NULL, *keyfile_bytes = NULL; -+ pem_password_cb *orig_passwd_cb = self->ctx->default_passwd_callback; -+ void *orig_passwd_userdata = self->ctx->default_passwd_callback_userdata; -+ _PySSLPasswordInfo pw_info = { NULL, NULL, NULL, 0, 0 }; -+ int r; -+ -+ errno = 0; -+ ERR_clear_error(); -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, -+ "et|etO:load_cert_chain", kwlist, -+ Py_FileSystemDefaultEncoding, &certfile_bytes, -+ Py_FileSystemDefaultEncoding, &keyfile_bytes, -+ &password)) -+ return NULL; -+ if (password && password != Py_None) { -+ if (PyCallable_Check(password)) { -+ pw_info.callable = password; -+ } else if (!_pwinfo_set(&pw_info, password, -+ "password should be a string or callable")) { -+ goto error; -+ } -+ SSL_CTX_set_default_passwd_cb(self->ctx, _password_callback); -+ SSL_CTX_set_default_passwd_cb_userdata(self->ctx, &pw_info); -+ } -+ PySSL_BEGIN_ALLOW_THREADS_S(pw_info.thread_state); -+ r = SSL_CTX_use_certificate_chain_file(self->ctx, certfile_bytes); -+ PySSL_END_ALLOW_THREADS_S(pw_info.thread_state); -+ if (r != 1) { -+ if (pw_info.error) { -+ ERR_clear_error(); -+ /* the password callback has already set the error information */ -+ } -+ else if (errno != 0) { -+ ERR_clear_error(); -+ PyErr_SetFromErrno(PyExc_IOError); -+ } -+ else { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ } -+ goto error; -+ } -+ PySSL_BEGIN_ALLOW_THREADS_S(pw_info.thread_state); -+ r = SSL_CTX_use_PrivateKey_file(self->ctx, -+ keyfile_bytes ? keyfile_bytes : certfile_bytes, -+ SSL_FILETYPE_PEM); -+ PySSL_END_ALLOW_THREADS_S(pw_info.thread_state); -+ if (r != 1) { -+ if (pw_info.error) { -+ ERR_clear_error(); -+ /* the password callback has already set the error information */ -+ } -+ else if (errno != 0) { -+ ERR_clear_error(); -+ PyErr_SetFromErrno(PyExc_IOError); -+ } -+ else { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ } -+ goto error; -+ } -+ PySSL_BEGIN_ALLOW_THREADS_S(pw_info.thread_state); -+ r = SSL_CTX_check_private_key(self->ctx); -+ PySSL_END_ALLOW_THREADS_S(pw_info.thread_state); -+ if (r != 1) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ goto error; -+ } -+ SSL_CTX_set_default_passwd_cb(self->ctx, orig_passwd_cb); -+ SSL_CTX_set_default_passwd_cb_userdata(self->ctx, orig_passwd_userdata); -+ PyMem_Free(pw_info.password); -+ Py_RETURN_NONE; -+ -+error: -+ SSL_CTX_set_default_passwd_cb(self->ctx, orig_passwd_cb); -+ SSL_CTX_set_default_passwd_cb_userdata(self->ctx, orig_passwd_userdata); -+ PyMem_Free(pw_info.password); -+ PyMem_Free(keyfile_bytes); -+ PyMem_Free(certfile_bytes); -+ return NULL; -+} -+ -+/* internal helper function, returns -1 on error -+ */ -+static int -+_add_ca_certs(PySSLContext *self, void *data, Py_ssize_t len, -+ int filetype) -+{ -+ BIO *biobuf = NULL; -+ X509_STORE *store; -+ int retval = 0, err, loaded = 0; -+ -+ assert(filetype == SSL_FILETYPE_ASN1 || filetype == SSL_FILETYPE_PEM); -+ -+ if (len <= 0) { -+ PyErr_SetString(PyExc_ValueError, -+ "Empty certificate data"); -+ return -1; -+ } else if (len > INT_MAX) { -+ PyErr_SetString(PyExc_OverflowError, -+ "Certificate data is too long."); -+ return -1; -+ } -+ -+ biobuf = BIO_new_mem_buf(data, (int)len); -+ if (biobuf == NULL) { -+ _setSSLError("Can't allocate buffer", 0, __FILE__, __LINE__); -+ return -1; -+ } -+ -+ store = SSL_CTX_get_cert_store(self->ctx); -+ assert(store != NULL); -+ -+ while (1) { -+ X509 *cert = NULL; -+ int r; -+ -+ if (filetype == SSL_FILETYPE_ASN1) { -+ cert = d2i_X509_bio(biobuf, NULL); -+ } else { -+ cert = PEM_read_bio_X509(biobuf, NULL, -+ self->ctx->default_passwd_callback, -+ self->ctx->default_passwd_callback_userdata); -+ } -+ if (cert == NULL) { -+ break; -+ } -+ r = X509_STORE_add_cert(store, cert); -+ X509_free(cert); -+ if (!r) { -+ err = ERR_peek_last_error(); -+ if ((ERR_GET_LIB(err) == ERR_LIB_X509) && -+ (ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) { -+ /* cert already in hash table, not an error */ -+ ERR_clear_error(); -+ } else { -+ break; -+ } -+ } -+ loaded++; -+ } -+ -+ err = ERR_peek_last_error(); -+ if ((filetype == SSL_FILETYPE_ASN1) && -+ (loaded > 0) && -+ (ERR_GET_LIB(err) == ERR_LIB_ASN1) && -+ (ERR_GET_REASON(err) == ASN1_R_HEADER_TOO_LONG)) { -+ /* EOF ASN1 file, not an error */ -+ ERR_clear_error(); -+ retval = 0; -+ } else if ((filetype == SSL_FILETYPE_PEM) && -+ (loaded > 0) && -+ (ERR_GET_LIB(err) == ERR_LIB_PEM) && -+ (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { -+ /* EOF PEM file, not an error */ -+ ERR_clear_error(); -+ retval = 0; -+ } else { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ retval = -1; -+ } -+ -+ BIO_free(biobuf); -+ return retval; -+} -+ -+ -+static PyObject * -+load_verify_locations(PySSLContext *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"cafile", "capath", "cadata", NULL}; -+ PyObject *cadata = NULL, *cafile = NULL, *capath = NULL; -+ PyObject *cafile_bytes = NULL, *capath_bytes = NULL; -+ const char *cafile_buf = NULL, *capath_buf = NULL; -+ int r = 0, ok = 1; -+ -+ errno = 0; -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, -+ "|OOO:load_verify_locations", kwlist, -+ &cafile, &capath, &cadata)) -+ return NULL; -+ -+ if (cafile == Py_None) -+ cafile = NULL; -+ if (capath == Py_None) -+ capath = NULL; -+ if (cadata == Py_None) -+ cadata = NULL; -+ -+ if (cafile == NULL && capath == NULL && cadata == NULL) { -+ PyErr_SetString(PyExc_TypeError, -+ "cafile, capath and cadata cannot be all omitted"); -+ goto error; -+ } -+ -+ if (cafile) { -+ cafile_bytes = PyString_AsEncodedObject( -+ cafile, Py_FileSystemDefaultEncoding, "strict"); -+ if (!cafile_bytes) { -+ goto error; -+ } -+ } -+ if (capath) { -+ capath_bytes = PyString_AsEncodedObject( -+ capath, Py_FileSystemDefaultEncoding, "strict"); -+ if (!capath_bytes) { -+ goto error; -+ } -+ } -+ -+ /* validata cadata type and load cadata */ -+ if (cadata) { -+ Py_buffer buf; -+ PyObject *cadata_ascii = NULL; -+ -+ if (!PyUnicode_Check(cadata) && PyObject_GetBuffer(cadata, &buf, PyBUF_SIMPLE) == 0) { -+ if (!PyBuffer_IsContiguous(&buf, 'C') || buf.ndim > 1) { -+ PyBuffer_Release(&buf); -+ PyErr_SetString(PyExc_TypeError, -+ "cadata should be a contiguous buffer with " -+ "a single dimension"); -+ goto error; -+ } -+ r = _add_ca_certs(self, buf.buf, buf.len, SSL_FILETYPE_ASN1); -+ PyBuffer_Release(&buf); -+ if (r == -1) { -+ goto error; -+ } -+ } else { -+ PyErr_Clear(); -+ cadata_ascii = PyUnicode_AsASCIIString(cadata); -+ if (cadata_ascii == NULL) { -+ PyErr_SetString(PyExc_TypeError, -+ "cadata should be a ASCII string or a " -+ "bytes-like object"); -+ goto error; -+ } -+ r = _add_ca_certs(self, -+ PyBytes_AS_STRING(cadata_ascii), -+ PyBytes_GET_SIZE(cadata_ascii), -+ SSL_FILETYPE_PEM); -+ Py_DECREF(cadata_ascii); -+ if (r == -1) { -+ goto error; -+ } -+ } -+ } -+ -+ /* load cafile or capath */ -+ if (cafile_bytes || capath_bytes) { -+ if (cafile) -+ cafile_buf = PyBytes_AS_STRING(cafile_bytes); -+ if (capath) -+ capath_buf = PyBytes_AS_STRING(capath_bytes); -+ PySSL_BEGIN_ALLOW_THREADS -+ r = SSL_CTX_load_verify_locations( -+ self->ctx, -+ cafile_buf, -+ capath_buf); -+ PySSL_END_ALLOW_THREADS -+ if (r != 1) { -+ ok = 0; -+ if (errno != 0) { -+ ERR_clear_error(); -+ PyErr_SetFromErrno(PyExc_IOError); -+ } -+ else { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ } -+ goto error; -+ } -+ } -+ goto end; -+ -+ error: -+ ok = 0; -+ end: -+ Py_XDECREF(cafile_bytes); -+ Py_XDECREF(capath_bytes); -+ if (ok) { -+ Py_RETURN_NONE; -+ } else { -+ return NULL; -+ } -+} -+ -+static PyObject * -+load_dh_params(PySSLContext *self, PyObject *filepath) -+{ -+ BIO *bio; -+ DH *dh; -+ char *path = PyBytes_AsString(filepath); -+ if (!path) { -+ return NULL; -+ } -+ -+ bio = BIO_new_file(path, "r"); -+ if (bio == NULL) { -+ ERR_clear_error(); -+ PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, filepath); -+ return NULL; -+ } -+ errno = 0; -+ PySSL_BEGIN_ALLOW_THREADS -+ dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); -+ BIO_free(bio); -+ PySSL_END_ALLOW_THREADS -+ if (dh == NULL) { -+ if (errno != 0) { -+ ERR_clear_error(); -+ PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, filepath); -+ } -+ else { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ } -+ return NULL; -+ } -+ if (SSL_CTX_set_tmp_dh(self->ctx, dh) == 0) -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ DH_free(dh); -+ Py_RETURN_NONE; -+} -+ -+static PyObject * -+context_wrap_socket(PySSLContext *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"sock", "server_side", "server_hostname", "ssl_sock", NULL}; -+ PySocketSockObject *sock; -+ int server_side = 0; -+ char *hostname = NULL; -+ PyObject *hostname_obj, *ssl_sock = Py_None, *res; -+ -+ /* server_hostname is either None (or absent), or to be encoded -+ using the idna encoding. */ -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!i|O!O:_wrap_socket", kwlist, -+ PySocketModule.Sock_Type, -+ &sock, &server_side, -+ Py_TYPE(Py_None), &hostname_obj, -+ &ssl_sock)) { -+ PyErr_Clear(); -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!iet|O:_wrap_socket", kwlist, -+ PySocketModule.Sock_Type, -+ &sock, &server_side, -+ "idna", &hostname, &ssl_sock)) -+ return NULL; -+#if !HAVE_SNI -+ PyMem_Free(hostname); -+ PyErr_SetString(PyExc_ValueError, "server_hostname is not supported " -+ "by your OpenSSL library"); -+ return NULL; -+#endif -+ } -+ -+ res = (PyObject *) newPySSLSocket(self, sock, server_side, -+ hostname, ssl_sock); -+ if (hostname != NULL) -+ PyMem_Free(hostname); -+ return res; -+} -+ -+static PyObject * -+session_stats(PySSLContext *self, PyObject *unused) -+{ -+ int r; -+ PyObject *value, *stats = PyDict_New(); -+ if (!stats) -+ return NULL; -+ -+#define ADD_STATS(SSL_NAME, KEY_NAME) \ -+ value = PyLong_FromLong(SSL_CTX_sess_ ## SSL_NAME (self->ctx)); \ -+ if (value == NULL) \ -+ goto error; \ -+ r = PyDict_SetItemString(stats, KEY_NAME, value); \ -+ Py_DECREF(value); \ -+ if (r < 0) \ -+ goto error; -+ -+ ADD_STATS(number, "number"); -+ ADD_STATS(connect, "connect"); -+ ADD_STATS(connect_good, "connect_good"); -+ ADD_STATS(connect_renegotiate, "connect_renegotiate"); -+ ADD_STATS(accept, "accept"); -+ ADD_STATS(accept_good, "accept_good"); -+ ADD_STATS(accept_renegotiate, "accept_renegotiate"); -+ ADD_STATS(accept, "accept"); -+ ADD_STATS(hits, "hits"); -+ ADD_STATS(misses, "misses"); -+ ADD_STATS(timeouts, "timeouts"); -+ ADD_STATS(cache_full, "cache_full"); -+ -+#undef ADD_STATS -+ -+ return stats; -+ -+error: -+ Py_DECREF(stats); -+ return NULL; -+} -+ -+static PyObject * -+set_default_verify_paths(PySSLContext *self, PyObject *unused) -+{ -+ if (!SSL_CTX_set_default_verify_paths(self->ctx)) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ return NULL; -+ } -+ Py_RETURN_NONE; -+} -+ -+#ifndef OPENSSL_NO_ECDH -+static PyObject * -+set_ecdh_curve(PySSLContext *self, PyObject *name) -+{ -+ char *name_bytes; -+ int nid; -+ EC_KEY *key; -+ -+ name_bytes = PyBytes_AsString(name); -+ if (!name_bytes) { -+ return NULL; -+ } -+ nid = OBJ_sn2nid(name_bytes); -+ if (nid == 0) { -+ PyErr_Format(PyExc_ValueError, -+ "unknown elliptic curve name %R", name); -+ return NULL; -+ } -+ key = EC_KEY_new_by_curve_name(nid); -+ if (key == NULL) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ return NULL; -+ } -+ SSL_CTX_set_tmp_ecdh(self->ctx, key); -+ EC_KEY_free(key); -+ Py_RETURN_NONE; -+} -+#endif -+ -+#if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT) -+static int -+_servername_callback(SSL *s, int *al, void *args) -+{ -+ int ret; -+ PySSLContext *ssl_ctx = (PySSLContext *) args; -+ PySSLSocket *ssl; -+ PyObject *servername_o; -+ PyObject *servername_idna; -+ PyObject *result; -+ /* The high-level ssl.SSLSocket object */ -+ PyObject *ssl_socket; -+ const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); -+#ifdef WITH_THREAD -+ PyGILState_STATE gstate = PyGILState_Ensure(); -+#endif -+ -+ if (ssl_ctx->set_hostname == NULL) { -+ /* remove race condition in this the call back while if removing the -+ * callback is in progress */ -+#ifdef WITH_THREAD -+ PyGILState_Release(gstate); -+#endif -+ return SSL_TLSEXT_ERR_OK; -+ } -+ -+ ssl = SSL_get_app_data(s); -+ assert(PySSLSocket_Check(ssl)); -+ ssl_socket = PyWeakref_GetObject(ssl->ssl_sock); -+ Py_INCREF(ssl_socket); -+ if (ssl_socket == Py_None) { -+ goto error; -+ } -+ -+ if (servername == NULL) { -+ result = PyObject_CallFunctionObjArgs(ssl_ctx->set_hostname, ssl_socket, -+ Py_None, ssl_ctx, NULL); -+ } -+ else { -+ servername_o = PyBytes_FromString(servername); -+ if (servername_o == NULL) { -+ PyErr_WriteUnraisable((PyObject *) ssl_ctx); -+ goto error; -+ } -+ servername_idna = PyUnicode_FromEncodedObject(servername_o, "idna", NULL); -+ if (servername_idna == NULL) { -+ PyErr_WriteUnraisable(servername_o); -+ Py_DECREF(servername_o); -+ goto error; -+ } -+ Py_DECREF(servername_o); -+ result = PyObject_CallFunctionObjArgs(ssl_ctx->set_hostname, ssl_socket, -+ servername_idna, ssl_ctx, NULL); -+ Py_DECREF(servername_idna); -+ } -+ Py_DECREF(ssl_socket); -+ -+ if (result == NULL) { -+ PyErr_WriteUnraisable(ssl_ctx->set_hostname); -+ *al = SSL_AD_HANDSHAKE_FAILURE; -+ ret = SSL_TLSEXT_ERR_ALERT_FATAL; -+ } -+ else { -+ if (result != Py_None) { -+ *al = (int) PyLong_AsLong(result); -+ if (PyErr_Occurred()) { -+ PyErr_WriteUnraisable(result); -+ *al = SSL_AD_INTERNAL_ERROR; -+ } -+ ret = SSL_TLSEXT_ERR_ALERT_FATAL; -+ } -+ else { -+ ret = SSL_TLSEXT_ERR_OK; -+ } -+ Py_DECREF(result); -+ } -+ -+#ifdef WITH_THREAD -+ PyGILState_Release(gstate); -+#endif -+ return ret; -+ -+error: -+ Py_DECREF(ssl_socket); -+ *al = SSL_AD_INTERNAL_ERROR; -+ ret = SSL_TLSEXT_ERR_ALERT_FATAL; -+#ifdef WITH_THREAD -+ PyGILState_Release(gstate); -+#endif -+ return ret; -+} -+#endif -+ -+PyDoc_STRVAR(PySSL_set_servername_callback_doc, -+"set_servername_callback(method)\n\ -+\n\ -+This sets a callback that will be called when a server name is provided by\n\ -+the SSL/TLS client in the SNI extension.\n\ -+\n\ -+If the argument is None then the callback is disabled. The method is called\n\ -+with the SSLSocket, the server name as a string, and the SSLContext object.\n\ -+See RFC 6066 for details of the SNI extension."); -+ -+static PyObject * -+set_servername_callback(PySSLContext *self, PyObject *args) -+{ -+#if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT) -+ PyObject *cb; -+ -+ if (!PyArg_ParseTuple(args, "O", &cb)) -+ return NULL; -+ -+ Py_CLEAR(self->set_hostname); -+ if (cb == Py_None) { -+ SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); -+ } -+ else { -+ if (!PyCallable_Check(cb)) { -+ SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); -+ PyErr_SetString(PyExc_TypeError, -+ "not a callable object"); -+ return NULL; -+ } -+ Py_INCREF(cb); -+ self->set_hostname = cb; -+ SSL_CTX_set_tlsext_servername_callback(self->ctx, _servername_callback); -+ SSL_CTX_set_tlsext_servername_arg(self->ctx, self); -+ } -+ Py_RETURN_NONE; -+#else -+ PyErr_SetString(PyExc_NotImplementedError, -+ "The TLS extension servername callback, " -+ "SSL_CTX_set_tlsext_servername_callback, " -+ "is not in the current OpenSSL library."); -+ return NULL; -+#endif -+} -+ -+PyDoc_STRVAR(PySSL_get_stats_doc, -+"cert_store_stats() -> {'crl': int, 'x509_ca': int, 'x509': int}\n\ -+\n\ -+Returns quantities of loaded X.509 certificates. X.509 certificates with a\n\ -+CA extension and certificate revocation lists inside the context's cert\n\ -+store.\n\ -+NOTE: Certificates in a capath directory aren't loaded unless they have\n\ -+been used at least once."); -+ -+static PyObject * -+cert_store_stats(PySSLContext *self) -+{ -+ X509_STORE *store; -+ X509_OBJECT *obj; -+ int x509 = 0, crl = 0, pkey = 0, ca = 0, i; -+ -+ store = SSL_CTX_get_cert_store(self->ctx); -+ for (i = 0; i < sk_X509_OBJECT_num(store->objs); i++) { -+ obj = sk_X509_OBJECT_value(store->objs, i); -+ switch (obj->type) { -+ case X509_LU_X509: -+ x509++; -+ if (X509_check_ca(obj->data.x509)) { -+ ca++; -+ } -+ break; -+ case X509_LU_CRL: -+ crl++; -+ break; -+ case X509_LU_PKEY: -+ pkey++; -+ break; -+ default: -+ /* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY. -+ * As far as I can tell they are internal states and never -+ * stored in a cert store */ -+ break; -+ } -+ } -+ return Py_BuildValue("{sisisi}", "x509", x509, "crl", crl, -+ "x509_ca", ca); -+} -+ -+PyDoc_STRVAR(PySSL_get_ca_certs_doc, -+"get_ca_certs(binary_form=False) -> list of loaded certificate\n\ -+\n\ -+Returns a list of dicts with information of loaded CA certs. If the\n\ -+optional argument is True, returns a DER-encoded copy of the CA certificate.\n\ -+NOTE: Certificates in a capath directory aren't loaded unless they have\n\ -+been used at least once."); -+ -+static PyObject * -+get_ca_certs(PySSLContext *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"binary_form", NULL}; -+ X509_STORE *store; -+ PyObject *ci = NULL, *rlist = NULL, *py_binary_mode = Py_False; -+ int i; -+ int binary_mode = 0; -+ -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:get_ca_certs", -+ kwlist, &py_binary_mode)) { -+ return NULL; -+ } -+ binary_mode = PyObject_IsTrue(py_binary_mode); -+ if (binary_mode < 0) { -+ return NULL; -+ } -+ -+ if ((rlist = PyList_New(0)) == NULL) { -+ return NULL; -+ } -+ -+ store = SSL_CTX_get_cert_store(self->ctx); -+ for (i = 0; i < sk_X509_OBJECT_num(store->objs); i++) { -+ X509_OBJECT *obj; -+ X509 *cert; -+ -+ obj = sk_X509_OBJECT_value(store->objs, i); -+ if (obj->type != X509_LU_X509) { -+ /* not a x509 cert */ -+ continue; -+ } -+ /* CA for any purpose */ -+ cert = obj->data.x509; -+ if (!X509_check_ca(cert)) { -+ continue; -+ } -+ if (binary_mode) { -+ ci = _certificate_to_der(cert); -+ } else { -+ ci = _decode_certificate(cert); -+ } -+ if (ci == NULL) { -+ goto error; -+ } -+ if (PyList_Append(rlist, ci) == -1) { -+ goto error; -+ } -+ Py_CLEAR(ci); -+ } -+ return rlist; -+ -+ error: -+ Py_XDECREF(ci); -+ Py_XDECREF(rlist); -+ return NULL; -+} -+ -+ -+static PyGetSetDef context_getsetlist[] = { -+ {"check_hostname", (getter) get_check_hostname, -+ (setter) set_check_hostname, NULL}, -+ {"options", (getter) get_options, -+ (setter) set_options, NULL}, -+#ifdef HAVE_OPENSSL_VERIFY_PARAM -+ {"verify_flags", (getter) get_verify_flags, -+ (setter) set_verify_flags, NULL}, -+#endif -+ {"verify_mode", (getter) get_verify_mode, -+ (setter) set_verify_mode, NULL}, -+ {NULL}, /* sentinel */ -+}; -+ -+static struct PyMethodDef context_methods[] = { -+ {"_wrap_socket", (PyCFunction) context_wrap_socket, -+ METH_VARARGS | METH_KEYWORDS, NULL}, -+ {"set_ciphers", (PyCFunction) set_ciphers, -+ METH_VARARGS, NULL}, -+ {"_set_npn_protocols", (PyCFunction) _set_npn_protocols, -+ METH_VARARGS, NULL}, -+ {"load_cert_chain", (PyCFunction) load_cert_chain, -+ METH_VARARGS | METH_KEYWORDS, NULL}, -+ {"load_dh_params", (PyCFunction) load_dh_params, -+ METH_O, NULL}, -+ {"load_verify_locations", (PyCFunction) load_verify_locations, -+ METH_VARARGS | METH_KEYWORDS, NULL}, -+ {"session_stats", (PyCFunction) session_stats, -+ METH_NOARGS, NULL}, -+ {"set_default_verify_paths", (PyCFunction) set_default_verify_paths, -+ METH_NOARGS, NULL}, -+#ifndef OPENSSL_NO_ECDH -+ {"set_ecdh_curve", (PyCFunction) set_ecdh_curve, -+ METH_O, NULL}, -+#endif -+ {"set_servername_callback", (PyCFunction) set_servername_callback, -+ METH_VARARGS, PySSL_set_servername_callback_doc}, -+ {"cert_store_stats", (PyCFunction) cert_store_stats, -+ METH_NOARGS, PySSL_get_stats_doc}, -+ {"get_ca_certs", (PyCFunction) get_ca_certs, -+ METH_VARARGS | METH_KEYWORDS, PySSL_get_ca_certs_doc}, -+ {NULL, NULL} /* sentinel */ -+}; -+ -+static PyTypeObject PySSLContext_Type = { -+ PyVarObject_HEAD_INIT(NULL, 0) -+ "_ssl._SSLContext", /*tp_name*/ -+ sizeof(PySSLContext), /*tp_basicsize*/ -+ 0, /*tp_itemsize*/ -+ (destructor)context_dealloc, /*tp_dealloc*/ -+ 0, /*tp_print*/ -+ 0, /*tp_getattr*/ -+ 0, /*tp_setattr*/ -+ 0, /*tp_reserved*/ -+ 0, /*tp_repr*/ -+ 0, /*tp_as_number*/ -+ 0, /*tp_as_sequence*/ -+ 0, /*tp_as_mapping*/ -+ 0, /*tp_hash*/ -+ 0, /*tp_call*/ -+ 0, /*tp_str*/ -+ 0, /*tp_getattro*/ -+ 0, /*tp_setattro*/ -+ 0, /*tp_as_buffer*/ -+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ -+ 0, /*tp_doc*/ -+ (traverseproc) context_traverse, /*tp_traverse*/ -+ (inquiry) context_clear, /*tp_clear*/ -+ 0, /*tp_richcompare*/ -+ 0, /*tp_weaklistoffset*/ -+ 0, /*tp_iter*/ -+ 0, /*tp_iternext*/ -+ context_methods, /*tp_methods*/ -+ 0, /*tp_members*/ -+ context_getsetlist, /*tp_getset*/ -+ 0, /*tp_base*/ -+ 0, /*tp_dict*/ -+ 0, /*tp_descr_get*/ -+ 0, /*tp_descr_set*/ -+ 0, /*tp_dictoffset*/ -+ 0, /*tp_init*/ -+ 0, /*tp_alloc*/ -+ context_new, /*tp_new*/ -+}; -+ -+ -+ - #ifdef HAVE_OPENSSL_RAND - - /* helper routines for seeding the SSL PRNG */ -@@ -1572,12 +3212,21 @@ static PyObject * - PySSL_RAND_add(PyObject *self, PyObject *args) - { - char *buf; -- int len; -+ Py_ssize_t len, written; - double entropy; - - if (!PyArg_ParseTuple(args, "s#d:RAND_add", &buf, &len, &entropy)) - return NULL; -- RAND_add(buf, len, entropy); -+ do { -+ if (len >= INT_MAX) { -+ written = INT_MAX; -+ } else { -+ written = len; -+ } -+ RAND_add(buf, (int)written, entropy); -+ buf += written; -+ len -= written; -+ } while (len); - Py_INCREF(Py_None); - return Py_None; - } -@@ -1591,7 +3240,7 @@ bound on the entropy contained in string - static PyObject * - PySSL_RAND_status(PyObject *self) - { -- return PyInt_FromLong(RAND_status()); -+ return PyLong_FromLong(RAND_status()); - } - - PyDoc_STRVAR(PySSL_RAND_status_doc, -@@ -1630,21 +3279,413 @@ fails or if it does not provide enough d - #endif /* HAVE_OPENSSL_RAND */ - - -+PyDoc_STRVAR(PySSL_get_default_verify_paths_doc, -+"get_default_verify_paths() -> tuple\n\ -+\n\ -+Return search paths and environment vars that are used by SSLContext's\n\ -+set_default_verify_paths() to load default CAs. The values are\n\ -+'cert_file_env', 'cert_file', 'cert_dir_env', 'cert_dir'."); -+ -+static PyObject * -+PySSL_get_default_verify_paths(PyObject *self) -+{ -+ PyObject *ofile_env = NULL; -+ PyObject *ofile = NULL; -+ PyObject *odir_env = NULL; -+ PyObject *odir = NULL; -+ -+#define convert(info, target) { \ -+ const char *tmp = (info); \ -+ target = NULL; \ -+ if (!tmp) { Py_INCREF(Py_None); target = Py_None; } \ -+ else { target = PyBytes_FromString(tmp); } \ -+ if (!target) goto error; \ -+ } while(0) -+ -+ convert(X509_get_default_cert_file_env(), ofile_env); -+ convert(X509_get_default_cert_file(), ofile); -+ convert(X509_get_default_cert_dir_env(), odir_env); -+ convert(X509_get_default_cert_dir(), odir); -+#undef convert -+ -+ return Py_BuildValue("NNNN", ofile_env, ofile, odir_env, odir); -+ -+ error: -+ Py_XDECREF(ofile_env); -+ Py_XDECREF(ofile); -+ Py_XDECREF(odir_env); -+ Py_XDECREF(odir); -+ return NULL; -+} -+ -+static PyObject* -+asn1obj2py(ASN1_OBJECT *obj) -+{ -+ int nid; -+ const char *ln, *sn; -+ char buf[100]; -+ Py_ssize_t buflen; -+ -+ nid = OBJ_obj2nid(obj); -+ if (nid == NID_undef) { -+ PyErr_Format(PyExc_ValueError, "Unknown object"); -+ return NULL; -+ } -+ sn = OBJ_nid2sn(nid); -+ ln = OBJ_nid2ln(nid); -+ buflen = OBJ_obj2txt(buf, sizeof(buf), obj, 1); -+ if (buflen < 0) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ return NULL; -+ } -+ if (buflen) { -+ return Py_BuildValue("isss#", nid, sn, ln, buf, buflen); -+ } else { -+ return Py_BuildValue("issO", nid, sn, ln, Py_None); -+ } -+} -+ -+PyDoc_STRVAR(PySSL_txt2obj_doc, -+"txt2obj(txt, name=False) -> (nid, shortname, longname, oid)\n\ -+\n\ -+Lookup NID, short name, long name and OID of an ASN1_OBJECT. By default\n\ -+objects are looked up by OID. With name=True short and long name are also\n\ -+matched."); -+ -+static PyObject* -+PySSL_txt2obj(PyObject *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"txt", "name", NULL}; -+ PyObject *result = NULL; -+ char *txt; -+ PyObject *pyname = Py_None; -+ int name = 0; -+ ASN1_OBJECT *obj; -+ -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O:txt2obj", -+ kwlist, &txt, &pyname)) { -+ return NULL; -+ } -+ name = PyObject_IsTrue(pyname); -+ if (name < 0) -+ return NULL; -+ obj = OBJ_txt2obj(txt, name ? 0 : 1); -+ if (obj == NULL) { -+ PyErr_Format(PyExc_ValueError, "unknown object '%.100s'", txt); -+ return NULL; -+ } -+ result = asn1obj2py(obj); -+ ASN1_OBJECT_free(obj); -+ return result; -+} -+ -+PyDoc_STRVAR(PySSL_nid2obj_doc, -+"nid2obj(nid) -> (nid, shortname, longname, oid)\n\ -+\n\ -+Lookup NID, short name, long name and OID of an ASN1_OBJECT by NID."); -+ -+static PyObject* -+PySSL_nid2obj(PyObject *self, PyObject *args) -+{ -+ PyObject *result = NULL; -+ int nid; -+ ASN1_OBJECT *obj; -+ -+ if (!PyArg_ParseTuple(args, "i:nid2obj", &nid)) { -+ return NULL; -+ } -+ if (nid < NID_undef) { -+ PyErr_SetString(PyExc_ValueError, "NID must be positive."); -+ return NULL; -+ } -+ obj = OBJ_nid2obj(nid); -+ if (obj == NULL) { -+ PyErr_Format(PyExc_ValueError, "unknown NID %i", nid); -+ return NULL; -+ } -+ result = asn1obj2py(obj); -+ ASN1_OBJECT_free(obj); -+ return result; -+} -+ -+#ifdef _MSC_VER -+ -+static PyObject* -+certEncodingType(DWORD encodingType) -+{ -+ static PyObject *x509_asn = NULL; -+ static PyObject *pkcs_7_asn = NULL; -+ -+ if (x509_asn == NULL) { -+ x509_asn = PyUnicode_InternFromString("x509_asn"); -+ if (x509_asn == NULL) -+ return NULL; -+ } -+ if (pkcs_7_asn == NULL) { -+ pkcs_7_asn = PyUnicode_InternFromString("pkcs_7_asn"); -+ if (pkcs_7_asn == NULL) -+ return NULL; -+ } -+ switch(encodingType) { -+ case X509_ASN_ENCODING: -+ Py_INCREF(x509_asn); -+ return x509_asn; -+ case PKCS_7_ASN_ENCODING: -+ Py_INCREF(pkcs_7_asn); -+ return pkcs_7_asn; -+ default: -+ return PyLong_FromLong(encodingType); -+ } -+} -+ -+static PyObject* -+parseKeyUsage(PCCERT_CONTEXT pCertCtx, DWORD flags) -+{ -+ CERT_ENHKEY_USAGE *usage; -+ DWORD size, error, i; -+ PyObject *retval; -+ -+ if (!CertGetEnhancedKeyUsage(pCertCtx, flags, NULL, &size)) { -+ error = GetLastError(); -+ if (error == CRYPT_E_NOT_FOUND) { -+ Py_RETURN_TRUE; -+ } -+ return PyErr_SetFromWindowsErr(error); -+ } -+ -+ usage = (CERT_ENHKEY_USAGE*)PyMem_Malloc(size); -+ if (usage == NULL) { -+ return PyErr_NoMemory(); -+ } -+ -+ /* Now get the actual enhanced usage property */ -+ if (!CertGetEnhancedKeyUsage(pCertCtx, flags, usage, &size)) { -+ PyMem_Free(usage); -+ error = GetLastError(); -+ if (error == CRYPT_E_NOT_FOUND) { -+ Py_RETURN_TRUE; -+ } -+ return PyErr_SetFromWindowsErr(error); -+ } -+ retval = PySet_New(NULL); -+ if (retval == NULL) { -+ goto error; -+ } -+ for (i = 0; i < usage->cUsageIdentifier; ++i) { -+ if (usage->rgpszUsageIdentifier[i]) { -+ PyObject *oid; -+ int err; -+ oid = PyUnicode_FromString(usage->rgpszUsageIdentifier[i]); -+ if (oid == NULL) { -+ Py_CLEAR(retval); -+ goto error; -+ } -+ err = PySet_Add(retval, oid); -+ Py_DECREF(oid); -+ if (err == -1) { -+ Py_CLEAR(retval); -+ goto error; -+ } -+ } -+ } -+ error: -+ PyMem_Free(usage); -+ return retval; -+} -+ -+PyDoc_STRVAR(PySSL_enum_certificates_doc, -+"enum_certificates(store_name) -> []\n\ -+\n\ -+Retrieve certificates from Windows' cert store. store_name may be one of\n\ -+'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.\n\ -+The function returns a list of (bytes, encoding_type, trust) tuples. The\n\ -+encoding_type flag can be interpreted with X509_ASN_ENCODING or\n\ -+PKCS_7_ASN_ENCODING. The trust setting is either a set of OIDs or the\n\ -+boolean True."); -+ -+static PyObject * -+PySSL_enum_certificates(PyObject *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"store_name", NULL}; -+ char *store_name; -+ HCERTSTORE hStore = NULL; -+ PCCERT_CONTEXT pCertCtx = NULL; -+ PyObject *keyusage = NULL, *cert = NULL, *enc = NULL, *tup = NULL; -+ PyObject *result = NULL; -+ -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_certificates", -+ kwlist, &store_name)) { -+ return NULL; -+ } -+ result = PyList_New(0); -+ if (result == NULL) { -+ return NULL; -+ } -+ hStore = CertOpenSystemStore((HCRYPTPROV)NULL, store_name); -+ if (hStore == NULL) { -+ Py_DECREF(result); -+ return PyErr_SetFromWindowsErr(GetLastError()); -+ } -+ -+ while (pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) { -+ cert = PyBytes_FromStringAndSize((const char*)pCertCtx->pbCertEncoded, -+ pCertCtx->cbCertEncoded); -+ if (!cert) { -+ Py_CLEAR(result); -+ break; -+ } -+ if ((enc = certEncodingType(pCertCtx->dwCertEncodingType)) == NULL) { -+ Py_CLEAR(result); -+ break; -+ } -+ keyusage = parseKeyUsage(pCertCtx, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG); -+ if (keyusage == Py_True) { -+ Py_DECREF(keyusage); -+ keyusage = parseKeyUsage(pCertCtx, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG); -+ } -+ if (keyusage == NULL) { -+ Py_CLEAR(result); -+ break; -+ } -+ if ((tup = PyTuple_New(3)) == NULL) { -+ Py_CLEAR(result); -+ break; -+ } -+ PyTuple_SET_ITEM(tup, 0, cert); -+ cert = NULL; -+ PyTuple_SET_ITEM(tup, 1, enc); -+ enc = NULL; -+ PyTuple_SET_ITEM(tup, 2, keyusage); -+ keyusage = NULL; -+ if (PyList_Append(result, tup) < 0) { -+ Py_CLEAR(result); -+ break; -+ } -+ Py_CLEAR(tup); -+ } -+ if (pCertCtx) { -+ /* loop ended with an error, need to clean up context manually */ -+ CertFreeCertificateContext(pCertCtx); -+ } -+ -+ /* In error cases cert, enc and tup may not be NULL */ -+ Py_XDECREF(cert); -+ Py_XDECREF(enc); -+ Py_XDECREF(keyusage); -+ Py_XDECREF(tup); -+ -+ if (!CertCloseStore(hStore, 0)) { -+ /* This error case might shadow another exception.*/ -+ Py_XDECREF(result); -+ return PyErr_SetFromWindowsErr(GetLastError()); -+ } -+ return result; -+} -+ -+PyDoc_STRVAR(PySSL_enum_crls_doc, -+"enum_crls(store_name) -> []\n\ -+\n\ -+Retrieve CRLs from Windows' cert store. store_name may be one of\n\ -+'CA', 'ROOT' or 'MY'. The system may provide more cert storages, too.\n\ -+The function returns a list of (bytes, encoding_type) tuples. The\n\ -+encoding_type flag can be interpreted with X509_ASN_ENCODING or\n\ -+PKCS_7_ASN_ENCODING."); -+ -+static PyObject * -+PySSL_enum_crls(PyObject *self, PyObject *args, PyObject *kwds) -+{ -+ char *kwlist[] = {"store_name", NULL}; -+ char *store_name; -+ HCERTSTORE hStore = NULL; -+ PCCRL_CONTEXT pCrlCtx = NULL; -+ PyObject *crl = NULL, *enc = NULL, *tup = NULL; -+ PyObject *result = NULL; -+ -+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_crls", -+ kwlist, &store_name)) { -+ return NULL; -+ } -+ result = PyList_New(0); -+ if (result == NULL) { -+ return NULL; -+ } -+ hStore = CertOpenSystemStore((HCRYPTPROV)NULL, store_name); -+ if (hStore == NULL) { -+ Py_DECREF(result); -+ return PyErr_SetFromWindowsErr(GetLastError()); -+ } -+ -+ while (pCrlCtx = CertEnumCRLsInStore(hStore, pCrlCtx)) { -+ crl = PyBytes_FromStringAndSize((const char*)pCrlCtx->pbCrlEncoded, -+ pCrlCtx->cbCrlEncoded); -+ if (!crl) { -+ Py_CLEAR(result); -+ break; -+ } -+ if ((enc = certEncodingType(pCrlCtx->dwCertEncodingType)) == NULL) { -+ Py_CLEAR(result); -+ break; -+ } -+ if ((tup = PyTuple_New(2)) == NULL) { -+ Py_CLEAR(result); -+ break; -+ } -+ PyTuple_SET_ITEM(tup, 0, crl); -+ crl = NULL; -+ PyTuple_SET_ITEM(tup, 1, enc); -+ enc = NULL; -+ -+ if (PyList_Append(result, tup) < 0) { -+ Py_CLEAR(result); -+ break; -+ } -+ Py_CLEAR(tup); -+ } -+ if (pCrlCtx) { -+ /* loop ended with an error, need to clean up context manually */ -+ CertFreeCRLContext(pCrlCtx); -+ } -+ -+ /* In error cases cert, enc and tup may not be NULL */ -+ Py_XDECREF(crl); -+ Py_XDECREF(enc); -+ Py_XDECREF(tup); -+ -+ if (!CertCloseStore(hStore, 0)) { -+ /* This error case might shadow another exception.*/ -+ Py_XDECREF(result); -+ return PyErr_SetFromWindowsErr(GetLastError()); -+ } -+ return result; -+} -+ -+#endif /* _MSC_VER */ -+ - /* List of functions exported by this module. */ - - static PyMethodDef PySSL_methods[] = { -- {"sslwrap", PySSL_sslwrap, -- METH_VARARGS, ssl_doc}, - {"_test_decode_cert", PySSL_test_decode_certificate, - METH_VARARGS}, - #ifdef HAVE_OPENSSL_RAND - {"RAND_add", PySSL_RAND_add, METH_VARARGS, - PySSL_RAND_add_doc}, -- {"RAND_egd", PySSL_RAND_egd, METH_O, -+ {"RAND_egd", PySSL_RAND_egd, METH_VARARGS, - PySSL_RAND_egd_doc}, - {"RAND_status", (PyCFunction)PySSL_RAND_status, METH_NOARGS, - PySSL_RAND_status_doc}, - #endif -+ {"get_default_verify_paths", (PyCFunction)PySSL_get_default_verify_paths, -+ METH_NOARGS, PySSL_get_default_verify_paths_doc}, -+#ifdef _MSC_VER -+ {"enum_certificates", (PyCFunction)PySSL_enum_certificates, -+ METH_VARARGS | METH_KEYWORDS, PySSL_enum_certificates_doc}, -+ {"enum_crls", (PyCFunction)PySSL_enum_crls, -+ METH_VARARGS | METH_KEYWORDS, PySSL_enum_crls_doc}, -+#endif -+ {"txt2obj", (PyCFunction)PySSL_txt2obj, -+ METH_VARARGS | METH_KEYWORDS, PySSL_txt2obj_doc}, -+ {"nid2obj", (PyCFunction)PySSL_nid2obj, -+ METH_VARARGS, PySSL_nid2obj_doc}, - {NULL, NULL} /* Sentinel */ - }; - -@@ -1672,16 +3713,17 @@ static unsigned long - } - #endif - --static void _ssl_thread_locking_function (int mode, int n, const char *file, int line) { -+static void _ssl_thread_locking_function -+ (int mode, int n, const char *file, int line) { - /* this function is needed to perform locking on shared data - structures. (Note that OpenSSL uses a number of global data -- structures that will be implicitly shared whenever multiple threads -- use OpenSSL.) Multi-threaded applications will crash at random if -- it is not set. -- -- locking_function() must be able to handle up to CRYPTO_num_locks() -- different mutex locks. It sets the n-th lock if mode & CRYPTO_LOCK, and -- releases it otherwise. -+ structures that will be implicitly shared whenever multiple -+ threads use OpenSSL.) Multi-threaded applications will -+ crash at random if it is not set. -+ -+ locking_function() must be able to handle up to -+ CRYPTO_num_locks() different mutex locks. It sets the n-th -+ lock if mode & CRYPTO_LOCK, and releases it otherwise. - - file and line are the file number of the function setting the - lock. They can be useful for debugging. -@@ -1705,10 +3747,11 @@ static int _setup_ssl_threads(void) { - if (_ssl_locks == NULL) { - _ssl_locks_count = CRYPTO_num_locks(); - _ssl_locks = (PyThread_type_lock *) -- malloc(sizeof(PyThread_type_lock) * _ssl_locks_count); -+ PyMem_Malloc(sizeof(PyThread_type_lock) * _ssl_locks_count); - if (_ssl_locks == NULL) - return 0; -- memset(_ssl_locks, 0, sizeof(PyThread_type_lock) * _ssl_locks_count); -+ memset(_ssl_locks, 0, -+ sizeof(PyThread_type_lock) * _ssl_locks_count); - for (i = 0; i < _ssl_locks_count; i++) { - _ssl_locks[i] = PyThread_allocate_lock(); - if (_ssl_locks[i] == NULL) { -@@ -1716,7 +3759,7 @@ static int _setup_ssl_threads(void) { - for (j = 0; j < i; j++) { - PyThread_free_lock(_ssl_locks[j]); - } -- free(_ssl_locks); -+ PyMem_Free(_ssl_locks); - return 0; - } - } -@@ -1736,14 +3779,39 @@ PyDoc_STRVAR(module_doc, - "Implementation module for SSL socket operations. See the socket module\n\ - for documentation."); - -+ -+ -+ -+static void -+parse_openssl_version(unsigned long libver, -+ unsigned int *major, unsigned int *minor, -+ unsigned int *fix, unsigned int *patch, -+ unsigned int *status) -+{ -+ *status = libver & 0xF; -+ libver >>= 4; -+ *patch = libver & 0xFF; -+ libver >>= 8; -+ *fix = libver & 0xFF; -+ libver >>= 8; -+ *minor = libver & 0xFF; -+ libver >>= 8; -+ *major = libver & 0xFF; -+} -+ - PyMODINIT_FUNC - init_ssl(void) - { - PyObject *m, *d, *r; - unsigned long libver; - unsigned int major, minor, fix, patch, status; -- -- Py_TYPE(&PySSL_Type) = &PyType_Type; -+ struct py_ssl_error_code *errcode; -+ struct py_ssl_library_code *libcode; -+ -+ if (PyType_Ready(&PySSLContext_Type) < 0) -+ return; -+ if (PyType_Ready(&PySSLSocket_Type) < 0) -+ return; - - m = Py_InitModule3("_ssl", PySSL_methods, module_doc); - if (m == NULL) -@@ -1766,15 +3834,53 @@ init_ssl(void) - OpenSSL_add_all_algorithms(); - - /* Add symbols to module dict */ -- PySSLErrorObject = PyErr_NewException("ssl.SSLError", -- PySocketModule.error, -- NULL); -+ PySSLErrorObject = PyErr_NewExceptionWithDoc( -+ "ssl.SSLError", SSLError_doc, -+ PySocketModule.error, NULL); - if (PySSLErrorObject == NULL) - return; -- if (PyDict_SetItemString(d, "SSLError", PySSLErrorObject) != 0) -+ ((PyTypeObject *)PySSLErrorObject)->tp_str = (reprfunc)SSLError_str; -+ -+ PySSLZeroReturnErrorObject = PyErr_NewExceptionWithDoc( -+ "ssl.SSLZeroReturnError", SSLZeroReturnError_doc, -+ PySSLErrorObject, NULL); -+ PySSLWantReadErrorObject = PyErr_NewExceptionWithDoc( -+ "ssl.SSLWantReadError", SSLWantReadError_doc, -+ PySSLErrorObject, NULL); -+ PySSLWantWriteErrorObject = PyErr_NewExceptionWithDoc( -+ "ssl.SSLWantWriteError", SSLWantWriteError_doc, -+ PySSLErrorObject, NULL); -+ PySSLSyscallErrorObject = PyErr_NewExceptionWithDoc( -+ "ssl.SSLSyscallError", SSLSyscallError_doc, -+ PySSLErrorObject, NULL); -+ PySSLEOFErrorObject = PyErr_NewExceptionWithDoc( -+ "ssl.SSLEOFError", SSLEOFError_doc, -+ PySSLErrorObject, NULL); -+ if (PySSLZeroReturnErrorObject == NULL -+ || PySSLWantReadErrorObject == NULL -+ || PySSLWantWriteErrorObject == NULL -+ || PySSLSyscallErrorObject == NULL -+ || PySSLEOFErrorObject == NULL) - return; -- if (PyDict_SetItemString(d, "SSLType", -- (PyObject *)&PySSL_Type) != 0) -+ -+ ((PyTypeObject *)PySSLZeroReturnErrorObject)->tp_str = (reprfunc)SSLError_str; -+ ((PyTypeObject *)PySSLWantReadErrorObject)->tp_str = (reprfunc)SSLError_str; -+ ((PyTypeObject *)PySSLWantWriteErrorObject)->tp_str = (reprfunc)SSLError_str; -+ ((PyTypeObject *)PySSLSyscallErrorObject)->tp_str = (reprfunc)SSLError_str; -+ ((PyTypeObject *)PySSLEOFErrorObject)->tp_str = (reprfunc)SSLError_str; -+ -+ if (PyDict_SetItemString(d, "SSLError", PySSLErrorObject) != 0 -+ || PyDict_SetItemString(d, "SSLZeroReturnError", PySSLZeroReturnErrorObject) != 0 -+ || PyDict_SetItemString(d, "SSLWantReadError", PySSLWantReadErrorObject) != 0 -+ || PyDict_SetItemString(d, "SSLWantWriteError", PySSLWantWriteErrorObject) != 0 -+ || PyDict_SetItemString(d, "SSLSyscallError", PySSLSyscallErrorObject) != 0 -+ || PyDict_SetItemString(d, "SSLEOFError", PySSLEOFErrorObject) != 0) -+ return; -+ if (PyDict_SetItemString(d, "_SSLContext", -+ (PyObject *)&PySSLContext_Type) != 0) -+ return; -+ if (PyDict_SetItemString(d, "_SSLSocket", -+ (PyObject *)&PySSLSocket_Type) != 0) - return; - PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN", - PY_SSL_ERROR_ZERO_RETURN); -@@ -1802,6 +3908,66 @@ init_ssl(void) - PY_SSL_CERT_OPTIONAL); - PyModule_AddIntConstant(m, "CERT_REQUIRED", - PY_SSL_CERT_REQUIRED); -+ /* CRL verification for verification_flags */ -+ PyModule_AddIntConstant(m, "VERIFY_DEFAULT", -+ 0); -+ PyModule_AddIntConstant(m, "VERIFY_CRL_CHECK_LEAF", -+ X509_V_FLAG_CRL_CHECK); -+ PyModule_AddIntConstant(m, "VERIFY_CRL_CHECK_CHAIN", -+ X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); -+ PyModule_AddIntConstant(m, "VERIFY_X509_STRICT", -+ X509_V_FLAG_X509_STRICT); -+ -+ /* Alert Descriptions from ssl.h */ -+ /* note RESERVED constants no longer intended for use have been removed */ -+ /* http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6 */ -+ -+#define ADD_AD_CONSTANT(s) \ -+ PyModule_AddIntConstant(m, "ALERT_DESCRIPTION_"#s, \ -+ SSL_AD_##s) -+ -+ ADD_AD_CONSTANT(CLOSE_NOTIFY); -+ ADD_AD_CONSTANT(UNEXPECTED_MESSAGE); -+ ADD_AD_CONSTANT(BAD_RECORD_MAC); -+ ADD_AD_CONSTANT(RECORD_OVERFLOW); -+ ADD_AD_CONSTANT(DECOMPRESSION_FAILURE); -+ ADD_AD_CONSTANT(HANDSHAKE_FAILURE); -+ ADD_AD_CONSTANT(BAD_CERTIFICATE); -+ ADD_AD_CONSTANT(UNSUPPORTED_CERTIFICATE); -+ ADD_AD_CONSTANT(CERTIFICATE_REVOKED); -+ ADD_AD_CONSTANT(CERTIFICATE_EXPIRED); -+ ADD_AD_CONSTANT(CERTIFICATE_UNKNOWN); -+ ADD_AD_CONSTANT(ILLEGAL_PARAMETER); -+ ADD_AD_CONSTANT(UNKNOWN_CA); -+ ADD_AD_CONSTANT(ACCESS_DENIED); -+ ADD_AD_CONSTANT(DECODE_ERROR); -+ ADD_AD_CONSTANT(DECRYPT_ERROR); -+ ADD_AD_CONSTANT(PROTOCOL_VERSION); -+ ADD_AD_CONSTANT(INSUFFICIENT_SECURITY); -+ ADD_AD_CONSTANT(INTERNAL_ERROR); -+ ADD_AD_CONSTANT(USER_CANCELLED); -+ ADD_AD_CONSTANT(NO_RENEGOTIATION); -+ /* Not all constants are in old OpenSSL versions */ -+#ifdef SSL_AD_UNSUPPORTED_EXTENSION -+ ADD_AD_CONSTANT(UNSUPPORTED_EXTENSION); -+#endif -+#ifdef SSL_AD_CERTIFICATE_UNOBTAINABLE -+ ADD_AD_CONSTANT(CERTIFICATE_UNOBTAINABLE); -+#endif -+#ifdef SSL_AD_UNRECOGNIZED_NAME -+ ADD_AD_CONSTANT(UNRECOGNIZED_NAME); -+#endif -+#ifdef SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE -+ ADD_AD_CONSTANT(BAD_CERTIFICATE_STATUS_RESPONSE); -+#endif -+#ifdef SSL_AD_BAD_CERTIFICATE_HASH_VALUE -+ ADD_AD_CONSTANT(BAD_CERTIFICATE_HASH_VALUE); -+#endif -+#ifdef SSL_AD_UNKNOWN_PSK_IDENTITY -+ ADD_AD_CONSTANT(UNKNOWN_PSK_IDENTITY); -+#endif -+ -+#undef ADD_AD_CONSTANT - - /* protocol versions */ - #ifndef OPENSSL_NO_SSL2 -@@ -1814,6 +3980,109 @@ init_ssl(void) - PY_SSL_VERSION_SSL23); - PyModule_AddIntConstant(m, "PROTOCOL_TLSv1", - PY_SSL_VERSION_TLS1); -+#if HAVE_TLSv1_2 -+ PyModule_AddIntConstant(m, "PROTOCOL_TLSv1_1", -+ PY_SSL_VERSION_TLS1_1); -+ PyModule_AddIntConstant(m, "PROTOCOL_TLSv1_2", -+ PY_SSL_VERSION_TLS1_2); -+#endif -+ -+ /* protocol options */ -+ PyModule_AddIntConstant(m, "OP_ALL", -+ SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); -+ PyModule_AddIntConstant(m, "OP_NO_SSLv2", SSL_OP_NO_SSLv2); -+ PyModule_AddIntConstant(m, "OP_NO_SSLv3", SSL_OP_NO_SSLv3); -+ PyModule_AddIntConstant(m, "OP_NO_TLSv1", SSL_OP_NO_TLSv1); -+#if HAVE_TLSv1_2 -+ PyModule_AddIntConstant(m, "OP_NO_TLSv1_1", SSL_OP_NO_TLSv1_1); -+ PyModule_AddIntConstant(m, "OP_NO_TLSv1_2", SSL_OP_NO_TLSv1_2); -+#endif -+ PyModule_AddIntConstant(m, "OP_CIPHER_SERVER_PREFERENCE", -+ SSL_OP_CIPHER_SERVER_PREFERENCE); -+ PyModule_AddIntConstant(m, "OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE); -+#ifdef SSL_OP_SINGLE_ECDH_USE -+ PyModule_AddIntConstant(m, "OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE); -+#endif -+#ifdef SSL_OP_NO_COMPRESSION -+ PyModule_AddIntConstant(m, "OP_NO_COMPRESSION", -+ SSL_OP_NO_COMPRESSION); -+#endif -+ -+#if HAVE_SNI -+ r = Py_True; -+#else -+ r = Py_False; -+#endif -+ Py_INCREF(r); -+ PyModule_AddObject(m, "HAS_SNI", r); -+ -+#if HAVE_OPENSSL_FINISHED -+ r = Py_True; -+#else -+ r = Py_False; -+#endif -+ Py_INCREF(r); -+ PyModule_AddObject(m, "HAS_TLS_UNIQUE", r); -+ -+#ifdef OPENSSL_NO_ECDH -+ r = Py_False; -+#else -+ r = Py_True; -+#endif -+ Py_INCREF(r); -+ PyModule_AddObject(m, "HAS_ECDH", r); -+ -+#ifdef OPENSSL_NPN_NEGOTIATED -+ r = Py_True; -+#else -+ r = Py_False; -+#endif -+ Py_INCREF(r); -+ PyModule_AddObject(m, "HAS_NPN", r); -+ -+ /* Mappings for error codes */ -+ err_codes_to_names = PyDict_New(); -+ err_names_to_codes = PyDict_New(); -+ if (err_codes_to_names == NULL || err_names_to_codes == NULL) -+ return; -+ errcode = error_codes; -+ while (errcode->mnemonic != NULL) { -+ PyObject *mnemo, *key; -+ mnemo = PyUnicode_FromString(errcode->mnemonic); -+ key = Py_BuildValue("ii", errcode->library, errcode->reason); -+ if (mnemo == NULL || key == NULL) -+ return; -+ if (PyDict_SetItem(err_codes_to_names, key, mnemo)) -+ return; -+ if (PyDict_SetItem(err_names_to_codes, mnemo, key)) -+ return; -+ Py_DECREF(key); -+ Py_DECREF(mnemo); -+ errcode++; -+ } -+ if (PyModule_AddObject(m, "err_codes_to_names", err_codes_to_names)) -+ return; -+ if (PyModule_AddObject(m, "err_names_to_codes", err_names_to_codes)) -+ return; -+ -+ lib_codes_to_names = PyDict_New(); -+ if (lib_codes_to_names == NULL) -+ return; -+ libcode = library_codes; -+ while (libcode->library != NULL) { -+ PyObject *mnemo, *key; -+ key = PyLong_FromLong(libcode->code); -+ mnemo = PyUnicode_FromString(libcode->library); -+ if (key == NULL || mnemo == NULL) -+ return; -+ if (PyDict_SetItem(lib_codes_to_names, key, mnemo)) -+ return; -+ Py_DECREF(key); -+ Py_DECREF(mnemo); -+ libcode++; -+ } -+ if (PyModule_AddObject(m, "lib_codes_to_names", lib_codes_to_names)) -+ return; - - /* OpenSSL version */ - /* SSLeay() gives us the version of the library linked against, -@@ -1825,15 +4094,7 @@ init_ssl(void) - return; - if (PyModule_AddObject(m, "OPENSSL_VERSION_NUMBER", r)) - return; -- status = libver & 0xF; -- libver >>= 4; -- patch = libver & 0xFF; -- libver >>= 8; -- fix = libver & 0xFF; -- libver >>= 8; -- minor = libver & 0xFF; -- libver >>= 8; -- major = libver & 0xFF; -+ parse_openssl_version(libver, &major, &minor, &fix, &patch, &status); - r = Py_BuildValue("IIIII", major, minor, fix, patch, status); - if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION_INFO", r)) - return; -@@ -1841,4 +4102,9 @@ init_ssl(void) - if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION", r)) - return; - -+ libver = OPENSSL_VERSION_NUMBER; -+ parse_openssl_version(libver, &major, &minor, &fix, &patch, &status); -+ r = Py_BuildValue("IIIII", major, minor, fix, patch, status); -+ if (r == NULL || PyModule_AddObject(m, "_OPENSSL_API_VERSION", r)) -+ return; - } -diff --git a/Modules/_ssl_data.h b/Modules/_ssl_data.h -new file mode 100644 ---- /dev/null -+++ b/Modules/_ssl_data.h -@@ -0,0 +1,1653 @@ -+/* File generated by Tools/ssl/make_ssl_data.py */ -+/* Generated on 2012-05-16T23:56:40.981382 */ -+ -+static struct py_ssl_library_code library_codes[] = { -+ {"PEM", ERR_LIB_PEM}, -+ {"SSL", ERR_LIB_SSL}, -+ {"X509", ERR_LIB_X509}, -+ { NULL } -+}; -+ -+static struct py_ssl_error_code error_codes[] = { -+ #ifdef PEM_R_BAD_BASE64_DECODE -+ {"BAD_BASE64_DECODE", ERR_LIB_PEM, PEM_R_BAD_BASE64_DECODE}, -+ #else -+ {"BAD_BASE64_DECODE", ERR_LIB_PEM, 100}, -+ #endif -+ #ifdef PEM_R_BAD_DECRYPT -+ {"BAD_DECRYPT", ERR_LIB_PEM, PEM_R_BAD_DECRYPT}, -+ #else -+ {"BAD_DECRYPT", ERR_LIB_PEM, 101}, -+ #endif -+ #ifdef PEM_R_BAD_END_LINE -+ {"BAD_END_LINE", ERR_LIB_PEM, PEM_R_BAD_END_LINE}, -+ #else -+ {"BAD_END_LINE", ERR_LIB_PEM, 102}, -+ #endif -+ #ifdef PEM_R_BAD_IV_CHARS -+ {"BAD_IV_CHARS", ERR_LIB_PEM, PEM_R_BAD_IV_CHARS}, -+ #else -+ {"BAD_IV_CHARS", ERR_LIB_PEM, 103}, -+ #endif -+ #ifdef PEM_R_BAD_MAGIC_NUMBER -+ {"BAD_MAGIC_NUMBER", ERR_LIB_PEM, PEM_R_BAD_MAGIC_NUMBER}, -+ #else -+ {"BAD_MAGIC_NUMBER", ERR_LIB_PEM, 116}, -+ #endif -+ #ifdef PEM_R_BAD_PASSWORD_READ -+ {"BAD_PASSWORD_READ", ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ}, -+ #else -+ {"BAD_PASSWORD_READ", ERR_LIB_PEM, 104}, -+ #endif -+ #ifdef PEM_R_BAD_VERSION_NUMBER -+ {"BAD_VERSION_NUMBER", ERR_LIB_PEM, PEM_R_BAD_VERSION_NUMBER}, -+ #else -+ {"BAD_VERSION_NUMBER", ERR_LIB_PEM, 117}, -+ #endif -+ #ifdef PEM_R_BIO_WRITE_FAILURE -+ {"BIO_WRITE_FAILURE", ERR_LIB_PEM, PEM_R_BIO_WRITE_FAILURE}, -+ #else -+ {"BIO_WRITE_FAILURE", ERR_LIB_PEM, 118}, -+ #endif -+ #ifdef PEM_R_CIPHER_IS_NULL -+ {"CIPHER_IS_NULL", ERR_LIB_PEM, PEM_R_CIPHER_IS_NULL}, -+ #else -+ {"CIPHER_IS_NULL", ERR_LIB_PEM, 127}, -+ #endif -+ #ifdef PEM_R_ERROR_CONVERTING_PRIVATE_KEY -+ {"ERROR_CONVERTING_PRIVATE_KEY", ERR_LIB_PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY}, -+ #else -+ {"ERROR_CONVERTING_PRIVATE_KEY", ERR_LIB_PEM, 115}, -+ #endif -+ #ifdef PEM_R_EXPECTING_PRIVATE_KEY_BLOB -+ {"EXPECTING_PRIVATE_KEY_BLOB", ERR_LIB_PEM, PEM_R_EXPECTING_PRIVATE_KEY_BLOB}, -+ #else -+ {"EXPECTING_PRIVATE_KEY_BLOB", ERR_LIB_PEM, 119}, -+ #endif -+ #ifdef PEM_R_EXPECTING_PUBLIC_KEY_BLOB -+ {"EXPECTING_PUBLIC_KEY_BLOB", ERR_LIB_PEM, PEM_R_EXPECTING_PUBLIC_KEY_BLOB}, -+ #else -+ {"EXPECTING_PUBLIC_KEY_BLOB", ERR_LIB_PEM, 120}, -+ #endif -+ #ifdef PEM_R_INCONSISTENT_HEADER -+ {"INCONSISTENT_HEADER", ERR_LIB_PEM, PEM_R_INCONSISTENT_HEADER}, -+ #else -+ {"INCONSISTENT_HEADER", ERR_LIB_PEM, 121}, -+ #endif -+ #ifdef PEM_R_KEYBLOB_HEADER_PARSE_ERROR -+ {"KEYBLOB_HEADER_PARSE_ERROR", ERR_LIB_PEM, PEM_R_KEYBLOB_HEADER_PARSE_ERROR}, -+ #else -+ {"KEYBLOB_HEADER_PARSE_ERROR", ERR_LIB_PEM, 122}, -+ #endif -+ #ifdef PEM_R_KEYBLOB_TOO_SHORT -+ {"KEYBLOB_TOO_SHORT", ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT}, -+ #else -+ {"KEYBLOB_TOO_SHORT", ERR_LIB_PEM, 123}, -+ #endif -+ #ifdef PEM_R_NOT_DEK_INFO -+ {"NOT_DEK_INFO", ERR_LIB_PEM, PEM_R_NOT_DEK_INFO}, -+ #else -+ {"NOT_DEK_INFO", ERR_LIB_PEM, 105}, -+ #endif -+ #ifdef PEM_R_NOT_ENCRYPTED -+ {"NOT_ENCRYPTED", ERR_LIB_PEM, PEM_R_NOT_ENCRYPTED}, -+ #else -+ {"NOT_ENCRYPTED", ERR_LIB_PEM, 106}, -+ #endif -+ #ifdef PEM_R_NOT_PROC_TYPE -+ {"NOT_PROC_TYPE", ERR_LIB_PEM, PEM_R_NOT_PROC_TYPE}, -+ #else -+ {"NOT_PROC_TYPE", ERR_LIB_PEM, 107}, -+ #endif -+ #ifdef PEM_R_NO_START_LINE -+ {"NO_START_LINE", ERR_LIB_PEM, PEM_R_NO_START_LINE}, -+ #else -+ {"NO_START_LINE", ERR_LIB_PEM, 108}, -+ #endif -+ #ifdef PEM_R_PROBLEMS_GETTING_PASSWORD -+ {"PROBLEMS_GETTING_PASSWORD", ERR_LIB_PEM, PEM_R_PROBLEMS_GETTING_PASSWORD}, -+ #else -+ {"PROBLEMS_GETTING_PASSWORD", ERR_LIB_PEM, 109}, -+ #endif -+ #ifdef PEM_R_PUBLIC_KEY_NO_RSA -+ {"PUBLIC_KEY_NO_RSA", ERR_LIB_PEM, PEM_R_PUBLIC_KEY_NO_RSA}, -+ #else -+ {"PUBLIC_KEY_NO_RSA", ERR_LIB_PEM, 110}, -+ #endif -+ #ifdef PEM_R_PVK_DATA_TOO_SHORT -+ {"PVK_DATA_TOO_SHORT", ERR_LIB_PEM, PEM_R_PVK_DATA_TOO_SHORT}, -+ #else -+ {"PVK_DATA_TOO_SHORT", ERR_LIB_PEM, 124}, -+ #endif -+ #ifdef PEM_R_PVK_TOO_SHORT -+ {"PVK_TOO_SHORT", ERR_LIB_PEM, PEM_R_PVK_TOO_SHORT}, -+ #else -+ {"PVK_TOO_SHORT", ERR_LIB_PEM, 125}, -+ #endif -+ #ifdef PEM_R_READ_KEY -+ {"READ_KEY", ERR_LIB_PEM, PEM_R_READ_KEY}, -+ #else -+ {"READ_KEY", ERR_LIB_PEM, 111}, -+ #endif -+ #ifdef PEM_R_SHORT_HEADER -+ {"SHORT_HEADER", ERR_LIB_PEM, PEM_R_SHORT_HEADER}, -+ #else -+ {"SHORT_HEADER", ERR_LIB_PEM, 112}, -+ #endif -+ #ifdef PEM_R_UNSUPPORTED_CIPHER -+ {"UNSUPPORTED_CIPHER", ERR_LIB_PEM, PEM_R_UNSUPPORTED_CIPHER}, -+ #else -+ {"UNSUPPORTED_CIPHER", ERR_LIB_PEM, 113}, -+ #endif -+ #ifdef PEM_R_UNSUPPORTED_ENCRYPTION -+ {"UNSUPPORTED_ENCRYPTION", ERR_LIB_PEM, PEM_R_UNSUPPORTED_ENCRYPTION}, -+ #else -+ {"UNSUPPORTED_ENCRYPTION", ERR_LIB_PEM, 114}, -+ #endif -+ #ifdef PEM_R_UNSUPPORTED_KEY_COMPONENTS -+ {"UNSUPPORTED_KEY_COMPONENTS", ERR_LIB_PEM, PEM_R_UNSUPPORTED_KEY_COMPONENTS}, -+ #else -+ {"UNSUPPORTED_KEY_COMPONENTS", ERR_LIB_PEM, 126}, -+ #endif -+ #ifdef SSL_R_APP_DATA_IN_HANDSHAKE -+ {"APP_DATA_IN_HANDSHAKE", ERR_LIB_SSL, SSL_R_APP_DATA_IN_HANDSHAKE}, -+ #else -+ {"APP_DATA_IN_HANDSHAKE", ERR_LIB_SSL, 100}, -+ #endif -+ #ifdef SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT -+ {"ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT", ERR_LIB_SSL, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT}, -+ #else -+ {"ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT", ERR_LIB_SSL, 272}, -+ #endif -+ #ifdef SSL_R_BAD_ALERT_RECORD -+ {"BAD_ALERT_RECORD", ERR_LIB_SSL, SSL_R_BAD_ALERT_RECORD}, -+ #else -+ {"BAD_ALERT_RECORD", ERR_LIB_SSL, 101}, -+ #endif -+ #ifdef SSL_R_BAD_AUTHENTICATION_TYPE -+ {"BAD_AUTHENTICATION_TYPE", ERR_LIB_SSL, SSL_R_BAD_AUTHENTICATION_TYPE}, -+ #else -+ {"BAD_AUTHENTICATION_TYPE", ERR_LIB_SSL, 102}, -+ #endif -+ #ifdef SSL_R_BAD_CHANGE_CIPHER_SPEC -+ {"BAD_CHANGE_CIPHER_SPEC", ERR_LIB_SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC}, -+ #else -+ {"BAD_CHANGE_CIPHER_SPEC", ERR_LIB_SSL, 103}, -+ #endif -+ #ifdef SSL_R_BAD_CHECKSUM -+ {"BAD_CHECKSUM", ERR_LIB_SSL, SSL_R_BAD_CHECKSUM}, -+ #else -+ {"BAD_CHECKSUM", ERR_LIB_SSL, 104}, -+ #endif -+ #ifdef SSL_R_BAD_DATA_RETURNED_BY_CALLBACK -+ {"BAD_DATA_RETURNED_BY_CALLBACK", ERR_LIB_SSL, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK}, -+ #else -+ {"BAD_DATA_RETURNED_BY_CALLBACK", ERR_LIB_SSL, 106}, -+ #endif -+ #ifdef SSL_R_BAD_DECOMPRESSION -+ {"BAD_DECOMPRESSION", ERR_LIB_SSL, SSL_R_BAD_DECOMPRESSION}, -+ #else -+ {"BAD_DECOMPRESSION", ERR_LIB_SSL, 107}, -+ #endif -+ #ifdef SSL_R_BAD_DH_G_LENGTH -+ {"BAD_DH_G_LENGTH", ERR_LIB_SSL, SSL_R_BAD_DH_G_LENGTH}, -+ #else -+ {"BAD_DH_G_LENGTH", ERR_LIB_SSL, 108}, -+ #endif -+ #ifdef SSL_R_BAD_DH_PUB_KEY_LENGTH -+ {"BAD_DH_PUB_KEY_LENGTH", ERR_LIB_SSL, SSL_R_BAD_DH_PUB_KEY_LENGTH}, -+ #else -+ {"BAD_DH_PUB_KEY_LENGTH", ERR_LIB_SSL, 109}, -+ #endif -+ #ifdef SSL_R_BAD_DH_P_LENGTH -+ {"BAD_DH_P_LENGTH", ERR_LIB_SSL, SSL_R_BAD_DH_P_LENGTH}, -+ #else -+ {"BAD_DH_P_LENGTH", ERR_LIB_SSL, 110}, -+ #endif -+ #ifdef SSL_R_BAD_DIGEST_LENGTH -+ {"BAD_DIGEST_LENGTH", ERR_LIB_SSL, SSL_R_BAD_DIGEST_LENGTH}, -+ #else -+ {"BAD_DIGEST_LENGTH", ERR_LIB_SSL, 111}, -+ #endif -+ #ifdef SSL_R_BAD_DSA_SIGNATURE -+ {"BAD_DSA_SIGNATURE", ERR_LIB_SSL, SSL_R_BAD_DSA_SIGNATURE}, -+ #else -+ {"BAD_DSA_SIGNATURE", ERR_LIB_SSL, 112}, -+ #endif -+ #ifdef SSL_R_BAD_ECC_CERT -+ {"BAD_ECC_CERT", ERR_LIB_SSL, SSL_R_BAD_ECC_CERT}, -+ #else -+ {"BAD_ECC_CERT", ERR_LIB_SSL, 304}, -+ #endif -+ #ifdef SSL_R_BAD_ECDSA_SIGNATURE -+ {"BAD_ECDSA_SIGNATURE", ERR_LIB_SSL, SSL_R_BAD_ECDSA_SIGNATURE}, -+ #else -+ {"BAD_ECDSA_SIGNATURE", ERR_LIB_SSL, 305}, -+ #endif -+ #ifdef SSL_R_BAD_ECPOINT -+ {"BAD_ECPOINT", ERR_LIB_SSL, SSL_R_BAD_ECPOINT}, -+ #else -+ {"BAD_ECPOINT", ERR_LIB_SSL, 306}, -+ #endif -+ #ifdef SSL_R_BAD_HANDSHAKE_LENGTH -+ {"BAD_HANDSHAKE_LENGTH", ERR_LIB_SSL, SSL_R_BAD_HANDSHAKE_LENGTH}, -+ #else -+ {"BAD_HANDSHAKE_LENGTH", ERR_LIB_SSL, 332}, -+ #endif -+ #ifdef SSL_R_BAD_HELLO_REQUEST -+ {"BAD_HELLO_REQUEST", ERR_LIB_SSL, SSL_R_BAD_HELLO_REQUEST}, -+ #else -+ {"BAD_HELLO_REQUEST", ERR_LIB_SSL, 105}, -+ #endif -+ #ifdef SSL_R_BAD_LENGTH -+ {"BAD_LENGTH", ERR_LIB_SSL, SSL_R_BAD_LENGTH}, -+ #else -+ {"BAD_LENGTH", ERR_LIB_SSL, 271}, -+ #endif -+ #ifdef SSL_R_BAD_MAC_DECODE -+ {"BAD_MAC_DECODE", ERR_LIB_SSL, SSL_R_BAD_MAC_DECODE}, -+ #else -+ {"BAD_MAC_DECODE", ERR_LIB_SSL, 113}, -+ #endif -+ #ifdef SSL_R_BAD_MAC_LENGTH -+ {"BAD_MAC_LENGTH", ERR_LIB_SSL, SSL_R_BAD_MAC_LENGTH}, -+ #else -+ {"BAD_MAC_LENGTH", ERR_LIB_SSL, 333}, -+ #endif -+ #ifdef SSL_R_BAD_MESSAGE_TYPE -+ {"BAD_MESSAGE_TYPE", ERR_LIB_SSL, SSL_R_BAD_MESSAGE_TYPE}, -+ #else -+ {"BAD_MESSAGE_TYPE", ERR_LIB_SSL, 114}, -+ #endif -+ #ifdef SSL_R_BAD_PACKET_LENGTH -+ {"BAD_PACKET_LENGTH", ERR_LIB_SSL, SSL_R_BAD_PACKET_LENGTH}, -+ #else -+ {"BAD_PACKET_LENGTH", ERR_LIB_SSL, 115}, -+ #endif -+ #ifdef SSL_R_BAD_PROTOCOL_VERSION_NUMBER -+ {"BAD_PROTOCOL_VERSION_NUMBER", ERR_LIB_SSL, SSL_R_BAD_PROTOCOL_VERSION_NUMBER}, -+ #else -+ {"BAD_PROTOCOL_VERSION_NUMBER", ERR_LIB_SSL, 116}, -+ #endif -+ #ifdef SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH -+ {"BAD_PSK_IDENTITY_HINT_LENGTH", ERR_LIB_SSL, SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH}, -+ #else -+ {"BAD_PSK_IDENTITY_HINT_LENGTH", ERR_LIB_SSL, 316}, -+ #endif -+ #ifdef SSL_R_BAD_RESPONSE_ARGUMENT -+ {"BAD_RESPONSE_ARGUMENT", ERR_LIB_SSL, SSL_R_BAD_RESPONSE_ARGUMENT}, -+ #else -+ {"BAD_RESPONSE_ARGUMENT", ERR_LIB_SSL, 117}, -+ #endif -+ #ifdef SSL_R_BAD_RSA_DECRYPT -+ {"BAD_RSA_DECRYPT", ERR_LIB_SSL, SSL_R_BAD_RSA_DECRYPT}, -+ #else -+ {"BAD_RSA_DECRYPT", ERR_LIB_SSL, 118}, -+ #endif -+ #ifdef SSL_R_BAD_RSA_ENCRYPT -+ {"BAD_RSA_ENCRYPT", ERR_LIB_SSL, SSL_R_BAD_RSA_ENCRYPT}, -+ #else -+ {"BAD_RSA_ENCRYPT", ERR_LIB_SSL, 119}, -+ #endif -+ #ifdef SSL_R_BAD_RSA_E_LENGTH -+ {"BAD_RSA_E_LENGTH", ERR_LIB_SSL, SSL_R_BAD_RSA_E_LENGTH}, -+ #else -+ {"BAD_RSA_E_LENGTH", ERR_LIB_SSL, 120}, -+ #endif -+ #ifdef SSL_R_BAD_RSA_MODULUS_LENGTH -+ {"BAD_RSA_MODULUS_LENGTH", ERR_LIB_SSL, SSL_R_BAD_RSA_MODULUS_LENGTH}, -+ #else -+ {"BAD_RSA_MODULUS_LENGTH", ERR_LIB_SSL, 121}, -+ #endif -+ #ifdef SSL_R_BAD_RSA_SIGNATURE -+ {"BAD_RSA_SIGNATURE", ERR_LIB_SSL, SSL_R_BAD_RSA_SIGNATURE}, -+ #else -+ {"BAD_RSA_SIGNATURE", ERR_LIB_SSL, 122}, -+ #endif -+ #ifdef SSL_R_BAD_SIGNATURE -+ {"BAD_SIGNATURE", ERR_LIB_SSL, SSL_R_BAD_SIGNATURE}, -+ #else -+ {"BAD_SIGNATURE", ERR_LIB_SSL, 123}, -+ #endif -+ #ifdef SSL_R_BAD_SSL_FILETYPE -+ {"BAD_SSL_FILETYPE", ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE}, -+ #else -+ {"BAD_SSL_FILETYPE", ERR_LIB_SSL, 124}, -+ #endif -+ #ifdef SSL_R_BAD_SSL_SESSION_ID_LENGTH -+ {"BAD_SSL_SESSION_ID_LENGTH", ERR_LIB_SSL, SSL_R_BAD_SSL_SESSION_ID_LENGTH}, -+ #else -+ {"BAD_SSL_SESSION_ID_LENGTH", ERR_LIB_SSL, 125}, -+ #endif -+ #ifdef SSL_R_BAD_STATE -+ {"BAD_STATE", ERR_LIB_SSL, SSL_R_BAD_STATE}, -+ #else -+ {"BAD_STATE", ERR_LIB_SSL, 126}, -+ #endif -+ #ifdef SSL_R_BAD_WRITE_RETRY -+ {"BAD_WRITE_RETRY", ERR_LIB_SSL, SSL_R_BAD_WRITE_RETRY}, -+ #else -+ {"BAD_WRITE_RETRY", ERR_LIB_SSL, 127}, -+ #endif -+ #ifdef SSL_R_BIO_NOT_SET -+ {"BIO_NOT_SET", ERR_LIB_SSL, SSL_R_BIO_NOT_SET}, -+ #else -+ {"BIO_NOT_SET", ERR_LIB_SSL, 128}, -+ #endif -+ #ifdef SSL_R_BLOCK_CIPHER_PAD_IS_WRONG -+ {"BLOCK_CIPHER_PAD_IS_WRONG", ERR_LIB_SSL, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG}, -+ #else -+ {"BLOCK_CIPHER_PAD_IS_WRONG", ERR_LIB_SSL, 129}, -+ #endif -+ #ifdef SSL_R_BN_LIB -+ {"BN_LIB", ERR_LIB_SSL, SSL_R_BN_LIB}, -+ #else -+ {"BN_LIB", ERR_LIB_SSL, 130}, -+ #endif -+ #ifdef SSL_R_CA_DN_LENGTH_MISMATCH -+ {"CA_DN_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_CA_DN_LENGTH_MISMATCH}, -+ #else -+ {"CA_DN_LENGTH_MISMATCH", ERR_LIB_SSL, 131}, -+ #endif -+ #ifdef SSL_R_CA_DN_TOO_LONG -+ {"CA_DN_TOO_LONG", ERR_LIB_SSL, SSL_R_CA_DN_TOO_LONG}, -+ #else -+ {"CA_DN_TOO_LONG", ERR_LIB_SSL, 132}, -+ #endif -+ #ifdef SSL_R_CCS_RECEIVED_EARLY -+ {"CCS_RECEIVED_EARLY", ERR_LIB_SSL, SSL_R_CCS_RECEIVED_EARLY}, -+ #else -+ {"CCS_RECEIVED_EARLY", ERR_LIB_SSL, 133}, -+ #endif -+ #ifdef SSL_R_CERTIFICATE_VERIFY_FAILED -+ {"CERTIFICATE_VERIFY_FAILED", ERR_LIB_SSL, SSL_R_CERTIFICATE_VERIFY_FAILED}, -+ #else -+ {"CERTIFICATE_VERIFY_FAILED", ERR_LIB_SSL, 134}, -+ #endif -+ #ifdef SSL_R_CERT_LENGTH_MISMATCH -+ {"CERT_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_CERT_LENGTH_MISMATCH}, -+ #else -+ {"CERT_LENGTH_MISMATCH", ERR_LIB_SSL, 135}, -+ #endif -+ #ifdef SSL_R_CHALLENGE_IS_DIFFERENT -+ {"CHALLENGE_IS_DIFFERENT", ERR_LIB_SSL, SSL_R_CHALLENGE_IS_DIFFERENT}, -+ #else -+ {"CHALLENGE_IS_DIFFERENT", ERR_LIB_SSL, 136}, -+ #endif -+ #ifdef SSL_R_CIPHER_CODE_WRONG_LENGTH -+ {"CIPHER_CODE_WRONG_LENGTH", ERR_LIB_SSL, SSL_R_CIPHER_CODE_WRONG_LENGTH}, -+ #else -+ {"CIPHER_CODE_WRONG_LENGTH", ERR_LIB_SSL, 137}, -+ #endif -+ #ifdef SSL_R_CIPHER_OR_HASH_UNAVAILABLE -+ {"CIPHER_OR_HASH_UNAVAILABLE", ERR_LIB_SSL, SSL_R_CIPHER_OR_HASH_UNAVAILABLE}, -+ #else -+ {"CIPHER_OR_HASH_UNAVAILABLE", ERR_LIB_SSL, 138}, -+ #endif -+ #ifdef SSL_R_CIPHER_TABLE_SRC_ERROR -+ {"CIPHER_TABLE_SRC_ERROR", ERR_LIB_SSL, SSL_R_CIPHER_TABLE_SRC_ERROR}, -+ #else -+ {"CIPHER_TABLE_SRC_ERROR", ERR_LIB_SSL, 139}, -+ #endif -+ #ifdef SSL_R_CLIENTHELLO_TLSEXT -+ {"CLIENTHELLO_TLSEXT", ERR_LIB_SSL, SSL_R_CLIENTHELLO_TLSEXT}, -+ #else -+ {"CLIENTHELLO_TLSEXT", ERR_LIB_SSL, 226}, -+ #endif -+ #ifdef SSL_R_COMPRESSED_LENGTH_TOO_LONG -+ {"COMPRESSED_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_COMPRESSED_LENGTH_TOO_LONG}, -+ #else -+ {"COMPRESSED_LENGTH_TOO_LONG", ERR_LIB_SSL, 140}, -+ #endif -+ #ifdef SSL_R_COMPRESSION_DISABLED -+ {"COMPRESSION_DISABLED", ERR_LIB_SSL, SSL_R_COMPRESSION_DISABLED}, -+ #else -+ {"COMPRESSION_DISABLED", ERR_LIB_SSL, 343}, -+ #endif -+ #ifdef SSL_R_COMPRESSION_FAILURE -+ {"COMPRESSION_FAILURE", ERR_LIB_SSL, SSL_R_COMPRESSION_FAILURE}, -+ #else -+ {"COMPRESSION_FAILURE", ERR_LIB_SSL, 141}, -+ #endif -+ #ifdef SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE -+ {"COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE", ERR_LIB_SSL, SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE}, -+ #else -+ {"COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE", ERR_LIB_SSL, 307}, -+ #endif -+ #ifdef SSL_R_COMPRESSION_LIBRARY_ERROR -+ {"COMPRESSION_LIBRARY_ERROR", ERR_LIB_SSL, SSL_R_COMPRESSION_LIBRARY_ERROR}, -+ #else -+ {"COMPRESSION_LIBRARY_ERROR", ERR_LIB_SSL, 142}, -+ #endif -+ #ifdef SSL_R_CONNECTION_ID_IS_DIFFERENT -+ {"CONNECTION_ID_IS_DIFFERENT", ERR_LIB_SSL, SSL_R_CONNECTION_ID_IS_DIFFERENT}, -+ #else -+ {"CONNECTION_ID_IS_DIFFERENT", ERR_LIB_SSL, 143}, -+ #endif -+ #ifdef SSL_R_CONNECTION_TYPE_NOT_SET -+ {"CONNECTION_TYPE_NOT_SET", ERR_LIB_SSL, SSL_R_CONNECTION_TYPE_NOT_SET}, -+ #else -+ {"CONNECTION_TYPE_NOT_SET", ERR_LIB_SSL, 144}, -+ #endif -+ #ifdef SSL_R_COOKIE_MISMATCH -+ {"COOKIE_MISMATCH", ERR_LIB_SSL, SSL_R_COOKIE_MISMATCH}, -+ #else -+ {"COOKIE_MISMATCH", ERR_LIB_SSL, 308}, -+ #endif -+ #ifdef SSL_R_DATA_BETWEEN_CCS_AND_FINISHED -+ {"DATA_BETWEEN_CCS_AND_FINISHED", ERR_LIB_SSL, SSL_R_DATA_BETWEEN_CCS_AND_FINISHED}, -+ #else -+ {"DATA_BETWEEN_CCS_AND_FINISHED", ERR_LIB_SSL, 145}, -+ #endif -+ #ifdef SSL_R_DATA_LENGTH_TOO_LONG -+ {"DATA_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_DATA_LENGTH_TOO_LONG}, -+ #else -+ {"DATA_LENGTH_TOO_LONG", ERR_LIB_SSL, 146}, -+ #endif -+ #ifdef SSL_R_DECRYPTION_FAILED -+ {"DECRYPTION_FAILED", ERR_LIB_SSL, SSL_R_DECRYPTION_FAILED}, -+ #else -+ {"DECRYPTION_FAILED", ERR_LIB_SSL, 147}, -+ #endif -+ #ifdef SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC -+ {"DECRYPTION_FAILED_OR_BAD_RECORD_MAC", ERR_LIB_SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC}, -+ #else -+ {"DECRYPTION_FAILED_OR_BAD_RECORD_MAC", ERR_LIB_SSL, 281}, -+ #endif -+ #ifdef SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG -+ {"DH_PUBLIC_VALUE_LENGTH_IS_WRONG", ERR_LIB_SSL, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG}, -+ #else -+ {"DH_PUBLIC_VALUE_LENGTH_IS_WRONG", ERR_LIB_SSL, 148}, -+ #endif -+ #ifdef SSL_R_DIGEST_CHECK_FAILED -+ {"DIGEST_CHECK_FAILED", ERR_LIB_SSL, SSL_R_DIGEST_CHECK_FAILED}, -+ #else -+ {"DIGEST_CHECK_FAILED", ERR_LIB_SSL, 149}, -+ #endif -+ #ifdef SSL_R_DTLS_MESSAGE_TOO_BIG -+ {"DTLS_MESSAGE_TOO_BIG", ERR_LIB_SSL, SSL_R_DTLS_MESSAGE_TOO_BIG}, -+ #else -+ {"DTLS_MESSAGE_TOO_BIG", ERR_LIB_SSL, 334}, -+ #endif -+ #ifdef SSL_R_DUPLICATE_COMPRESSION_ID -+ {"DUPLICATE_COMPRESSION_ID", ERR_LIB_SSL, SSL_R_DUPLICATE_COMPRESSION_ID}, -+ #else -+ {"DUPLICATE_COMPRESSION_ID", ERR_LIB_SSL, 309}, -+ #endif -+ #ifdef SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT -+ {"ECC_CERT_NOT_FOR_KEY_AGREEMENT", ERR_LIB_SSL, SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT}, -+ #else -+ {"ECC_CERT_NOT_FOR_KEY_AGREEMENT", ERR_LIB_SSL, 317}, -+ #endif -+ #ifdef SSL_R_ECC_CERT_NOT_FOR_SIGNING -+ {"ECC_CERT_NOT_FOR_SIGNING", ERR_LIB_SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING}, -+ #else -+ {"ECC_CERT_NOT_FOR_SIGNING", ERR_LIB_SSL, 318}, -+ #endif -+ #ifdef SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE -+ {"ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE", ERR_LIB_SSL, SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE}, -+ #else -+ {"ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE", ERR_LIB_SSL, 322}, -+ #endif -+ #ifdef SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE -+ {"ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE", ERR_LIB_SSL, SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE}, -+ #else -+ {"ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE", ERR_LIB_SSL, 323}, -+ #endif -+ #ifdef SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER -+ {"ECGROUP_TOO_LARGE_FOR_CIPHER", ERR_LIB_SSL, SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER}, -+ #else -+ {"ECGROUP_TOO_LARGE_FOR_CIPHER", ERR_LIB_SSL, 310}, -+ #endif -+ #ifdef SSL_R_ENCRYPTED_LENGTH_TOO_LONG -+ {"ENCRYPTED_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_ENCRYPTED_LENGTH_TOO_LONG}, -+ #else -+ {"ENCRYPTED_LENGTH_TOO_LONG", ERR_LIB_SSL, 150}, -+ #endif -+ #ifdef SSL_R_ERROR_GENERATING_TMP_RSA_KEY -+ {"ERROR_GENERATING_TMP_RSA_KEY", ERR_LIB_SSL, SSL_R_ERROR_GENERATING_TMP_RSA_KEY}, -+ #else -+ {"ERROR_GENERATING_TMP_RSA_KEY", ERR_LIB_SSL, 282}, -+ #endif -+ #ifdef SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST -+ {"ERROR_IN_RECEIVED_CIPHER_LIST", ERR_LIB_SSL, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST}, -+ #else -+ {"ERROR_IN_RECEIVED_CIPHER_LIST", ERR_LIB_SSL, 151}, -+ #endif -+ #ifdef SSL_R_EXCESSIVE_MESSAGE_SIZE -+ {"EXCESSIVE_MESSAGE_SIZE", ERR_LIB_SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE}, -+ #else -+ {"EXCESSIVE_MESSAGE_SIZE", ERR_LIB_SSL, 152}, -+ #endif -+ #ifdef SSL_R_EXTRA_DATA_IN_MESSAGE -+ {"EXTRA_DATA_IN_MESSAGE", ERR_LIB_SSL, SSL_R_EXTRA_DATA_IN_MESSAGE}, -+ #else -+ {"EXTRA_DATA_IN_MESSAGE", ERR_LIB_SSL, 153}, -+ #endif -+ #ifdef SSL_R_GOT_A_FIN_BEFORE_A_CCS -+ {"GOT_A_FIN_BEFORE_A_CCS", ERR_LIB_SSL, SSL_R_GOT_A_FIN_BEFORE_A_CCS}, -+ #else -+ {"GOT_A_FIN_BEFORE_A_CCS", ERR_LIB_SSL, 154}, -+ #endif -+ #ifdef SSL_R_HTTPS_PROXY_REQUEST -+ {"HTTPS_PROXY_REQUEST", ERR_LIB_SSL, SSL_R_HTTPS_PROXY_REQUEST}, -+ #else -+ {"HTTPS_PROXY_REQUEST", ERR_LIB_SSL, 155}, -+ #endif -+ #ifdef SSL_R_HTTP_REQUEST -+ {"HTTP_REQUEST", ERR_LIB_SSL, SSL_R_HTTP_REQUEST}, -+ #else -+ {"HTTP_REQUEST", ERR_LIB_SSL, 156}, -+ #endif -+ #ifdef SSL_R_ILLEGAL_PADDING -+ {"ILLEGAL_PADDING", ERR_LIB_SSL, SSL_R_ILLEGAL_PADDING}, -+ #else -+ {"ILLEGAL_PADDING", ERR_LIB_SSL, 283}, -+ #endif -+ #ifdef SSL_R_INCONSISTENT_COMPRESSION -+ {"INCONSISTENT_COMPRESSION", ERR_LIB_SSL, SSL_R_INCONSISTENT_COMPRESSION}, -+ #else -+ {"INCONSISTENT_COMPRESSION", ERR_LIB_SSL, 340}, -+ #endif -+ #ifdef SSL_R_INVALID_CHALLENGE_LENGTH -+ {"INVALID_CHALLENGE_LENGTH", ERR_LIB_SSL, SSL_R_INVALID_CHALLENGE_LENGTH}, -+ #else -+ {"INVALID_CHALLENGE_LENGTH", ERR_LIB_SSL, 158}, -+ #endif -+ #ifdef SSL_R_INVALID_COMMAND -+ {"INVALID_COMMAND", ERR_LIB_SSL, SSL_R_INVALID_COMMAND}, -+ #else -+ {"INVALID_COMMAND", ERR_LIB_SSL, 280}, -+ #endif -+ #ifdef SSL_R_INVALID_COMPRESSION_ALGORITHM -+ {"INVALID_COMPRESSION_ALGORITHM", ERR_LIB_SSL, SSL_R_INVALID_COMPRESSION_ALGORITHM}, -+ #else -+ {"INVALID_COMPRESSION_ALGORITHM", ERR_LIB_SSL, 341}, -+ #endif -+ #ifdef SSL_R_INVALID_PURPOSE -+ {"INVALID_PURPOSE", ERR_LIB_SSL, SSL_R_INVALID_PURPOSE}, -+ #else -+ {"INVALID_PURPOSE", ERR_LIB_SSL, 278}, -+ #endif -+ #ifdef SSL_R_INVALID_STATUS_RESPONSE -+ {"INVALID_STATUS_RESPONSE", ERR_LIB_SSL, SSL_R_INVALID_STATUS_RESPONSE}, -+ #else -+ {"INVALID_STATUS_RESPONSE", ERR_LIB_SSL, 328}, -+ #endif -+ #ifdef SSL_R_INVALID_TICKET_KEYS_LENGTH -+ {"INVALID_TICKET_KEYS_LENGTH", ERR_LIB_SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH}, -+ #else -+ {"INVALID_TICKET_KEYS_LENGTH", ERR_LIB_SSL, 325}, -+ #endif -+ #ifdef SSL_R_INVALID_TRUST -+ {"INVALID_TRUST", ERR_LIB_SSL, SSL_R_INVALID_TRUST}, -+ #else -+ {"INVALID_TRUST", ERR_LIB_SSL, 279}, -+ #endif -+ #ifdef SSL_R_KEY_ARG_TOO_LONG -+ {"KEY_ARG_TOO_LONG", ERR_LIB_SSL, SSL_R_KEY_ARG_TOO_LONG}, -+ #else -+ {"KEY_ARG_TOO_LONG", ERR_LIB_SSL, 284}, -+ #endif -+ #ifdef SSL_R_KRB5 -+ {"KRB5", ERR_LIB_SSL, SSL_R_KRB5}, -+ #else -+ {"KRB5", ERR_LIB_SSL, 285}, -+ #endif -+ #ifdef SSL_R_KRB5_C_CC_PRINC -+ {"KRB5_C_CC_PRINC", ERR_LIB_SSL, SSL_R_KRB5_C_CC_PRINC}, -+ #else -+ {"KRB5_C_CC_PRINC", ERR_LIB_SSL, 286}, -+ #endif -+ #ifdef SSL_R_KRB5_C_GET_CRED -+ {"KRB5_C_GET_CRED", ERR_LIB_SSL, SSL_R_KRB5_C_GET_CRED}, -+ #else -+ {"KRB5_C_GET_CRED", ERR_LIB_SSL, 287}, -+ #endif -+ #ifdef SSL_R_KRB5_C_INIT -+ {"KRB5_C_INIT", ERR_LIB_SSL, SSL_R_KRB5_C_INIT}, -+ #else -+ {"KRB5_C_INIT", ERR_LIB_SSL, 288}, -+ #endif -+ #ifdef SSL_R_KRB5_C_MK_REQ -+ {"KRB5_C_MK_REQ", ERR_LIB_SSL, SSL_R_KRB5_C_MK_REQ}, -+ #else -+ {"KRB5_C_MK_REQ", ERR_LIB_SSL, 289}, -+ #endif -+ #ifdef SSL_R_KRB5_S_BAD_TICKET -+ {"KRB5_S_BAD_TICKET", ERR_LIB_SSL, SSL_R_KRB5_S_BAD_TICKET}, -+ #else -+ {"KRB5_S_BAD_TICKET", ERR_LIB_SSL, 290}, -+ #endif -+ #ifdef SSL_R_KRB5_S_INIT -+ {"KRB5_S_INIT", ERR_LIB_SSL, SSL_R_KRB5_S_INIT}, -+ #else -+ {"KRB5_S_INIT", ERR_LIB_SSL, 291}, -+ #endif -+ #ifdef SSL_R_KRB5_S_RD_REQ -+ {"KRB5_S_RD_REQ", ERR_LIB_SSL, SSL_R_KRB5_S_RD_REQ}, -+ #else -+ {"KRB5_S_RD_REQ", ERR_LIB_SSL, 292}, -+ #endif -+ #ifdef SSL_R_KRB5_S_TKT_EXPIRED -+ {"KRB5_S_TKT_EXPIRED", ERR_LIB_SSL, SSL_R_KRB5_S_TKT_EXPIRED}, -+ #else -+ {"KRB5_S_TKT_EXPIRED", ERR_LIB_SSL, 293}, -+ #endif -+ #ifdef SSL_R_KRB5_S_TKT_NYV -+ {"KRB5_S_TKT_NYV", ERR_LIB_SSL, SSL_R_KRB5_S_TKT_NYV}, -+ #else -+ {"KRB5_S_TKT_NYV", ERR_LIB_SSL, 294}, -+ #endif -+ #ifdef SSL_R_KRB5_S_TKT_SKEW -+ {"KRB5_S_TKT_SKEW", ERR_LIB_SSL, SSL_R_KRB5_S_TKT_SKEW}, -+ #else -+ {"KRB5_S_TKT_SKEW", ERR_LIB_SSL, 295}, -+ #endif -+ #ifdef SSL_R_LENGTH_MISMATCH -+ {"LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH}, -+ #else -+ {"LENGTH_MISMATCH", ERR_LIB_SSL, 159}, -+ #endif -+ #ifdef SSL_R_LENGTH_TOO_SHORT -+ {"LENGTH_TOO_SHORT", ERR_LIB_SSL, SSL_R_LENGTH_TOO_SHORT}, -+ #else -+ {"LENGTH_TOO_SHORT", ERR_LIB_SSL, 160}, -+ #endif -+ #ifdef SSL_R_LIBRARY_BUG -+ {"LIBRARY_BUG", ERR_LIB_SSL, SSL_R_LIBRARY_BUG}, -+ #else -+ {"LIBRARY_BUG", ERR_LIB_SSL, 274}, -+ #endif -+ #ifdef SSL_R_LIBRARY_HAS_NO_CIPHERS -+ {"LIBRARY_HAS_NO_CIPHERS", ERR_LIB_SSL, SSL_R_LIBRARY_HAS_NO_CIPHERS}, -+ #else -+ {"LIBRARY_HAS_NO_CIPHERS", ERR_LIB_SSL, 161}, -+ #endif -+ #ifdef SSL_R_MESSAGE_TOO_LONG -+ {"MESSAGE_TOO_LONG", ERR_LIB_SSL, SSL_R_MESSAGE_TOO_LONG}, -+ #else -+ {"MESSAGE_TOO_LONG", ERR_LIB_SSL, 296}, -+ #endif -+ #ifdef SSL_R_MISSING_DH_DSA_CERT -+ {"MISSING_DH_DSA_CERT", ERR_LIB_SSL, SSL_R_MISSING_DH_DSA_CERT}, -+ #else -+ {"MISSING_DH_DSA_CERT", ERR_LIB_SSL, 162}, -+ #endif -+ #ifdef SSL_R_MISSING_DH_KEY -+ {"MISSING_DH_KEY", ERR_LIB_SSL, SSL_R_MISSING_DH_KEY}, -+ #else -+ {"MISSING_DH_KEY", ERR_LIB_SSL, 163}, -+ #endif -+ #ifdef SSL_R_MISSING_DH_RSA_CERT -+ {"MISSING_DH_RSA_CERT", ERR_LIB_SSL, SSL_R_MISSING_DH_RSA_CERT}, -+ #else -+ {"MISSING_DH_RSA_CERT", ERR_LIB_SSL, 164}, -+ #endif -+ #ifdef SSL_R_MISSING_DSA_SIGNING_CERT -+ {"MISSING_DSA_SIGNING_CERT", ERR_LIB_SSL, SSL_R_MISSING_DSA_SIGNING_CERT}, -+ #else -+ {"MISSING_DSA_SIGNING_CERT", ERR_LIB_SSL, 165}, -+ #endif -+ #ifdef SSL_R_MISSING_EXPORT_TMP_DH_KEY -+ {"MISSING_EXPORT_TMP_DH_KEY", ERR_LIB_SSL, SSL_R_MISSING_EXPORT_TMP_DH_KEY}, -+ #else -+ {"MISSING_EXPORT_TMP_DH_KEY", ERR_LIB_SSL, 166}, -+ #endif -+ #ifdef SSL_R_MISSING_EXPORT_TMP_RSA_KEY -+ {"MISSING_EXPORT_TMP_RSA_KEY", ERR_LIB_SSL, SSL_R_MISSING_EXPORT_TMP_RSA_KEY}, -+ #else -+ {"MISSING_EXPORT_TMP_RSA_KEY", ERR_LIB_SSL, 167}, -+ #endif -+ #ifdef SSL_R_MISSING_RSA_CERTIFICATE -+ {"MISSING_RSA_CERTIFICATE", ERR_LIB_SSL, SSL_R_MISSING_RSA_CERTIFICATE}, -+ #else -+ {"MISSING_RSA_CERTIFICATE", ERR_LIB_SSL, 168}, -+ #endif -+ #ifdef SSL_R_MISSING_RSA_ENCRYPTING_CERT -+ {"MISSING_RSA_ENCRYPTING_CERT", ERR_LIB_SSL, SSL_R_MISSING_RSA_ENCRYPTING_CERT}, -+ #else -+ {"MISSING_RSA_ENCRYPTING_CERT", ERR_LIB_SSL, 169}, -+ #endif -+ #ifdef SSL_R_MISSING_RSA_SIGNING_CERT -+ {"MISSING_RSA_SIGNING_CERT", ERR_LIB_SSL, SSL_R_MISSING_RSA_SIGNING_CERT}, -+ #else -+ {"MISSING_RSA_SIGNING_CERT", ERR_LIB_SSL, 170}, -+ #endif -+ #ifdef SSL_R_MISSING_TMP_DH_KEY -+ {"MISSING_TMP_DH_KEY", ERR_LIB_SSL, SSL_R_MISSING_TMP_DH_KEY}, -+ #else -+ {"MISSING_TMP_DH_KEY", ERR_LIB_SSL, 171}, -+ #endif -+ #ifdef SSL_R_MISSING_TMP_ECDH_KEY -+ {"MISSING_TMP_ECDH_KEY", ERR_LIB_SSL, SSL_R_MISSING_TMP_ECDH_KEY}, -+ #else -+ {"MISSING_TMP_ECDH_KEY", ERR_LIB_SSL, 311}, -+ #endif -+ #ifdef SSL_R_MISSING_TMP_RSA_KEY -+ {"MISSING_TMP_RSA_KEY", ERR_LIB_SSL, SSL_R_MISSING_TMP_RSA_KEY}, -+ #else -+ {"MISSING_TMP_RSA_KEY", ERR_LIB_SSL, 172}, -+ #endif -+ #ifdef SSL_R_MISSING_TMP_RSA_PKEY -+ {"MISSING_TMP_RSA_PKEY", ERR_LIB_SSL, SSL_R_MISSING_TMP_RSA_PKEY}, -+ #else -+ {"MISSING_TMP_RSA_PKEY", ERR_LIB_SSL, 173}, -+ #endif -+ #ifdef SSL_R_MISSING_VERIFY_MESSAGE -+ {"MISSING_VERIFY_MESSAGE", ERR_LIB_SSL, SSL_R_MISSING_VERIFY_MESSAGE}, -+ #else -+ {"MISSING_VERIFY_MESSAGE", ERR_LIB_SSL, 174}, -+ #endif -+ #ifdef SSL_R_NON_SSLV2_INITIAL_PACKET -+ {"NON_SSLV2_INITIAL_PACKET", ERR_LIB_SSL, SSL_R_NON_SSLV2_INITIAL_PACKET}, -+ #else -+ {"NON_SSLV2_INITIAL_PACKET", ERR_LIB_SSL, 175}, -+ #endif -+ #ifdef SSL_R_NO_CERTIFICATES_RETURNED -+ {"NO_CERTIFICATES_RETURNED", ERR_LIB_SSL, SSL_R_NO_CERTIFICATES_RETURNED}, -+ #else -+ {"NO_CERTIFICATES_RETURNED", ERR_LIB_SSL, 176}, -+ #endif -+ #ifdef SSL_R_NO_CERTIFICATE_ASSIGNED -+ {"NO_CERTIFICATE_ASSIGNED", ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_ASSIGNED}, -+ #else -+ {"NO_CERTIFICATE_ASSIGNED", ERR_LIB_SSL, 177}, -+ #endif -+ #ifdef SSL_R_NO_CERTIFICATE_RETURNED -+ {"NO_CERTIFICATE_RETURNED", ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_RETURNED}, -+ #else -+ {"NO_CERTIFICATE_RETURNED", ERR_LIB_SSL, 178}, -+ #endif -+ #ifdef SSL_R_NO_CERTIFICATE_SET -+ {"NO_CERTIFICATE_SET", ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_SET}, -+ #else -+ {"NO_CERTIFICATE_SET", ERR_LIB_SSL, 179}, -+ #endif -+ #ifdef SSL_R_NO_CERTIFICATE_SPECIFIED -+ {"NO_CERTIFICATE_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_SPECIFIED}, -+ #else -+ {"NO_CERTIFICATE_SPECIFIED", ERR_LIB_SSL, 180}, -+ #endif -+ #ifdef SSL_R_NO_CIPHERS_AVAILABLE -+ {"NO_CIPHERS_AVAILABLE", ERR_LIB_SSL, SSL_R_NO_CIPHERS_AVAILABLE}, -+ #else -+ {"NO_CIPHERS_AVAILABLE", ERR_LIB_SSL, 181}, -+ #endif -+ #ifdef SSL_R_NO_CIPHERS_PASSED -+ {"NO_CIPHERS_PASSED", ERR_LIB_SSL, SSL_R_NO_CIPHERS_PASSED}, -+ #else -+ {"NO_CIPHERS_PASSED", ERR_LIB_SSL, 182}, -+ #endif -+ #ifdef SSL_R_NO_CIPHERS_SPECIFIED -+ {"NO_CIPHERS_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_CIPHERS_SPECIFIED}, -+ #else -+ {"NO_CIPHERS_SPECIFIED", ERR_LIB_SSL, 183}, -+ #endif -+ #ifdef SSL_R_NO_CIPHER_LIST -+ {"NO_CIPHER_LIST", ERR_LIB_SSL, SSL_R_NO_CIPHER_LIST}, -+ #else -+ {"NO_CIPHER_LIST", ERR_LIB_SSL, 184}, -+ #endif -+ #ifdef SSL_R_NO_CIPHER_MATCH -+ {"NO_CIPHER_MATCH", ERR_LIB_SSL, SSL_R_NO_CIPHER_MATCH}, -+ #else -+ {"NO_CIPHER_MATCH", ERR_LIB_SSL, 185}, -+ #endif -+ #ifdef SSL_R_NO_CLIENT_CERT_METHOD -+ {"NO_CLIENT_CERT_METHOD", ERR_LIB_SSL, SSL_R_NO_CLIENT_CERT_METHOD}, -+ #else -+ {"NO_CLIENT_CERT_METHOD", ERR_LIB_SSL, 331}, -+ #endif -+ #ifdef SSL_R_NO_CLIENT_CERT_RECEIVED -+ {"NO_CLIENT_CERT_RECEIVED", ERR_LIB_SSL, SSL_R_NO_CLIENT_CERT_RECEIVED}, -+ #else -+ {"NO_CLIENT_CERT_RECEIVED", ERR_LIB_SSL, 186}, -+ #endif -+ #ifdef SSL_R_NO_COMPRESSION_SPECIFIED -+ {"NO_COMPRESSION_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_COMPRESSION_SPECIFIED}, -+ #else -+ {"NO_COMPRESSION_SPECIFIED", ERR_LIB_SSL, 187}, -+ #endif -+ #ifdef SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER -+ {"NO_GOST_CERTIFICATE_SENT_BY_PEER", ERR_LIB_SSL, SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER}, -+ #else -+ {"NO_GOST_CERTIFICATE_SENT_BY_PEER", ERR_LIB_SSL, 330}, -+ #endif -+ #ifdef SSL_R_NO_METHOD_SPECIFIED -+ {"NO_METHOD_SPECIFIED", ERR_LIB_SSL, SSL_R_NO_METHOD_SPECIFIED}, -+ #else -+ {"NO_METHOD_SPECIFIED", ERR_LIB_SSL, 188}, -+ #endif -+ #ifdef SSL_R_NO_PRIVATEKEY -+ {"NO_PRIVATEKEY", ERR_LIB_SSL, SSL_R_NO_PRIVATEKEY}, -+ #else -+ {"NO_PRIVATEKEY", ERR_LIB_SSL, 189}, -+ #endif -+ #ifdef SSL_R_NO_PRIVATE_KEY_ASSIGNED -+ {"NO_PRIVATE_KEY_ASSIGNED", ERR_LIB_SSL, SSL_R_NO_PRIVATE_KEY_ASSIGNED}, -+ #else -+ {"NO_PRIVATE_KEY_ASSIGNED", ERR_LIB_SSL, 190}, -+ #endif -+ #ifdef SSL_R_NO_PROTOCOLS_AVAILABLE -+ {"NO_PROTOCOLS_AVAILABLE", ERR_LIB_SSL, SSL_R_NO_PROTOCOLS_AVAILABLE}, -+ #else -+ {"NO_PROTOCOLS_AVAILABLE", ERR_LIB_SSL, 191}, -+ #endif -+ #ifdef SSL_R_NO_PUBLICKEY -+ {"NO_PUBLICKEY", ERR_LIB_SSL, SSL_R_NO_PUBLICKEY}, -+ #else -+ {"NO_PUBLICKEY", ERR_LIB_SSL, 192}, -+ #endif -+ #ifdef SSL_R_NO_RENEGOTIATION -+ {"NO_RENEGOTIATION", ERR_LIB_SSL, SSL_R_NO_RENEGOTIATION}, -+ #else -+ {"NO_RENEGOTIATION", ERR_LIB_SSL, 339}, -+ #endif -+ #ifdef SSL_R_NO_REQUIRED_DIGEST -+ {"NO_REQUIRED_DIGEST", ERR_LIB_SSL, SSL_R_NO_REQUIRED_DIGEST}, -+ #else -+ {"NO_REQUIRED_DIGEST", ERR_LIB_SSL, 324}, -+ #endif -+ #ifdef SSL_R_NO_SHARED_CIPHER -+ {"NO_SHARED_CIPHER", ERR_LIB_SSL, SSL_R_NO_SHARED_CIPHER}, -+ #else -+ {"NO_SHARED_CIPHER", ERR_LIB_SSL, 193}, -+ #endif -+ #ifdef SSL_R_NO_VERIFY_CALLBACK -+ {"NO_VERIFY_CALLBACK", ERR_LIB_SSL, SSL_R_NO_VERIFY_CALLBACK}, -+ #else -+ {"NO_VERIFY_CALLBACK", ERR_LIB_SSL, 194}, -+ #endif -+ #ifdef SSL_R_NULL_SSL_CTX -+ {"NULL_SSL_CTX", ERR_LIB_SSL, SSL_R_NULL_SSL_CTX}, -+ #else -+ {"NULL_SSL_CTX", ERR_LIB_SSL, 195}, -+ #endif -+ #ifdef SSL_R_NULL_SSL_METHOD_PASSED -+ {"NULL_SSL_METHOD_PASSED", ERR_LIB_SSL, SSL_R_NULL_SSL_METHOD_PASSED}, -+ #else -+ {"NULL_SSL_METHOD_PASSED", ERR_LIB_SSL, 196}, -+ #endif -+ #ifdef SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED -+ {"OLD_SESSION_CIPHER_NOT_RETURNED", ERR_LIB_SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED}, -+ #else -+ {"OLD_SESSION_CIPHER_NOT_RETURNED", ERR_LIB_SSL, 197}, -+ #endif -+ #ifdef SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED -+ {"OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED", ERR_LIB_SSL, SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED}, -+ #else -+ {"OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED", ERR_LIB_SSL, 344}, -+ #endif -+ #ifdef SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE -+ {"ONLY_TLS_ALLOWED_IN_FIPS_MODE", ERR_LIB_SSL, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE}, -+ #else -+ {"ONLY_TLS_ALLOWED_IN_FIPS_MODE", ERR_LIB_SSL, 297}, -+ #endif -+ #ifdef SSL_R_OPAQUE_PRF_INPUT_TOO_LONG -+ {"OPAQUE_PRF_INPUT_TOO_LONG", ERR_LIB_SSL, SSL_R_OPAQUE_PRF_INPUT_TOO_LONG}, -+ #else -+ {"OPAQUE_PRF_INPUT_TOO_LONG", ERR_LIB_SSL, 327}, -+ #endif -+ #ifdef SSL_R_PACKET_LENGTH_TOO_LONG -+ {"PACKET_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_PACKET_LENGTH_TOO_LONG}, -+ #else -+ {"PACKET_LENGTH_TOO_LONG", ERR_LIB_SSL, 198}, -+ #endif -+ #ifdef SSL_R_PARSE_TLSEXT -+ {"PARSE_TLSEXT", ERR_LIB_SSL, SSL_R_PARSE_TLSEXT}, -+ #else -+ {"PARSE_TLSEXT", ERR_LIB_SSL, 227}, -+ #endif -+ #ifdef SSL_R_PATH_TOO_LONG -+ {"PATH_TOO_LONG", ERR_LIB_SSL, SSL_R_PATH_TOO_LONG}, -+ #else -+ {"PATH_TOO_LONG", ERR_LIB_SSL, 270}, -+ #endif -+ #ifdef SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE -+ {"PEER_DID_NOT_RETURN_A_CERTIFICATE", ERR_LIB_SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE}, -+ #else -+ {"PEER_DID_NOT_RETURN_A_CERTIFICATE", ERR_LIB_SSL, 199}, -+ #endif -+ #ifdef SSL_R_PEER_ERROR -+ {"PEER_ERROR", ERR_LIB_SSL, SSL_R_PEER_ERROR}, -+ #else -+ {"PEER_ERROR", ERR_LIB_SSL, 200}, -+ #endif -+ #ifdef SSL_R_PEER_ERROR_CERTIFICATE -+ {"PEER_ERROR_CERTIFICATE", ERR_LIB_SSL, SSL_R_PEER_ERROR_CERTIFICATE}, -+ #else -+ {"PEER_ERROR_CERTIFICATE", ERR_LIB_SSL, 201}, -+ #endif -+ #ifdef SSL_R_PEER_ERROR_NO_CERTIFICATE -+ {"PEER_ERROR_NO_CERTIFICATE", ERR_LIB_SSL, SSL_R_PEER_ERROR_NO_CERTIFICATE}, -+ #else -+ {"PEER_ERROR_NO_CERTIFICATE", ERR_LIB_SSL, 202}, -+ #endif -+ #ifdef SSL_R_PEER_ERROR_NO_CIPHER -+ {"PEER_ERROR_NO_CIPHER", ERR_LIB_SSL, SSL_R_PEER_ERROR_NO_CIPHER}, -+ #else -+ {"PEER_ERROR_NO_CIPHER", ERR_LIB_SSL, 203}, -+ #endif -+ #ifdef SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE -+ {"PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE", ERR_LIB_SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE}, -+ #else -+ {"PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE", ERR_LIB_SSL, 204}, -+ #endif -+ #ifdef SSL_R_PRE_MAC_LENGTH_TOO_LONG -+ {"PRE_MAC_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_PRE_MAC_LENGTH_TOO_LONG}, -+ #else -+ {"PRE_MAC_LENGTH_TOO_LONG", ERR_LIB_SSL, 205}, -+ #endif -+ #ifdef SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS -+ {"PROBLEMS_MAPPING_CIPHER_FUNCTIONS", ERR_LIB_SSL, SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS}, -+ #else -+ {"PROBLEMS_MAPPING_CIPHER_FUNCTIONS", ERR_LIB_SSL, 206}, -+ #endif -+ #ifdef SSL_R_PROTOCOL_IS_SHUTDOWN -+ {"PROTOCOL_IS_SHUTDOWN", ERR_LIB_SSL, SSL_R_PROTOCOL_IS_SHUTDOWN}, -+ #else -+ {"PROTOCOL_IS_SHUTDOWN", ERR_LIB_SSL, 207}, -+ #endif -+ #ifdef SSL_R_PSK_IDENTITY_NOT_FOUND -+ {"PSK_IDENTITY_NOT_FOUND", ERR_LIB_SSL, SSL_R_PSK_IDENTITY_NOT_FOUND}, -+ #else -+ {"PSK_IDENTITY_NOT_FOUND", ERR_LIB_SSL, 223}, -+ #endif -+ #ifdef SSL_R_PSK_NO_CLIENT_CB -+ {"PSK_NO_CLIENT_CB", ERR_LIB_SSL, SSL_R_PSK_NO_CLIENT_CB}, -+ #else -+ {"PSK_NO_CLIENT_CB", ERR_LIB_SSL, 224}, -+ #endif -+ #ifdef SSL_R_PSK_NO_SERVER_CB -+ {"PSK_NO_SERVER_CB", ERR_LIB_SSL, SSL_R_PSK_NO_SERVER_CB}, -+ #else -+ {"PSK_NO_SERVER_CB", ERR_LIB_SSL, 225}, -+ #endif -+ #ifdef SSL_R_PUBLIC_KEY_ENCRYPT_ERROR -+ {"PUBLIC_KEY_ENCRYPT_ERROR", ERR_LIB_SSL, SSL_R_PUBLIC_KEY_ENCRYPT_ERROR}, -+ #else -+ {"PUBLIC_KEY_ENCRYPT_ERROR", ERR_LIB_SSL, 208}, -+ #endif -+ #ifdef SSL_R_PUBLIC_KEY_IS_NOT_RSA -+ {"PUBLIC_KEY_IS_NOT_RSA", ERR_LIB_SSL, SSL_R_PUBLIC_KEY_IS_NOT_RSA}, -+ #else -+ {"PUBLIC_KEY_IS_NOT_RSA", ERR_LIB_SSL, 209}, -+ #endif -+ #ifdef SSL_R_PUBLIC_KEY_NOT_RSA -+ {"PUBLIC_KEY_NOT_RSA", ERR_LIB_SSL, SSL_R_PUBLIC_KEY_NOT_RSA}, -+ #else -+ {"PUBLIC_KEY_NOT_RSA", ERR_LIB_SSL, 210}, -+ #endif -+ #ifdef SSL_R_READ_BIO_NOT_SET -+ {"READ_BIO_NOT_SET", ERR_LIB_SSL, SSL_R_READ_BIO_NOT_SET}, -+ #else -+ {"READ_BIO_NOT_SET", ERR_LIB_SSL, 211}, -+ #endif -+ #ifdef SSL_R_READ_TIMEOUT_EXPIRED -+ {"READ_TIMEOUT_EXPIRED", ERR_LIB_SSL, SSL_R_READ_TIMEOUT_EXPIRED}, -+ #else -+ {"READ_TIMEOUT_EXPIRED", ERR_LIB_SSL, 312}, -+ #endif -+ #ifdef SSL_R_READ_WRONG_PACKET_TYPE -+ {"READ_WRONG_PACKET_TYPE", ERR_LIB_SSL, SSL_R_READ_WRONG_PACKET_TYPE}, -+ #else -+ {"READ_WRONG_PACKET_TYPE", ERR_LIB_SSL, 212}, -+ #endif -+ #ifdef SSL_R_RECORD_LENGTH_MISMATCH -+ {"RECORD_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_RECORD_LENGTH_MISMATCH}, -+ #else -+ {"RECORD_LENGTH_MISMATCH", ERR_LIB_SSL, 213}, -+ #endif -+ #ifdef SSL_R_RECORD_TOO_LARGE -+ {"RECORD_TOO_LARGE", ERR_LIB_SSL, SSL_R_RECORD_TOO_LARGE}, -+ #else -+ {"RECORD_TOO_LARGE", ERR_LIB_SSL, 214}, -+ #endif -+ #ifdef SSL_R_RECORD_TOO_SMALL -+ {"RECORD_TOO_SMALL", ERR_LIB_SSL, SSL_R_RECORD_TOO_SMALL}, -+ #else -+ {"RECORD_TOO_SMALL", ERR_LIB_SSL, 298}, -+ #endif -+ #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG -+ {"RENEGOTIATE_EXT_TOO_LONG", ERR_LIB_SSL, SSL_R_RENEGOTIATE_EXT_TOO_LONG}, -+ #else -+ {"RENEGOTIATE_EXT_TOO_LONG", ERR_LIB_SSL, 335}, -+ #endif -+ #ifdef SSL_R_RENEGOTIATION_ENCODING_ERR -+ {"RENEGOTIATION_ENCODING_ERR", ERR_LIB_SSL, SSL_R_RENEGOTIATION_ENCODING_ERR}, -+ #else -+ {"RENEGOTIATION_ENCODING_ERR", ERR_LIB_SSL, 336}, -+ #endif -+ #ifdef SSL_R_RENEGOTIATION_MISMATCH -+ {"RENEGOTIATION_MISMATCH", ERR_LIB_SSL, SSL_R_RENEGOTIATION_MISMATCH}, -+ #else -+ {"RENEGOTIATION_MISMATCH", ERR_LIB_SSL, 337}, -+ #endif -+ #ifdef SSL_R_REQUIRED_CIPHER_MISSING -+ {"REQUIRED_CIPHER_MISSING", ERR_LIB_SSL, SSL_R_REQUIRED_CIPHER_MISSING}, -+ #else -+ {"REQUIRED_CIPHER_MISSING", ERR_LIB_SSL, 215}, -+ #endif -+ #ifdef SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING -+ {"REQUIRED_COMPRESSSION_ALGORITHM_MISSING", ERR_LIB_SSL, SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING}, -+ #else -+ {"REQUIRED_COMPRESSSION_ALGORITHM_MISSING", ERR_LIB_SSL, 342}, -+ #endif -+ #ifdef SSL_R_REUSE_CERT_LENGTH_NOT_ZERO -+ {"REUSE_CERT_LENGTH_NOT_ZERO", ERR_LIB_SSL, SSL_R_REUSE_CERT_LENGTH_NOT_ZERO}, -+ #else -+ {"REUSE_CERT_LENGTH_NOT_ZERO", ERR_LIB_SSL, 216}, -+ #endif -+ #ifdef SSL_R_REUSE_CERT_TYPE_NOT_ZERO -+ {"REUSE_CERT_TYPE_NOT_ZERO", ERR_LIB_SSL, SSL_R_REUSE_CERT_TYPE_NOT_ZERO}, -+ #else -+ {"REUSE_CERT_TYPE_NOT_ZERO", ERR_LIB_SSL, 217}, -+ #endif -+ #ifdef SSL_R_REUSE_CIPHER_LIST_NOT_ZERO -+ {"REUSE_CIPHER_LIST_NOT_ZERO", ERR_LIB_SSL, SSL_R_REUSE_CIPHER_LIST_NOT_ZERO}, -+ #else -+ {"REUSE_CIPHER_LIST_NOT_ZERO", ERR_LIB_SSL, 218}, -+ #endif -+ #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING -+ {"SCSV_RECEIVED_WHEN_RENEGOTIATING", ERR_LIB_SSL, SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING}, -+ #else -+ {"SCSV_RECEIVED_WHEN_RENEGOTIATING", ERR_LIB_SSL, 345}, -+ #endif -+ #ifdef SSL_R_SERVERHELLO_TLSEXT -+ {"SERVERHELLO_TLSEXT", ERR_LIB_SSL, SSL_R_SERVERHELLO_TLSEXT}, -+ #else -+ {"SERVERHELLO_TLSEXT", ERR_LIB_SSL, 275}, -+ #endif -+ #ifdef SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED -+ {"SESSION_ID_CONTEXT_UNINITIALIZED", ERR_LIB_SSL, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED}, -+ #else -+ {"SESSION_ID_CONTEXT_UNINITIALIZED", ERR_LIB_SSL, 277}, -+ #endif -+ #ifdef SSL_R_SHORT_READ -+ {"SHORT_READ", ERR_LIB_SSL, SSL_R_SHORT_READ}, -+ #else -+ {"SHORT_READ", ERR_LIB_SSL, 219}, -+ #endif -+ #ifdef SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE -+ {"SIGNATURE_FOR_NON_SIGNING_CERTIFICATE", ERR_LIB_SSL, SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE}, -+ #else -+ {"SIGNATURE_FOR_NON_SIGNING_CERTIFICATE", ERR_LIB_SSL, 220}, -+ #endif -+ #ifdef SSL_R_SSL23_DOING_SESSION_ID_REUSE -+ {"SSL23_DOING_SESSION_ID_REUSE", ERR_LIB_SSL, SSL_R_SSL23_DOING_SESSION_ID_REUSE}, -+ #else -+ {"SSL23_DOING_SESSION_ID_REUSE", ERR_LIB_SSL, 221}, -+ #endif -+ #ifdef SSL_R_SSL2_CONNECTION_ID_TOO_LONG -+ {"SSL2_CONNECTION_ID_TOO_LONG", ERR_LIB_SSL, SSL_R_SSL2_CONNECTION_ID_TOO_LONG}, -+ #else -+ {"SSL2_CONNECTION_ID_TOO_LONG", ERR_LIB_SSL, 299}, -+ #endif -+ #ifdef SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT -+ {"SSL3_EXT_INVALID_ECPOINTFORMAT", ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT}, -+ #else -+ {"SSL3_EXT_INVALID_ECPOINTFORMAT", ERR_LIB_SSL, 321}, -+ #endif -+ #ifdef SSL_R_SSL3_EXT_INVALID_SERVERNAME -+ {"SSL3_EXT_INVALID_SERVERNAME", ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_SERVERNAME}, -+ #else -+ {"SSL3_EXT_INVALID_SERVERNAME", ERR_LIB_SSL, 319}, -+ #endif -+ #ifdef SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE -+ {"SSL3_EXT_INVALID_SERVERNAME_TYPE", ERR_LIB_SSL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE}, -+ #else -+ {"SSL3_EXT_INVALID_SERVERNAME_TYPE", ERR_LIB_SSL, 320}, -+ #endif -+ #ifdef SSL_R_SSL3_SESSION_ID_TOO_LONG -+ {"SSL3_SESSION_ID_TOO_LONG", ERR_LIB_SSL, SSL_R_SSL3_SESSION_ID_TOO_LONG}, -+ #else -+ {"SSL3_SESSION_ID_TOO_LONG", ERR_LIB_SSL, 300}, -+ #endif -+ #ifdef SSL_R_SSL3_SESSION_ID_TOO_SHORT -+ {"SSL3_SESSION_ID_TOO_SHORT", ERR_LIB_SSL, SSL_R_SSL3_SESSION_ID_TOO_SHORT}, -+ #else -+ {"SSL3_SESSION_ID_TOO_SHORT", ERR_LIB_SSL, 222}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_BAD_CERTIFICATE -+ {"SSLV3_ALERT_BAD_CERTIFICATE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_BAD_CERTIFICATE}, -+ #else -+ {"SSLV3_ALERT_BAD_CERTIFICATE", ERR_LIB_SSL, 1042}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_BAD_RECORD_MAC -+ {"SSLV3_ALERT_BAD_RECORD_MAC", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_BAD_RECORD_MAC}, -+ #else -+ {"SSLV3_ALERT_BAD_RECORD_MAC", ERR_LIB_SSL, 1020}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED -+ {"SSLV3_ALERT_CERTIFICATE_EXPIRED", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED}, -+ #else -+ {"SSLV3_ALERT_CERTIFICATE_EXPIRED", ERR_LIB_SSL, 1045}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED -+ {"SSLV3_ALERT_CERTIFICATE_REVOKED", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED}, -+ #else -+ {"SSLV3_ALERT_CERTIFICATE_REVOKED", ERR_LIB_SSL, 1044}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN -+ {"SSLV3_ALERT_CERTIFICATE_UNKNOWN", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN}, -+ #else -+ {"SSLV3_ALERT_CERTIFICATE_UNKNOWN", ERR_LIB_SSL, 1046}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE -+ {"SSLV3_ALERT_DECOMPRESSION_FAILURE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE}, -+ #else -+ {"SSLV3_ALERT_DECOMPRESSION_FAILURE", ERR_LIB_SSL, 1030}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE -+ {"SSLV3_ALERT_HANDSHAKE_FAILURE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE}, -+ #else -+ {"SSLV3_ALERT_HANDSHAKE_FAILURE", ERR_LIB_SSL, 1040}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER -+ {"SSLV3_ALERT_ILLEGAL_PARAMETER", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER}, -+ #else -+ {"SSLV3_ALERT_ILLEGAL_PARAMETER", ERR_LIB_SSL, 1047}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_NO_CERTIFICATE -+ {"SSLV3_ALERT_NO_CERTIFICATE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_NO_CERTIFICATE}, -+ #else -+ {"SSLV3_ALERT_NO_CERTIFICATE", ERR_LIB_SSL, 1041}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE -+ {"SSLV3_ALERT_UNEXPECTED_MESSAGE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE}, -+ #else -+ {"SSLV3_ALERT_UNEXPECTED_MESSAGE", ERR_LIB_SSL, 1010}, -+ #endif -+ #ifdef SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE -+ {"SSLV3_ALERT_UNSUPPORTED_CERTIFICATE", ERR_LIB_SSL, SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE}, -+ #else -+ {"SSLV3_ALERT_UNSUPPORTED_CERTIFICATE", ERR_LIB_SSL, 1043}, -+ #endif -+ #ifdef SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION -+ {"SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION", ERR_LIB_SSL, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION}, -+ #else -+ {"SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION", ERR_LIB_SSL, 228}, -+ #endif -+ #ifdef SSL_R_SSL_HANDSHAKE_FAILURE -+ {"SSL_HANDSHAKE_FAILURE", ERR_LIB_SSL, SSL_R_SSL_HANDSHAKE_FAILURE}, -+ #else -+ {"SSL_HANDSHAKE_FAILURE", ERR_LIB_SSL, 229}, -+ #endif -+ #ifdef SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS -+ {"SSL_LIBRARY_HAS_NO_CIPHERS", ERR_LIB_SSL, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS}, -+ #else -+ {"SSL_LIBRARY_HAS_NO_CIPHERS", ERR_LIB_SSL, 230}, -+ #endif -+ #ifdef SSL_R_SSL_SESSION_ID_CALLBACK_FAILED -+ {"SSL_SESSION_ID_CALLBACK_FAILED", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CALLBACK_FAILED}, -+ #else -+ {"SSL_SESSION_ID_CALLBACK_FAILED", ERR_LIB_SSL, 301}, -+ #endif -+ #ifdef SSL_R_SSL_SESSION_ID_CONFLICT -+ {"SSL_SESSION_ID_CONFLICT", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONFLICT}, -+ #else -+ {"SSL_SESSION_ID_CONFLICT", ERR_LIB_SSL, 302}, -+ #endif -+ #ifdef SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG -+ {"SSL_SESSION_ID_CONTEXT_TOO_LONG", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG}, -+ #else -+ {"SSL_SESSION_ID_CONTEXT_TOO_LONG", ERR_LIB_SSL, 273}, -+ #endif -+ #ifdef SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH -+ {"SSL_SESSION_ID_HAS_BAD_LENGTH", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH}, -+ #else -+ {"SSL_SESSION_ID_HAS_BAD_LENGTH", ERR_LIB_SSL, 303}, -+ #endif -+ #ifdef SSL_R_SSL_SESSION_ID_IS_DIFFERENT -+ {"SSL_SESSION_ID_IS_DIFFERENT", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_IS_DIFFERENT}, -+ #else -+ {"SSL_SESSION_ID_IS_DIFFERENT", ERR_LIB_SSL, 231}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_ACCESS_DENIED -+ {"TLSV1_ALERT_ACCESS_DENIED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_ACCESS_DENIED}, -+ #else -+ {"TLSV1_ALERT_ACCESS_DENIED", ERR_LIB_SSL, 1049}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_DECODE_ERROR -+ {"TLSV1_ALERT_DECODE_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECODE_ERROR}, -+ #else -+ {"TLSV1_ALERT_DECODE_ERROR", ERR_LIB_SSL, 1050}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_DECRYPTION_FAILED -+ {"TLSV1_ALERT_DECRYPTION_FAILED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECRYPTION_FAILED}, -+ #else -+ {"TLSV1_ALERT_DECRYPTION_FAILED", ERR_LIB_SSL, 1021}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_DECRYPT_ERROR -+ {"TLSV1_ALERT_DECRYPT_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_DECRYPT_ERROR}, -+ #else -+ {"TLSV1_ALERT_DECRYPT_ERROR", ERR_LIB_SSL, 1051}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION -+ {"TLSV1_ALERT_EXPORT_RESTRICTION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION}, -+ #else -+ {"TLSV1_ALERT_EXPORT_RESTRICTION", ERR_LIB_SSL, 1060}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY -+ {"TLSV1_ALERT_INSUFFICIENT_SECURITY", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY}, -+ #else -+ {"TLSV1_ALERT_INSUFFICIENT_SECURITY", ERR_LIB_SSL, 1071}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_INTERNAL_ERROR -+ {"TLSV1_ALERT_INTERNAL_ERROR", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INTERNAL_ERROR}, -+ #else -+ {"TLSV1_ALERT_INTERNAL_ERROR", ERR_LIB_SSL, 1080}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_NO_RENEGOTIATION -+ {"TLSV1_ALERT_NO_RENEGOTIATION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_NO_RENEGOTIATION}, -+ #else -+ {"TLSV1_ALERT_NO_RENEGOTIATION", ERR_LIB_SSL, 1100}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_PROTOCOL_VERSION -+ {"TLSV1_ALERT_PROTOCOL_VERSION", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_PROTOCOL_VERSION}, -+ #else -+ {"TLSV1_ALERT_PROTOCOL_VERSION", ERR_LIB_SSL, 1070}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_RECORD_OVERFLOW -+ {"TLSV1_ALERT_RECORD_OVERFLOW", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_RECORD_OVERFLOW}, -+ #else -+ {"TLSV1_ALERT_RECORD_OVERFLOW", ERR_LIB_SSL, 1022}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_UNKNOWN_CA -+ {"TLSV1_ALERT_UNKNOWN_CA", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_UNKNOWN_CA}, -+ #else -+ {"TLSV1_ALERT_UNKNOWN_CA", ERR_LIB_SSL, 1048}, -+ #endif -+ #ifdef SSL_R_TLSV1_ALERT_USER_CANCELLED -+ {"TLSV1_ALERT_USER_CANCELLED", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_USER_CANCELLED}, -+ #else -+ {"TLSV1_ALERT_USER_CANCELLED", ERR_LIB_SSL, 1090}, -+ #endif -+ #ifdef SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE -+ {"TLSV1_BAD_CERTIFICATE_HASH_VALUE", ERR_LIB_SSL, SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE}, -+ #else -+ {"TLSV1_BAD_CERTIFICATE_HASH_VALUE", ERR_LIB_SSL, 1114}, -+ #endif -+ #ifdef SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE -+ {"TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE", ERR_LIB_SSL, SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE}, -+ #else -+ {"TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE", ERR_LIB_SSL, 1113}, -+ #endif -+ #ifdef SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE -+ {"TLSV1_CERTIFICATE_UNOBTAINABLE", ERR_LIB_SSL, SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE}, -+ #else -+ {"TLSV1_CERTIFICATE_UNOBTAINABLE", ERR_LIB_SSL, 1111}, -+ #endif -+ #ifdef SSL_R_TLSV1_UNRECOGNIZED_NAME -+ {"TLSV1_UNRECOGNIZED_NAME", ERR_LIB_SSL, SSL_R_TLSV1_UNRECOGNIZED_NAME}, -+ #else -+ {"TLSV1_UNRECOGNIZED_NAME", ERR_LIB_SSL, 1112}, -+ #endif -+ #ifdef SSL_R_TLSV1_UNSUPPORTED_EXTENSION -+ {"TLSV1_UNSUPPORTED_EXTENSION", ERR_LIB_SSL, SSL_R_TLSV1_UNSUPPORTED_EXTENSION}, -+ #else -+ {"TLSV1_UNSUPPORTED_EXTENSION", ERR_LIB_SSL, 1110}, -+ #endif -+ #ifdef SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER -+ {"TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER", ERR_LIB_SSL, SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER}, -+ #else -+ {"TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER", ERR_LIB_SSL, 232}, -+ #endif -+ #ifdef SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST -+ {"TLS_INVALID_ECPOINTFORMAT_LIST", ERR_LIB_SSL, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST}, -+ #else -+ {"TLS_INVALID_ECPOINTFORMAT_LIST", ERR_LIB_SSL, 157}, -+ #endif -+ #ifdef SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST -+ {"TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST", ERR_LIB_SSL, SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST}, -+ #else -+ {"TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST", ERR_LIB_SSL, 233}, -+ #endif -+ #ifdef SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG -+ {"TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG", ERR_LIB_SSL, SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG}, -+ #else -+ {"TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG", ERR_LIB_SSL, 234}, -+ #endif -+ #ifdef SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER -+ {"TRIED_TO_USE_UNSUPPORTED_CIPHER", ERR_LIB_SSL, SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER}, -+ #else -+ {"TRIED_TO_USE_UNSUPPORTED_CIPHER", ERR_LIB_SSL, 235}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_DECODE_DH_CERTS -+ {"UNABLE_TO_DECODE_DH_CERTS", ERR_LIB_SSL, SSL_R_UNABLE_TO_DECODE_DH_CERTS}, -+ #else -+ {"UNABLE_TO_DECODE_DH_CERTS", ERR_LIB_SSL, 236}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_DECODE_ECDH_CERTS -+ {"UNABLE_TO_DECODE_ECDH_CERTS", ERR_LIB_SSL, SSL_R_UNABLE_TO_DECODE_ECDH_CERTS}, -+ #else -+ {"UNABLE_TO_DECODE_ECDH_CERTS", ERR_LIB_SSL, 313}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY -+ {"UNABLE_TO_EXTRACT_PUBLIC_KEY", ERR_LIB_SSL, SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY}, -+ #else -+ {"UNABLE_TO_EXTRACT_PUBLIC_KEY", ERR_LIB_SSL, 237}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_FIND_DH_PARAMETERS -+ {"UNABLE_TO_FIND_DH_PARAMETERS", ERR_LIB_SSL, SSL_R_UNABLE_TO_FIND_DH_PARAMETERS}, -+ #else -+ {"UNABLE_TO_FIND_DH_PARAMETERS", ERR_LIB_SSL, 238}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS -+ {"UNABLE_TO_FIND_ECDH_PARAMETERS", ERR_LIB_SSL, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS}, -+ #else -+ {"UNABLE_TO_FIND_ECDH_PARAMETERS", ERR_LIB_SSL, 314}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS -+ {"UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS", ERR_LIB_SSL, SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS}, -+ #else -+ {"UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS", ERR_LIB_SSL, 239}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_FIND_SSL_METHOD -+ {"UNABLE_TO_FIND_SSL_METHOD", ERR_LIB_SSL, SSL_R_UNABLE_TO_FIND_SSL_METHOD}, -+ #else -+ {"UNABLE_TO_FIND_SSL_METHOD", ERR_LIB_SSL, 240}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES -+ {"UNABLE_TO_LOAD_SSL2_MD5_ROUTINES", ERR_LIB_SSL, SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES}, -+ #else -+ {"UNABLE_TO_LOAD_SSL2_MD5_ROUTINES", ERR_LIB_SSL, 241}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES -+ {"UNABLE_TO_LOAD_SSL3_MD5_ROUTINES", ERR_LIB_SSL, SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES}, -+ #else -+ {"UNABLE_TO_LOAD_SSL3_MD5_ROUTINES", ERR_LIB_SSL, 242}, -+ #endif -+ #ifdef SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES -+ {"UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES", ERR_LIB_SSL, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES}, -+ #else -+ {"UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES", ERR_LIB_SSL, 243}, -+ #endif -+ #ifdef SSL_R_UNEXPECTED_MESSAGE -+ {"UNEXPECTED_MESSAGE", ERR_LIB_SSL, SSL_R_UNEXPECTED_MESSAGE}, -+ #else -+ {"UNEXPECTED_MESSAGE", ERR_LIB_SSL, 244}, -+ #endif -+ #ifdef SSL_R_UNEXPECTED_RECORD -+ {"UNEXPECTED_RECORD", ERR_LIB_SSL, SSL_R_UNEXPECTED_RECORD}, -+ #else -+ {"UNEXPECTED_RECORD", ERR_LIB_SSL, 245}, -+ #endif -+ #ifdef SSL_R_UNINITIALIZED -+ {"UNINITIALIZED", ERR_LIB_SSL, SSL_R_UNINITIALIZED}, -+ #else -+ {"UNINITIALIZED", ERR_LIB_SSL, 276}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_ALERT_TYPE -+ {"UNKNOWN_ALERT_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_ALERT_TYPE}, -+ #else -+ {"UNKNOWN_ALERT_TYPE", ERR_LIB_SSL, 246}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_CERTIFICATE_TYPE -+ {"UNKNOWN_CERTIFICATE_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE}, -+ #else -+ {"UNKNOWN_CERTIFICATE_TYPE", ERR_LIB_SSL, 247}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_CIPHER_RETURNED -+ {"UNKNOWN_CIPHER_RETURNED", ERR_LIB_SSL, SSL_R_UNKNOWN_CIPHER_RETURNED}, -+ #else -+ {"UNKNOWN_CIPHER_RETURNED", ERR_LIB_SSL, 248}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_CIPHER_TYPE -+ {"UNKNOWN_CIPHER_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_CIPHER_TYPE}, -+ #else -+ {"UNKNOWN_CIPHER_TYPE", ERR_LIB_SSL, 249}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE -+ {"UNKNOWN_KEY_EXCHANGE_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE}, -+ #else -+ {"UNKNOWN_KEY_EXCHANGE_TYPE", ERR_LIB_SSL, 250}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_PKEY_TYPE -+ {"UNKNOWN_PKEY_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_PKEY_TYPE}, -+ #else -+ {"UNKNOWN_PKEY_TYPE", ERR_LIB_SSL, 251}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_PROTOCOL -+ {"UNKNOWN_PROTOCOL", ERR_LIB_SSL, SSL_R_UNKNOWN_PROTOCOL}, -+ #else -+ {"UNKNOWN_PROTOCOL", ERR_LIB_SSL, 252}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_REMOTE_ERROR_TYPE -+ {"UNKNOWN_REMOTE_ERROR_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_REMOTE_ERROR_TYPE}, -+ #else -+ {"UNKNOWN_REMOTE_ERROR_TYPE", ERR_LIB_SSL, 253}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_SSL_VERSION -+ {"UNKNOWN_SSL_VERSION", ERR_LIB_SSL, SSL_R_UNKNOWN_SSL_VERSION}, -+ #else -+ {"UNKNOWN_SSL_VERSION", ERR_LIB_SSL, 254}, -+ #endif -+ #ifdef SSL_R_UNKNOWN_STATE -+ {"UNKNOWN_STATE", ERR_LIB_SSL, SSL_R_UNKNOWN_STATE}, -+ #else -+ {"UNKNOWN_STATE", ERR_LIB_SSL, 255}, -+ #endif -+ #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED -+ {"UNSAFE_LEGACY_RENEGOTIATION_DISABLED", ERR_LIB_SSL, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED}, -+ #else -+ {"UNSAFE_LEGACY_RENEGOTIATION_DISABLED", ERR_LIB_SSL, 338}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_CIPHER -+ {"UNSUPPORTED_CIPHER", ERR_LIB_SSL, SSL_R_UNSUPPORTED_CIPHER}, -+ #else -+ {"UNSUPPORTED_CIPHER", ERR_LIB_SSL, 256}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM -+ {"UNSUPPORTED_COMPRESSION_ALGORITHM", ERR_LIB_SSL, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM}, -+ #else -+ {"UNSUPPORTED_COMPRESSION_ALGORITHM", ERR_LIB_SSL, 257}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_DIGEST_TYPE -+ {"UNSUPPORTED_DIGEST_TYPE", ERR_LIB_SSL, SSL_R_UNSUPPORTED_DIGEST_TYPE}, -+ #else -+ {"UNSUPPORTED_DIGEST_TYPE", ERR_LIB_SSL, 326}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_ELLIPTIC_CURVE -+ {"UNSUPPORTED_ELLIPTIC_CURVE", ERR_LIB_SSL, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE}, -+ #else -+ {"UNSUPPORTED_ELLIPTIC_CURVE", ERR_LIB_SSL, 315}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_PROTOCOL -+ {"UNSUPPORTED_PROTOCOL", ERR_LIB_SSL, SSL_R_UNSUPPORTED_PROTOCOL}, -+ #else -+ {"UNSUPPORTED_PROTOCOL", ERR_LIB_SSL, 258}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_SSL_VERSION -+ {"UNSUPPORTED_SSL_VERSION", ERR_LIB_SSL, SSL_R_UNSUPPORTED_SSL_VERSION}, -+ #else -+ {"UNSUPPORTED_SSL_VERSION", ERR_LIB_SSL, 259}, -+ #endif -+ #ifdef SSL_R_UNSUPPORTED_STATUS_TYPE -+ {"UNSUPPORTED_STATUS_TYPE", ERR_LIB_SSL, SSL_R_UNSUPPORTED_STATUS_TYPE}, -+ #else -+ {"UNSUPPORTED_STATUS_TYPE", ERR_LIB_SSL, 329}, -+ #endif -+ #ifdef SSL_R_WRITE_BIO_NOT_SET -+ {"WRITE_BIO_NOT_SET", ERR_LIB_SSL, SSL_R_WRITE_BIO_NOT_SET}, -+ #else -+ {"WRITE_BIO_NOT_SET", ERR_LIB_SSL, 260}, -+ #endif -+ #ifdef SSL_R_WRONG_CIPHER_RETURNED -+ {"WRONG_CIPHER_RETURNED", ERR_LIB_SSL, SSL_R_WRONG_CIPHER_RETURNED}, -+ #else -+ {"WRONG_CIPHER_RETURNED", ERR_LIB_SSL, 261}, -+ #endif -+ #ifdef SSL_R_WRONG_MESSAGE_TYPE -+ {"WRONG_MESSAGE_TYPE", ERR_LIB_SSL, SSL_R_WRONG_MESSAGE_TYPE}, -+ #else -+ {"WRONG_MESSAGE_TYPE", ERR_LIB_SSL, 262}, -+ #endif -+ #ifdef SSL_R_WRONG_NUMBER_OF_KEY_BITS -+ {"WRONG_NUMBER_OF_KEY_BITS", ERR_LIB_SSL, SSL_R_WRONG_NUMBER_OF_KEY_BITS}, -+ #else -+ {"WRONG_NUMBER_OF_KEY_BITS", ERR_LIB_SSL, 263}, -+ #endif -+ #ifdef SSL_R_WRONG_SIGNATURE_LENGTH -+ {"WRONG_SIGNATURE_LENGTH", ERR_LIB_SSL, SSL_R_WRONG_SIGNATURE_LENGTH}, -+ #else -+ {"WRONG_SIGNATURE_LENGTH", ERR_LIB_SSL, 264}, -+ #endif -+ #ifdef SSL_R_WRONG_SIGNATURE_SIZE -+ {"WRONG_SIGNATURE_SIZE", ERR_LIB_SSL, SSL_R_WRONG_SIGNATURE_SIZE}, -+ #else -+ {"WRONG_SIGNATURE_SIZE", ERR_LIB_SSL, 265}, -+ #endif -+ #ifdef SSL_R_WRONG_SSL_VERSION -+ {"WRONG_SSL_VERSION", ERR_LIB_SSL, SSL_R_WRONG_SSL_VERSION}, -+ #else -+ {"WRONG_SSL_VERSION", ERR_LIB_SSL, 266}, -+ #endif -+ #ifdef SSL_R_WRONG_VERSION_NUMBER -+ {"WRONG_VERSION_NUMBER", ERR_LIB_SSL, SSL_R_WRONG_VERSION_NUMBER}, -+ #else -+ {"WRONG_VERSION_NUMBER", ERR_LIB_SSL, 267}, -+ #endif -+ #ifdef SSL_R_X509_LIB -+ {"X509_LIB", ERR_LIB_SSL, SSL_R_X509_LIB}, -+ #else -+ {"X509_LIB", ERR_LIB_SSL, 268}, -+ #endif -+ #ifdef SSL_R_X509_VERIFICATION_SETUP_PROBLEMS -+ {"X509_VERIFICATION_SETUP_PROBLEMS", ERR_LIB_SSL, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS}, -+ #else -+ {"X509_VERIFICATION_SETUP_PROBLEMS", ERR_LIB_SSL, 269}, -+ #endif -+ #ifdef X509_R_BAD_X509_FILETYPE -+ {"BAD_X509_FILETYPE", ERR_LIB_X509, X509_R_BAD_X509_FILETYPE}, -+ #else -+ {"BAD_X509_FILETYPE", ERR_LIB_X509, 100}, -+ #endif -+ #ifdef X509_R_BASE64_DECODE_ERROR -+ {"BASE64_DECODE_ERROR", ERR_LIB_X509, X509_R_BASE64_DECODE_ERROR}, -+ #else -+ {"BASE64_DECODE_ERROR", ERR_LIB_X509, 118}, -+ #endif -+ #ifdef X509_R_CANT_CHECK_DH_KEY -+ {"CANT_CHECK_DH_KEY", ERR_LIB_X509, X509_R_CANT_CHECK_DH_KEY}, -+ #else -+ {"CANT_CHECK_DH_KEY", ERR_LIB_X509, 114}, -+ #endif -+ #ifdef X509_R_CERT_ALREADY_IN_HASH_TABLE -+ {"CERT_ALREADY_IN_HASH_TABLE", ERR_LIB_X509, X509_R_CERT_ALREADY_IN_HASH_TABLE}, -+ #else -+ {"CERT_ALREADY_IN_HASH_TABLE", ERR_LIB_X509, 101}, -+ #endif -+ #ifdef X509_R_ERR_ASN1_LIB -+ {"ERR_ASN1_LIB", ERR_LIB_X509, X509_R_ERR_ASN1_LIB}, -+ #else -+ {"ERR_ASN1_LIB", ERR_LIB_X509, 102}, -+ #endif -+ #ifdef X509_R_INVALID_DIRECTORY -+ {"INVALID_DIRECTORY", ERR_LIB_X509, X509_R_INVALID_DIRECTORY}, -+ #else -+ {"INVALID_DIRECTORY", ERR_LIB_X509, 113}, -+ #endif -+ #ifdef X509_R_INVALID_FIELD_NAME -+ {"INVALID_FIELD_NAME", ERR_LIB_X509, X509_R_INVALID_FIELD_NAME}, -+ #else -+ {"INVALID_FIELD_NAME", ERR_LIB_X509, 119}, -+ #endif -+ #ifdef X509_R_INVALID_TRUST -+ {"INVALID_TRUST", ERR_LIB_X509, X509_R_INVALID_TRUST}, -+ #else -+ {"INVALID_TRUST", ERR_LIB_X509, 123}, -+ #endif -+ #ifdef X509_R_KEY_TYPE_MISMATCH -+ {"KEY_TYPE_MISMATCH", ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH}, -+ #else -+ {"KEY_TYPE_MISMATCH", ERR_LIB_X509, 115}, -+ #endif -+ #ifdef X509_R_KEY_VALUES_MISMATCH -+ {"KEY_VALUES_MISMATCH", ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH}, -+ #else -+ {"KEY_VALUES_MISMATCH", ERR_LIB_X509, 116}, -+ #endif -+ #ifdef X509_R_LOADING_CERT_DIR -+ {"LOADING_CERT_DIR", ERR_LIB_X509, X509_R_LOADING_CERT_DIR}, -+ #else -+ {"LOADING_CERT_DIR", ERR_LIB_X509, 103}, -+ #endif -+ #ifdef X509_R_LOADING_DEFAULTS -+ {"LOADING_DEFAULTS", ERR_LIB_X509, X509_R_LOADING_DEFAULTS}, -+ #else -+ {"LOADING_DEFAULTS", ERR_LIB_X509, 104}, -+ #endif -+ #ifdef X509_R_METHOD_NOT_SUPPORTED -+ {"METHOD_NOT_SUPPORTED", ERR_LIB_X509, X509_R_METHOD_NOT_SUPPORTED}, -+ #else -+ {"METHOD_NOT_SUPPORTED", ERR_LIB_X509, 124}, -+ #endif -+ #ifdef X509_R_NO_CERT_SET_FOR_US_TO_VERIFY -+ {"NO_CERT_SET_FOR_US_TO_VERIFY", ERR_LIB_X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY}, -+ #else -+ {"NO_CERT_SET_FOR_US_TO_VERIFY", ERR_LIB_X509, 105}, -+ #endif -+ #ifdef X509_R_PUBLIC_KEY_DECODE_ERROR -+ {"PUBLIC_KEY_DECODE_ERROR", ERR_LIB_X509, X509_R_PUBLIC_KEY_DECODE_ERROR}, -+ #else -+ {"PUBLIC_KEY_DECODE_ERROR", ERR_LIB_X509, 125}, -+ #endif -+ #ifdef X509_R_PUBLIC_KEY_ENCODE_ERROR -+ {"PUBLIC_KEY_ENCODE_ERROR", ERR_LIB_X509, X509_R_PUBLIC_KEY_ENCODE_ERROR}, -+ #else -+ {"PUBLIC_KEY_ENCODE_ERROR", ERR_LIB_X509, 126}, -+ #endif -+ #ifdef X509_R_SHOULD_RETRY -+ {"SHOULD_RETRY", ERR_LIB_X509, X509_R_SHOULD_RETRY}, -+ #else -+ {"SHOULD_RETRY", ERR_LIB_X509, 106}, -+ #endif -+ #ifdef X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN -+ {"UNABLE_TO_FIND_PARAMETERS_IN_CHAIN", ERR_LIB_X509, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN}, -+ #else -+ {"UNABLE_TO_FIND_PARAMETERS_IN_CHAIN", ERR_LIB_X509, 107}, -+ #endif -+ #ifdef X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY -+ {"UNABLE_TO_GET_CERTS_PUBLIC_KEY", ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY}, -+ #else -+ {"UNABLE_TO_GET_CERTS_PUBLIC_KEY", ERR_LIB_X509, 108}, -+ #endif -+ #ifdef X509_R_UNKNOWN_KEY_TYPE -+ {"UNKNOWN_KEY_TYPE", ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE}, -+ #else -+ {"UNKNOWN_KEY_TYPE", ERR_LIB_X509, 117}, -+ #endif -+ #ifdef X509_R_UNKNOWN_NID -+ {"UNKNOWN_NID", ERR_LIB_X509, X509_R_UNKNOWN_NID}, -+ #else -+ {"UNKNOWN_NID", ERR_LIB_X509, 109}, -+ #endif -+ #ifdef X509_R_UNKNOWN_PURPOSE_ID -+ {"UNKNOWN_PURPOSE_ID", ERR_LIB_X509, X509_R_UNKNOWN_PURPOSE_ID}, -+ #else -+ {"UNKNOWN_PURPOSE_ID", ERR_LIB_X509, 121}, -+ #endif -+ #ifdef X509_R_UNKNOWN_TRUST_ID -+ {"UNKNOWN_TRUST_ID", ERR_LIB_X509, X509_R_UNKNOWN_TRUST_ID}, -+ #else -+ {"UNKNOWN_TRUST_ID", ERR_LIB_X509, 120}, -+ #endif -+ #ifdef X509_R_UNSUPPORTED_ALGORITHM -+ {"UNSUPPORTED_ALGORITHM", ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM}, -+ #else -+ {"UNSUPPORTED_ALGORITHM", ERR_LIB_X509, 111}, -+ #endif -+ #ifdef X509_R_WRONG_LOOKUP_TYPE -+ {"WRONG_LOOKUP_TYPE", ERR_LIB_X509, X509_R_WRONG_LOOKUP_TYPE}, -+ #else -+ {"WRONG_LOOKUP_TYPE", ERR_LIB_X509, 112}, -+ #endif -+ #ifdef X509_R_WRONG_TYPE -+ {"WRONG_TYPE", ERR_LIB_X509, X509_R_WRONG_TYPE}, -+ #else -+ {"WRONG_TYPE", ERR_LIB_X509, 122}, -+ #endif -+ { NULL } -+}; -diff --git a/Tools/ssl/make_ssl_data.py b/Tools/ssl/make_ssl_data.py -new file mode 100755 ---- /dev/null -+++ b/Tools/ssl/make_ssl_data.py -@@ -0,0 +1,68 @@ -+#! /usr/bin/env python3 -+ -+""" -+This script should be called *manually* when we want to upgrade SSLError -+`library` and `reason` mnemnonics to a more recent OpenSSL version. -+ -+It takes two arguments: -+- the path to the OpenSSL include files' directory -+ (e.g. openssl-1.0.1-beta3/include/openssl/) -+- the path to the C file to be generated -+ (probably Modules/_ssl_data.h) -+""" -+ -+import datetime -+import os -+import re -+import sys -+ -+ -+def parse_error_codes(h_file, prefix): -+ pat = re.compile(r"#define\W+(%s([\w]+))\W+(\d+)\b" % re.escape(prefix)) -+ codes = [] -+ with open(h_file, "r", encoding="latin1") as f: -+ for line in f: -+ match = pat.search(line) -+ if match: -+ code, name, num = match.groups() -+ num = int(num) -+ codes.append((code, name, num)) -+ return codes -+ -+if __name__ == "__main__": -+ openssl_inc = sys.argv[1] -+ outfile = sys.argv[2] -+ use_stdout = outfile == '-' -+ f = sys.stdout if use_stdout else open(outfile, "w") -+ error_libraries = ( -+ # (library code, mnemonic, error prefix, header file) -+ ('ERR_LIB_PEM', 'PEM', 'PEM_R_', 'pem.h'), -+ ('ERR_LIB_SSL', 'SSL', 'SSL_R_', 'ssl.h'), -+ ('ERR_LIB_X509', 'X509', 'X509_R_', 'x509.h'), -+ ) -+ def w(l): -+ f.write(l + "\n") -+ w("/* File generated by Tools/ssl/make_ssl_data.py */") -+ w("/* Generated on %s */" % datetime.datetime.now().isoformat()) -+ w("") -+ -+ w("static struct py_ssl_library_code library_codes[] = {") -+ for libcode, mnemo, _, _ in error_libraries: -+ w(' {"%s", %s},' % (mnemo, libcode)) -+ w(' { NULL }') -+ w('};') -+ w("") -+ -+ w("static struct py_ssl_error_code error_codes[] = {") -+ for libcode, _, prefix, h_file in error_libraries: -+ codes = parse_error_codes(os.path.join(openssl_inc, h_file), prefix) -+ for code, name, num in sorted(codes): -+ w(' #ifdef %s' % (code)) -+ w(' {"%s", %s, %s},' % (name, libcode, code)) -+ w(' #else') -+ w(' {"%s", %s, %d},' % (name, libcode, num)) -+ w(' #endif') -+ w(' { NULL }') -+ w('};') -+ if not use_stdout: -+ f.close() -diff --git a/Tools/ssl/test_multiple_versions.py b/Tools/ssl/test_multiple_versions.py -new file mode 100644 ---- /dev/null -+++ b/Tools/ssl/test_multiple_versions.py -@@ -0,0 +1,241 @@ -+#./python -+"""Run Python tests with multiple installations of OpenSSL -+ -+The script -+ -+ (1) downloads OpenSSL tar bundle -+ (2) extracts it to ../openssl/src/openssl-VERSION/ -+ (3) compiles OpenSSL -+ (4) installs OpenSSL into ../openssl/VERSION/ -+ (5) forces a recompilation of Python modules using the -+ header and library files from ../openssl/VERSION/ -+ (6) runs Python's test suite -+ -+The script must be run with Python's build directory as current working -+directory: -+ -+ ./python Tools/ssl/test_multiple_versions.py -+ -+The script uses LD_RUN_PATH, LD_LIBRARY_PATH, CPPFLAGS and LDFLAGS to bend -+search paths for header files and shared libraries. It's known to work on -+Linux with GCC 4.x. -+ -+(c) 2013 Christian Heimes -+""" -+import logging -+import os -+import tarfile -+import shutil -+import subprocess -+import sys -+from urllib import urlopen -+ -+log = logging.getLogger("multissl") -+ -+OPENSSL_VERSIONS = [ -+ "0.9.7m", "0.9.8i", "0.9.8l", "0.9.8m", "0.9.8y", "1.0.0k", "1.0.1e" -+] -+FULL_TESTS = [ -+ "test_asyncio", "test_ftplib", "test_hashlib", "test_httplib", -+ "test_imaplib", "test_nntplib", "test_poplib", "test_smtplib", -+ "test_smtpnet", "test_urllib2_localnet", "test_venv" -+] -+MINIMAL_TESTS = ["test_ssl", "test_hashlib"] -+CADEFAULT = True -+HERE = os.path.abspath(os.getcwd()) -+DEST_DIR = os.path.abspath(os.path.join(HERE, os.pardir, "openssl")) -+ -+ -+class BuildSSL(object): -+ url_template = "https://www.openssl.org/source/openssl-{}.tar.gz" -+ -+ module_files = ["Modules/_ssl.c", -+ "Modules/socketmodule.c", -+ "Modules/_hashopenssl.c"] -+ -+ def __init__(self, version, openssl_compile_args=(), destdir=DEST_DIR): -+ self._check_python_builddir() -+ self.version = version -+ self.openssl_compile_args = openssl_compile_args -+ # installation directory -+ self.install_dir = os.path.join(destdir, version) -+ # source file -+ self.src_file = os.path.join(destdir, "src", -+ "openssl-{}.tar.gz".format(version)) -+ # build directory (removed after install) -+ self.build_dir = os.path.join(destdir, "src", -+ "openssl-{}".format(version)) -+ -+ @property -+ def openssl_cli(self): -+ """openssl CLI binary""" -+ return os.path.join(self.install_dir, "bin", "openssl") -+ -+ @property -+ def openssl_version(self): -+ """output of 'bin/openssl version'""" -+ env = os.environ.copy() -+ env["LD_LIBRARY_PATH"] = self.lib_dir -+ cmd = [self.openssl_cli, "version"] -+ return self._subprocess_output(cmd, env=env) -+ -+ @property -+ def pyssl_version(self): -+ """Value of ssl.OPENSSL_VERSION""" -+ env = os.environ.copy() -+ env["LD_LIBRARY_PATH"] = self.lib_dir -+ cmd = ["./python", "-c", "import ssl; print(ssl.OPENSSL_VERSION)"] -+ return self._subprocess_output(cmd, env=env) -+ -+ @property -+ def include_dir(self): -+ return os.path.join(self.install_dir, "include") -+ -+ @property -+ def lib_dir(self): -+ return os.path.join(self.install_dir, "lib") -+ -+ @property -+ def has_openssl(self): -+ return os.path.isfile(self.openssl_cli) -+ -+ @property -+ def has_src(self): -+ return os.path.isfile(self.src_file) -+ -+ def _subprocess_call(self, cmd, stdout=subprocess.DEVNULL, env=None, -+ **kwargs): -+ log.debug("Call '{}'".format(" ".join(cmd))) -+ return subprocess.check_call(cmd, stdout=stdout, env=env, **kwargs) -+ -+ def _subprocess_output(self, cmd, env=None, **kwargs): -+ log.debug("Call '{}'".format(" ".join(cmd))) -+ out = subprocess.check_output(cmd, env=env) -+ return out.strip().decode("utf-8") -+ -+ def _check_python_builddir(self): -+ if not os.path.isfile("python") or not os.path.isfile("setup.py"): -+ raise ValueError("Script must be run in Python build directory") -+ -+ def _download_openssl(self): -+ """Download OpenSSL source dist""" -+ src_dir = os.path.dirname(self.src_file) -+ if not os.path.isdir(src_dir): -+ os.makedirs(src_dir) -+ url = self.url_template.format(self.version) -+ log.info("Downloading OpenSSL from {}".format(url)) -+ req = urlopen(url, cadefault=CADEFAULT) -+ # KISS, read all, write all -+ data = req.read() -+ log.info("Storing {}".format(self.src_file)) -+ with open(self.src_file, "wb") as f: -+ f.write(data) -+ -+ def _unpack_openssl(self): -+ """Unpack tar.gz bundle""" -+ # cleanup -+ if os.path.isdir(self.build_dir): -+ shutil.rmtree(self.build_dir) -+ os.makedirs(self.build_dir) -+ -+ tf = tarfile.open(self.src_file) -+ base = "openssl-{}/".format(self.version) -+ # force extraction into build dir -+ members = tf.getmembers() -+ for member in members: -+ if not member.name.startswith(base): -+ raise ValueError(member.name) -+ member.name = member.name[len(base):] -+ log.info("Unpacking files to {}".format(self.build_dir)) -+ tf.extractall(self.build_dir, members) -+ -+ def _build_openssl(self): -+ """Now build openssl""" -+ log.info("Running build in {}".format(self.install_dir)) -+ cwd = self.build_dir -+ cmd = ["./config", "shared", "--prefix={}".format(self.install_dir)] -+ cmd.extend(self.openssl_compile_args) -+ self._subprocess_call(cmd, cwd=cwd) -+ self._subprocess_call(["make"], cwd=cwd) -+ -+ def _install_openssl(self, remove=True): -+ self._subprocess_call(["make", "install"], cwd=self.build_dir) -+ if remove: -+ shutil.rmtree(self.build_dir) -+ -+ def install_openssl(self): -+ if not self.has_openssl: -+ if not self.has_src: -+ self._download_openssl() -+ else: -+ log.debug("Already has src {}".format(self.src_file)) -+ self._unpack_openssl() -+ self._build_openssl() -+ self._install_openssl() -+ else: -+ log.info("Already has installation {}".format(self.install_dir)) -+ # validate installation -+ version = self.openssl_version -+ if self.version not in version: -+ raise ValueError(version) -+ -+ def touch_pymods(self): -+ # force a rebuild of all modules that use OpenSSL APIs -+ for fname in self.module_files: -+ os.utime(fname) -+ -+ def recompile_pymods(self): -+ log.info("Using OpenSSL build from {}".format(self.build_dir)) -+ # overwrite header and library search paths -+ env = os.environ.copy() -+ env["CPPFLAGS"] = "-I{}".format(self.include_dir) -+ env["LDFLAGS"] = "-L{}".format(self.lib_dir) -+ # set rpath -+ env["LD_RUN_PATH"] = self.lib_dir -+ -+ log.info("Rebuilding Python modules") -+ self.touch_pymods() -+ cmd = ["./python", "setup.py", "build"] -+ self._subprocess_call(cmd, env=env) -+ -+ def check_pyssl(self): -+ version = self.pyssl_version -+ if self.version not in version: -+ raise ValueError(version) -+ -+ def run_pytests(self, *args): -+ cmd = ["./python", "-m", "test"] -+ cmd.extend(args) -+ self._subprocess_call(cmd, stdout=None) -+ -+ def run_python_tests(self, *args): -+ self.recompile_pymods() -+ self.check_pyssl() -+ self.run_pytests(*args) -+ -+ -+def main(*args): -+ builders = [] -+ for version in OPENSSL_VERSIONS: -+ if version in ("0.9.8i", "0.9.8l"): -+ openssl_compile_args = ("no-asm",) -+ else: -+ openssl_compile_args = () -+ builder = BuildSSL(version, openssl_compile_args) -+ builder.install_openssl() -+ builders.append(builder) -+ -+ for builder in builders: -+ builder.run_python_tests(*args) -+ # final touch -+ builder.touch_pymods() -+ -+ -+if __name__ == "__main__": -+ logging.basicConfig(level=logging.INFO, -+ format="*** %(levelname)s %(message)s") -+ args = sys.argv[1:] -+ if not args: -+ args = ["-unetwork", "-v"] -+ args.extend(FULL_TESTS) -+ main(*args) - - diff --git a/SOURCES/00215-pep466-reflect-openssl-settings-ssltests.patch b/SOURCES/00215-pep466-reflect-openssl-settings-ssltests.patch deleted file mode 100644 index 34fd3ba..0000000 --- a/SOURCES/00215-pep466-reflect-openssl-settings-ssltests.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff -up Python-2.7.5/Lib/test/test_ssl.py.ssl2 Python-2.7.5/Lib/test/test_ssl.py ---- Python-2.7.5/Lib/test/test_ssl.py.ssl2 2015-03-04 12:19:26.345387741 +0100 -+++ Python-2.7.5/Lib/test/test_ssl.py 2015-03-04 12:32:43.485702679 +0100 -@@ -689,7 +689,8 @@ class ContextTests(unittest.TestCase): - @skip_if_broken_ubuntu_ssl - def test_options(self): - ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -- # OP_ALL | OP_NO_SSLv2 is the default value -+ self.assertEqual(ssl.OP_ALL, ctx.options) -+ ctx.options |= ssl.OP_NO_SSLv2 - self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2, - ctx.options) - ctx.options |= ssl.OP_NO_SSLv3 -@@ -2142,9 +2143,9 @@ else: - # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, - client_options=ssl.OP_NO_SSLv2) -- try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True, - client_options=ssl.OP_NO_SSLv3) -- try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True, - client_options=ssl.OP_NO_TLSv1) - - @skip_if_broken_ubuntu_ssl - diff --git a/SOURCES/00216-pep466-fix-load-verify-locs-unicode.patch b/SOURCES/00216-pep466-fix-load-verify-locs-unicode.patch deleted file mode 100644 index 87ee80b..0000000 --- a/SOURCES/00216-pep466-fix-load-verify-locs-unicode.patch +++ /dev/null @@ -1,72 +0,0 @@ - -# HG changeset patch -# User Benjamin Peterson -# Date 1409232801 14400 -# Node ID 97081a80f487841d81aeed55d398a1dba1faca00 -# Parent 3ae399c6ecf685086ebf07e17717955f21e14cb8 -fix load_verify_locations on unicode paths (closes #22244) - -diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py ---- a/Lib/test/test_ssl.py -+++ b/Lib/test/test_ssl.py -@@ -850,11 +850,14 @@ class ContextTests(unittest.TestCase): - ctx.load_verify_locations(cafile=CERTFILE, capath=None) - ctx.load_verify_locations(BYTES_CERTFILE) - ctx.load_verify_locations(cafile=BYTES_CERTFILE, capath=None) -+ ctx.load_verify_locations(cafile=BYTES_CERTFILE.decode('utf-8')) - self.assertRaises(TypeError, ctx.load_verify_locations) - self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None) - with self.assertRaises(IOError) as cm: - ctx.load_verify_locations(WRONGCERT) - self.assertEqual(cm.exception.errno, errno.ENOENT) -+ with self.assertRaises(IOError): -+ ctx.load_verify_locations(u'') - with self.assertRaisesRegexp(ssl.SSLError, "PEM lib"): - ctx.load_verify_locations(BADCERT) - ctx.load_verify_locations(CERTFILE, CAPATH) -diff --git a/Modules/_ssl.c b/Modules/_ssl.c ---- a/Modules/_ssl.c -+++ b/Modules/_ssl.c -@@ -2628,17 +2628,33 @@ load_verify_locations(PySSLContext *self - } - - if (cafile) { -- cafile_bytes = PyString_AsEncodedObject( -- cafile, Py_FileSystemDefaultEncoding, "strict"); -- if (!cafile_bytes) { -- goto error; -+ if (PyString_Check(cafile)) { -+ Py_INCREF(cafile); -+ cafile_bytes = cafile; -+ } else { -+ PyObject *u = PyUnicode_FromObject(cafile); -+ if (!u) -+ goto error; -+ cafile_bytes = PyUnicode_AsEncodedString( -+ u, Py_FileSystemDefaultEncoding, NULL); -+ Py_DECREF(u); -+ if (!cafile_bytes) -+ goto error; - } - } - if (capath) { -- capath_bytes = PyString_AsEncodedObject( -- capath, Py_FileSystemDefaultEncoding, "strict"); -- if (!capath_bytes) { -- goto error; -+ if (PyString_Check(capath)) { -+ Py_INCREF(capath); -+ capath_bytes = capath; -+ } else { -+ PyObject *u = PyUnicode_FromObject(capath); -+ if (!u) -+ goto error; -+ capath_bytes = PyUnicode_AsEncodedString( -+ u, Py_FileSystemDefaultEncoding, NULL); -+ Py_DECREF(u); -+ if (!capath_bytes) -+ goto error; - } - } - - diff --git a/SOURCES/00217-pep466-backport-hashlib-algorithm-consts.patch b/SOURCES/00217-pep466-backport-hashlib-algorithm-consts.patch deleted file mode 100644 index eb7866c..0000000 --- a/SOURCES/00217-pep466-backport-hashlib-algorithm-consts.patch +++ /dev/null @@ -1,189 +0,0 @@ - -# HG changeset patch -# User Benjamin Peterson -# Date 1409233289 14400 -# Node ID 3f73c44b1fd1d442d6841493328e9756fb5e7ef5 -# Parent 97081a80f487841d81aeed55d398a1dba1faca00 -PEP 466: backport hashlib algorithm constants (closes #21307) - -diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst ---- a/Doc/library/hashlib.rst -+++ b/Doc/library/hashlib.rst -@@ -88,6 +88,24 @@ This module provides the following const - - .. versionadded:: 2.7 - -+.. data:: algorithms_guaranteed -+ -+ A set containing the names of the hash algorithms guaranteed to be supported -+ by this module on all platforms. -+ -+ .. versionadded:: 2.7.9 -+ -+.. data:: algorithms_available -+ -+ A set containing the names of the hash algorithms that are available in the -+ running Python interpreter. These names will be recognized when passed to -+ :func:`new`. :attr:`algorithms_guaranteed` will always be a subset. The -+ same algorithm may appear multiple times in this set under different names -+ (thanks to OpenSSL). -+ -+ .. versionadded:: 2.7.9 -+ -+ - The following values are provided as constant attributes of the hash objects - returned by the constructors: - -diff -up Python-2.7.5/Lib/hashlib.py.hash Python-2.7.5/Lib/hashlib.py ---- Python-2.7.5/Lib/hashlib.py.hash 2015-03-04 17:05:57.496598686 +0100 -+++ Python-2.7.5/Lib/hashlib.py 2015-03-04 17:11:34.872739103 +0100 -@@ -18,8 +18,9 @@ than using new(): - - md5(), sha1(), sha224(), sha256(), sha384(), and sha512() - --More algorithms may be available on your platform but the above are --guaranteed to exist. -+More algorithms may be available on your platform but the above are guaranteed -+to exist. See the algorithms_guaranteed and algorithms_available attributes -+to find out what algorithm names can be passed to new(). - - NOTE: If you want the adler32 or crc32 hash functions they are available in - the zlib module. -@@ -75,9 +76,14 @@ More condensed: - # always available algorithm is added. - __always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512') - -+algorithms_guaranteed = set(__always_supported) -+algorithms_available = set(__always_supported) -+ - algorithms = __always_supported - --__all__ = __always_supported + ('new', 'algorithms', 'pbkdf2_hmac') -+__all__ = __always_supported + ('new', 'algorithms_guaranteed', -+ 'algorithms_available', 'algorithms', -+ 'pbkdf2_hmac') - - - def __get_openssl_constructor(name): -@@ -110,6 +116,8 @@ try: - import _hashlib - new = __hash_new - __get_hash = __get_openssl_constructor -+ algorithms_available = algorithms_available.union( -+ _hashlib.openssl_md_meth_names) - except ImportError: - # We don't build the legacy modules - raise -diff -up Python-2.7.5/Modules/_hashopenssl.c.hash Python-2.7.5/Modules/_hashopenssl.c ---- Python-2.7.5/Modules/_hashopenssl.c.hash 2015-03-04 17:06:18.246791837 +0100 -+++ Python-2.7.5/Modules/_hashopenssl.c 2015-03-04 17:16:17.696369000 +0100 -@@ -784,6 +784,61 @@ pbkdf2_hmac(PyObject *self, PyObject *ar - - #endif - -+/* State for our callback function so that it can accumulate a result. */ -+typedef struct _internal_name_mapper_state { -+ PyObject *set; -+ int error; -+} _InternalNameMapperState; -+ -+ -+/* A callback function to pass to OpenSSL's OBJ_NAME_do_all(...) */ -+static void -+_openssl_hash_name_mapper(const OBJ_NAME *openssl_obj_name, void *arg) -+{ -+ _InternalNameMapperState *state = (_InternalNameMapperState *)arg; -+ PyObject *py_name; -+ -+ assert(state != NULL); -+ if (openssl_obj_name == NULL) -+ return; -+ /* Ignore aliased names, they pollute the list and OpenSSL appears to -+ * have a its own definition of alias as the resulting list still -+ * contains duplicate and alternate names for several algorithms. */ -+ if (openssl_obj_name->alias) -+ return; -+ -+ py_name = PyString_FromString(openssl_obj_name->name); -+ if (py_name == NULL) { -+ state->error = 1; -+ } else { -+ if (PySet_Add(state->set, py_name) != 0) { -+ state->error = 1; -+ } -+ Py_DECREF(py_name); -+ } -+} -+ -+ -+/* Ask OpenSSL for a list of supported ciphers, filling in a Python set. */ -+static PyObject* -+generate_hash_name_list(void) -+{ -+ _InternalNameMapperState state; -+ state.set = PyFrozenSet_New(NULL); -+ if (state.set == NULL) -+ return NULL; -+ state.error = 0; -+ -+ OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, &_openssl_hash_name_mapper, &state); -+ -+ if (state.error) { -+ Py_DECREF(state.set); -+ return NULL; -+ } -+ return state.set; -+} -+ -+ - /* - * This macro and function generates a family of constructor function - * definitions for specific hash algorithms. These constructors are much -@@ -924,11 +979,11 @@ static struct PyMethodDef EVP_functions[ - PyMODINIT_FUNC - init_hashlib(void) - { -- PyObject *m; -+ PyObject *m, *openssl_md_meth_names; - - SSL_load_error_strings(); - SSL_library_init(); -- OpenSSL_add_all_digests(); -+ ERR_load_crypto_strings(); - - Py_TYPE(&EVPtype) = &PyType_Type; - if (PyType_Ready(&EVPtype) < 0) -@@ -938,6 +993,14 @@ init_hashlib(void) - if (m == NULL) - return; - -+ openssl_md_meth_names = generate_hash_name_list(); -+ if (openssl_md_meth_names == NULL) { -+ return; -+ } -+ if (PyModule_AddObject(m, "openssl_md_meth_names", openssl_md_meth_names)) { -+ return; -+ } -+ - #if HASH_OBJ_CONSTRUCTOR - Py_INCREF(&EVPtype); - PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype); -diff -up Python-2.7.5/Lib/test/test_hashlib.py.hash Python-2.7.5/Lib/test/test_hashlib.py ---- Python-2.7.5/Lib/test/test_hashlib.py.hash 2015-03-04 18:04:57.823553474 +0100 -+++ Python-2.7.5/Lib/test/test_hashlib.py 2015-03-04 18:06:39.395499123 +0100 -@@ -107,6 +107,15 @@ class HashLibTestCase(unittest.TestCase) - tuple([_algo for _algo in self.supported_hash_names if - _algo.islower()])) - -+ def test_algorithms_guaranteed(self): -+ self.assertEqual(hashlib.algorithms_guaranteed, -+ set(_algo for _algo in self.supported_hash_names -+ if _algo.islower())) -+ -+ def test_algorithms_available(self): -+ self.assertTrue(set(hashlib.algorithms_guaranteed). -+ issubset(hashlib.algorithms_available)) -+ - def test_unknown_hash(self): - self.assertRaises(ValueError, hashlib.new, 'spam spam spam spam spam') - self.assertRaises(TypeError, hashlib.new, 1) diff --git a/SOURCES/00218-pep466-backport-urandom-pers-fd.patch b/SOURCES/00218-pep466-backport-urandom-pers-fd.patch deleted file mode 100644 index 0d1a810..0000000 --- a/SOURCES/00218-pep466-backport-urandom-pers-fd.patch +++ /dev/null @@ -1,171 +0,0 @@ - -# HG changeset patch -# User Benjamin Peterson -# Date 1409243400 14400 -# Node ID 3e7f8855078855a9409bc2c1372de89cb021d6c8 -# Parent 3f73c44b1fd1d442d6841493328e9756fb5e7ef5 -PEP 466: backport persistent urandom fd (closes #21305) - -Patch from Alex Gaynor. - -diff --git a/Python/pythonrun.c b/Python/pythonrun.c ---- a/Python/pythonrun.c -+++ b/Python/pythonrun.c -@@ -536,6 +536,7 @@ Py_Finalize(void) - PyInt_Fini(); - PyFloat_Fini(); - PyDict_Fini(); -+ _PyRandom_Fini(); - - #ifdef Py_USING_UNICODE - /* Cleanup Unicode implementation */ -diff --git a/Include/pythonrun.h b/Include/pythonrun.h -index c319c52..57ef2bb 100644 ---- a/Include/pythonrun.h -+++ b/Include/pythonrun.h -@@ -145,6 +145,7 @@ PyAPI_FUNC(void) PyInt_Fini(void); - PyAPI_FUNC(void) PyFloat_Fini(void); - PyAPI_FUNC(void) PyOS_FiniInterrupts(void); - PyAPI_FUNC(void) PyByteArray_Fini(void); -+PyAPI_FUNC(void) _PyRandom_Fini(void); - - PyAPI_DATA(PyThreadState *) _Py_Finalizing; - -diff -up Python-2.7.5/Python/random.c.urandom Python-2.7.5/Python/random.c ---- Python-2.7.5/Python/random.c.urandom 2015-03-06 08:22:10.244699950 +0100 -+++ Python-2.7.5/Python/random.c 2015-03-06 08:24:57.907317272 +0100 -@@ -118,10 +118,16 @@ vms_urandom(unsigned char *buffer, Py_ss - - #if !defined(MS_WINDOWS) && !defined(__VMS) - -+static struct { -+ int fd; -+ dev_t st_dev; -+ ino_t st_ino; -+} urandom_cache = { -1 }; -+ - /* Read size bytes from /dev/urandom into buffer. - Call Py_FatalError() on error. */ - static void --dev_urandom_noraise(char *buffer, Py_ssize_t size) -+dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size) - { - int fd; - Py_ssize_t n; -@@ -156,22 +162,57 @@ dev_urandom_python(char *buffer, Py_ssiz - { - int fd; - Py_ssize_t n; -+ struct stat st; - - if (size <= 0) - return 0; - -- Py_BEGIN_ALLOW_THREADS -- fd = open("/dev/urandom", O_RDONLY); -- Py_END_ALLOW_THREADS -- if (fd < 0) -- { -- if (errno == ENOENT || errno == ENXIO || -- errno == ENODEV || errno == EACCES) -- PyErr_SetString(PyExc_NotImplementedError, -- "/dev/urandom (or equivalent) not found"); -- else -- PyErr_SetFromErrno(PyExc_OSError); -- return -1; -+ if (urandom_cache.fd >= 0) { -+ /* Does the fd point to the same thing as before? (issue #21207) */ -+ if (fstat(urandom_cache.fd, &st) -+ || st.st_dev != urandom_cache.st_dev -+ || st.st_ino != urandom_cache.st_ino) { -+ /* Something changed: forget the cached fd (but don't close it, -+ since it probably points to something important for some -+ third-party code). */ -+ urandom_cache.fd = -1; -+ } -+ } -+ if (urandom_cache.fd >= 0) -+ fd = urandom_cache.fd; -+ else { -+ Py_BEGIN_ALLOW_THREADS -+ fd = open("/dev/urandom", O_RDONLY); -+ Py_END_ALLOW_THREADS -+ if (fd < 0) -+ { -+ if (errno == ENOENT || errno == ENXIO || -+ errno == ENODEV || errno == EACCES) -+ PyErr_SetString(PyExc_NotImplementedError, -+ "/dev/urandom (or equivalent) not found"); -+ else -+ PyErr_SetFromErrno(PyExc_OSError); -+ return -1; -+ } -+ if (urandom_cache.fd >= 0) { -+ /* urandom_fd was initialized by another thread while we were -+ not holding the GIL, keep it. */ -+ close(fd); -+ fd = urandom_cache.fd; -+ } -+ else { -+ if (fstat(fd, &st)) { -+ PyErr_SetFromErrno(PyExc_OSError); -+ close(fd); -+ return -1; -+ } -+ else { -+ urandom_cache.fd = fd; -+ urandom_cache.st_dev = st.st_dev; -+ urandom_cache.st_ino = st.st_ino; -+ } -+ } -+ - } - - Py_BEGIN_ALLOW_THREADS -@@ -191,12 +235,21 @@ dev_urandom_python(char *buffer, Py_ssiz - PyErr_Format(PyExc_RuntimeError, - "Failed to read %zi bytes from /dev/urandom", - size); -- close(fd); - return -1; - } -- close(fd); - return 0; - } -+ -+static void -+dev_urandom_close(void) -+{ -+ if (urandom_cache.fd >= 0) { -+ close(urandom_cache.fd); -+ urandom_cache.fd = -1; -+ } -+} -+ -+ - #endif /* !defined(MS_WINDOWS) && !defined(__VMS) */ - - /* Fill buffer with pseudo-random bytes generated by a linear congruent -@@ -300,8 +353,21 @@ _PyRandom_Init(void) - # ifdef __VMS - vms_urandom((unsigned char *)secret, secret_size, 0); - # else -- dev_urandom_noraise((char*)secret, secret_size); -+ dev_urandom_noraise((unsigned char*)secret, secret_size); - # endif - #endif - } - } -+ -+void -+_PyRandom_Fini(void) -+{ -+#ifdef MS_WINDOWS -+ if (hCryptProv) { -+ CryptReleaseContext(hCryptProv, 0); -+ hCryptProv = 0; -+ } -+#else -+ dev_urandom_close(); -+#endif -+} diff --git a/SOURCES/00219-pep466-fix-referenced-sslwrap.patch b/SOURCES/00219-pep466-fix-referenced-sslwrap.patch deleted file mode 100644 index f8ccc90..0000000 --- a/SOURCES/00219-pep466-fix-referenced-sslwrap.patch +++ /dev/null @@ -1,91 +0,0 @@ - -# HG changeset patch -# User Benjamin Peterson -# Date 1412221981 14400 -# Node ID 1a36d4e8cf4edfdc4c7d59a40075b8cf00e3ad3c -# Parent 222e0faa5fa9567f657f13fc78a60069142e09ae -fix sslwrap_simple (closes #22523) - -Thanks Alex Gaynor. - -diff --git a/Lib/ssl.py b/Lib/ssl.py ---- a/Lib/ssl.py -+++ b/Lib/ssl.py -@@ -969,16 +969,16 @@ def get_protocol_name(protocol_code): - # a replacement for the old socket.ssl function - - def sslwrap_simple(sock, keyfile=None, certfile=None): -- - """A replacement for the old socket.ssl function. Designed - for compability with Python 2.5 and earlier. Will disappear in - Python 3.0.""" -- - if hasattr(sock, "_sock"): - sock = sock._sock - -- ssl_sock = _ssl.sslwrap(sock, 0, keyfile, certfile, CERT_NONE, -- PROTOCOL_SSLv23, None) -+ ctx = SSLContext(PROTOCOL_SSLv23) -+ if keyfile or certfile: -+ ctx.load_cert_chain(certfile, keyfile) -+ ssl_sock = ctx._wrap_socket(sock, server_side=False) - try: - sock.getpeername() - except socket_error: -diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py ---- a/Lib/test/test_ssl.py -+++ b/Lib/test/test_ssl.py -@@ -94,6 +94,8 @@ class BasicTests(unittest.TestCase): - pass - else: - raise -+ -+ - def can_clear_options(): - # 0.9.8m or higher - return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15) -@@ -2944,7 +2946,7 @@ def test_main(verbose=False): - if not os.path.exists(filename): - raise support.TestFailed("Can't read certificate file %r" % filename) - -- tests = [ContextTests, BasicSocketTests, SSLErrorTests] -+ tests = [ContextTests, BasicTests, BasicSocketTests, SSLErrorTests] - - if support.is_resource_enabled('network'): - tests.append(NetworkedTests) -diff --git a/Modules/_ssl.c b/Modules/_ssl.c ---- a/Modules/_ssl.c -+++ b/Modules/_ssl.c -@@ -517,10 +517,12 @@ newPySSLSocket(PySSLContext *sslctx, PyS - self->socket_type = socket_type; - self->Socket = sock; - Py_INCREF(self->Socket); -- self->ssl_sock = PyWeakref_NewRef(ssl_sock, NULL); -- if (self->ssl_sock == NULL) { -- Py_DECREF(self); -- return NULL; -+ if (ssl_sock != Py_None) { -+ self->ssl_sock = PyWeakref_NewRef(ssl_sock, NULL); -+ if (self->ssl_sock == NULL) { -+ Py_DECREF(self); -+ return NULL; -+ } - } - return self; - } -@@ -2931,8 +2933,12 @@ static int - - ssl = SSL_get_app_data(s); - assert(PySSLSocket_Check(ssl)); -- ssl_socket = PyWeakref_GetObject(ssl->ssl_sock); -- Py_INCREF(ssl_socket); -+ if (ssl->ssl_sock == NULL) { -+ ssl_socket = Py_None; -+ } else { -+ ssl_socket = PyWeakref_GetObject(ssl->ssl_sock); -+ Py_INCREF(ssl_socket); -+ } - if (ssl_socket == Py_None) { - goto error; - } - diff --git a/SOURCES/00220-pep466-allow-passing-ssl-urrlib-httplib.patch b/SOURCES/00220-pep466-allow-passing-ssl-urrlib-httplib.patch deleted file mode 100644 index 152868a..0000000 --- a/SOURCES/00220-pep466-allow-passing-ssl-urrlib-httplib.patch +++ /dev/null @@ -1,677 +0,0 @@ - -# HG changeset patch -# User Benjamin Peterson -# Date 1416764565 21600 -# Node ID 1882157b298a164291d2b3a8b9525eb0902895f6 -# Parent 588ebc8fd3daf7307961cd614c4da9525bb67313 -allow passing cert/ssl information to urllib2.urlopen and httplib.HTTPSConnection - -This is basically a backport of issues #9003 and #22366. - -diff --git a/Doc/library/httplib.rst b/Doc/library/httplib.rst ---- a/Doc/library/httplib.rst -+++ b/Doc/library/httplib.rst -@@ -70,12 +70,25 @@ The module provides the following classe - *source_address* was added. - - --.. class:: HTTPSConnection(host[, port[, key_file[, cert_file[, strict[, timeout[, source_address]]]]]]) -+.. class:: HTTPSConnection(host[, port[, key_file[, cert_file[, strict[, timeout[, source_address, context, check_hostname]]]]]]) - - A subclass of :class:`HTTPConnection` that uses SSL for communication with -- secure servers. Default port is ``443``. *key_file* is the name of a PEM -- formatted file that contains your private key. *cert_file* is a PEM formatted -- certificate chain file. -+ secure servers. Default port is ``443``. If *context* is specified, it must -+ be a :class:`ssl.SSLContext` instance describing the various SSL options. -+ -+ *key_file* and *cert_file* are deprecated, please use -+ :meth:`ssl.SSLContext.load_cert_chain` instead, or let -+ :func:`ssl.create_default_context` select the system's trusted CA -+ certificates for you. -+ -+ Please read :ref:`ssl-security` for more information on best practices. -+ -+ .. note:: -+ If *context* is specified and has a :attr:`~ssl.SSLContext.verify_mode` -+ of either :data:`~ssl.CERT_OPTIONAL` or :data:`~ssl.CERT_REQUIRED`, then -+ by default *host* is matched against the host name(s) allowed by the -+ server's certificate. If you want to change that behaviour, you can -+ explicitly set *check_hostname* to False. - - .. warning:: - This does not do any verification of the server's certificate. -@@ -88,6 +101,9 @@ The module provides the following classe - .. versionchanged:: 2.7 - *source_address* was added. - -+ .. versionchanged:: 2.7.9 -+ *context* and *check_hostname* was added. -+ - - .. class:: HTTPResponse(sock, debuglevel=0, strict=0) - -diff --git a/Lib/test/keycert2.pem b/Lib/test/keycert2.pem -new file mode 100644 ---- /dev/null -+++ b/Lib/test/keycert2.pem -@@ -0,0 +1,31 @@ -+-----BEGIN PRIVATE KEY----- -+MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBANcLaMB7T/Wi9DBc -+PltGzgt8cxsv55m7PQPHMZvn6Ke8xmNqcmEzib8opRwKGrCV6TltKeFlNSg8dwQK -+Tl4ktyTkGCVweRQJ37AkBayvEBml5s+QD4vlhqkJPsL/Nsd+fnqngOGc5+59+C6r -+s3XpiLlF5ah/z8q92Mnw54nypw1JAgMBAAECgYBE3t2Mj7GbDLZB6rj5yKJioVfI -+BD6bSJEQ7bGgqdQkLFwpKMU7BiN+ekjuwvmrRkesYZ7BFgXBPiQrwhU5J28Tpj5B -+EOMYSIOHfzdalhxDGM1q2oK9LDFiCotTaSdEzMYadel5rmKXJ0zcK2Jho0PCuECf -+tf/ghRxK+h1Hm0tKgQJBAO6MdGDSmGKYX6/5kPDje7we/lSLorSDkYmV0tmVShsc -+JxgaGaapazceA/sHL3Myx7Eenkip+yPYDXEDFvAKNDECQQDmxsT9NOp6mo7ISvky -+GFr2vVHsJ745BMWoma4rFjPBVnS8RkgK+b2EpDCdZSrQ9zw2r8sKTgrEyrDiGTEg -+wJyZAkA8OOc0flYMJg2aHnYR6kwVjPmGHI5h5gk648EMPx0rROs1sXkiUwkHLCOz -+HvhCq+Iv+9vX2lnVjbiu/CmxRdIxAkA1YEfzoKeTD+hyXxTgB04Sv5sRGegfXAEz -+i8gC4zG5R/vcCA1lrHmvEiLEZL/QcT6WD3bQvVg0SAU9ZkI8pxARAkA7yqMSvP1l -+gJXy44R+rzpLYb1/PtiLkIkaKG3x9TUfPnfD2jY09fPkZlfsRU3/uS09IkhSwimV -+d5rWoljEfdou -+-----END PRIVATE KEY----- -+-----BEGIN CERTIFICATE----- -+MIICXTCCAcagAwIBAgIJALVQzebTtrXFMA0GCSqGSIb3DQEBBQUAMGIxCzAJBgNV -+BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u -+IFNvZnR3YXJlIEZvdW5kYXRpb24xFTATBgNVBAMMDGZha2Vob3N0bmFtZTAeFw0x -+NDExMjMxNzAwMDdaFw0yNDExMjAxNzAwMDdaMGIxCzAJBgNVBAYTAlhZMRcwFQYD -+VQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9uIFNvZnR3YXJlIEZv -+dW5kYXRpb24xFTATBgNVBAMMDGZha2Vob3N0bmFtZTCBnzANBgkqhkiG9w0BAQEF -+AAOBjQAwgYkCgYEA1wtowHtP9aL0MFw+W0bOC3xzGy/nmbs9A8cxm+fop7zGY2py -+YTOJvyilHAoasJXpOW0p4WU1KDx3BApOXiS3JOQYJXB5FAnfsCQFrK8QGaXmz5AP -+i+WGqQk+wv82x35+eqeA4Zzn7n34LquzdemIuUXlqH/Pyr3YyfDnifKnDUkCAwEA -+AaMbMBkwFwYDVR0RBBAwDoIMZmFrZWhvc3RuYW1lMA0GCSqGSIb3DQEBBQUAA4GB -+AKuay3vDKfWzt5+ch/HHBsert84ISot4fUjzXDA/oOgTOEjVcSShHxqNShMOW1oA -+QYBpBB/5Kx5RkD/w6imhucxt2WQPRgjX4x4bwMipVH/HvFDp03mG51/Cpi1TyZ74 -+El7qa/Pd4lHhOLzMKBA6503fpeYSFUIBxZbGLqylqRK7 -+-----END CERTIFICATE----- -diff --git a/Lib/test/selfsigned_pythontestdotnet.pem b/Lib/test/selfsigned_pythontestdotnet.pem -new file mode 100644 ---- /dev/null -+++ b/Lib/test/selfsigned_pythontestdotnet.pem -@@ -0,0 +1,16 @@ -+-----BEGIN CERTIFICATE----- -+MIIChzCCAfCgAwIBAgIJAKGU95wKR8pSMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV -+BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u -+IFNvZnR3YXJlIEZvdW5kYXRpb24xIzAhBgNVBAMMGnNlbGYtc2lnbmVkLnB5dGhv -+bnRlc3QubmV0MB4XDTE0MTEwMjE4MDkyOVoXDTI0MTAzMDE4MDkyOVowcDELMAkG -+A1UEBhMCWFkxFzAVBgNVBAcMDkNhc3RsZSBBbnRocmF4MSMwIQYDVQQKDBpQeXRo -+b24gU29mdHdhcmUgRm91bmRhdGlvbjEjMCEGA1UEAwwac2VsZi1zaWduZWQucHl0 -+aG9udGVzdC5uZXQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANDXQXW9tjyZ -+Xt0Iv2tLL1+jinr4wGg36ioLDLFkMf+2Y1GL0v0BnKYG4N1OKlAU15LXGeGer8vm -+Sv/yIvmdrELvhAbbo3w4a9TMYQA4XkIVLdvu3mvNOAet+8PMJxn26dbDhG809ALv -+EHY57lQsBS3G59RZyBPVqAqmImWNJnVzAgMBAAGjKTAnMCUGA1UdEQQeMByCGnNl -+bGYtc2lnbmVkLnB5dGhvbnRlc3QubmV0MA0GCSqGSIb3DQEBBQUAA4GBAIOXmdtM -+eG9qzP9TiXW/Gc/zI4cBfdCpC+Y4gOfC9bQUC7hefix4iO3+iZjgy3X/FaRxUUoV -+HKiXcXIaWqTSUWp45cSh0MbwZXudp6JIAptzdAhvvCrPKeC9i9GvxsPD4LtDAL97 -+vSaxQBezA7hdxZd90/EeyMgVZgAnTCnvAWX9 -+-----END CERTIFICATE----- -diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py ---- a/Lib/test/test_urllib2.py -+++ b/Lib/test/test_urllib2.py -@@ -8,6 +8,11 @@ import StringIO - import urllib2 - from urllib2 import Request, OpenerDirector - -+try: -+ import ssl -+except ImportError: -+ ssl = None -+ - # XXX - # Request - # CacheFTPHandler (hard to write) -@@ -47,6 +52,14 @@ class TrivialTests(unittest.TestCase): - for string, list in tests: - self.assertEqual(urllib2.parse_http_list(string), list) - -+ @unittest.skipUnless(ssl, "ssl module required") -+ def test_cafile_and_context(self): -+ context = ssl.create_default_context() -+ with self.assertRaises(ValueError): -+ urllib2.urlopen( -+ "https://localhost", cafile="/nonexistent/path", context=context -+ ) -+ - - def test_request_headers_dict(): - """ -diff --git a/Lib/urllib2.py b/Lib/urllib2.py ---- a/Lib/urllib2.py -+++ b/Lib/urllib2.py -@@ -109,6 +109,14 @@ try: - except ImportError: - from StringIO import StringIO - -+# check for SSL -+try: -+ import ssl -+except ImportError: -+ _have_ssl = False -+else: -+ _have_ssl = True -+ - from urllib import (unwrap, unquote, splittype, splithost, quote, - addinfourl, splitport, splittag, toBytes, - splitattr, ftpwrapper, splituser, splitpasswd, splitvalue) -@@ -120,11 +128,30 @@ from urllib import localhost, url2pathna - __version__ = sys.version[:3] - - _opener = None --def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): -+def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, -+ cafile=None, capath=None, cadefault=False, context=None): - global _opener -- if _opener is None: -- _opener = build_opener() -- return _opener.open(url, data, timeout) -+ if cafile or capath or cadefault: -+ if context is not None: -+ raise ValueError( -+ "You can't pass both context and any of cafile, capath, and " -+ "cadefault" -+ ) -+ if not _have_ssl: -+ raise ValueError('SSL support not available') -+ context = ssl._create_stdlib_context(cert_reqs=ssl.CERT_REQUIRED, -+ cafile=cafile, -+ capath=capath) -+ https_handler = HTTPSHandler(context=context, check_hostname=True) -+ opener = build_opener(https_handler) -+ elif context: -+ https_handler = HTTPSHandler(context=context) -+ opener = build_opener(https_handler) -+ elif _opener is None: -+ _opener = opener = build_opener() -+ else: -+ opener = _opener -+ return opener.open(url, data, timeout) - - def install_opener(opener): - global _opener -@@ -1121,7 +1148,7 @@ class AbstractHTTPHandler(BaseHandler): - - return request - -- def do_open(self, http_class, req): -+ def do_open(self, http_class, req, **http_conn_args): - """Return an addinfourl object for the request, using http_class. - - http_class must implement the HTTPConnection API from httplib. -@@ -1135,7 +1162,8 @@ class AbstractHTTPHandler(BaseHandler): - if not host: - raise URLError('no host given') - -- h = http_class(host, timeout=req.timeout) # will parse host:port -+ # will parse host:port -+ h = http_class(host, timeout=req.timeout, **http_conn_args) - h.set_debuglevel(self._debuglevel) - - headers = dict(req.unredirected_hdrs) -@@ -1203,8 +1231,14 @@ class HTTPHandler(AbstractHTTPHandler): - if hasattr(httplib, 'HTTPS'): - class HTTPSHandler(AbstractHTTPHandler): - -+ def __init__(self, debuglevel=0, context=None, check_hostname=None): -+ AbstractHTTPHandler.__init__(self, debuglevel) -+ self._context = context -+ self._check_hostname = check_hostname -+ - def https_open(self, req): -- return self.do_open(httplib.HTTPSConnection, req) -+ return self.do_open(httplib.HTTPSConnection, req, -+ context=self._context, check_hostname=self._check_hostname) - - https_request = AbstractHTTPHandler.do_request_ - -diff -up Python-2.7.5/Lib/test/test_urllib2_localnet.py.ctx Python-2.7.5/Lib/test/test_urllib2_localnet.py ---- Python-2.7.5/Lib/test/test_urllib2_localnet.py.ctx 2015-03-30 10:13:48.351310552 +0200 -+++ Python-2.7.5/Lib/test/test_urllib2_localnet.py 2015-03-30 10:14:54.715713679 +0200 -@@ -1,3 +1,4 @@ -+import os - import urlparse - import urllib2 - import BaseHTTPServer -@@ -11,6 +12,17 @@ from test import test_support - mimetools = test_support.import_module('mimetools', deprecated=True) - threading = test_support.import_module('threading') - -+try: -+ import ssl -+except ImportError: -+ ssl = None -+ -+here = os.path.dirname(__file__) -+# Self-signed cert file for 'localhost' -+CERT_localhost = os.path.join(here, 'keycert.pem') -+# Self-signed cert file for 'fakehostname' -+CERT_fakehostname = os.path.join(here, 'keycert2.pem') -+ - # Loopback http server infrastructure - - class LoopbackHttpServer(BaseHTTPServer.HTTPServer): -@@ -25,7 +37,7 @@ class LoopbackHttpServer(BaseHTTPServer. - - # Set the timeout of our listening socket really low so - # that we can stop the server easily. -- self.socket.settimeout(1.0) -+ self.socket.settimeout(0.1) - - def get_request(self): - """BaseHTTPServer method, overridden.""" -@@ -354,6 +366,19 @@ class TestUrlopen(BaseTestCase): - urllib2.install_opener(opener) - super(TestUrlopen, self).setUp() - -+ def urlopen(self, url, data=None, **kwargs): -+ l = [] -+ f = urllib2.urlopen(url, data, **kwargs) -+ try: -+ # Exercise various methods -+ l.extend(f.readlines(200)) -+ l.append(f.readline()) -+ l.append(f.read(1024)) -+ l.append(f.read()) -+ finally: -+ f.close() -+ return b"".join(l) -+ - def start_server(self, responses): - handler = GetRequestHandler(responses) - -@@ -364,6 +389,16 @@ class TestUrlopen(BaseTestCase): - handler.port = port - return handler - -+ def start_https_server(self, responses=None, **kwargs): -+ if not hasattr(urllib2, 'HTTPSHandler'): -+ self.skipTest('ssl support required') -+ from test.ssl_servers import make_https_server -+ if responses is None: -+ responses = [(200, [], b"we care a bit")] -+ handler = GetRequestHandler(responses) -+ server = make_https_server(self, handler_class=handler, **kwargs) -+ handler.port = server.port -+ return handler - - def test_redirection(self): - expected_response = 'We got here...' -@@ -434,6 +469,28 @@ class TestUrlopen(BaseTestCase): - finally: - self.server.stop() - -+ def test_https(self): -+ handler = self.start_https_server() -+ context = ssl.create_default_context(cafile=CERT_localhost) -+ data = self.urlopen("https://localhost:%s/bizarre" % handler.port, context=context) -+ self.assertEqual(data, b"we care a bit") -+ -+ def test_https_with_cafile(self): -+ handler = self.start_https_server(certfile=CERT_localhost) -+ import ssl -+ # Good cert -+ data = self.urlopen("https://localhost:%s/bizarre" % handler.port, -+ cafile=CERT_localhost) -+ self.assertEqual(data, b"we care a bit") -+ # Bad cert -+ with self.assertRaises(urllib2.URLError) as cm: -+ self.urlopen("https://localhost:%s/bizarre" % handler.port, -+ cafile=CERT_fakehostname) -+ # Good cert, but mismatching hostname -+ handler = self.start_https_server(certfile=CERT_fakehostname) -+ with self.assertRaises(ssl.CertificateError) as cm: -+ self.urlopen("https://localhost:%s/bizarre" % handler.port, -+ cafile=CERT_fakehostname) - - def test_sending_headers(self): - handler = self.start_server([(200, [], "we don't care")]) -diff -up Python-2.7.5/Doc/library/urllib2.rst.ctx Python-2.7.5/Doc/library/urllib2.rst ---- Python-2.7.5/Doc/library/urllib2.rst.ctx 2015-03-30 10:20:15.958747076 +0200 -+++ Python-2.7.5/Doc/library/urllib2.rst 2015-03-30 10:30:46.172779366 +0200 -@@ -22,13 +22,10 @@ redirections, cookies and more. - The :mod:`urllib2` module defines the following functions: - - --.. function:: urlopen(url[, data][, timeout]) -+.. function:: urlopen(url[, data[, timeout[, cafile[, capath[, cadefault[, context]]]]]) - - Open the URL *url*, which can be either a string or a :class:`Request` object. - -- .. warning:: -- HTTPS requests do not do any verification of the server's certificate. -- - *data* may be a string specifying additional data to send to the server, or - ``None`` if no such data is needed. Currently HTTP requests are the only ones - that use *data*; the HTTP request will be a POST instead of a GET when the -@@ -41,7 +38,19 @@ The :mod:`urllib2` module defines the following functions: - The optional *timeout* parameter specifies a timeout in seconds for blocking - operations like the connection attempt (if not specified, the global default - timeout setting will be used). This actually only works for HTTP, HTTPS and -- FTP connections. -+ FTP connections. -+ -+ If *context* is specified, it must be a :class:`ssl.SSLContext` instance -+ describing the various SSL options. See :class:`~httplib.HTTPSConnection` for -+ more details. -+ -+ The optional *cafile* and *capath* parameters specify a set of trusted CA -+ certificates for HTTPS requests. *cafile* should point to a single file -+ containing a bundle of CA certificates, whereas *capath* should point to a -+ directory of hashed certificate files. More information can be found in -+ :meth:`ssl.SSLContext.load_verify_locations`. -+ -+ The *cadefault* parameter is ignored. - - This function returns a file-like object with three additional methods: - -@@ -66,7 +75,10 @@ The :mod:`urllib2` module defines the fo - handled through the proxy. - - .. versionchanged:: 2.6 -- *timeout* was added. -+ *timeout* was added. -+ -+ .. versionchanged:: 2.7.9 -+ *cafile*, *capath*, *cadefault*, and *context* were added. - - - .. function:: install_opener(opener) -@@ -280,9 +292,13 @@ The following classes are provided: - A class to handle opening of HTTP URLs. - - --.. class:: HTTPSHandler() -+.. class:: HTTPSHandler([debuglevel[, context[, check_hostname]]]) -+ -+ A class to handle opening of HTTPS URLs. *context* and *check_hostname* have -+ the same meaning as for :class:`httplib.HTTPSConnection`. - -- A class to handle opening of HTTPS URLs. -+ .. versionchanged:: 2.7.9 -+ *context* and *check_hostname* were added. - - - .. class:: FileHandler() -diff -up Python-2.7.5/Lib/httplib.py.ctx Python-2.7.5/Lib/httplib.py ---- Python-2.7.5/Lib/httplib.py.ctx 2015-03-30 10:19:52.551521393 +0200 -+++ Python-2.7.5/Lib/httplib.py 2015-03-30 10:30:05.045386751 +0200 -@@ -1159,21 +1159,44 @@ else: - - def __init__(self, host, port=None, key_file=None, cert_file=None, - strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, -- source_address=None): -+ source_address=None, context=None, check_hostname=None): - HTTPConnection.__init__(self, host, port, strict, timeout, - source_address) - self.key_file = key_file - self.cert_file = cert_file -+ if context is None: -+ context = ssl.create_default_context() -+ will_verify = context.verify_mode != ssl.CERT_NONE -+ if check_hostname is None: -+ check_hostname = will_verify -+ elif check_hostname and not will_verify: -+ raise ValueError("check_hostname needs a SSL context with " -+ "either CERT_OPTIONAL or CERT_REQUIRED") -+ if key_file or cert_file: -+ context.load_cert_chain(cert_file, key_file) -+ self._context = context -+ self._check_hostname = check_hostname - - def connect(self): - "Connect to a host on a given (SSL) port." - -- sock = self._create_connection((self.host, self.port), -- self.timeout, self.source_address) -+ HTTPConnection.connect(self) -+ - if self._tunnel_host: -- self.sock = sock -- self._tunnel() -- self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file) -+ server_hostname = self._tunnel_host -+ else: -+ server_hostname = self.host -+ sni_hostname = server_hostname if ssl.HAS_SNI else None -+ -+ self.sock = self._context.wrap_socket(self.sock, -+ server_hostname=sni_hostname) -+ if not self._context.check_hostname and self._check_hostname: -+ try: -+ ssl.match_hostname(self.sock.getpeercert(), server_hostname) -+ except Exception: -+ self.sock.shutdown(socket.SHUT_RDWR) -+ self.sock.close() -+ raise - - __all__.append("HTTPSConnection") - -diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py -index 4b2a638..f7e0583 100644 ---- a/Lib/test/test_httplib.py -+++ b/Lib/test/test_httplib.py -@@ -1,6 +1,7 @@ - import httplib - import array - import httplib -+import os - import StringIO - import socket - import errno -@@ -10,6 +11,14 @@ TestCase = unittest.TestCase - - from test import test_support - -+here = os.path.dirname(__file__) -+# Self-signed cert file for 'localhost' -+CERT_localhost = os.path.join(here, 'keycert.pem') -+# Self-signed cert file for 'fakehostname' -+CERT_fakehostname = os.path.join(here, 'keycert2.pem') -+# Self-signed cert file for self-signed.pythontest.net -+CERT_selfsigned_pythontestdotnet = os.path.join(here, 'selfsigned_pythontestdotnet.pem') -+ - HOST = test_support.HOST - - class FakeSocket: -@@ -507,35 +516,140 @@ class TimeoutTest(TestCase): - httpConn.close() - - --class HTTPSTimeoutTest(TestCase): -+class HTTPSTest(TestCase): - # XXX Here should be tests for HTTPS, there isn't any right now! -+ def setUp(self): -+ if not hasattr(httplib, 'HTTPSConnection'): -+ self.skipTest('ssl support required') -+ -+ def make_server(self, certfile): -+ from test.ssl_servers import make_https_server -+ return make_https_server(self, certfile=certfile) - - def test_attributes(self): -- # simple test to check it's storing it -- if hasattr(httplib, 'HTTPSConnection'): -- h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30) -- self.assertEqual(h.timeout, 30) -+ # simple test to check it's storing the timeout -+ h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30) -+ self.assertEqual(h.timeout, 30) -+ -+ def test_networked(self): -+ # Default settings: requires a valid cert from a trusted CA -+ import ssl -+ test_support.requires('network') -+ with test_support.transient_internet('self-signed.pythontest.net'): -+ h = httplib.HTTPSConnection('self-signed.pythontest.net', 443) -+ with self.assertRaises(ssl.SSLError) as exc_info: -+ h.request('GET', '/') -+ self.assertEqual(exc_info.exception.reason, 'CERTIFICATE_VERIFY_FAILED') -+ -+ def test_networked_noverification(self): -+ # Switch off cert verification -+ import ssl -+ test_support.requires('network') -+ with test_support.transient_internet('self-signed.pythontest.net'): -+ context = ssl._create_stdlib_context() -+ h = httplib.HTTPSConnection('self-signed.pythontest.net', 443, -+ context=context) -+ h.request('GET', '/') -+ resp = h.getresponse() -+ self.assertIn('nginx', resp.getheader('server')) -+ -+ def test_networked_trusted_by_default_cert(self): -+ # Default settings: requires a valid cert from a trusted CA -+ test_support.requires('network') -+ with test_support.transient_internet('www.python.org'): -+ h = httplib.HTTPSConnection('www.python.org', 443) -+ h.request('GET', '/') -+ resp = h.getresponse() -+ content_type = resp.getheader('content-type') -+ self.assertIn('text/html', content_type) -+ -+ def test_networked_good_cert(self): -+ # We feed the server's cert as a validating cert -+ import ssl -+ test_support.requires('network') -+ with test_support.transient_internet('self-signed.pythontest.net'): -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.load_verify_locations(CERT_selfsigned_pythontestdotnet) -+ h = httplib.HTTPSConnection('self-signed.pythontest.net', 443, context=context) -+ h.request('GET', '/') -+ resp = h.getresponse() -+ server_string = resp.getheader('server') -+ self.assertIn('nginx', server_string) -+ -+ def test_networked_bad_cert(self): -+ # We feed a "CA" cert that is unrelated to the server's cert -+ import ssl -+ test_support.requires('network') -+ with test_support.transient_internet('self-signed.pythontest.net'): -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.load_verify_locations(CERT_localhost) -+ h = httplib.HTTPSConnection('self-signed.pythontest.net', 443, context=context) -+ with self.assertRaises(ssl.SSLError) as exc_info: -+ h.request('GET', '/') -+ self.assertEqual(exc_info.exception.reason, 'CERTIFICATE_VERIFY_FAILED') -+ -+ def test_local_unknown_cert(self): -+ # The custom cert isn't known to the default trust bundle -+ import ssl -+ server = self.make_server(CERT_localhost) -+ h = httplib.HTTPSConnection('localhost', server.port) -+ with self.assertRaises(ssl.SSLError) as exc_info: -+ h.request('GET', '/') -+ self.assertEqual(exc_info.exception.reason, 'CERTIFICATE_VERIFY_FAILED') -+ -+ def test_local_good_hostname(self): -+ # The (valid) cert validates the HTTP hostname -+ import ssl -+ server = self.make_server(CERT_localhost) -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.load_verify_locations(CERT_localhost) -+ h = httplib.HTTPSConnection('localhost', server.port, context=context) -+ h.request('GET', '/nonexistent') -+ resp = h.getresponse() -+ self.assertEqual(resp.status, 404) -+ -+ def test_local_bad_hostname(self): -+ # The (valid) cert doesn't validate the HTTP hostname -+ import ssl -+ server = self.make_server(CERT_fakehostname) -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.verify_mode = ssl.CERT_REQUIRED -+ context.load_verify_locations(CERT_fakehostname) -+ h = httplib.HTTPSConnection('localhost', server.port, context=context) -+ with self.assertRaises(ssl.CertificateError): -+ h.request('GET', '/') -+ # Same with explicit check_hostname=True -+ h = httplib.HTTPSConnection('localhost', server.port, context=context, -+ check_hostname=True) -+ with self.assertRaises(ssl.CertificateError): -+ h.request('GET', '/') -+ # With check_hostname=False, the mismatching is ignored -+ h = httplib.HTTPSConnection('localhost', server.port, context=context, -+ check_hostname=False) -+ h.request('GET', '/nonexistent') -+ resp = h.getresponse() -+ self.assertEqual(resp.status, 404) - -- @unittest.skipIf(not hasattr(httplib, 'HTTPS'), 'httplib.HTTPS not available') - def test_host_port(self): - # Check invalid host_port - -- # Note that httplib does not accept user:password@ in the host-port. - for hp in ("www.python.org:abc", "user:password@www.python.org"): -- self.assertRaises(httplib.InvalidURL, httplib.HTTP, hp) -+ self.assertRaises(httplib.InvalidURL, httplib.HTTPSConnection, hp) - -- for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", "fe80::207:e9ff:fe9b", -- 8000), -- ("pypi.python.org:443", "pypi.python.org", 443), -- ("pypi.python.org", "pypi.python.org", 443), -- ("pypi.python.org:", "pypi.python.org", 443), -- ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 443)): -- http = httplib.HTTPS(hp) -- c = http._conn -- if h != c.host: -- self.fail("Host incorrectly parsed: %s != %s" % (h, c.host)) -- if p != c.port: -- self.fail("Port incorrectly parsed: %s != %s" % (p, c.host)) -+ for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", -+ "fe80::207:e9ff:fe9b", 8000), -+ ("www.python.org:443", "www.python.org", 443), -+ ("www.python.org:", "www.python.org", 443), -+ ("www.python.org", "www.python.org", 443), -+ ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 443), -+ ("[fe80::207:e9ff:fe9b]:", "fe80::207:e9ff:fe9b", -+ 443)): -+ c = httplib.HTTPSConnection(hp) -+ self.assertEqual(h, c.host) -+ self.assertEqual(p, c.port) - - - class TunnelTests(TestCase): -@@ -576,10 +690,10 @@ class TunnelTests(TestCase): - self.assertTrue('CONNECT destination.com' in conn.sock.data) - self.assertTrue('Host: destination.com' in conn.sock.data) - -- -+@test_support.reap_threads - def test_main(verbose=None): - test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest, -- HTTPSTimeoutTest, SourceAddressTest, TunnelTests) -+ HTTPSTest, SourceAddressTest) - - if __name__ == '__main__': - test_main() -diff -up Python-2.7.5/Lib/test/test_ssl.py.ctx Python-2.7.5/Lib/test/test_ssl.py ---- Python-2.7.5/Lib/test/test_ssl.py.ctx 2015-03-30 10:18:55.677973042 +0200 -+++ Python-2.7.5/Lib/test/test_ssl.py 2015-03-30 10:22:02.323772604 +0200 -@@ -14,7 +14,7 @@ import os - import errno - import pprint - import tempfile --import urllib -+import urllib2 - import traceback - import weakref - import platform -@@ -2332,9 +2332,10 @@ else: - d1 = f.read() - d2 = '' - # now fetch the same data from the HTTPS server -- url = 'https://%s:%d/%s' % ( -- HOST, server.port, os.path.split(CERTFILE)[1]) -- f = urllib.urlopen(url) -+ url = 'https://localhost:%d/%s' % ( -+ server.port, os.path.split(CERTFILE)[1]) -+ context = ssl.create_default_context(cafile=CERTFILE) -+ f = urllib2.urlopen(url, context=context) - try: - dlen = f.info().getheader("content-length") - if dlen and (int(dlen) > 0): diff --git a/SOURCES/00221-pep466-backport-sslwrap-c-ssl.patch b/SOURCES/00221-pep466-backport-sslwrap-c-ssl.patch deleted file mode 100644 index 521d6b8..0000000 --- a/SOURCES/00221-pep466-backport-sslwrap-c-ssl.patch +++ /dev/null @@ -1,266 +0,0 @@ -diff --git a/_ssl.c b/_ssl.c -index 5fb6e28..1332547 100644 ---- a/Modules/_ssl.c -+++ b/Modules/_ssl.c -@@ -226,6 +226,19 @@ typedef struct { - enum py_ssl_server_or_client socket_type; - } PySSLSocket; - -+typedef struct { -+ PyObject_HEAD -+ PySocketSockObject *Socket; /* Socket on which we're layered */ -+ SSL_CTX* ctx; -+ SSL* ssl; -+ X509* peer_cert; -+ char server[X509_NAME_MAXLEN]; -+ char issuer[X509_NAME_MAXLEN]; -+ int shutdown_seen_zero; -+ -+} PySSLObject; -+ -+static PyTypeObject PySSL_Type; - static PyTypeObject PySSLContext_Type; - static PyTypeObject PySSLSocket_Type; - -@@ -527,6 +540,203 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, - return self; - } - -+static PySSLObject * -+newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file, -+ enum py_ssl_server_or_client socket_type, -+ enum py_ssl_cert_requirements certreq, -+ enum py_ssl_version proto_version, -+ char *cacerts_file, char *ciphers) -+{ -+ PySSLObject *self; -+ char *errstr = NULL; -+ int ret; -+ int verification_mode; -+ long options; -+ -+ self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */ -+ if (self == NULL) -+ return NULL; -+ memset(self->server, '\0', sizeof(char) * X509_NAME_MAXLEN); -+ memset(self->issuer, '\0', sizeof(char) * X509_NAME_MAXLEN); -+ self->peer_cert = NULL; -+ self->ssl = NULL; -+ self->ctx = NULL; -+ self->Socket = NULL; -+ self->shutdown_seen_zero = 0; -+ -+ /* Make sure the SSL error state is initialized */ -+ (void) ERR_get_state(); -+ ERR_clear_error(); -+ -+ if ((key_file && !cert_file) || (!key_file && cert_file)) { -+ errstr = ERRSTR("Both the key & certificate files " -+ "must be specified"); -+ goto fail; -+ } -+ -+ if ((socket_type == PY_SSL_SERVER) && -+ ((key_file == NULL) || (cert_file == NULL))) { -+ errstr = ERRSTR("Both the key & certificate files " -+ "must be specified for server-side operation"); -+ goto fail; -+ } -+ -+ PySSL_BEGIN_ALLOW_THREADS -+ if (proto_version == PY_SSL_VERSION_TLS1) -+ self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ -+ else if (proto_version == PY_SSL_VERSION_SSL3) -+ self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ -+#ifndef OPENSSL_NO_SSL2 -+ else if (proto_version == PY_SSL_VERSION_SSL2) -+ self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ -+#endif -+ else if (proto_version == PY_SSL_VERSION_SSL23) -+ self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ -+ PySSL_END_ALLOW_THREADS -+ -+ if (self->ctx == NULL) { -+ errstr = ERRSTR("Invalid SSL protocol variant specified."); -+ goto fail; -+ } -+ -+ if (ciphers != NULL) { -+ ret = SSL_CTX_set_cipher_list(self->ctx, ciphers); -+ if (ret == 0) { -+ errstr = ERRSTR("No cipher can be selected."); -+ goto fail; -+ } -+ } -+ -+ if (certreq != PY_SSL_CERT_NONE) { -+ if (cacerts_file == NULL) { -+ errstr = ERRSTR("No root certificates specified for " -+ "verification of other-side certificates."); -+ goto fail; -+ } else { -+ PySSL_BEGIN_ALLOW_THREADS -+ ret = SSL_CTX_load_verify_locations(self->ctx, -+ cacerts_file, -+ NULL); -+ PySSL_END_ALLOW_THREADS -+ if (ret != 1) { -+ _setSSLError(NULL, 0, __FILE__, __LINE__); -+ goto fail; -+ } -+ } -+ } -+ if (key_file) { -+ PySSL_BEGIN_ALLOW_THREADS -+ ret = SSL_CTX_use_PrivateKey_file(self->ctx, key_file, -+ SSL_FILETYPE_PEM); -+ PySSL_END_ALLOW_THREADS -+ if (ret != 1) { -+ _setSSLError(NULL, ret, __FILE__, __LINE__); -+ goto fail; -+ } -+ -+ PySSL_BEGIN_ALLOW_THREADS -+ ret = SSL_CTX_use_certificate_chain_file(self->ctx, -+ cert_file); -+ PySSL_END_ALLOW_THREADS -+ if (ret != 1) { -+ /* -+ fprintf(stderr, "ret is %d, errcode is %lu, %lu, with file \"%s\"\n", -+ ret, ERR_peek_error(), ERR_peek_last_error(), cert_file); -+ */ -+ if (ERR_peek_last_error() != 0) { -+ _setSSLError(NULL, ret, __FILE__, __LINE__); -+ goto fail; -+ } -+ } -+ } -+ -+ /* ssl compatibility */ -+ options = SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; -+ if (proto_version != PY_SSL_VERSION_SSL2) -+ options |= SSL_OP_NO_SSLv2; -+ SSL_CTX_set_options(self->ctx, options); -+ -+ verification_mode = SSL_VERIFY_NONE; -+ if (certreq == PY_SSL_CERT_OPTIONAL) -+ verification_mode = SSL_VERIFY_PEER; -+ else if (certreq == PY_SSL_CERT_REQUIRED) -+ verification_mode = (SSL_VERIFY_PEER | -+ SSL_VERIFY_FAIL_IF_NO_PEER_CERT); -+ SSL_CTX_set_verify(self->ctx, verification_mode, -+ NULL); /* set verify lvl */ -+ -+ PySSL_BEGIN_ALLOW_THREADS -+ self->ssl = SSL_new(self->ctx); /* New ssl struct */ -+ PySSL_END_ALLOW_THREADS -+ SSL_set_fd(self->ssl, Sock->sock_fd); /* Set the socket for SSL */ -+#ifdef SSL_MODE_AUTO_RETRY -+ SSL_set_mode(self->ssl, SSL_MODE_AUTO_RETRY); -+#endif -+ -+ /* If the socket is in non-blocking mode or timeout mode, set the BIO -+ * to non-blocking mode (blocking is the default) -+ */ -+ if (Sock->sock_timeout >= 0.0) { -+ /* Set both the read and write BIO's to non-blocking mode */ -+ BIO_set_nbio(SSL_get_rbio(self->ssl), 1); -+ BIO_set_nbio(SSL_get_wbio(self->ssl), 1); -+ } -+ -+ PySSL_BEGIN_ALLOW_THREADS -+ if (socket_type == PY_SSL_CLIENT) -+ SSL_set_connect_state(self->ssl); -+ else -+ SSL_set_accept_state(self->ssl); -+ PySSL_END_ALLOW_THREADS -+ -+ self->Socket = Sock; -+ Py_INCREF(self->Socket); -+ return self; -+ fail: -+ if (errstr) -+ PyErr_SetString(PySSLErrorObject, errstr); -+ Py_DECREF(self); -+ return NULL; -+} -+ -+static PyObject * -+PySSL_sslwrap(PyObject *self, PyObject *args) -+{ -+ PySocketSockObject *Sock; -+ int server_side = 0; -+ int verification_mode = PY_SSL_CERT_NONE; -+ int protocol = PY_SSL_VERSION_SSL23; -+ char *key_file = NULL; -+ char *cert_file = NULL; -+ char *cacerts_file = NULL; -+ char *ciphers = NULL; -+ -+ if (!PyArg_ParseTuple(args, "O!i|zziizz:sslwrap", -+ PySocketModule.Sock_Type, -+ &Sock, -+ &server_side, -+ &key_file, &cert_file, -+ &verification_mode, &protocol, -+ &cacerts_file, &ciphers)) -+ return NULL; -+ -+ /* -+ fprintf(stderr, -+ "server_side is %d, keyfile %p, certfile %p, verify_mode %d, " -+ "protocol %d, certs %p\n", -+ server_side, key_file, cert_file, verification_mode, -+ protocol, cacerts_file); -+ */ -+ -+ return (PyObject *) newPySSLObject(Sock, key_file, cert_file, -+ server_side, verification_mode, -+ protocol, cacerts_file, -+ ciphers); -+} -+ -+PyDoc_STRVAR(ssl_doc, -+"sslwrap(socket, server_side, [keyfile, certfile, certs_mode, protocol,\n" -+" cacertsfile, ciphers]) -> sslobject"); - - /* SSL object methods */ - -@@ -1911,6 +2121,7 @@ static PyGetSetDef ssl_getsetlist[] = { - }; - - static PyMethodDef PySSLMethods[] = { -+ {"sslwrap", PySSL_sslwrap, METH_VARARGS, ssl_doc}, - {"do_handshake", (PyCFunction)PySSL_SSLdo_handshake, METH_NOARGS}, - {"write", (PyCFunction)PySSL_SSLwrite, METH_VARARGS, - PySSL_SSLwrite_doc}, -@@ -1969,6 +2180,29 @@ static PyTypeObject PySSLSocket_Type = { - ssl_getsetlist, /*tp_getset*/ - }; - -+static PyObject *PySSL_getattr(PySSLObject *self, char *name) -+{ -+ return Py_FindMethod(PySSLMethods, (PyObject *)self, name); -+} -+ -+static PyTypeObject PySSL_Type = { -+ PyVarObject_HEAD_INIT(NULL, 0) -+ "ssl.SSLContext", /*tp_name*/ -+ sizeof(PySSLObject), /*tp_basicsize*/ -+ 0, /*tp_itemsize*/ -+ /* methods */ -+ (destructor)PySSL_dealloc, /*tp_dealloc*/ -+ 0, /*tp_print*/ -+ (getattrfunc)PySSL_getattr, /*tp_getattr*/ -+ 0, /*tp_setattr*/ -+ 0, /*tp_compare*/ -+ 0, /*tp_repr*/ -+ 0, /*tp_as_number*/ -+ 0, /*tp_as_sequence*/ -+ 0, /*tp_as_mapping*/ -+ 0, /*tp_hash*/ -+}; -+ - - /* - * _SSLContext objects diff --git a/SOURCES/00222-add-2014-bit-dh-key.patch b/SOURCES/00222-add-2014-bit-dh-key.patch deleted file mode 100644 index 6a7838e..0000000 --- a/SOURCES/00222-add-2014-bit-dh-key.patch +++ /dev/null @@ -1,49 +0,0 @@ - -# HG changeset patch -# User Benjamin Peterson -# Date 1427947446 14400 -# Node ID 4f2391e866434a94ca6d87dff5ea01fcab91d08a -# Parent 5d88f653187203d85f4cfd4877f093af3919035b -replace 512 bit dh key with a 2014 bit one (closes #23844) - -Patch by CĂ©dric Krier. - -diff --git a/Lib/test/dh1024.pem b/Lib/test/dh1024.pem -new file mode 100644 ---- /dev/null -+++ b/Lib/test/dh1024.pem -@@ -0,0 +1,7 @@ -+-----BEGIN DH PARAMETERS----- -+MIGHAoGBAIbzw1s9CT8SV5yv6L7esdAdZYZjPi3qWFs61CYTFFQnf2s/d09NYaJt -+rrvJhIzWavqnue71qXCf83/J3nz3FEwUU/L0mGyheVbsSHiI64wUo3u50wK5Igo0 -+RNs/LD0irs7m0icZ//hijafTU+JOBiuA8zMI+oZfU7BGuc9XrUprAgEC -+-----END DH PARAMETERS----- -+ -+Generated with: openssl dhparam -out dh1024.pem 1024 -diff --git a/Lib/test/dh512.pem b/Lib/test/dh512.pem -deleted file mode 100644 ---- a/Lib/test/dh512.pem -+++ /dev/null -@@ -1,9 +0,0 @@ -------BEGIN DH PARAMETERS----- --MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak --XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC -------END DH PARAMETERS----- -- --These are the 512 bit DH parameters from "Assigned Number for SKIP Protocols" --(http://www.skip-vpn.org/spec/numbers.html). --See there for how they were generated. --Note that g is not a generator, but this is not a problem since p is a safe prime. -diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py ---- a/Lib/test/test_ssl.py -+++ b/Lib/test/test_ssl.py -@@ -66,7 +66,7 @@ BADKEY = data_file("badkey.pem") - NOKIACERT = data_file("nokia.pem") - NULLBYTECERT = data_file("nullbytecert.pem") - --DHFILE = data_file("dh512.pem") -+DHFILE = data_file("dh1024.pem") - BYTES_DHFILE = DHFILE.encode(sys.getfilesystemencoding()) - - - diff --git a/SOURCES/00223-pep476-verify-certs-by-default.patch b/SOURCES/00223-pep476-verify-certs-by-default.patch deleted file mode 100644 index d62703f..0000000 --- a/SOURCES/00223-pep476-verify-certs-by-default.patch +++ /dev/null @@ -1,153 +0,0 @@ - -# HG changeset patch -# User Benjamin Peterson -# Date 1416798122 21600 -# Node ID fb83916c3ea12899569e88a7505469a90ab1f674 -# Parent c84f36a5f556867c2ec50453dc879a500032d377 -pep 476: verify certificates by default (#22417) - -diff --git a/Doc/library/httplib.rst b/Doc/library/httplib.rst ---- a/Doc/library/httplib.rst -+++ b/Doc/library/httplib.rst -@@ -90,9 +90,6 @@ The module provides the following classe - server's certificate. If you want to change that behaviour, you can - explicitly set *check_hostname* to False. - -- .. warning:: -- This does not do any verification of the server's certificate. -- - .. versionadded:: 2.0 - - .. versionchanged:: 2.6 -@@ -104,6 +101,11 @@ The module provides the following classe - .. versionchanged:: 2.7.9 - *context* and *check_hostname* was added. - -+ This class now performs all the necessary certificate and hostname checks -+ by default. To revert to the previous, unverified, behavior -+ :func:`ssl._create_unverified_context` can be passed to the *context* -+ parameter. -+ - - .. class:: HTTPResponse(sock, debuglevel=0, strict=0) - -diff --git a/Lib/httplib.py b/Lib/httplib.py ---- a/Lib/httplib.py -+++ b/Lib/httplib.py -@@ -1193,7 +1193,7 @@ else: - self.key_file = key_file - self.cert_file = cert_file - if context is None: -- context = ssl.create_default_context() -+ context = ssl._create_default_https_context() - will_verify = context.verify_mode != ssl.CERT_NONE - if check_hostname is None: - check_hostname = will_verify -diff --git a/Lib/ssl.py b/Lib/ssl.py ---- a/Lib/ssl.py -+++ b/Lib/ssl.py -@@ -427,8 +427,7 @@ def create_default_context(purpose=Purpo - context.load_default_certs(purpose) - return context - -- --def _create_stdlib_context(protocol=PROTOCOL_SSLv23, cert_reqs=None, -+def _create_unverified_context(protocol=PROTOCOL_SSLv23, cert_reqs=None, - check_hostname=False, purpose=Purpose.SERVER_AUTH, - certfile=None, keyfile=None, - cafile=None, capath=None, cadata=None): -@@ -469,6 +468,14 @@ def _create_stdlib_context(protocol=PROT - - return context - -+# Used by http.client if no context is explicitly passed. -+_create_default_https_context = create_default_context -+ -+ -+# Backwards compatibility alias, even though it's not a public name. -+_create_stdlib_context = _create_unverified_context -+ -+ - class SSLSocket(socket): - """This class implements a subtype of socket.socket that wraps - the underlying OS socket in an SSL context when necessary, and -diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py ---- a/Lib/test/test_httplib.py -+++ b/Lib/test/test_httplib.py -@@ -1,10 +1,9 @@ - import httplib - import array --import httplib --import os - import StringIO - import socket - import errno -+import os - - import unittest - TestCase = unittest.TestCase -diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py ---- a/Lib/test/test_urllib2_localnet.py -+++ b/Lib/test/test_urllib2_localnet.py -@@ -5,6 +5,7 @@ import urllib2 - import BaseHTTPServer - import unittest - import hashlib -+import ssl - - from test import test_support - -@@ -562,15 +563,37 @@ class TestUrlopen(BaseTestCase): - cafile=CERT_localhost) - self.assertEqual(data, b"we care a bit") - # Bad cert -- with self.assertRaises(urllib2.URLError) as cm: -+ with self.assertRaises(urllib2.URLError): - self.urlopen("https://localhost:%s/bizarre" % handler.port, - cafile=CERT_fakehostname) - # Good cert, but mismatching hostname - handler = self.start_https_server(certfile=CERT_fakehostname) -- with self.assertRaises(ssl.CertificateError) as cm: -+ with self.assertRaises(ssl.CertificateError): - self.urlopen("https://localhost:%s/bizarre" % handler.port, - cafile=CERT_fakehostname) - -+ def test_https_with_cadefault(self): -+ handler = self.start_https_server(certfile=CERT_localhost) -+ # Self-signed cert should fail verification with system certificate store -+ with self.assertRaises(urllib2.URLError): -+ self.urlopen("https://localhost:%s/bizarre" % handler.port, -+ cadefault=True) -+ -+ def test_https_sni(self): -+ if ssl is None: -+ self.skipTest("ssl module required") -+ if not ssl.HAS_SNI: -+ self.skipTest("SNI support required in OpenSSL") -+ sni_name = [None] -+ def cb_sni(ssl_sock, server_name, initial_context): -+ sni_name[0] = server_name -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ context.set_servername_callback(cb_sni) -+ handler = self.start_https_server(context=context, certfile=CERT_localhost) -+ context = ssl.create_default_context(cafile=CERT_localhost) -+ self.urlopen("https://localhost:%s" % handler.port, context=context) -+ self.assertEqual(sni_name[0], "localhost") -+ - def test_sending_headers(self): - handler = self.start_server([(200, [], "we don't care")]) - -diff -up Python-2.7.5/Doc/library/xmlrpclib.rst.ver Python-2.7.5/Doc/library/xmlrpclib.rst ---- Python-2.7.5/Doc/library/xmlrpclib.rst.ver 2015-03-30 13:59:29.243493601 +0200 -+++ Python-2.7.5/Doc/library/xmlrpclib.rst 2015-03-30 14:03:40.509532180 +0200 -@@ -34,6 +34,10 @@ between conformable Python objects and X - constructed data. If you need to parse untrusted or unauthenticated data see - :ref:`xml-vulnerabilities`. - -+.. versionchanged:: 2.7.9 -+ -+ For https URIs, :mod:`xmlrpclib` now performs all the necessary certificate -+ and hostname checks by default - - .. class:: ServerProxy(uri[, transport[, encoding[, verbose[, allow_none[, use_datetime]]]]]) - diff --git a/SOURCES/00224-PEP-493-Re-add-file-based-configuration-of-HTTPS-ver.patch b/SOURCES/00224-PEP-493-Re-add-file-based-configuration-of-HTTPS-ver.patch new file mode 100644 index 0000000..57b1b07 --- /dev/null +++ b/SOURCES/00224-PEP-493-Re-add-file-based-configuration-of-HTTPS-ver.patch @@ -0,0 +1,57 @@ +From 9051b49f652b3d98a3cb1868c8da8281710ddcab Mon Sep 17 00:00:00 2001 +From: Tomas Orsava +Date: Tue, 7 Feb 2017 16:28:29 +0100 +Subject: [PATCH] PEP 493: Re-add file-based configuration of HTTPS + verification + +--- + Lib/ssl.py | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/Lib/ssl.py b/Lib/ssl.py +index f28c863..ad5a93a 100644 +--- a/Lib/ssl.py ++++ b/Lib/ssl.py +@@ -499,15 +499,35 @@ def _create_unverified_context(protocol=PROTOCOL_TLS, cert_reqs=None, + # Backwards compatibility alias, even though it's not a public name. + _create_stdlib_context = _create_unverified_context + +-# PEP 493: Verify HTTPS by default, but allow envvar to override that ++# PEP 493: Verify HTTPS by default, but allow envvar or file based ++# configuration to override that + _https_verify_envvar = 'PYTHONHTTPSVERIFY' ++_cert_verification_config = '/opt/rh/python27/root/etc/python/cert-verification.cfg' + + def _get_https_context_factory(): ++ # Check for an environmental override of the default behaviour + if not sys.flags.ignore_environment: + config_setting = os.environ.get(_https_verify_envvar) +- 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 ++ context_factories = { ++ 'enable': create_default_context, ++ 'disable': _create_unverified_context, ++ 'platform_default': create_default_context, ++ } ++ import ConfigParser ++ config = ConfigParser.RawConfigParser() ++ config.read(_cert_verification_config) ++ try: ++ verify_mode = config.get('https', 'verify') ++ except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): ++ verify_mode = 'platform_default' ++ default_factory = context_factories.get('platform_default') ++ return context_factories.get(verify_mode, default_factory) + + _create_default_https_context = _get_https_context_factory() + +-- +2.11.0 + diff --git a/SOURCES/00224-pep476-add-toggle-for-cert-verify.patch b/SOURCES/00224-pep476-add-toggle-for-cert-verify.patch deleted file mode 100644 index d0d37ab..0000000 --- a/SOURCES/00224-pep476-add-toggle-for-cert-verify.patch +++ /dev/null @@ -1,104 +0,0 @@ -diff -up Python-2.7.5/Lib/ssl.py.cert Python-2.7.5/Lib/ssl.py ---- Python-2.7.5/Lib/ssl.py.cert 2015-03-30 14:52:12.172241615 +0200 -+++ Python-2.7.5/Lib/ssl.py 2015-03-30 15:16:49.168185354 +0200 -@@ -466,8 +466,27 @@ def _create_unverified_context(protocol= - - return context - -+_cert_verification_config = '/opt/rh/python27/root/etc/python/cert-verification.cfg' -+ -+def _get_verify_status(protocol): -+ context_factory = { -+ 'platform_default': _create_unverified_context, -+ 'enable': create_default_context, -+ 'disable': _create_unverified_context -+ } -+ import ConfigParser -+ try: -+ config = ConfigParser.RawConfigParser() -+ config.read(_cert_verification_config) -+ status = config.get(protocol, 'verify') -+ except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): -+ status = 'platform_default' -+ default = context_factory.get('platform_default') -+ return context_factory.get(status, default) -+ -+ - # Used by http.client if no context is explicitly passed. --_create_default_https_context = create_default_context -+_create_default_https_context = _get_verify_status('https') - - - # Backwards compatibility alias, even though it's not a public name. -diff -up Python-2.7.5/Lib/test/test_httplib.py.cert Python-2.7.5/Lib/test/test_httplib.py ---- Python-2.7.5/Lib/test/test_httplib.py.cert 2015-03-30 16:45:30.738794461 +0200 -+++ Python-2.7.5/Lib/test/test_httplib.py 2015-03-30 16:54:48.065062351 +0200 -@@ -516,12 +516,24 @@ class HTTPSTest(TestCase): - h = httplib.HTTPSConnection(HOST, TimeoutTest.PORT, timeout=30) - self.assertEqual(h.timeout, 30) - -+ def test_networked_default(self): -+ # specific to RHEL -+ # Default settings: doesnt requires a valid cert from a trusted CA -+ test_support.requires('network') -+ with test_support.transient_internet('self-signed.pythontest.net'): -+ h = httplib.HTTPSConnection('self-signed.pythontest.net', 443) -+ h.request('GET', '/') -+ resp = h.getresponse() -+ self.assertIn('nginx', resp.getheader('server')) -+ -+ # We have to pass safe context to test cert verification -+ # RHEL by default disable cert verification - def test_networked(self): -- # Default settings: requires a valid cert from a trusted CA - import ssl - test_support.requires('network') - with test_support.transient_internet('self-signed.pythontest.net'): -- h = httplib.HTTPSConnection('self-signed.pythontest.net', 443) -+ context = ssl.create_default_context() -+ h = httplib.HTTPSConnection('self-signed.pythontest.net', 443, context=context) - with self.assertRaises(ssl.SSLError) as exc_info: - h.request('GET', '/') - self.assertEqual(exc_info.exception.reason, 'CERTIFICATE_VERIFY_FAILED') -@@ -542,8 +554,10 @@ class HTTPSTest(TestCase): - def test_networked_trusted_by_default_cert(self): - # Default settings: requires a valid cert from a trusted CA - test_support.requires('network') -+ import ssl - with test_support.transient_internet('www.python.org'): -- h = httplib.HTTPSConnection('www.python.org', 443) -+ context = ssl.create_default_context() -+ h = httplib.HTTPSConnection('www.python.org', 443, context=context) - h.request('GET', '/') - resp = h.getresponse() - content_type = resp.getheader('content-type') -@@ -579,7 +592,8 @@ class HTTPSTest(TestCase): - # The custom cert isn't known to the default trust bundle - import ssl - server = self.make_server(CERT_localhost) -- h = httplib.HTTPSConnection('localhost', server.port) -+ context = ssl.create_default_context() -+ h = httplib.HTTPSConnection('localhost', server.port, context=context) - with self.assertRaises(ssl.SSLError) as exc_info: - h.request('GET', '/') - self.assertEqual(exc_info.exception.reason, 'CERTIFICATE_VERIFY_FAILED') -@@ -624,6 +638,9 @@ class HTTPSTest(TestCase): - for hp in ("www.python.org:abc", "user:password@www.python.org"): - self.assertRaises(httplib.InvalidURL, httplib.HTTPSConnection, hp) - -+ import ssl -+ context = ssl.create_default_context() -+ - for hp, h, p in (("[fe80::207:e9ff:fe9b]:8000", - "fe80::207:e9ff:fe9b", 8000), - ("www.python.org:443", "www.python.org", 443), -@@ -632,7 +648,7 @@ class HTTPSTest(TestCase): - ("[fe80::207:e9ff:fe9b]", "fe80::207:e9ff:fe9b", 443), - ("[fe80::207:e9ff:fe9b]:", "fe80::207:e9ff:fe9b", - 443)): -- c = httplib.HTTPSConnection(hp) -+ c = httplib.HTTPSConnection(hp, context=context) - self.assertEqual(h, c.host) - self.assertEqual(p, c.port) - - diff --git a/SOURCES/00227-accept-none-keyfile-loadcertchain.patch b/SOURCES/00227-accept-none-keyfile-loadcertchain.patch deleted file mode 100644 index 28d241b..0000000 --- a/SOURCES/00227-accept-none-keyfile-loadcertchain.patch +++ /dev/null @@ -1,66 +0,0 @@ -diff --git a/Modules/_ssl.c b/Modules/_ssl.c ---- a/Modules/_ssl.c -+++ b/Modules/_ssl.c -@@ -2681,8 +2681,8 @@ static PyObject * - load_cert_chain(PySSLContext *self, PyObject *args, PyObject *kwds) - { - char *kwlist[] = {"certfile", "keyfile", "password", NULL}; -- PyObject *password = NULL; -- char *certfile_bytes = NULL, *keyfile_bytes = NULL; -+ PyObject *keyfile = NULL, *keyfile_bytes = NULL, *password = NULL; -+ char *certfile_bytes = NULL; - pem_password_cb *orig_passwd_cb = self->ctx->default_passwd_callback; - void *orig_passwd_userdata = self->ctx->default_passwd_callback_userdata; - _PySSLPasswordInfo pw_info = { NULL, NULL, NULL, 0, 0 }; -@@ -2690,11 +2690,27 @@ load_cert_chain(PySSLContext *self, PyOb - errno = 0; - ERR_clear_error(); - if (!PyArg_ParseTupleAndKeywords(args, kwds, -- "et|etO:load_cert_chain", kwlist, -+ "et|OO:load_cert_chain", kwlist, - Py_FileSystemDefaultEncoding, &certfile_bytes, -- Py_FileSystemDefaultEncoding, &keyfile_bytes, -- &password)) -+ &keyfile, &password)) - return NULL; -+ -+ if (keyfile && keyfile != Py_None) { -+ if (PyString_Check(keyfile)) { -+ Py_INCREF(keyfile); -+ keyfile_bytes = keyfile; -+ } else { -+ PyObject *u = PyUnicode_FromObject(keyfile); -+ if (!u) -+ goto error; -+ keyfile_bytes = PyUnicode_AsEncodedString( -+ u, Py_FileSystemDefaultEncoding, NULL); -+ Py_DECREF(u); -+ if (!keyfile_bytes) -+ goto error; -+ } -+ } -+ - if (password && password != Py_None) { - if (PyCallable_Check(password)) { - pw_info.callable = password; -@@ -2725,7 +2741,7 @@ load_cert_chain(PySSLContext *self, PyOb - } - PySSL_BEGIN_ALLOW_THREADS_S(pw_info.thread_state); - r = SSL_CTX_use_PrivateKey_file(self->ctx, -- keyfile_bytes ? keyfile_bytes : certfile_bytes, -+ keyfile_bytes ? PyBytes_AS_STRING(keyfile_bytes) : certfile_bytes, - SSL_FILETYPE_PEM); - PySSL_END_ALLOW_THREADS_S(pw_info.thread_state); - if (r != 1) { -@@ -2756,8 +2772,8 @@ load_cert_chain(PySSLContext *self, PyOb - error: - SSL_CTX_set_default_passwd_cb(self->ctx, orig_passwd_cb); - SSL_CTX_set_default_passwd_cb_userdata(self->ctx, orig_passwd_userdata); -+ Py_XDECREF(keyfile_bytes); - PyMem_Free(pw_info.password); -- PyMem_Free(keyfile_bytes); - PyMem_Free(certfile_bytes); - return NULL; - } - - diff --git a/SOURCES/00228-backport-ssl-version.patch b/SOURCES/00228-backport-ssl-version.patch deleted file mode 100644 index 40ac04c..0000000 --- a/SOURCES/00228-backport-ssl-version.patch +++ /dev/null @@ -1,260 +0,0 @@ - -# HG changeset patch -# User Alex Gaynor -# Date 1409862802 25200 -# Node ID 16c86a6bdbe2a545dd2de02dc9f347c2b3ae7220 -# Parent f17ab9fed3b03191df975ecdde2cc07cee915319 -Issue #20421: Add a .version() method to SSL sockets exposing the actual protocol version in use. - -Backport from default. - -diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst ---- a/Doc/library/ssl.rst -+++ b/Doc/library/ssl.rst -@@ -867,10 +867,10 @@ SSL sockets also have the following addi - - .. method:: SSLSocket.selected_npn_protocol() - -- Returns the protocol that was selected during the TLS/SSL handshake. If -- :meth:`SSLContext.set_npn_protocols` was not called, or if the other party -- does not support NPN, or if the handshake has not yet happened, this will -- return ``None``. -+ Returns the higher-level protocol that was selected during the TLS/SSL -+ handshake. If :meth:`SSLContext.set_npn_protocols` was not called, or -+ if the other party does not support NPN, or if the handshake has not yet -+ happened, this will return ``None``. - - .. versionadded:: 2.7.9 - -@@ -882,6 +882,16 @@ SSL sockets also have the following addi - returned socket should always be used for further communication with the - other side of the connection, rather than the original socket. - -+.. method:: SSLSocket.version() -+ -+ Return the actual SSL protocol version negotiated by the connection -+ as a string, or ``None`` is no secure connection is established. -+ As of this writing, possible return values include ``"SSLv2"``, -+ ``"SSLv3"``, ``"TLSv1"``, ``"TLSv1.1"`` and ``"TLSv1.2"``. -+ Recent OpenSSL versions may define more return values. -+ -+ .. versionadded:: 3.5 -+ - .. attribute:: SSLSocket.context - - The :class:`SSLContext` object this SSL socket is tied to. If the SSL -diff --git a/Lib/ssl.py b/Lib/ssl.py ---- a/Lib/ssl.py -+++ b/Lib/ssl.py -@@ -862,6 +862,15 @@ class SSLSocket(socket): - return None - return self._sslobj.tls_unique_cb() - -+ def version(self): -+ """ -+ Return a string identifying the protocol version used by the -+ current SSL channel, or None if there is no established channel. -+ """ -+ if self._sslobj is None: -+ return None -+ return self._sslobj.version() -+ - - def wrap_socket(sock, keyfile=None, certfile=None, - server_side=False, cert_reqs=CERT_NONE, -diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py ---- a/Lib/test/test_ssl.py -+++ b/Lib/test/test_ssl.py -@@ -1904,7 +1904,8 @@ else: - 'compression': s.compression(), - 'cipher': s.cipher(), - 'peercert': s.getpeercert(), -- 'client_npn_protocol': s.selected_npn_protocol() -+ 'client_npn_protocol': s.selected_npn_protocol(), -+ 'version': s.version(), - }) - s.close() - stats['server_npn_protocols'] = server.selected_protocols -@@ -1912,6 +1913,13 @@ else: - - def try_protocol_combo(server_protocol, client_protocol, expect_success, - certsreqs=None, server_options=0, client_options=0): -+ """ -+ Try to SSL-connect using *client_protocol* to *server_protocol*. -+ If *expect_success* is true, assert that the connection succeeds, -+ if it's false, assert that the connection fails. -+ Also, if *expect_success* is a string, assert that it is the protocol -+ version actually used by the connection. -+ """ - if certsreqs is None: - certsreqs = ssl.CERT_NONE - certtype = { -@@ -1941,8 +1949,8 @@ else: - ctx.load_cert_chain(CERTFILE) - ctx.load_verify_locations(CERTFILE) - try: -- server_params_test(client_context, server_context, -- chatty=False, connectionchatty=False) -+ stats = server_params_test(client_context, server_context, -+ chatty=False, connectionchatty=False) - # Protocol mismatch can result in either an SSLError, or a - # "Connection reset by peer" error. - except ssl.SSLError: -@@ -1957,6 +1965,10 @@ else: - "Client protocol %s succeeded with server protocol %s!" - % (ssl.get_protocol_name(client_protocol), - ssl.get_protocol_name(server_protocol))) -+ elif (expect_success is not True -+ and expect_success != stats['version']): -+ raise AssertionError("version mismatch: expected %r, got %r" -+ % (expect_success, stats['version'])) - - - class ThreadedTests(unittest.TestCase): -@@ -2186,17 +2198,17 @@ else: - sys.stdout.write( - " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n" - % str(x)) -- try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True) -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, 'SSLv3') - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True) -- try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True) -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1') - -- try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL) - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL) -- try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL) - -- try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED) - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED) -- try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED) - - # Server with specific SSL options - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, -@@ -2213,9 +2225,9 @@ else: - """Connecting to an SSLv3 server with various client options""" - if support.verbose: - sys.stdout.write("\n") -- try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True) -- try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) -- try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) -+ try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3') -+ try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL) -+ try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED) - if hasattr(ssl, 'PROTOCOL_SSLv2'): - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False) - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False, -@@ -2223,7 +2235,7 @@ else: - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False) - if no_sslv2_implies_sslv3_hello(): - # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs -- try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True, -+ try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, 'SSLv3', - client_options=ssl.OP_NO_SSLv2) - - @skip_if_broken_ubuntu_ssl -@@ -2231,9 +2243,9 @@ else: - """Connecting to a TLSv1 server with various client options""" - if support.verbose: - sys.stdout.write("\n") -- try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True) -- try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) -- try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1') -+ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED) - if hasattr(ssl, 'PROTOCOL_SSLv2'): - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False) - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False) -@@ -2248,14 +2260,14 @@ else: - Testing against older TLS versions.""" - if support.verbose: - sys.stdout.write("\n") -- try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, True) -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1') - if hasattr(ssl, 'PROTOCOL_SSLv2'): - try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False) - try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False) - try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False, - client_options=ssl.OP_NO_TLSv1_1) - -- try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True) -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1') - try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False) - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False) - -@@ -2268,7 +2280,7 @@ else: - Testing against older TLS versions.""" - if support.verbose: - sys.stdout.write("\n") -- try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, True, -+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2', - server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2, - client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,) - if hasattr(ssl, 'PROTOCOL_SSLv2'): -@@ -2277,7 +2289,7 @@ else: - try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv23, False, - client_options=ssl.OP_NO_TLSv1_2) - -- try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, True) -+ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2') - try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False) - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False) - try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False) -@@ -2619,6 +2631,21 @@ else: - s.connect((HOST, server.port)) - self.assertIn("no shared cipher", str(server.conn_errors[0])) - -+ def test_version_basic(self): -+ """ -+ Basic tests for SSLSocket.version(). -+ More tests are done in the test_protocol_*() methods. -+ """ -+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ with ThreadedEchoServer(CERTFILE, -+ ssl_version=ssl.PROTOCOL_TLSv1, -+ chatty=False) as server: -+ with closing(context.wrap_socket(socket.socket())) as s: -+ self.assertIs(s.version(), None) -+ s.connect((HOST, server.port)) -+ self.assertEqual(s.version(), "TLSv1") -+ self.assertIs(s.version(), None) -+ - @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL") - def test_default_ecdh_curve(self): - # Issue #21015: elliptic curve-based Diffie Hellman key exchange -diff --git a/Modules/_ssl.c b/Modules/_ssl.c ---- a/Modules/_ssl.c -+++ b/Modules/_ssl.c -@@ -1384,6 +1384,18 @@ static PyObject *PySSL_cipher (PySSLSock - return NULL; - } - -+static PyObject *PySSL_version(PySSLSocket *self) -+{ -+ const char *version; -+ -+ if (self->ssl == NULL) -+ Py_RETURN_NONE; -+ version = SSL_get_version(self->ssl); -+ if (!strcmp(version, "unknown")) -+ Py_RETURN_NONE; -+ return PyUnicode_FromString(version); -+} -+ - #ifdef OPENSSL_NPN_NEGOTIATED - static PyObject *PySSL_selected_npn_protocol(PySSLSocket *self) { - const unsigned char *out; -@@ -1907,6 +1919,7 @@ static PyMethodDef PySSLMethods[] = { - {"peer_certificate", (PyCFunction)PySSL_peercert, METH_VARARGS, - PySSL_peercert_doc}, - {"cipher", (PyCFunction)PySSL_cipher, METH_NOARGS}, -+ {"version", (PyCFunction)PySSL_version, METH_NOARGS}, - #ifdef OPENSSL_NPN_NEGOTIATED - {"selected_npn_protocol", (PyCFunction)PySSL_selected_npn_protocol, METH_NOARGS}, - #endif - diff --git a/SOURCES/00229-fix-hashlib-openssl-init.patch b/SOURCES/00229-fix-hashlib-openssl-init.patch deleted file mode 100644 index c23ca72..0000000 --- a/SOURCES/00229-fix-hashlib-openssl-init.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c -index a41c97e..2c8a18f 100644 ---- a/Modules/_hashopenssl.c -+++ b/Modules/_hashopenssl.c -@@ -984,6 +984,7 @@ init_hashlib(void) - SSL_load_error_strings(); - SSL_library_init(); - ERR_load_crypto_strings(); -+ OpenSSL_add_all_digests(); - - Py_TYPE(&EVPtype) = &PyType_Type; - if (PyType_Ready(&EVPtype) < 0) diff --git a/SOURCES/00230-adjusted-tests-to-determine-if-SSLv2-is-enabled-or-not.patch b/SOURCES/00230-adjusted-tests-to-determine-if-SSLv2-is-enabled-or-not.patch deleted file mode 100644 index 9e941e6..0000000 --- a/SOURCES/00230-adjusted-tests-to-determine-if-SSLv2-is-enabled-or-not.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 4f118fdad37e47301047a0729552ff8f5e80ffcf Mon Sep 17 00:00:00 2001 -From: Charalampos Stratakis -Date: Tue, 12 Apr 2016 12:59:36 +0200 -Subject: [PATCH] Adjusted tests to determine if SSLv2 is enabled or not - ---- - Lib/test/test_ssl.py | 30 ++++++++++++++++++++++++------ - 1 file changed, 24 insertions(+), 6 deletions(-) - -diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py -index 498a489..9bf3260 100644 ---- a/Lib/test/test_ssl.py -+++ b/Lib/test/test_ssl.py -@@ -104,6 +104,12 @@ def no_sslv2_implies_sslv3_hello(): - # 0.9.7h or higher - return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15) - -+def default_context_has_no_sslv2(): -+ # Function for tests to determine if openssl package has disabled SSLv2 or not -+ # See rhbz#1319703 -+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -+ return ctx.options & ssl.OP_NO_SSLv2 -+ - def have_verify_flags(): - # 0.9.8 or higher - return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15) -@@ -709,7 +715,10 @@ class ContextTests(unittest.TestCase): - @skip_if_broken_ubuntu_ssl - def test_options(self): - ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) -- self.assertEqual(ssl.OP_ALL, ctx.options) -+ if default_context_has_no_sslv2(): -+ self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2, ctx.options) -+ else: -+ self.assertEqual(ssl.OP_ALL, ctx.options) - ctx.options |= ssl.OP_NO_SSLv2 - self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2, - ctx.options) -@@ -2170,7 +2179,10 @@ else: - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED) -- try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True) -+ if default_context_has_no_sslv2(): -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False) -+ else: -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False) - # SSLv23 client with specific SSL options -@@ -2178,10 +2190,16 @@ else: - # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, - client_options=ssl.OP_NO_SSLv2) -- try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True, -- client_options=ssl.OP_NO_SSLv3) -- try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True, -- client_options=ssl.OP_NO_TLSv1) -+ if default_context_has_no_sslv2(): -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_SSLv3) -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, -+ client_options=ssl.OP_NO_TLSv1) -+ else: -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True, -+ client_options=ssl.OP_NO_SSLv3) -+ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True, -+ client_options=ssl.OP_NO_TLSv1) - - @skip_if_broken_ubuntu_ssl - def test_protocol_sslv23(self): --- -2.5.5 - diff --git a/SOURCES/00232-use-Py_ssize_t-for-file-offset-and-length-computations-in-iteration.patch b/SOURCES/00232-use-Py_ssize_t-for-file-offset-and-length-computations-in-iteration.patch deleted file mode 100644 index 9aaa635..0000000 --- a/SOURCES/00232-use-Py_ssize_t-for-file-offset-and-length-computations-in-iteration.patch +++ /dev/null @@ -1,101 +0,0 @@ -From ee2958f8a13facbc2bddef1b4b84b0fe0b1bc4c9 Mon Sep 17 00:00:00 2001 -From: Charalampos Stratakis -Date: Thu, 28 Apr 2016 17:20:09 +0200 -Subject: [PATCH] use Py_ssize_t for file offset and length computations in - iteration - ---- - Lib/test/test_file2k.py | 16 +++++++++++++++- - Objects/fileobject.c | 15 +++++++-------- - 2 files changed, 22 insertions(+), 9 deletions(-) - -diff --git a/Lib/test/test_file2k.py b/Lib/test/test_file2k.py -index d1c1e35..b640aeb 100644 ---- a/Lib/test/test_file2k.py -+++ b/Lib/test/test_file2k.py -@@ -14,7 +14,7 @@ except ImportError: - threading = None - - from test import test_support --from test.test_support import TESTFN, run_unittest -+from test.test_support import TESTFN, run_unittest, requires - from UserList import UserList - - class AutoFileTests(unittest.TestCase): -@@ -437,6 +437,20 @@ class OtherFileTests(unittest.TestCase): - finally: - f.close() - -+ @test_support.precisionbigmemtest(2**31, 2.5, dry_run=False) -+ def test_very_long_line(self, size): -+ # Issue #22526 -+ requires('largefile') -+ with open(TESTFN, "wb") as fp: -+ fp.seek(size - 1) -+ fp.write("\0") -+ with open(TESTFN, "rb") as fp: -+ for l in fp: -+ pass -+ self.assertEqual(len(l), size) -+ self.assertEqual(l.count("\0"), size) -+ l = None -+ - class FileSubclassTests(unittest.TestCase): - - def testExit(self): -diff --git a/Objects/fileobject.c b/Objects/fileobject.c -index 5594058..55e074b 100644 ---- a/Objects/fileobject.c -+++ b/Objects/fileobject.c -@@ -2236,7 +2236,7 @@ drop_readahead(PyFileObject *f) - (unless at EOF) and no more than bufsize. Returns negative value on - error, will set MemoryError if bufsize bytes cannot be allocated. */ - static int --readahead(PyFileObject *f, int bufsize) -+readahead(PyFileObject *f, Py_ssize_t bufsize) - { - Py_ssize_t chunksize; - -@@ -2274,7 +2274,7 @@ readahead(PyFileObject *f, int bufsize) - logarithmic buffer growth to about 50 even when reading a 1gb line. */ - - static PyStringObject * --readahead_get_line_skip(PyFileObject *f, int skip, int bufsize) -+readahead_get_line_skip(PyFileObject *f, Py_ssize_t skip, Py_ssize_t bufsize) - { - PyStringObject* s; - char *bufptr; -@@ -2294,10 +2294,10 @@ readahead_get_line_skip(PyFileObject *f, int skip, int bufsize) - bufptr++; /* Count the '\n' */ - len = bufptr - f->f_bufptr; - s = (PyStringObject *) -- PyString_FromStringAndSize(NULL, skip+len); -+ PyString_FromStringAndSize(NULL, skip + len); - if (s == NULL) - return NULL; -- memcpy(PyString_AS_STRING(s)+skip, f->f_bufptr, len); -+ memcpy(PyString_AS_STRING(s) + skip, f->f_bufptr, len); - f->f_bufptr = bufptr; - if (bufptr == f->f_bufend) - drop_readahead(f); -@@ -2305,14 +2305,13 @@ readahead_get_line_skip(PyFileObject *f, int skip, int bufsize) - bufptr = f->f_bufptr; - buf = f->f_buf; - f->f_buf = NULL; /* Force new readahead buffer */ -- assert(skip+len < INT_MAX); -- s = readahead_get_line_skip( -- f, (int)(skip+len), bufsize + (bufsize>>2) ); -+ assert(len <= PY_SSIZE_T_MAX - skip); -+ s = readahead_get_line_skip(f, skip + len, bufsize + (bufsize>>2)); - if (s == NULL) { - PyMem_Free(buf); - return NULL; - } -- memcpy(PyString_AS_STRING(s)+skip, bufptr, len); -+ memcpy(PyString_AS_STRING(s) + skip, bufptr, len); - PyMem_Free(buf); - } - return s; --- -2.5.5 - diff --git a/SOURCES/00237-CVE-2016-0772-smtplib.patch b/SOURCES/00237-CVE-2016-0772-smtplib.patch deleted file mode 100644 index b11fac1..0000000 --- a/SOURCES/00237-CVE-2016-0772-smtplib.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 5b67aca6fb4246e84981d6361ba218bd52e73ac2 Mon Sep 17 00:00:00 2001 -From: Tomas Orsava -Date: Tue, 21 Jun 2016 15:52:03 +0200 -Subject: [PATCH] Raise an error when STARTTLS fails - -CVE-2016-0772 python: smtplib StartTLS stripping attack -rhbz#1303647: https://bugzilla.redhat.com/show_bug.cgi?id=1303647 - -Based on an upstream change by Benjamin Peterson -- in changeset 101886:b3ce713fb9be 2.7 -- https://hg.python.org/cpython/rev/b3ce713fb9be ---- - Lib/smtplib.py | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/Lib/smtplib.py b/Lib/smtplib.py -index dc16ef6..8bc806b 100755 ---- a/Lib/smtplib.py -+++ b/Lib/smtplib.py -@@ -655,6 +655,11 @@ class SMTP: - self.ehlo_resp = None - self.esmtp_features = {} - self.does_esmtp = 0 -+ else: -+ # RFC 3207: -+ # 501 Syntax error (no parameters allowed) -+ # 454 TLS not available due to temporary reason -+ raise SMTPResponseException(resp, reply) - return (resp, reply) - - def sendmail(self, from_addr, to_addrs, msg, mail_options=[], --- -2.5.5 - diff --git a/SOURCES/00238-CVE-2016-5699-httplib.patch b/SOURCES/00238-CVE-2016-5699-httplib.patch deleted file mode 100644 index 9ed24cc..0000000 --- a/SOURCES/00238-CVE-2016-5699-httplib.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 92f27ac1b4ec0a6712df0075e584b98ab2308a6f Mon Sep 17 00:00:00 2001 -From: Tomas Orsava -Date: Tue, 28 Jun 2016 15:04:56 +0200 -Subject: [PATCH] Disabled HTTP header injections in httplib - -CVE-2016-5699 python: http protocol steam injection attack -rhbz#1303699 : https://bugzilla.redhat.com/show_bug.cgi?id=1303699 - -Based on an upstream change by Demian Brecht and Serhiy Storchaka -- in changeset 94951:1c45047c5102 2.7 -- https://hg.python.org/cpython/rev/1c45047c5102 ---- - Lib/httplib.py | 40 +++++++++++++++++++++++++++++++++- - Lib/test/test_httplib.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 95 insertions(+), 1 deletion(-) - -diff --git a/Lib/httplib.py b/Lib/httplib.py -index 8517838..5c5500e 100644 ---- a/Lib/httplib.py -+++ b/Lib/httplib.py -@@ -68,6 +68,7 @@ Req-sent-unread-response _CS_REQ_SENT - - from array import array - import os -+import re - import socket - from sys import py3kwarning - from urlparse import urlsplit -@@ -218,6 +219,34 @@ _MAXLINE = 65536 - # maximum amount of headers accepted - _MAXHEADERS = 100 - -+# Header name/value ABNF (http://tools.ietf.org/html/rfc7230#section-3.2) -+# -+# VCHAR = %x21-7E -+# obs-text = %x80-FF -+# header-field = field-name ":" OWS field-value OWS -+# field-name = token -+# field-value = *( field-content / obs-fold ) -+# field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] -+# field-vchar = VCHAR / obs-text -+# -+# obs-fold = CRLF 1*( SP / HTAB ) -+# ; obsolete line folding -+# ; see Section 3.2.4 -+ -+# token = 1*tchar -+# -+# tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" -+# / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" -+# / DIGIT / ALPHA -+# ; any VCHAR, except delimiters -+# -+# VCHAR defined in http://tools.ietf.org/html/rfc5234#appendix-B.1 -+ -+# the patterns for both name and value are more leniant than RFC -+# definitions to allow for backwards compatibility -+_is_legal_header_name = re.compile(r'\A[^:\s][^:\r\n]*\Z').match -+_is_illegal_header_value = re.compile(r'\n(?![ \t])|\r(?![ \t\n])').search -+ - - class HTTPMessage(mimetools.Message): - -@@ -978,7 +1007,16 @@ class HTTPConnection: - if self.__state != _CS_REQ_STARTED: - raise CannotSendHeader() - -- hdr = '%s: %s' % (header, '\r\n\t'.join([str(v) for v in values])) -+ header = '%s' % header -+ if not _is_legal_header_name(header): -+ raise ValueError('Invalid header name %r' % (header,)) -+ -+ values = [str(v) for v in values] -+ for one_value in values: -+ if _is_illegal_header_value(one_value): -+ raise ValueError('Invalid header value %r' % (one_value,)) -+ -+ hdr = '%s: %s' % (header, '\r\n\t'.join(values)) - self._output(hdr) - - def endheaders(self, message_body=None): -diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py -index bc7f5a7..abc6a3c 100644 ---- a/Lib/test/test_httplib.py -+++ b/Lib/test/test_httplib.py -@@ -138,6 +138,33 @@ class HeaderTests(TestCase): - conn.putheader('Content-length',42) - self.assertIn('Content-length: 42', conn._buffer) - -+ conn.putheader('Foo', ' bar ') -+ self.assertIn(b'Foo: bar ', conn._buffer) -+ conn.putheader('Bar', '\tbaz\t') -+ self.assertIn(b'Bar: \tbaz\t', conn._buffer) -+ conn.putheader('Authorization', 'Bearer mytoken') -+ self.assertIn(b'Authorization: Bearer mytoken', conn._buffer) -+ conn.putheader('IterHeader', 'IterA', 'IterB') -+ self.assertIn(b'IterHeader: IterA\r\n\tIterB', conn._buffer) -+ conn.putheader('LatinHeader', b'\xFF') -+ self.assertIn(b'LatinHeader: \xFF', conn._buffer) -+ conn.putheader('Utf8Header', b'\xc3\x80') -+ self.assertIn(b'Utf8Header: \xc3\x80', conn._buffer) -+ conn.putheader('C1-Control', b'next\x85line') -+ self.assertIn(b'C1-Control: next\x85line', conn._buffer) -+ conn.putheader('Embedded-Fold-Space', 'is\r\n allowed') -+ self.assertIn(b'Embedded-Fold-Space: is\r\n allowed', conn._buffer) -+ conn.putheader('Embedded-Fold-Tab', 'is\r\n\tallowed') -+ self.assertIn(b'Embedded-Fold-Tab: is\r\n\tallowed', conn._buffer) -+ conn.putheader('Key Space', 'value') -+ self.assertIn(b'Key Space: value', conn._buffer) -+ conn.putheader('KeySpace ', 'value') -+ self.assertIn(b'KeySpace : value', conn._buffer) -+ conn.putheader(b'Nonbreak\xa0Space', 'value') -+ self.assertIn(b'Nonbreak\xa0Space: value', conn._buffer) -+ conn.putheader(b'\xa0NonbreakSpace', 'value') -+ self.assertIn(b'\xa0NonbreakSpace: value', conn._buffer) -+ - def test_ipv6host_header(self): - # Default host header on IPv6 transaction should wrapped by [] if - # its actual IPv6 address -@@ -157,6 +184,35 @@ class HeaderTests(TestCase): - conn.request('GET', '/foo') - self.assertTrue(sock.data.startswith(expected)) - -+ def test_invalid_headers(self): -+ conn = httplib.HTTPConnection('example.com') -+ conn.sock = FakeSocket('') -+ conn.putrequest('GET', '/') -+ -+ # http://tools.ietf.org/html/rfc7230#section-3.2.4, whitespace is no -+ # longer allowed in header names -+ cases = ( -+ (b'Invalid\r\nName', b'ValidValue'), -+ (b'Invalid\rName', b'ValidValue'), -+ (b'Invalid\nName', b'ValidValue'), -+ (b'\r\nInvalidName', b'ValidValue'), -+ (b'\rInvalidName', b'ValidValue'), -+ (b'\nInvalidName', b'ValidValue'), -+ (b' InvalidName', b'ValidValue'), -+ (b'\tInvalidName', b'ValidValue'), -+ (b'Invalid:Name', b'ValidValue'), -+ (b':InvalidName', b'ValidValue'), -+ (b'ValidName', b'Invalid\r\nValue'), -+ (b'ValidName', b'Invalid\rValue'), -+ (b'ValidName', b'Invalid\nValue'), -+ (b'ValidName', b'InvalidValue\r\n'), -+ (b'ValidName', b'InvalidValue\r'), -+ (b'ValidName', b'InvalidValue\n'), -+ ) -+ for name, value in cases: -+ with self.assertRaisesRegexp(ValueError, 'Invalid header'): -+ conn.putheader(name, value) -+ - - class BasicTest(TestCase): - def test_status_lines(self): --- -2.9.0 - diff --git a/SOURCES/00242-CVE-2016-1000110-httpoxy.patch b/SOURCES/00242-CVE-2016-1000110-httpoxy.patch deleted file mode 100644 index ada467c..0000000 --- a/SOURCES/00242-CVE-2016-1000110-httpoxy.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 3a184cc875709d4324d234a4b939d614a2c9bb0f Mon Sep 17 00:00:00 2001 -From: Charalampos Stratakis -Date: Mon, 1 Aug 2016 11:20:11 +0200 -Subject: [PATCH] =?UTF-8?q?Fix=20for=20CVE-2016-1000110=20http://bugs.pyth?= - =?UTF-8?q?on.org/issue27568=20Based=20on=20the=20patch=20by=20R=C3=A9mi?= - =?UTF-8?q?=20Rampin?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - ---- - Doc/howto/urllib2.rst | 5 +++++ - Doc/library/urllib.rst | 10 ++++++++++ - Doc/library/urllib2.rst | 4 ++++ - Lib/test/test_urllib.py | 12 ++++++++++++ - Lib/urllib.py | 9 +++++++++ - 5 files changed, 40 insertions(+) - -diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst -index f84bf08..6542846 100644 ---- a/Doc/howto/urllib2.rst -+++ b/Doc/howto/urllib2.rst -@@ -523,6 +523,11 @@ setting up a `Basic Authentication`_ handler : :: - through a proxy. However, this can be enabled by extending urllib2 as - shown in the recipe [#]_. - -+.. note:: -+ -+ ``HTTP_PROXY`` will be ignored if a variable ``REQUEST_METHOD`` is set; see -+ the documentation on :func:`~urllib.getproxies`. -+ - - Sockets and Layers - ================== -diff --git a/Doc/library/urllib.rst b/Doc/library/urllib.rst -index c7d200d..3b9876e 100644 ---- a/Doc/library/urllib.rst -+++ b/Doc/library/urllib.rst -@@ -280,6 +280,16 @@ Utility functions - find it, looks for proxy information from Mac OSX System Configuration for - Mac OS X and Windows Systems Registry for Windows. - -+ .. note:: -+ -+ If the environment variable ``REQUEST_METHOD`` is set, which usually -+ indicates your script is running in a CGI environment, the environment -+ variable ``HTTP_PROXY`` (uppercase ``_PROXY``) will be ignored. This is -+ because that variable can be injected by a client using the "Proxy:" -+ HTTP header. If you need to use an HTTP proxy in a CGI environment, -+ either use ``ProxyHandler`` explicitly, or make sure the variable name -+ is in lowercase (or at least the ``_proxy`` suffix). -+ - .. note:: - urllib also exposes certain utility functions like splittype, splithost and - others parsing url into various components. But it is recommended to use -diff --git a/Doc/library/urllib2.rst b/Doc/library/urllib2.rst -index 24deeb4..46fce59 100644 ---- a/Doc/library/urllib2.rst -+++ b/Doc/library/urllib2.rst -@@ -224,6 +224,10 @@ The following classes are provided: - - To disable autodetected proxy pass an empty dictionary. - -+ .. note:: -+ -+ ``HTTP_PROXY`` will be ignored if a variable ``REQUEST_METHOD`` is set; -+ see the documentation on :func:`~urllib.getproxies`. - - .. class:: HTTPPasswordMgr() - -diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py -index 3a273f8..3845012 100644 ---- a/Lib/test/test_urllib.py -+++ b/Lib/test/test_urllib.py -@@ -161,6 +161,18 @@ class ProxyTests(unittest.TestCase): - self.env.set('NO_PROXY', 'localhost, anotherdomain.com, newdomain.com') - self.assertTrue(urllib.proxy_bypass_environment('anotherdomain.com')) - -+ def test_proxy_cgi_ignore(self): -+ try: -+ self.env.set('HTTP_PROXY', 'http://somewhere:3128') -+ proxies = urllib.getproxies_environment() -+ self.assertEqual('http://somewhere:3128', proxies['http']) -+ self.env.set('REQUEST_METHOD', 'GET') -+ proxies = urllib.getproxies_environment() -+ self.assertNotIn('http', proxies) -+ finally: -+ self.env.unset('REQUEST_METHOD') -+ self.env.unset('HTTP_PROXY') -+ - - class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin): - """Test urlopen() opening a fake http connection.""" -diff --git a/Lib/urllib.py b/Lib/urllib.py -index f9655f9..9b31df1 100644 ---- a/Lib/urllib.py -+++ b/Lib/urllib.py -@@ -1361,11 +1361,20 @@ def getproxies_environment(): - [Fancy]URLopener constructor. - - """ -+ # Get all variables - proxies = {} - for name, value in os.environ.items(): - name = name.lower() - if value and name[-6:] == '_proxy': - proxies[name[:-6]] = value -+ -+ # CVE-2016-1000110 - If we are running as CGI script, forget HTTP_PROXY -+ # (non-all-lowercase) as it may be set from the web server by a "Proxy:" -+ # header from the client -+ # If "proxy" is lowercase, it will still be used thanks to the next block -+ if 'REQUEST_METHOD' in os.environ: -+ proxies.pop('http', None) -+ - return proxies - - def proxy_bypass_environment(host): --- -2.7.4 - diff --git a/SOURCES/CVE-2013-1752.patch b/SOURCES/CVE-2013-1752.patch deleted file mode 100644 index ff2be9d..0000000 --- a/SOURCES/CVE-2013-1752.patch +++ /dev/null @@ -1,203 +0,0 @@ - -# HG changeset patch -# User Benjamin Peterson -# Date 1417827758 18000 -# Node ID 339f877cca115c1901f5dd93d7bc066031d2a669 -# Parent 54af094087953f4997a4ead63e949d845c4b4412 -in poplib, limit maximum line length that we read from the network (closes #16041) - -Patch from Berker Peksag. - -diff --git a/Lib/poplib.py b/Lib/poplib.py ---- a/Lib/poplib.py -+++ b/Lib/poplib.py -@@ -32,6 +32,12 @@ CR = '\r' - LF = '\n' - CRLF = CR+LF - -+# maximal line length when calling readline(). This is to prevent -+# reading arbitrary length lines. RFC 1939 limits POP3 line length to -+# 512 characters, including CRLF. We have selected 2048 just to be on -+# the safe side. -+_MAXLINE = 2048 -+ - - class POP3: - -@@ -103,7 +109,9 @@ class POP3: - # Raise error_proto('-ERR EOF') if the connection is closed. - - def _getline(self): -- line = self.file.readline() -+ line = self.file.readline(_MAXLINE + 1) -+ if len(line) > _MAXLINE: -+ raise error_proto('line too long') - if self._debugging > 1: print '*get*', repr(line) - if not line: raise error_proto('-ERR EOF') - octets = len(line) -@@ -365,6 +373,8 @@ else: - match = renewline.match(self.buffer) - while not match: - self._fillBuffer() -+ if len(self.buffer) > _MAXLINE: -+ raise error_proto('line too long') - match = renewline.match(self.buffer) - line = match.group(0) - self.buffer = renewline.sub('' ,self.buffer, 1) -diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py ---- a/Lib/test/test_poplib.py -+++ b/Lib/test/test_poplib.py -@@ -198,6 +198,10 @@ class TestPOP3Class(TestCase): - 113) - self.assertEqual(self.client.retr('foo'), expected) - -+ def test_too_long_lines(self): -+ self.assertRaises(poplib.error_proto, self.client._shortcmd, -+ 'echo +%s' % ((poplib._MAXLINE + 10) * 'a')) -+ - def test_dele(self): - self.assertOK(self.client.dele('foo')) - - - -# HG changeset patch -# User Benjamin Peterson -# Date 1417827918 18000 -# Node ID 923aac88a3cc76a95d5a04d9d3ece245147a8064 -# Parent 339f877cca115c1901f5dd93d7bc066031d2a669 -smtplib: limit amount read from the network (closes #16042) - -diff --git a/Lib/smtplib.py b/Lib/smtplib.py ---- a/Lib/smtplib.py -+++ b/Lib/smtplib.py -@@ -57,6 +57,7 @@ from sys import stderr - SMTP_PORT = 25 - SMTP_SSL_PORT = 465 - CRLF = "\r\n" -+_MAXLINE = 8192 # more than 8 times larger than RFC 821, 4.5.3 - - OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I) - -@@ -179,10 +180,14 @@ else: - def __init__(self, sslobj): - self.sslobj = sslobj - -- def readline(self): -+ def readline(self, size=-1): -+ if size < 0: -+ size = None - str = "" - chr = None - while chr != "\n": -+ if size is not None and len(str) >= size: -+ break - chr = self.sslobj.read(1) - if not chr: - break -@@ -353,7 +358,7 @@ class SMTP: - self.file = self.sock.makefile('rb') - while 1: - try: -- line = self.file.readline() -+ line = self.file.readline(_MAXLINE + 1) - except socket.error as e: - self.close() - raise SMTPServerDisconnected("Connection unexpectedly closed: " -@@ -363,6 +368,8 @@ class SMTP: - raise SMTPServerDisconnected("Connection unexpectedly closed") - if self.debuglevel > 0: - print>>stderr, 'reply:', repr(line) -+ if len(line) > _MAXLINE: -+ raise SMTPResponseException(500, "Line too long.") - resp.append(line[4:].strip()) - code = line[:3] - # Check that the error code is syntactically correct. -diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py ---- a/Lib/test/test_smtplib.py -+++ b/Lib/test/test_smtplib.py -@@ -292,6 +292,33 @@ class BadHELOServerTests(unittest.TestCa - HOST, self.port, 'localhost', 3) - - -+@unittest.skipUnless(threading, 'Threading required for this test.') -+class TooLongLineTests(unittest.TestCase): -+ respdata = '250 OK' + ('.' * smtplib._MAXLINE * 2) + '\n' -+ -+ def setUp(self): -+ self.old_stdout = sys.stdout -+ self.output = StringIO.StringIO() -+ sys.stdout = self.output -+ -+ self.evt = threading.Event() -+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -+ self.sock.settimeout(15) -+ self.port = test_support.bind_port(self.sock) -+ servargs = (self.evt, self.respdata, self.sock) -+ threading.Thread(target=server, args=servargs).start() -+ self.evt.wait() -+ self.evt.clear() -+ -+ def tearDown(self): -+ self.evt.wait() -+ sys.stdout = self.old_stdout -+ -+ def testLineTooLong(self): -+ self.assertRaises(smtplib.SMTPResponseException, smtplib.SMTP, -+ HOST, self.port, 'localhost', 3) -+ -+ - sim_users = {'Mr.A@somewhere.com':'John A', - 'Ms.B@somewhere.com':'Sally B', - 'Mrs.C@somewhereesle.com':'Ruth C', -@@ -526,7 +553,8 @@ class SMTPSimTests(unittest.TestCase): - def test_main(verbose=None): - test_support.run_unittest(GeneralTests, DebuggingServerTests, - NonConnectingTests, -- BadHELOServerTests, SMTPSimTests) -+ BadHELOServerTests, SMTPSimTests, -+ TooLongLineTests) - - if __name__ == '__main__': - test_main() - -diff --git a/Lib/httplib.py b/Lib/httplib.py ---- a/Lib/httplib.py -+++ b/Lib/httplib.py -@@ -211,6 +211,10 @@ responses = { - # maximal line length when calling readline(). - _MAXLINE = 65536 - -+# maximum amount of headers accepted -+_MAXHEADERS = 100 -+ -+ - class HTTPMessage(mimetools.Message): - - def addheader(self, key, value): -@@ -267,6 +271,8 @@ class HTTPMessage(mimetools.Message): - elif self.seekable: - tell = self.fp.tell - while True: -+ if len(hlist) > _MAXHEADERS: -+ raise HTTPException("got more than %d headers" % _MAXHEADERS) - if tell: - try: - startofline = tell() - -diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py ---- a/Lib/test/test_httplib.py -+++ b/Lib/test/test_httplib.py -@@ -152,6 +152,13 @@ class BasicTest(TestCase): - if resp.read() != "": - self.fail("Did not expect response from HEAD request") - -+ def test_too_many_headers(self): -+ headers = '\r\n'.join('Header%d: foo' % i for i in xrange(200)) + '\r\n' -+ text = ('HTTP/1.1 200 OK\r\n' + headers) -+ s = FakeSocket(text) -+ r = httplib.HTTPResponse(s) -+ self.assertRaises(httplib.HTTPException, r.begin) -+ - def test_send_file(self): - expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \ - 'Accept-Encoding: identity\r\nContent-Length:' diff --git a/SOURCES/python-2.5.1-plural-fix.patch b/SOURCES/python-2.5.1-plural-fix.patch index 040adaf..5002cb2 100644 --- a/SOURCES/python-2.5.1-plural-fix.patch +++ b/SOURCES/python-2.5.1-plural-fix.patch @@ -7,6 +7,6 @@ diff -up Python-2.5.1/Lib/gettext.py.plural Python-2.5.1/Lib/gettext.py continue + if item.startswith("#"): + continue + k = v = None if ':' in item: k, v = item.split(':', 1) - k = k.strip().lower() diff --git a/SOURCES/python-2.7.3-debug-build.patch b/SOURCES/python-2.7.3-debug-build.patch index ee0b2a2..b7ba7ba 100644 --- a/SOURCES/python-2.7.3-debug-build.patch +++ b/SOURCES/python-2.7.3-debug-build.patch @@ -1,19 +1,40 @@ -diff -up Python-2.7.6/Lib/distutils/command/build_ext.py.debug-build Python-2.7.6/Lib/distutils/command/build_ext.py ---- Python-2.7.6/Lib/distutils/command/build_ext.py.debug-build 2013-11-10 08:36:40.000000000 +0100 -+++ Python-2.7.6/Lib/distutils/command/build_ext.py 2014-01-29 14:13:08.815888533 +0100 -@@ -674,7 +674,10 @@ class build_ext (Command): +From 898f93aa206e577dfe854c59bc62d0cea09cd5ed Mon Sep 17 00:00:00 2001 +From: Tomas Orsava +Date: Tue, 10 Jan 2017 16:19:50 +0100 +Subject: [PATCH] Patch to support building both optimized vs debug stacks DSO + ABIs, + +sharing the same .py and .pyc files, using "_d.so" to signify a debug build of +an extension module. +--- + Lib/distutils/command/build_ext.py | 7 ++++- + Lib/distutils/sysconfig.py | 5 ++-- + Lib/distutils/tests/test_install.py | 3 +- + Makefile.pre.in | 56 ++++++++++++++++++++----------------- + Misc/python-config.in | 2 +- + Modules/makesetup | 2 +- + Python/dynload_shlib.c | 11 ++++++-- + Python/sysmodule.c | 6 ++++ + configure.ac | 14 ++++++++-- + 9 files changed, 69 insertions(+), 37 deletions(-) + +diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py +index 2c68be3..029d144 100644 +--- a/Lib/distutils/command/build_ext.py ++++ b/Lib/distutils/command/build_ext.py +@@ -677,7 +677,10 @@ class build_ext (Command): so_ext = get_config_var('SO') if os.name == 'nt' and self.debug: return os.path.join(*ext_path) + '_d' + so_ext - return os.path.join(*ext_path) + so_ext -+ ++ + # Similarly, extensions in debug mode are named 'module_d.so', to + # avoid adding the _d to the SO config variable: + return os.path.join(*ext_path) + (sys.pydebug and "_d" or "") + so_ext def get_export_symbols (self, ext): """Return the list of symbols that a shared extension has to -@@ -759,6 +762,8 @@ class build_ext (Command): +@@ -762,6 +765,8 @@ class build_ext (Command): template = "python%d.%d" pythonlib = (template % (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) @@ -22,20 +43,21 @@ diff -up Python-2.7.6/Lib/distutils/command/build_ext.py.debug-build Python-2.7. return ext.libraries + [pythonlib] else: return ext.libraries -diff -up Python-2.7.6/Lib/distutils/sysconfig.py.debug-build Python-2.7.6/Lib/distutils/sysconfig.py ---- Python-2.7.6/Lib/distutils/sysconfig.py.debug-build 2014-01-29 14:13:08.770891379 +0100 -+++ Python-2.7.6/Lib/distutils/sysconfig.py 2014-01-29 14:13:08.815888533 +0100 -@@ -90,7 +90,8 @@ def get_python_inc(plat_specific=0, pref +diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py +index 3e7f077..ec5d584 100644 +--- a/Lib/distutils/sysconfig.py ++++ b/Lib/distutils/sysconfig.py +@@ -90,7 +90,8 @@ def get_python_inc(plat_specific=0, prefix=None): # Include is located in the srcdir inc_dir = os.path.join(srcdir, "Include") return inc_dir - return os.path.join(prefix, "include", "python" + get_python_version()) + return os.path.join(prefix, "include", -+ "python" + get_python_version() + (sys.pydebug and '-debug' or '')) ++ "python" + get_python_version() + (sys.pydebug and '-debug' or '')) elif os.name == "nt": return os.path.join(prefix, "include") elif os.name == "os2": -@@ -247,7 +248,7 @@ def get_makefile_filename(): +@@ -248,7 +249,7 @@ def get_makefile_filename(): if python_build: return os.path.join(project_base, "Makefile") lib_dir = get_python_lib(plat_specific=1, standard_lib=1) @@ -44,9 +66,10 @@ diff -up Python-2.7.6/Lib/distutils/sysconfig.py.debug-build Python-2.7.6/Lib/di def parse_config_h(fp, g=None): -diff -up Python-2.7.6/Lib/distutils/tests/test_install.py.debug-build Python-2.7.6/Lib/distutils/tests/test_install.py ---- Python-2.7.6/Lib/distutils/tests/test_install.py.debug-build 2014-01-29 14:13:08.779890810 +0100 -+++ Python-2.7.6/Lib/distutils/tests/test_install.py 2014-01-29 14:13:08.815888533 +0100 +diff --git a/Lib/distutils/tests/test_install.py b/Lib/distutils/tests/test_install.py +index 78fac46..d1d0931 100644 +--- a/Lib/distutils/tests/test_install.py ++++ b/Lib/distutils/tests/test_install.py @@ -20,8 +20,9 @@ from distutils.tests import support @@ -54,14 +77,15 @@ diff -up Python-2.7.6/Lib/distutils/tests/test_install.py.debug-build Python-2.7 - if os.name == 'nt' and sys.executable.endswith('_d.exe'): + if sys.pydebug: modname += '_d' -+ ++ return modname + sysconfig.get_config_var('SO') -diff -up Python-2.7.6/Makefile.pre.in.debug-build Python-2.7.6/Makefile.pre.in ---- Python-2.7.6/Makefile.pre.in.debug-build 2014-01-29 14:13:08.800889482 +0100 -+++ Python-2.7.6/Makefile.pre.in 2014-01-29 14:17:30.929316462 +0100 -@@ -111,8 +111,8 @@ SCRIPTDIR= $(prefix)/lib64 +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 997a2fc..467e782 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -116,8 +116,8 @@ SCRIPTDIR= $(prefix)/lib64 # Detailed destination directories BINLIBDEST= $(LIBDIR)/python$(VERSION) LIBDEST= $(SCRIPTDIR)/python$(VERSION) @@ -72,7 +96,7 @@ diff -up Python-2.7.6/Makefile.pre.in.debug-build Python-2.7.6/Makefile.pre.in LIBP= $(LIBDIR)/python$(VERSION) # Symbols used for using shared libraries -@@ -126,6 +126,12 @@ DESTSHARED= $(BINLIBDEST)/lib-dynload +@@ -131,6 +131,12 @@ DESTSHARED= $(BINLIBDEST)/lib-dynload EXE= @EXEEXT@ BUILDEXE= @BUILDEXEEXT@ @@ -85,7 +109,7 @@ diff -up Python-2.7.6/Makefile.pre.in.debug-build Python-2.7.6/Makefile.pre.in # Short name and location for Mac OS X Python framework UNIVERSALSDK=@UNIVERSALSDK@ PYTHONFRAMEWORK= @PYTHONFRAMEWORK@ -@@ -189,8 +195,8 @@ LIBOBJDIR= Python/ +@@ -197,8 +203,8 @@ LIBOBJDIR= Python/ LIBOBJS= @LIBOBJS@ UNICODE_OBJS= @UNICODE_OBJS@ @@ -96,7 +120,7 @@ diff -up Python-2.7.6/Makefile.pre.in.debug-build Python-2.7.6/Makefile.pre.in PYTHON_FOR_BUILD=@PYTHON_FOR_BUILD@ _PYTHON_HOST_PLATFORM=@_PYTHON_HOST_PLATFORM@ -@@ -464,7 +470,7 @@ sharedmods: $(BUILDPYTHON) pybuilddir.tx +@@ -547,7 +553,7 @@ sharedmods: $(BUILDPYTHON) pybuilddir.txt Modules/_math.o _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build @@ -105,7 +129,7 @@ diff -up Python-2.7.6/Makefile.pre.in.debug-build Python-2.7.6/Makefile.pre.in if test $(INSTSONAME) != $(LDLIBRARY); then \ $(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ $(LN) -f $(INSTSONAME) $@; \ -@@ -856,18 +862,18 @@ bininstall: altbininstall +@@ -954,18 +960,18 @@ bininstall: altbininstall then rm -f $(DESTDIR)$(BINDIR)/$(PYTHON); \ else true; \ fi @@ -135,7 +159,7 @@ diff -up Python-2.7.6/Makefile.pre.in.debug-build Python-2.7.6/Makefile.pre.in # Install the interpreter with $(VERSION) affixed # This goes into $(exec_prefix) -@@ -880,7 +886,7 @@ altbininstall: $(BUILDPYTHON) +@@ -978,7 +984,7 @@ altbininstall: $(BUILDPYTHON) else true; \ fi; \ done @@ -144,7 +168,7 @@ diff -up Python-2.7.6/Makefile.pre.in.debug-build Python-2.7.6/Makefile.pre.in if test -f $(LDLIBRARY); then \ if test -n "$(DLLLIBRARY)" ; then \ $(INSTALL_SHARED) $(DLLLIBRARY) $(DESTDIR)$(BINDIR); \ -@@ -1046,10 +1052,11 @@ $(srcdir)/Lib/$(PLATDIR): +@@ -1148,10 +1154,11 @@ $(srcdir)/Lib/$(PLATDIR): fi; \ cd $(srcdir)/Lib/$(PLATDIR); $(RUNSHARED) ./regen @@ -154,11 +178,11 @@ diff -up Python-2.7.6/Makefile.pre.in.debug-build Python-2.7.6/Makefile.pre.in # is not available in configure - sed -e "s,@EXENAME@,$(BINDIR)/python$(VERSION)$(EXE)," < $(srcdir)/Misc/python-config.in >python-config + sed -e "s,@EXENAME@,$(BINDIR)/python$(VERSION)$(DEBUG_SUFFIX)$(EXE)," < $(srcdir)/Misc/python-config.in >python$(DEBUG_SUFFIX)-config -+ ++ # Install the include files INCLDIRSTOMAKE=$(INCLUDEDIR) $(CONFINCLUDEDIR) $(INCLUDEPY) $(CONFINCLUDEPY) -@@ -1070,13 +1077,13 @@ inclinstall: +@@ -1172,13 +1179,13 @@ inclinstall: $(INSTALL_DATA) pyconfig.h $(DESTDIR)$(CONFINCLUDEPY)/pyconfig.h # Install the library and miscellaneous stuff needed for extending/embedding @@ -175,7 +199,7 @@ diff -up Python-2.7.6/Makefile.pre.in.debug-build Python-2.7.6/Makefile.pre.in @for i in $(LIBDIR) $(LIBP) $(LIBPL) $(LIBPC); \ do \ if test ! -d $(DESTDIR)$$i; then \ -@@ -1092,11 +1099,10 @@ libainstall: all python-config +@@ -1194,11 +1201,10 @@ libainstall: all python-config $(INSTALL_DATA) Modules/Setup $(DESTDIR)$(LIBPL)/Setup $(INSTALL_DATA) Modules/Setup.local $(DESTDIR)$(LIBPL)/Setup.local $(INSTALL_DATA) Modules/Setup.config $(DESTDIR)$(LIBPL)/Setup.config @@ -189,21 +213,23 @@ diff -up Python-2.7.6/Makefile.pre.in.debug-build Python-2.7.6/Makefile.pre.in @if [ -s Modules/python.exp -a \ "`echo $(MACHDEP) | sed 's/^\(...\).*/\1/'`" = "aix" ]; then \ echo; echo "Installing support files for building shared extension modules on AIX:"; \ -diff -up Python-2.7.6/Misc/python-config.in.debug-build Python-2.7.6/Misc/python-config.in ---- Python-2.7.6/Misc/python-config.in.debug-build 2013-11-10 08:36:41.000000000 +0100 -+++ Python-2.7.6/Misc/python-config.in 2014-01-29 14:13:08.816888470 +0100 -@@ -45,7 +45,7 @@ for opt in opt_flags: +diff --git a/Misc/python-config.in b/Misc/python-config.in +index a09e07c..c1691ef 100644 +--- a/Misc/python-config.in ++++ b/Misc/python-config.in +@@ -44,7 +44,7 @@ for opt in opt_flags: + print ' '.join(flags) elif opt in ('--libs', '--ldflags'): - libs = getvar('LIBS').split() + getvar('SYSLIBS').split() -- libs.append('-lpython'+pyver) -+ libs.append('-lpython' + pyver + (sys.pydebug and "_d" or "")) +- libs = ['-lpython' + pyver] ++ libs = ['-lpython' + pyver + (sys.pydebug and "_d" or "")] + libs += getvar('LIBS').split() + libs += getvar('SYSLIBS').split() # add the prefix/lib/pythonX.Y/config dir, but only if there is no - # shared library in prefix/lib/. - if opt == '--ldflags': -diff -up Python-2.7.6/Modules/makesetup.debug-build Python-2.7.6/Modules/makesetup ---- Python-2.7.6/Modules/makesetup.debug-build 2013-11-10 08:36:41.000000000 +0100 -+++ Python-2.7.6/Modules/makesetup 2014-01-29 14:13:08.817888407 +0100 +diff --git a/Modules/makesetup b/Modules/makesetup +index 1bffcbf..f0bc743 100755 +--- a/Modules/makesetup ++++ b/Modules/makesetup @@ -233,7 +233,7 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' | *$mod.o*) base=$mod;; *) base=${mod}module;; @@ -213,10 +239,11 @@ diff -up Python-2.7.6/Modules/makesetup.debug-build Python-2.7.6/Modules/makeset case $doconfig in no) SHAREDMODS="$SHAREDMODS $file";; esac -diff -up Python-2.7.6/Python/dynload_shlib.c.debug-build Python-2.7.6/Python/dynload_shlib.c ---- Python-2.7.6/Python/dynload_shlib.c.debug-build 2013-11-10 08:36:41.000000000 +0100 -+++ Python-2.7.6/Python/dynload_shlib.c 2014-01-29 14:13:08.817888407 +0100 -@@ -46,11 +46,16 @@ const struct filedescr _PyImport_DynLoad +diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c +index 17ebab1..02a94aa 100644 +--- a/Python/dynload_shlib.c ++++ b/Python/dynload_shlib.c +@@ -46,11 +46,16 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { {"module.exe", "rb", C_EXTENSION}, {"MODULE.EXE", "rb", C_EXTENSION}, #else @@ -236,26 +263,28 @@ diff -up Python-2.7.6/Python/dynload_shlib.c.debug-build Python-2.7.6/Python/dyn {0, 0} }; -diff -up Python-2.7.6/Python/sysmodule.c.debug-build Python-2.7.6/Python/sysmodule.c ---- Python-2.7.6/Python/sysmodule.c.debug-build 2013-11-10 08:36:41.000000000 +0100 -+++ Python-2.7.6/Python/sysmodule.c 2014-01-29 14:13:08.817888407 +0100 -@@ -1506,6 +1506,12 @@ _PySys_Init(void) +diff --git a/Python/sysmodule.c b/Python/sysmodule.c +index aeff38a..183e3cc 100644 +--- a/Python/sysmodule.c ++++ b/Python/sysmodule.c +@@ -1524,6 +1524,12 @@ _PySys_Init(void) PyString_FromString("legacy")); #endif +#ifdef Py_DEBUG -+ PyDict_SetItemString(sysdict, "pydebug", Py_True); ++ PyDict_SetItemString(sysdict, "pydebug", Py_True); +#else -+ PyDict_SetItemString(sysdict, "pydebug", Py_False); ++ PyDict_SetItemString(sysdict, "pydebug", Py_False); +#endif + #undef SET_SYS_FROM_STRING if (PyErr_Occurred()) return NULL; -diff -up Python-2.7.6/configure.ac.debug-build Python-2.7.6/configure.ac ---- Python-2.7.6/configure.ac.debug-build 2014-01-29 14:13:08.796889735 +0100 -+++ Python-2.7.6/configure.ac 2014-01-29 14:13:08.814888597 +0100 -@@ -738,7 +738,7 @@ AC_SUBST(LIBRARY) +diff --git a/configure.ac b/configure.ac +index 0a902c7..5caedb7 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -764,7 +764,7 @@ AC_SUBST(LIBRARY) AC_MSG_CHECKING(LIBRARY) if test -z "$LIBRARY" then @@ -264,7 +293,7 @@ diff -up Python-2.7.6/configure.ac.debug-build Python-2.7.6/configure.ac fi AC_MSG_RESULT($LIBRARY) -@@ -884,8 +884,8 @@ if test $enable_shared = "yes"; then +@@ -910,8 +910,8 @@ if test $enable_shared = "yes"; then INSTSONAME="$LDLIBRARY".$SOVERSION ;; Linux*|GNU*|NetBSD*|FreeBSD*|DragonFly*|OpenBSD*) @@ -275,7 +304,7 @@ diff -up Python-2.7.6/configure.ac.debug-build Python-2.7.6/configure.ac RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} case $ac_sys_system in FreeBSD*) -@@ -1028,6 +1028,14 @@ else AC_MSG_RESULT(no); Py_DEBUG='false' +@@ -1040,6 +1040,14 @@ else AC_MSG_RESULT(no); Py_DEBUG='false' fi], [AC_MSG_RESULT(no)]) @@ -290,3 +319,6 @@ diff -up Python-2.7.6/configure.ac.debug-build Python-2.7.6/configure.ac # XXX Shouldn't the code above that fiddles with BASECFLAGS and OPT be # merged with this chunk of code? +-- +2.11.0 + diff --git a/SOURCES/python-2.7.3-lib64.patch b/SOURCES/python-2.7.3-lib64.patch index 678d916..48fa9eb 100644 --- a/SOURCES/python-2.7.3-lib64.patch +++ b/SOURCES/python-2.7.3-lib64.patch @@ -1,6 +1,24 @@ -diff -up Python-2.7.6/Lib/distutils/command/install.py.lib64 Python-2.7.6/Lib/distutils/command/install.py ---- Python-2.7.6/Lib/distutils/command/install.py.lib64 2013-11-10 08:36:40.000000000 +0100 -+++ Python-2.7.6/Lib/distutils/command/install.py 2014-01-29 13:51:19.779590378 +0100 +From 0708de697e2e905387e969134fb4d832c769d9d8 Mon Sep 17 00:00:00 2001 +From: Tomas Orsava +Date: Tue, 10 Jan 2017 11:37:03 +0100 +Subject: [PATCH] Fixup various paths throughout the build and in distutils + from "lib" to "lib64" + +--- + Lib/distutils/command/install.py | 4 ++-- + Lib/distutils/sysconfig.py | 6 +++++- + Lib/site.py | 4 ++++ + Lib/test/test_site.py | 11 +++++++---- + Makefile.pre.in | 2 +- + Modules/Setup.dist | 4 ++-- + Modules/getpath.c | 6 +++--- + setup.py | 10 +++++----- + 8 files changed, 29 insertions(+), 18 deletions(-) + +diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py +index b9f1c6c..7b23714 100644 +--- a/Lib/distutils/command/install.py ++++ b/Lib/distutils/command/install.py @@ -42,14 +42,14 @@ else: INSTALL_SCHEMES = { 'unix_prefix': { @@ -18,10 +36,11 @@ diff -up Python-2.7.6/Lib/distutils/command/install.py.lib64 Python-2.7.6/Lib/di 'headers': '$base/include/python/$dist_name', 'scripts': '$base/bin', 'data' : '$base', -diff -up Python-2.7.6/Lib/distutils/sysconfig.py.lib64 Python-2.7.6/Lib/distutils/sysconfig.py ---- Python-2.7.6/Lib/distutils/sysconfig.py.lib64 2013-11-10 08:36:40.000000000 +0100 -+++ Python-2.7.6/Lib/distutils/sysconfig.py 2014-01-29 13:51:19.779590378 +0100 -@@ -119,8 +119,12 @@ def get_python_lib(plat_specific=0, stan +diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py +index 068d1ba..3e7f077 100644 +--- a/Lib/distutils/sysconfig.py ++++ b/Lib/distutils/sysconfig.py +@@ -119,8 +119,12 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None): prefix = plat_specific and EXEC_PREFIX or PREFIX if os.name == "posix": @@ -35,9 +54,10 @@ diff -up Python-2.7.6/Lib/distutils/sysconfig.py.lib64 Python-2.7.6/Lib/distutil if standard_lib: return libpython else: -diff -up Python-2.7.6/Lib/site.py.lib64 Python-2.7.6/Lib/site.py ---- Python-2.7.6/Lib/site.py.lib64 2013-11-10 08:36:40.000000000 +0100 -+++ Python-2.7.6/Lib/site.py 2014-01-29 13:51:19.779590378 +0100 +diff --git a/Lib/site.py b/Lib/site.py +index c360802..868b7cb 100644 +--- a/Lib/site.py ++++ b/Lib/site.py @@ -288,12 +288,16 @@ def getsitepackages(): if sys.platform in ('os2emx', 'riscos'): sitepackages.append(os.path.join(prefix, "Lib", "site-packages")) @@ -53,15 +73,16 @@ diff -up Python-2.7.6/Lib/site.py.lib64 Python-2.7.6/Lib/site.py sitepackages.append(prefix) + sitepackages.append(os.path.join(prefix, "lib64", "site-packages")) sitepackages.append(os.path.join(prefix, "lib", "site-packages")) - if sys.platform == "darwin": - # for framework builds *only* we add the standard Apple -diff -up Python-2.7.6/Lib/test/test_site.py.lib64 Python-2.7.6/Lib/test/test_site.py ---- Python-2.7.6/Lib/test/test_site.py.lib64 2013-11-10 08:36:40.000000000 +0100 -+++ Python-2.7.6/Lib/test/test_site.py 2014-01-29 13:51:19.780590315 +0100 -@@ -241,17 +241,20 @@ class HelperFunctionsTests(unittest.Test - self.assertEqual(dirs[2], wanted) + return sitepackages + +diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py +index d9a9324..64dd8e9 100644 +--- a/Lib/test/test_site.py ++++ b/Lib/test/test_site.py +@@ -235,17 +235,20 @@ class HelperFunctionsTests(unittest.TestCase): + self.assertEqual(dirs[0], wanted) elif os.sep == '/': - # OS X non-framwework builds, Linux, FreeBSD, etc + # OS X, Linux, FreeBSD, etc - self.assertEqual(len(dirs), 2) - wanted = os.path.join('xoxo', 'lib', 'python' + sys.version[:3], + self.assertEqual(len(dirs), 3) @@ -83,10 +104,11 @@ diff -up Python-2.7.6/Lib/test/test_site.py.lib64 Python-2.7.6/Lib/test/test_sit self.assertEqual(dirs[1], wanted) class PthFile(object): -diff -up Python-2.7.6/Makefile.pre.in.lib64 Python-2.7.6/Makefile.pre.in ---- Python-2.7.6/Makefile.pre.in.lib64 2014-01-29 13:51:19.773590757 +0100 -+++ Python-2.7.6/Makefile.pre.in 2014-01-29 13:51:19.780590315 +0100 -@@ -106,7 +106,7 @@ LIBDIR= @libdir@ +diff --git a/Makefile.pre.in b/Makefile.pre.in +index c0ad978..997a2fc 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -111,7 +111,7 @@ LIBDIR= @libdir@ MANDIR= @mandir@ INCLUDEDIR= @includedir@ CONFINCLUDEDIR= $(exec_prefix)/include @@ -95,9 +117,10 @@ diff -up Python-2.7.6/Makefile.pre.in.lib64 Python-2.7.6/Makefile.pre.in # Detailed destination directories BINLIBDEST= $(LIBDIR)/python$(VERSION) -diff -up Python-2.7.6/Modules/Setup.dist.lib64 Python-2.7.6/Modules/Setup.dist ---- Python-2.7.6/Modules/Setup.dist.lib64 2014-01-29 13:51:19.768591073 +0100 -+++ Python-2.7.6/Modules/Setup.dist 2014-01-29 13:51:19.781590252 +0100 +diff --git a/Modules/Setup.dist b/Modules/Setup.dist +index fbfa1c1..138fb33 100644 +--- a/Modules/Setup.dist ++++ b/Modules/Setup.dist @@ -416,7 +416,7 @@ gdbm gdbmmodule.c -lgdbm # Edit the variables DB and DBLIBVERto point to the db top directory # and the subdirectory of PORT where you built it. @@ -116,21 +139,11 @@ diff -up Python-2.7.6/Modules/Setup.dist.lib64 Python-2.7.6/Modules/Setup.dist # Interface to the Expat XML parser # -diff -up Python-2.7.6/Modules/getpath.c.lib64 Python-2.7.6/Modules/getpath.c ---- Python-2.7.6/Modules/getpath.c.lib64 2013-11-10 08:36:41.000000000 +0100 -+++ Python-2.7.6/Modules/getpath.c 2014-01-29 13:51:19.781590252 +0100 -@@ -117,8 +117,8 @@ - #endif - - #ifndef PYTHONPATH --#define PYTHONPATH PREFIX "/lib/python" VERSION ":" \ -- EXEC_PREFIX "/lib/python" VERSION "/lib-dynload" -+#define PYTHONPATH PREFIX "/lib64/python" VERSION ":" \ -+ EXEC_PREFIX "/lib64/python" VERSION "/lib-dynload" - #endif - - #ifndef LANDMARK -@@ -129,7 +129,7 @@ static char prefix[MAXPATHLEN+1]; +diff --git a/Modules/getpath.c b/Modules/getpath.c +index fd33a01..5b0eae6 100644 +--- a/Modules/getpath.c ++++ b/Modules/getpath.c +@@ -108,7 +108,7 @@ static char prefix[MAXPATHLEN+1]; static char exec_prefix[MAXPATHLEN+1]; static char progpath[MAXPATHLEN+1]; static char *module_search_path = NULL; @@ -139,7 +152,7 @@ diff -up Python-2.7.6/Modules/getpath.c.lib64 Python-2.7.6/Modules/getpath.c static void reduce(char *dir) -@@ -543,7 +543,7 @@ calculate_path(void) +@@ -538,7 +538,7 @@ calculate_path(void) } else strncpy(zip_path, PREFIX, MAXPATHLEN); @@ -148,7 +161,7 @@ diff -up Python-2.7.6/Modules/getpath.c.lib64 Python-2.7.6/Modules/getpath.c bufsz = strlen(zip_path); /* Replace "00" with version */ zip_path[bufsz - 6] = VERSION[0]; zip_path[bufsz - 5] = VERSION[2]; -@@ -553,7 +553,7 @@ calculate_path(void) +@@ -548,7 +548,7 @@ calculate_path(void) fprintf(stderr, "Could not find platform dependent libraries \n"); strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN); @@ -157,10 +170,11 @@ diff -up Python-2.7.6/Modules/getpath.c.lib64 Python-2.7.6/Modules/getpath.c } /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */ -diff -up Python-2.7.6/setup.py.lib64 Python-2.7.6/setup.py ---- Python-2.7.6/setup.py.lib64 2013-11-10 08:36:41.000000000 +0100 -+++ Python-2.7.6/setup.py 2014-01-29 13:56:02.713716528 +0100 -@@ -438,7 +438,7 @@ class PyBuildExt(build_ext): +diff --git a/setup.py b/setup.py +index 75d63b7..9fe7634 100644 +--- a/setup.py ++++ b/setup.py +@@ -456,7 +456,7 @@ class PyBuildExt(build_ext): def detect_modules(self): # Ensure that /usr/local is always used if not cross_compiling: @@ -169,7 +183,7 @@ diff -up Python-2.7.6/setup.py.lib64 Python-2.7.6/setup.py add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') if cross_compiling: self.add_gcc_paths() -@@ -758,11 +758,11 @@ class PyBuildExt(build_ext): +@@ -782,11 +782,11 @@ class PyBuildExt(build_ext): elif curses_library: readline_libs.append(curses_library) elif self.compiler.find_library_file(lib_dirs + @@ -183,7 +197,7 @@ diff -up Python-2.7.6/setup.py.lib64 Python-2.7.6/setup.py extra_link_args=readline_extra_link_args, libraries=readline_libs) ) else: -@@ -797,8 +797,8 @@ class PyBuildExt(build_ext): +@@ -821,8 +821,8 @@ class PyBuildExt(build_ext): if krb5_h: ssl_incs += krb5_h ssl_libs = find_library_file(self.compiler, 'ssl',lib_dirs, @@ -194,3 +208,6 @@ diff -up Python-2.7.6/setup.py.lib64 Python-2.7.6/setup.py ] ) if (ssl_incs is not None and +-- +2.11.0 + diff --git a/SOURCES/python-2.7rc1-binutils-no-dep.patch b/SOURCES/python-2.7rc1-binutils-no-dep.patch index ee6157c..d551333 100644 --- a/SOURCES/python-2.7rc1-binutils-no-dep.patch +++ b/SOURCES/python-2.7rc1-binutils-no-dep.patch @@ -1,14 +1,33 @@ -diff -up Python-2.7rc1/Lib/ctypes/util.py.binutils-no-dep Python-2.7rc1/Lib/ctypes/util.py ---- Python-2.7rc1/Lib/ctypes/util.py.binutils-no-dep 2010-03-15 09:42:23.000000000 -0400 -+++ Python-2.7rc1/Lib/ctypes/util.py 2010-06-06 05:03:02.155975210 -0400 -@@ -140,7 +140,9 @@ elif os.name == "posix": - dump = f.read() - rv = f.close() - if rv == 10: -- raise OSError, 'objdump command not found' +From f188693ef57719c02a9d6927272737fbfb633e4e Mon Sep 17 00:00:00 2001 +From: Tomas Orsava +Date: Tue, 10 Jan 2017 15:43:51 +0100 +Subject: [PATCH] Avoid using objdump to apparently minimize space requirements + +--- + Lib/ctypes/util.py | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py +index ab10ec5..923d1b7 100644 +--- a/Lib/ctypes/util.py ++++ b/Lib/ctypes/util.py +@@ -140,11 +140,15 @@ elif os.name == "posix": + # assuming GNU binutils / ELF + if not f: + return None +- cmd = 'if ! type objdump >/dev/null 2>&1; then exit; fi;' \ ++ cmd = 'if ! type objdump >/dev/null 2>&1; then exit 10; fi;' \ + 'objdump -p -j .dynamic 2>/dev/null "$1"' + proc = subprocess.Popen((cmd, '_get_soname', f), shell=True, + stdout=subprocess.PIPE) + [dump, _] = proc.communicate() ++ if proc.returncode == 10: + return os.path.basename(f) # This is good for GLibc, I think, + # and a dep on binutils is big (for + # live CDs). - f = os.popen(cmd) - try: - data = f.read() + res = re.search(br'\sSONAME\s+([^\s]+)', dump) + if not res: + return None +-- +2.11.0 + diff --git a/SOURCES/xmlrpc_gzip_27_parameter.patch b/SOURCES/xmlrpc_gzip_27_parameter.patch deleted file mode 100644 index a838c1f..0000000 --- a/SOURCES/xmlrpc_gzip_27_parameter.patch +++ /dev/null @@ -1,88 +0,0 @@ - -# HG changeset patch -# User Benjamin Peterson -# Date 1417828515 18000 -# Node ID d50096708b2d701937e78f525446d729fc28db88 -# Parent 923aac88a3cc76a95d5a04d9d3ece245147a8064 -add a default limit for the amount of data xmlrpclib.gzip_decode will return (closes #16043) - -diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py ---- a/Lib/test/test_xmlrpc.py -+++ b/Lib/test/test_xmlrpc.py -@@ -737,7 +737,7 @@ class GzipServerTestCase(BaseServerTestC - with cm: - p.pow(6, 8) - -- def test_gsip_response(self): -+ def test_gzip_response(self): - t = self.Transport() - p = xmlrpclib.ServerProxy(URL, transport=t) - old = self.requestHandler.encode_threshold -@@ -750,6 +750,23 @@ class GzipServerTestCase(BaseServerTestC - self.requestHandler.encode_threshold = old - self.assertTrue(a>b) - -+ def test_gzip_decode_limit(self): -+ max_gzip_decode = 20 * 1024 * 1024 -+ data = '\0' * max_gzip_decode -+ encoded = xmlrpclib.gzip_encode(data) -+ decoded = xmlrpclib.gzip_decode(encoded) -+ self.assertEqual(len(decoded), max_gzip_decode) -+ -+ data = '\0' * (max_gzip_decode + 1) -+ encoded = xmlrpclib.gzip_encode(data) -+ -+ with self.assertRaisesRegexp(ValueError, -+ "max gzipped payload length exceeded"): -+ xmlrpclib.gzip_decode(encoded) -+ -+ xmlrpclib.gzip_decode(encoded, max_decode=-1) -+ -+ - #Test special attributes of the ServerProxy object - class ServerProxyTestCase(unittest.TestCase): - def setUp(self): -diff --git a/Lib/xmlrpclib.py b/Lib/xmlrpclib.py ---- a/Lib/xmlrpclib.py -+++ b/Lib/xmlrpclib.py -@@ -49,6 +49,7 @@ - # 2003-07-12 gp Correct marshalling of Faults - # 2003-10-31 mvl Add multicall support - # 2004-08-20 mvl Bump minimum supported Python version to 2.1 -+# 2014-12-02 ch/doko Add workaround for gzip bomb vulnerability - # - # Copyright (c) 1999-2002 by Secret Labs AB. - # Copyright (c) 1999-2002 by Fredrik Lundh. -@@ -1165,10 +1166,13 @@ def gzip_encode(data): - # in the HTTP header, as described in RFC 1952 - # - # @param data The encoded data -+# @keyparam max_decode Maximum bytes to decode (20MB default), use negative -+# values for unlimited decoding - # @return the unencoded data - # @raises ValueError if data is not correctly coded. -+# @raises ValueError if max gzipped payload length exceeded - --def gzip_decode(data): -+def gzip_decode(data, max_decode=20971520): - """gzip encoded data -> unencoded data - - Decode data using the gzip content encoding as described in RFC 1952 -@@ -1178,11 +1182,16 @@ def gzip_decode(data): - f = StringIO.StringIO(data) - gzf = gzip.GzipFile(mode="rb", fileobj=f) - try: -- decoded = gzf.read() -+ if max_decode < 0: # no limit -+ decoded = gzf.read() -+ else: -+ decoded = gzf.read(max_decode + 1) - except IOError: - raise ValueError("invalid data") - f.close() - gzf.close() -+ if max_decode >= 0 and len(decoded) > max_decode: -+ raise ValueError("max gzipped payload length exceeded") - return decoded - - ## diff --git a/SPECS/python.spec b/SPECS/python.spec index 9d33b9e..ec9aaba 100644 --- a/SPECS/python.spec +++ b/SPECS/python.spec @@ -8,6 +8,8 @@ # Conditionals and other variables controlling the build # ====================================================== +%global with_rewheel 1 + %{!?__python_ver:%global __python_ver EMPTY} #global __python_ver 27 %global unicode ucs4 @@ -119,8 +121,8 @@ Summary: An interpreted, interactive, object-oriented programming language Name: %{?scl_prefix}%{python} # Remember to also rebase python-docs when changing this: -Version: 2.7.8 -Release: 16%{?dist} +Version: 2.7.13 +Release: 3%{?dist} License: Python Group: Development/Languages %{?scl:Requires: %{scl}-runtime} @@ -175,6 +177,14 @@ BuildRequires: valgrind-devel BuildRequires: zlib-devel +%if 0%{?with_rewheel} +BuildRequires: %{?scl_prefix}python-setuptools +BuildRequires: %{?scl_prefix}python-pip + +Requires: %{?scl_prefix}python-setuptools +Requires: %{?scl_prefix}python-pip +%endif + # ======================= @@ -736,7 +746,11 @@ Patch165: 00165-crypt-module-salt-backport.patch # a frame can't be read from the inferior process (rhbz#912025) # # Not yet sent upstream -Patch166: 00166-fix-fake-repr-in-gdb-hooks.patch +# ----- +# The original issue was a build failure on ARM, as that is no longer the case +# and the patch doesn't apply cleanly, I'm dropping it. However, should the +# issue arise again, the patch can be trivially rebased. +# Patch166: 00166-fix-fake-repr-in-gdb-hooks.patch # 00167 # # Don't run any of the stack navigation tests in test_gdb when Python is @@ -850,7 +864,9 @@ Patch181: 00181-allow-arbitrary-timeout-in-condition-wait.patch # Python recognizes ffi.h only if it contains "#define LIBFFI_H", # but the wrapper doesn't contain that, which makes the build fail # We patch this by also accepting "#define ffi_wrapper_h" -Patch184: 00184-ctypes-should-build-with-libffi-multilib-wrapper.patch +# --- +# Fixed upstream: http://bugs.python.org/issue26661 +# Patch184: 00184-ctypes-should-build-with-libffi-multilib-wrapper.patch # 00185 # # Makes urllib2 honor "no_proxy" enviroment variable for "ftp:" URLs @@ -900,99 +916,114 @@ Patch191: 00191-disable-NOOP.patch # Fix for CVE-2013-1752 # - multiple unbound readline() DoS flaws in python stdlib # rhbz#1046174 -Patch196: CVE-2013-1752.patch +# ----- +# Already upstream +# Patch196: CVE-2013-1752.patch # Fix for CVE-2013-1753 # - XMLRPC library unrestricted decompression of HTTP responses using gzip # enconding # rhbz#1046170 -Patch197: xmlrpc_gzip_27_parameter.patch +# ----- +# Already upstream +# Patch197: xmlrpc_gzip_27_parameter.patch + +# 00198 # +Patch198: 00198-add-rewheel-module.patch # ================== PEP466=========================== # Massive backport of PEP466 and relevant other fixes +# ==================================================== +# REMOVED after rebasing to 2.7.13 as it already contains this PEP # ================rhbz#1111461======================== # 00213 # # Fix %S, %R and %V formats of PyUnicode_FromFormat(). # http://bugs.python.org/issue122023 -Patch213: 00213-pep466-pyunicode_fromformat-fix-formats.patch +# Patch213: 00213-pep466-pyunicode_fromformat-fix-formats.patch # 00214 # # Backport SSL module from Python3 # http://bugs.python.org/issue21308 -Patch214: 00214-pep466-backport-py3-ssl-changes.patch +# Patch214: 00214-pep466-backport-py3-ssl-changes.patch # 00215 # # OpenSSL disabled various ciphers and protocols # we have to reflect it in tests -Patch215: 00215-pep466-reflect-openssl-settings-ssltests.patch +# Patch215: 00215-pep466-reflect-openssl-settings-ssltests.patch # 00216 # # fix load_verify_locations on unicode paths # http://bugs.python.org/issue22244 -Patch216: 00216-pep466-fix-load-verify-locs-unicode.patch +# Patch216: 00216-pep466-fix-load-verify-locs-unicode.patch # 00217 # # backport hashlib changes # http://bugs.python.org/issue21307 -Patch217: 00217-pep466-backport-hashlib-algorithm-consts.patch +# Patch217: 00217-pep466-backport-hashlib-algorithm-consts.patch # 00218 # # update os.urandom # http://bugs.python.org/issue21305 -Patch218: 00218-pep466-backport-urandom-pers-fd.patch +# Patch218: 00218-pep466-backport-urandom-pers-fd.patch # 00219 # # Lib/ssl.py still references _ssl.sslwrap # http://bugs.python.org/issue22523 -Patch219: 00219-pep466-fix-referenced-sslwrap.patch +# Patch219: 00219-pep466-fix-referenced-sslwrap.patch # 00220 # # allow passing cert/ssl information to urllib2.urlopen and httplib.HTTPSConnection -Patch220: 00220-pep466-allow-passing-ssl-urrlib-httplib.patch +# Patch220: 00220-pep466-allow-passing-ssl-urrlib-httplib.patch # 00221 # # Patch214 remove sslwrap from _ssl.c this so we have to reimplement it -Patch221: 00221-pep466-backport-sslwrap-c-ssl.patch +# Patch221: 00221-pep466-backport-sslwrap-c-ssl.patch # 00222 # # test_ssl: fails on recent libressl version with BAD_DH_P_LENGTH # https://bugs.python.org/issue23844 -Patch222: 00222-add-2014-bit-dh-key.patch +# Patch222: 00222-add-2014-bit-dh-key.patch # 00223 # # PEP 476: verify HTTPS certificates by default # http://bugs.python.org/issue22417 # Resolves:rhbz#1219110 -Patch223: 00223-pep476-verify-certs-by-default.patch +# Patch223: 00223-pep476-verify-certs-by-default.patch # 00224 # -# Add switch to toggle global verification on and off -# Resolves:rhbz#1219108 +# Re-add file based configuration to toggle HTTPS verification on and off +# Note: The 'platform_default' is now set to enabled # For more information see PEP493 -Patch224: 00224-pep476-add-toggle-for-cert-verify.patch +# Resolves: rhbz#1417838 and previously rhbz#1219108 +Patch224: 00224-PEP-493-Re-add-file-based-configuration-of-HTTPS-ver.patch # 00227 # # Make load_cert_chain function of SSLContext accept # keyfile which is set to None # Resolves: rhbz#1250611 -Patch227: 00227-accept-none-keyfile-loadcertchain.patch +# Patch227: 00227-accept-none-keyfile-loadcertchain.patch # 00228 # # Backport SSLSocket.version function # Resolves: rhbz#1259421 -Patch228: 00228-backport-ssl-version.patch +# Patch228: 00228-backport-ssl-version.patch # ================== !PEP466 =========================== # 00229 # # Initialize OpenSSL_add_all_digests in _hashlib # Resolves: rhbz#1318319 -Patch229: 00229-fix-hashlib-openssl-init.patch +# ----- +# Already upstream +# Patch229: 00229-fix-hashlib-openssl-init.patch # 00230 # # Adjusted tests to determine existence or lack of SSLv2 support # Resolves: rhbz#1319703 -Patch230: 00230-adjusted-tests-to-determine-if-SSLv2-is-enabled-or-not.patch +# ----- +# Upstream test suite was adjusted and Python now doesn't fail to build without +# this patch, therefore I'm dropping it. +# Patch230: 00230-adjusted-tests-to-determine-if-SSLv2-is-enabled-or-not.patch # 00231 # # Add choices for sort option of cProfile for better output message @@ -1000,35 +1031,40 @@ Patch230: 00230-adjusted-tests-to-determine-if-SSLv2-is-enabled-or-not.patch # Resolves: rhbz#1319655 Patch231: 00231-cprofile-sort-option.patch -# 00231 # +# 00232 # # Fix for iteration over files vith very long lines # http://bugs.python.org/issue22526 # Resolves: rhbz#1329141 -Patch232: 00232-use-Py_ssize_t-for-file-offset-and-length-computations-in-iteration.patch +# ----- +# Already upstream +# Patch232: 00232-use-Py_ssize_t-for-file-offset-and-length-computations-in-iteration.patch # 00237 # # CVE-2016-0772 python: smtplib StartTLS stripping attack # https://bugzilla.redhat.com/show_bug.cgi?id=1303647 -# FIXED UPSTREAM: https://hg.python.org/cpython/rev/b3ce713fb9be # Raise an error when STARTTLS fails # Resolves: rhbz#1346358 -Patch237: 00237-CVE-2016-0772-smtplib.patch +# ----- +# FIXED UPSTREAM: https://hg.python.org/cpython/rev/b3ce713fb9be +# Patch237: 00237-CVE-2016-0772-smtplib.patch # 00238 # # CVE-2016-5699 python: http protocol steam injection attack # https://bugzilla.redhat.com/show_bug.cgi?id=1303699 -# FIXED UPSTREAM: https://hg.python.org/cpython/rev/1c45047c5102 # Disabled HTTP header injections in httplib # Resolves: rhbz#1346358 -Patch238: 00238-CVE-2016-5699-httplib.patch +# ----- +# FIXED UPSTREAM: https://hg.python.org/cpython/rev/1c45047c5102 +# Patch238: 00238-CVE-2016-5699-httplib.patch # 00242 # # HTTPoxy attack (CVE-2016-1000110) # https://httpoxy.org/ -# FIXED UPSTREAM: http://bugs.python.org/issue27568 # Based on a patch by RĂ©mi Rampin # Resolves: rhbz#1359167 -Patch242: 00242-CVE-2016-1000110-httpoxy.patch +# ----- +# FIXED UPSTREAM: http://bugs.python.org/issue27568 +# Patch242: 00242-CVE-2016-1000110-httpoxy.patch # (New patches go here ^^^) # @@ -1379,7 +1415,7 @@ done # 00164: not for python 2 yet %patch165 -p1 mv Modules/cryptmodule.c Modules/_cryptmodule.c -%patch166 -p1 +# 00166: no longer needed %patch167 -p1 %patch168 -p1 %patch169 -p1 @@ -1398,35 +1434,39 @@ mv Modules/cryptmodule.c Modules/_cryptmodule.c # 00182: upstream as of Python 2.7.7 # 00183: upstream as of Python 2.7.7 # 00184: upstream as of Python 2.7.7 -%patch184 -p1 %patch185 -p1 %patch187 -p1 %patch189 -p1 %patch191 -p1 -%patch196 -p1 -%patch197 -p1 - -%patch213 -p1 -%patch214 -p1 -%patch215 -p1 -%patch216 -p1 -%patch217 -p1 -%patch218 -p1 -%patch219 -p1 -%patch220 -p1 -%patch221 -p1 -%patch222 -p1 -%patch223 -p1 +# 00196: upstream as of Python 2.7.9 +# 00197: upstream as of Python 2.7.9 + +%if 0%{with_rewheel} +%patch198 -p1 +%endif + +# 00213: PEP 466 backport, upstream as of 2.7.9 +# 00214: PEP 466 backport, upstream as of 2.7.9 +# 00215: PEP 466 backport, upstream as of 2.7.9 +# 00216: PEP 466 backport, upstream as of 2.7.9 +# 00217: PEP 466 backport, upstream as of 2.7.9 +# 00218: PEP 466 backport, upstream as of 2.7.9 +# 00219: PEP 466 backport, upstream as of 2.7.9 +# 00220: PEP 466 backport, upstream as of 2.7.9 +# 00221: PEP 466 backport, upstream as of 2.7.9 +# 00222: PEP 466 backport, upstream as of 2.7.9 +# 00223: PEP 466 backport, upstream as of 2.7.9 %patch224 -p1 -%patch227 -p1 -%patch228 -p1 -%patch229 -p1 -%patch230 -p1 +# 00227: PEP 466 backport, upstream as of 2.7.9 +# 00228: PEP 466 backport, upstream as of 2.7.9 + +# 00229: upstream +# 00230: no longer needed %patch231 -p1 -%patch232 -p1 -%patch237 -p1 -%patch238 -p1 -%patch242 -p1 +# 00232: upstream +# 00237: upstream +# 00238: upstream +# 00242: upstream # This shouldn't be necesarry, but is right now (2.2a3) find -name "*~" |xargs rm -f @@ -2090,6 +2130,15 @@ rm -fr %{buildroot} %doc systemtap-example.stp pyfuntop.stp %endif +%dir %{pylibdir}/ensurepip/ +%{pylibdir}/ensurepip/*.py* +%exclude %{pylibdir}/ensurepip/_bundled + +%if 0%{?with_rewheel} +%dir %{pylibdir}/ensurepip/rewheel/ +%{pylibdir}/ensurepip/rewheel/*.py* +%endif + %files devel %defattr(-,root,root,-) %{?scl:%{_root_prefix}/lib/rpm/redhat/brp-python-bytecompile-with-scl-python} @@ -2292,6 +2341,23 @@ rm -fr %{buildroot} # ====================================================== %changelog +* Tue Feb 07 2017 Tomas Orsava - 2.7.13-3 +- Reworked and readded patch 224: File based configuration of HTTPS verification +Resolves: rhbz#1417838 + +* Tue Jan 31 2017 Tomas Orsava - 2.7.13-2 +- Rebuilding because some .pyc/.pyo files were not properly generated in the + official build for some reason + +* Mon Jan 09 2017 Tomas Orsava - 2.7.13-1 +- Rebased to Python 2.7.13 +- Removed backport of PEP 466 (Patches 213-228) +- Rebased/rewritten patches 1, 6, 10, 55, 102, 112, 134, 136, 137, 146, 153, + 156, 167, 170, 180, 181, 189, 191 +- Dropped patches 166, 184, 196, 197, 229, 230, 232, 237, 238, 242 +- Added the rewheel module: patch 198 +Resolves: rhbz#1402809 + * Thu Aug 04 2016 Charalampos Stratakis - 2.7.8-16 - Fix for CVE-2016-1000110 HTTPoxy attack Resolves: rhbz#1359167