diff --git a/Src/IronPython.Modules/_ssl.cs b/Src/IronPython.Modules/_ssl.cs index 7a2b1deeb..45a81be16 100644 --- a/Src/IronPython.Modules/_ssl.cs +++ b/Src/IronPython.Modules/_ssl.cs @@ -109,17 +109,18 @@ public static void RAND_add(object buf, double entropy) { [PythonType] public class _SSLContext { - private readonly X509Certificate2Collection _cert_store = new X509Certificate2Collection(); - private string _cafile; + internal readonly X509Certificate2Collection _cert_store = new X509Certificate2Collection(); + internal string _cafile; private int _verify_mode = SSL_VERIFY_NONE; - public _SSLContext(CodeContext context, int protocol = PROTOCOL_SSLv23) { + public _SSLContext(CodeContext context, int protocol) { if (protocol != PROTOCOL_SSLv2 && protocol != PROTOCOL_SSLv23 && protocol != PROTOCOL_SSLv3 && protocol != PROTOCOL_TLSv1 && protocol != PROTOCOL_TLSv1_1 && protocol != PROTOCOL_TLSv1_2) { throw PythonOps.ValueError("invalid protocol version"); } this.protocol = protocol; + if (protocol != PROTOCOL_SSLv2) options |= OP_NO_SSLv2; if (protocol != PROTOCOL_SSLv3) @@ -175,14 +176,20 @@ public void load_cert_chain(string certfile, string keyfile = null, object passw } - public void load_verify_locations(CodeContext context, string cafile = null, string capath = null, object cadata = null) { + public void load_verify_locations(CodeContext context, object cafile = null, string capath = null, object cadata = null) { if (cafile == null && capath == null && cadata == null) { throw PythonOps.TypeError("cafile, capath and cadata cannot be all omitted"); } - if (cafile != null) { - _cert_store.Add(ReadCertificate(context, cafile)); - _cafile = cafile; + if (cafile is not null) { + if (cafile is string s) { + _cafile = s; + } else if (cafile is Bytes b) { + _cafile = b.MakeString(); + } else { + throw PythonOps.TypeError("cafile should be a valid filesystem path"); + } + _cert_store.Add(ReadCertificate(context, _cafile)); } if (capath != null) { @@ -207,8 +214,8 @@ public void load_verify_locations(CodeContext context, string cafile = null, str } } - public object _wrap_socket(CodeContext context, PythonSocket.socket sock, bool server_side, string server_hostname = null, object ssl_sock = null) { - return new _SSLSocket(context, sock, server_side, null, _cafile, verify_mode, protocol | options, null, _cert_store) { _serverHostName = server_hostname }; + public object _wrap_socket(CodeContext context, PythonSocket.socket sock, bool server_side, string server_hostname = null) { + return new _SSLSocket(context, this, sock, server_side, server_hostname); } } @@ -225,34 +232,22 @@ public class _SSLSocket { private Exception _validationFailure; internal string _serverHostName; - public _SSLSocket(CodeContext context, PythonSocket.socket sock, string keyfile = null, string certfile = null, X509Certificate2Collection certs = null) { - _context = context; - _sslStream = new SslStream(new NetworkStream(sock._socket, false), true, CertValidationCallback); - _socket = sock; - _protocol = PythonSsl.PROTOCOL_SSLv23 | PythonSsl.OP_NO_SSLv2 | PythonSsl.OP_NO_SSLv3; - _validate = false; - _certCollection = certs ?? new X509Certificate2Collection(); - } + public _SSLContext context { get; } - internal _SSLSocket(CodeContext context, - PythonSocket.socket sock, - bool server_side, - string keyfile = null, - string certfile = null, - int certs_mode = PythonSsl.CERT_NONE, - int protocol = (PythonSsl.PROTOCOL_SSLv23 | PythonSsl.OP_NO_SSLv2 | PythonSsl.OP_NO_SSLv3), - string cacertsfile = null, - X509Certificate2Collection certs = null) { + internal _SSLSocket(CodeContext context, _SSLContext sslcontext, PythonSocket.socket sock, bool server_side, string server_hostname) { if (sock == null) { throw PythonOps.TypeError("expected socket object, got None"); } + this.context = sslcontext; _serverSide = server_side; - bool validate; - _certsMode = certs_mode; + _serverHostName = server_hostname; + + _certsMode = sslcontext.verify_mode; + bool validate; RemoteCertificateValidationCallback callback; - switch (certs_mode) { + switch (_certsMode) { case PythonSsl.CERT_NONE: validate = false; callback = CertValidationCallback; @@ -266,28 +261,24 @@ internal _SSLSocket(CodeContext context, callback = CertValidationCallbackRequired; break; default: - throw new InvalidOperationException(String.Format("bad certs_mode: {0}", certs_mode)); + throw new InvalidOperationException(String.Format("bad certs_mode: {0}", _certsMode)); } _callback = callback; - if (certs != null) { - _certCollection = certs; + if (sslcontext._cert_store != null) { + _certCollection = sslcontext._cert_store; } - if (certfile != null) { - _cert = PythonSsl.ReadCertificate(context, certfile); - } - - if (cacertsfile != null) { - _certCollection = new X509Certificate2Collection(new[] { PythonSsl.ReadCertificate(context, cacertsfile) }); + if (sslcontext._cafile != null) { + _cert = PythonSsl.ReadCertificate(context, sslcontext._cafile); } _socket = sock; EnsureSslStream(false); - _protocol = protocol; + _protocol = sslcontext.protocol | sslcontext.options; _validate = validate; _context = context; } @@ -521,7 +512,7 @@ public object peer_certificate(bool binary_form) { if (peerCert != null) { if (binary_form) { - return peerCert.GetRawCertData().MakeString(); + return Bytes.Make(peerCert.GetRawCertData()); } else if (_validate) { return CertificateToPython(_context, peerCert); } @@ -548,24 +539,23 @@ public string issuer() { return String.Empty; } - [Documentation(@"read([len]) -> string - -Read up to len bytes from the SSL socket.")] - public object read(CodeContext/*!*/ context, int len, ByteArray buffer = null) { + [Documentation(@"read(size, [buffer]) +Read up to size bytes from the SSL socket.")] + public object read(CodeContext/*!*/ context, int size, ByteArray buffer = null) { EnsureSslStream(true); try { byte[] buf = new byte[2048]; - MemoryStream result = new MemoryStream(len); + MemoryStream result = new MemoryStream(size); while (true) { - int readLength = (len < buf.Length) ? len : buf.Length; + int readLength = (size < buf.Length) ? size : buf.Length; int bytes = _sslStream.Read(buf, 0, readLength); if (bytes > 0) { result.Write(buf, 0, bytes); - len -= bytes; + size -= bytes; } - if (bytes == 0 || len == 0 || bytes < readLength) { + if (bytes == 0 || size == 0 || bytes < readLength) { var res = result.ToArray(); if (buffer == null) return Bytes.Make(res); @@ -593,10 +583,9 @@ public string server() { return String.Empty; } - [Documentation(@"write(s) -> len + [Documentation(@"Writes the bytes-like object b into the SSL object. -Writes the string s into the SSL object. Returns the number -of bytes written.")] +Returns the number of bytes written.")] public int write(CodeContext/*!*/ context, Bytes data) { EnsureSslStream(true); @@ -1046,8 +1035,10 @@ private static Exception ErrorDecoding(CodeContext context, params object[] args public const int PROTOCOL_TLSv1_1 = 4; public const int PROTOCOL_TLSv1_2 = 5; - public const uint OP_ALL = 0x80000BFF; - public const uint OP_DONT_INSERT_EMPTY_FRAGMENTS = 0x00000800; + public const int OP_ALL = unchecked((int)0x800003FF); + public const int OP_CIPHER_SERVER_PREFERENCE = 0x400000; + public const int OP_SINGLE_DH_USE = 0x100000; + public const int OP_SINGLE_ECDH_USE = 0x80000; public const int OP_NO_SSLv2 = 0x01000000; public const int OP_NO_SSLv3 = 0x02000000; public const int OP_NO_TLSv1 = 0x04000000; diff --git a/Src/IronPythonTest/Cases/CPythonCasesManifest.ini b/Src/IronPythonTest/Cases/CPythonCasesManifest.ini index aa2ed6f05..cb9ecbe58 100644 --- a/Src/IronPythonTest/Cases/CPythonCasesManifest.ini +++ b/Src/IronPythonTest/Cases/CPythonCasesManifest.ini @@ -846,7 +846,7 @@ RunCondition=$(IS_POSIX) [CPython.test_sqlite] Ignore=true -[CPython.test_ssl] +[CPython.test_ssl] # IronPython.test_ssl_stdlib Ignore=true Reason=Blocking diff --git a/Src/StdLib/Lib/test/test_ssl.py b/Src/StdLib/Lib/test/test_ssl.py index 4fdb7f087..3798d1c03 100644 --- a/Src/StdLib/Lib/test/test_ssl.py +++ b/Src/StdLib/Lib/test/test_ssl.py @@ -76,6 +76,7 @@ def handle_error(prefix): sys.stdout.write(prefix + exc_format) def can_clear_options(): + if sys.implementation.name == 'ironpython': return True # 0.9.8m or higher return ssl._OPENSSL_API_VERSION >= (0, 9, 8, 13, 15) @@ -569,7 +570,10 @@ def test_enum_certificates(self): self.assertTrue(ssl.enum_certificates("ROOT")) self.assertRaises(TypeError, ssl.enum_certificates) - self.assertRaises(WindowsError, ssl.enum_certificates, "") + if sys.implementation.name == "ironpython": + self.assertEqual(ssl.enum_certificates(""), []) + else: + self.assertRaises(WindowsError, ssl.enum_certificates, "") trust_oids = set() for storename in ("CA", "ROOT"): diff --git a/Tests/modules/network_related/test__ssl.py b/Tests/modules/network_related/test__ssl.py index 0b6bb3185..e1ea0f3b2 100644 --- a/Tests/modules/network_related/test__ssl.py +++ b/Tests/modules/network_related/test__ssl.py @@ -9,6 +9,7 @@ import _ssl import os import socket +import sys import unittest from iptest import IronPythonTestCase, is_cli, is_netcoreapp, retryOnFailure, run_test, skipUnlessIronPython @@ -27,13 +28,22 @@ def test_constants(self): self.assertEqual(_ssl.CERT_NONE, 0) self.assertEqual(_ssl.CERT_OPTIONAL, 1) self.assertEqual(_ssl.CERT_REQUIRED, 2) - self.assertEqual(_ssl.PROTOCOL_SSLv2, 0) + if sys.version_info >= (3,5): + self.assertRaises(AttributeError, lambda: _ssl.PROTOCOL_SSLv2) + else: + self.assertEqual(_ssl.PROTOCOL_SSLv2, 0) self.assertEqual(_ssl.PROTOCOL_SSLv23, 2) - self.assertEqual(_ssl.PROTOCOL_SSLv3, 1) + if sys.version_info >= (3,7): + self.assertRaises(AttributeError, lambda: _ssl.PROTOCOL_SSLv3) + else: + self.assertEqual(_ssl.PROTOCOL_SSLv3, 1) self.assertEqual(_ssl.PROTOCOL_TLSv1, 3) self.assertEqual(_ssl.PROTOCOL_TLSv1_1, 4) self.assertEqual(_ssl.PROTOCOL_TLSv1_2, 5) - self.assertEqual(_ssl.OP_NO_SSLv2, 0x1000000) + if sys.version_info >= (3,7): + self.assertEqual(_ssl.OP_NO_SSLv2, 0) + else: + self.assertEqual(_ssl.OP_NO_SSLv2, 0x1000000) self.assertEqual(_ssl.OP_NO_SSLv3, 0x2000000) self.assertEqual(_ssl.OP_NO_TLSv1, 0x4000000) self.assertEqual(_ssl.OP_NO_TLSv1_1, 0x10000000) @@ -106,7 +116,8 @@ def test_SSLType_ssl(self): context = _ssl._SSLContext(_ssl.PROTOCOL_SSLv23) ssl_s = context._wrap_socket(s, False) - ssl_s.shutdown() + if is_cli: + ssl_s.shutdown() s.close() #sock, keyfile, certfile @@ -133,6 +144,7 @@ def test_SSLType_ssl_neg(self): #Cleanup s.close() + @skipUnlessIronPython() def test_SSLType_issuer(self): #--Positive s = socket.socket(socket.AF_INET) @@ -165,6 +177,7 @@ def test_SSLType_issuer(self): ssl_s.shutdown() s.close() + @skipUnlessIronPython() def test_SSLType_server(self): #--Positive s = socket.socket(socket.AF_INET) @@ -206,8 +219,12 @@ def test_SSLType_read_and_write(self): ssl_s = context._wrap_socket(s, False) ssl_s.do_handshake() - self.assertIn("Writes the string s into the SSL object.", ssl_s.write.__doc__) - self.assertIn("Read up to len bytes from the SSL socket.", ssl_s.read.__doc__) + if is_cli or sys.version_info >= (3,5): + self.assertIn("Writes the bytes-like object b into the SSL object.", ssl_s.write.__doc__) + self.assertIn("Read up to size bytes from the SSL socket.", ssl_s.read.__doc__) + else: + self.assertIn("Writes the string s into the SSL object.", ssl_s.write.__doc__) + self.assertIn("Read up to len bytes from the SSL socket.", ssl_s.read.__doc__) #Write self.assertEqual(ssl_s.write(SSL_REQUEST), @@ -225,7 +242,8 @@ def test_SSLType_read_and_write(self): self.assertIn(SSL_RESPONSE, response) #Cleanup - ssl_s.shutdown() + if is_cli: + ssl_s.shutdown() s.close() def test_parse_cert(self): diff --git a/Tests/test_socket_stdlib.py b/Tests/test_socket_stdlib.py index 7191abcac..663b098d3 100644 --- a/Tests/test_socket_stdlib.py +++ b/Tests/test_socket_stdlib.py @@ -519,7 +519,7 @@ def load_tests(loader, standard_tests, pattern): suite.addTest(unittest.expectedFailure(test.test_socket.UnbufferedFileObjectClassTestCase('testSmallReadNonBlocking'))) # TODO: figure out suite.addTest(test.test_socket.UnbufferedFileObjectClassTestCase('testUnbufferedRead')) suite.addTest(test.test_socket.UnbufferedFileObjectClassTestCase('testUnbufferedReadline')) - suite.addTest(test.test_socket.UnbufferedFileObjectClassTestCase('testWriteNonBlocking')) + #suite.addTest(test.test_socket.UnbufferedFileObjectClassTestCase('testWriteNonBlocking')) # fails intermittently during CI suite.addTest(test.test_socket.UnicodeReadFileObjectClassTestCase('testAttributes')) suite.addTest(test.test_socket.UnicodeReadFileObjectClassTestCase('testCloseAfterMakefile')) suite.addTest(test.test_socket.UnicodeReadFileObjectClassTestCase('testClosedAttr')) diff --git a/Tests/test_ssl_stdlib.py b/Tests/test_ssl_stdlib.py new file mode 100644 index 000000000..3fd588809 --- /dev/null +++ b/Tests/test_ssl_stdlib.py @@ -0,0 +1,130 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the Apache 2.0 License. +# See the LICENSE file in the project root for more information. + +## +## Run selected tests from test_ssl from StdLib +## + +import unittest +import sys + +from iptest import is_posix, run_test + +import test.test_ssl + +def load_tests(loader, standard_tests, pattern): + if sys.implementation.name == 'ironpython': + suite = unittest.TestSuite() + suite.addTest(test.test_ssl.BasicSocketTests('test_DER_to_PEM')) + suite.addTest(test.test_ssl.BasicSocketTests('test_asn1object')) + suite.addTest(test.test_ssl.BasicSocketTests('test_constants')) + suite.addTest(test.test_ssl.BasicSocketTests('test_dealloc_warn')) + suite.addTest(test.test_ssl.BasicSocketTests('test_enum_certificates')) + suite.addTest(unittest.expectedFailure(test.test_ssl.BasicSocketTests('test_enum_crls'))) # AssertionError: [] is not true + suite.addTest(unittest.expectedFailure(test.test_ssl.BasicSocketTests('test_errors'))) # AssertionError: OSError not raised + suite.addTest(unittest.expectedFailure(test.test_ssl.BasicSocketTests('test_get_default_verify_paths'))) # AttributeError: 'module' object has no attribute 'get_default_verify_paths' + suite.addTest(test.test_ssl.BasicSocketTests('test_match_hostname')) + suite.addTest(test.test_ssl.BasicSocketTests('test_openssl_version')) + suite.addTest(unittest.expectedFailure(test.test_ssl.BasicSocketTests('test_parse_cert'))) # KeyError: OCSP + suite.addTest(unittest.expectedFailure(test.test_ssl.BasicSocketTests('test_parse_cert_CVE_2013_4238'))) # AssertionError: Tuples differ + suite.addTest(unittest.expectedFailure(test.test_ssl.BasicSocketTests('test_parse_cert_CVE_2019_5010'))) # AssertionError + suite.addTest(test.test_ssl.BasicSocketTests('test_purpose_enum')) + suite.addTest(test.test_ssl.BasicSocketTests('test_random')) + suite.addTest(test.test_ssl.BasicSocketTests('test_random_fork')) + suite.addTest(test.test_ssl.BasicSocketTests('test_refcycle')) + suite.addTest(test.test_ssl.BasicSocketTests('test_server_side')) + suite.addTest(unittest.expectedFailure(test.test_ssl.BasicSocketTests('test_timeout'))) # AssertionError: 0.0 != None + suite.addTest(test.test_ssl.BasicSocketTests('test_tls_unique_channel_binding')) + suite.addTest(test.test_ssl.BasicSocketTests('test_unknown_channel_binding')) + suite.addTest(test.test_ssl.BasicSocketTests('test_unsupported_dtls')) + suite.addTest(test.test_ssl.BasicSocketTests('test_wrapped_unconnected')) + suite.addTest(test.test_ssl.ContextTests('test__create_stdlib_context')) + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_cert_store_stats'))) # AttributeError: 'SSLContext' object has no attribute 'cert_store_stats' + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_check_hostname'))) # AssertionError: ValueError not raised + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_ciphers'))) # AssertionError: SSLError not raised + suite.addTest(test.test_ssl.ContextTests('test_constructor')) + suite.addTest(test.test_ssl.ContextTests('test_create_default_context')) + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_get_ca_certs'))) # AttributeError: 'SSLContext' object has no attribute 'get_ca_certs' + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_load_cert_chain'))) # AssertionError: OSError not raised + suite.addTest(test.test_ssl.ContextTests('test_load_default_certs')) + if is_posix: + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_load_default_certs_env'))) # 'SSLContext' object has no attribute 'cert_store_stats' + else: + suite.addTest(test.test_ssl.ContextTests('test_load_default_certs_env')) + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_load_default_certs_env_windows'))) # AttributeError: 'SSLContext' object has no attribute 'cert_store_stats' + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_load_dh_params'))) # AttributeError: 'SSLContext' object has no attribute 'load_dh_params' + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_load_verify_cadata'))) # AttributeError: 'SSLContext' object has no attribute 'cert_store_stats' + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_load_verify_locations'))) # AssertionError: "PEM lib" does not match ... + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_options'))) # AssertionError: -2097150977 != 50331648 + suite.addTest(test.test_ssl.ContextTests('test_protocol')) + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_session_stats'))) # AttributeError: 'SSLContext' object has no attribute 'session_stats' + suite.addTest(test.test_ssl.ContextTests('test_set_default_verify_paths')) + suite.addTest(test.test_ssl.ContextTests('test_set_ecdh_curve')) + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_sni_callback'))) # AttributeError: 'SSLContext' object has no attribute 'set_servername_callback' + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_sni_callback_refcycle'))) # AttributeError: 'SSLContext' object has no attribute 'set_servername_callback' + suite.addTest(test.test_ssl.ContextTests('test_verify_flags')) + suite.addTest(unittest.expectedFailure(test.test_ssl.ContextTests('test_verify_mode'))) # AssertionError: ValueError not raised + suite.addTest(test.test_ssl.NetworkedTests('test_algorithms')) + suite.addTest(unittest.expectedFailure(test.test_ssl.NetworkedTests('test_ciphers'))) # AssertionError: SSLError not raised + suite.addTest(unittest.expectedFailure(test.test_ssl.NetworkedTests('test_connect'))) # AssertionError: {} != None + suite.addTest(unittest.expectedFailure(test.test_ssl.NetworkedTests('test_connect_cadata'))) # ssl.SSLError: [Errno 'errors while validating certificate chain: '] RemoteCertificateChainErrors + suite.addTest(unittest.expectedFailure(test.test_ssl.NetworkedTests('test_connect_capath'))) # ssl.SSLError: [Errno 'errors while validating certificate chain: '] RemoteCertificateChainErrors + suite.addTest(unittest.expectedFailure(test.test_ssl.NetworkedTests('test_connect_ex'))) # ssl.SSLError: [Errno 'errors while validating certificate chain: '] RemoteCertificateChainErrors + #suite.addTest(test.test_ssl.NetworkedTests('test_connect_ex_error')) # slow + suite.addTest(unittest.expectedFailure(test.test_ssl.NetworkedTests('test_connect_with_context'))) # AssertionError: {} != None + suite.addTest(unittest.expectedFailure(test.test_ssl.NetworkedTests('test_context_setget'))) # AttributeError: '_SSLSocket' object has no attribute 'context' + suite.addTest(unittest.expectedFailure(test.test_ssl.NetworkedTests('test_get_ca_certs_capath'))) # AttributeError: 'SSLContext' object has no attribute 'get_ca_certs' + suite.addTest(unittest.expectedFailure(test.test_ssl.NetworkedTests('test_get_server_certificate'))) # ssl.SSLError: [Errno 'errors while validating certificate chain: '] RemoteCertificateNameMismatch, RemoteCertificateChainErrors + if is_posix: + suite.addTest(unittest.expectedFailure(test.test_ssl.NetworkedTests('test_makefile_close'))) # OSError: [Errno 9] Bad file descriptor + else: + suite.addTest(test.test_ssl.NetworkedTests('test_makefile_close')) + suite.addTest(unittest.expectedFailure(test.test_ssl.NetworkedTests('test_non_blocking_connect_ex'))) # OSError: [Errno -2146232800] The operation is not allowed on a non-blocking Socket. + suite.addTest(unittest.expectedFailure(test.test_ssl.NetworkedTests('test_non_blocking_handshake'))) # TypeError: Value cannot be null. + suite.addTest(test.test_ssl.NetworkedTests('test_timeout_connect_ex')) + suite.addTest(unittest.expectedFailure(test.test_ssl.SSLErrorTests('test_lib_reason'))) # AttributeError: 'SSLContext' object has no attribute 'load_dh_params' + suite.addTest(unittest.expectedFailure(test.test_ssl.SSLErrorTests('test_str'))) # AssertionError: '[Errno 1] foo' != 'foo' + #suite.addTest(unittest.expectedFailure(test.test_ssl.SSLErrorTests('test_subclass'))) # blocking + #suite.addTest(test.test_ssl.ThreadedTests('test_asyncore_server')) + #suite.addTest(test.test_ssl.ThreadedTests('test_check_hostname')) + #suite.addTest(test.test_ssl.ThreadedTests('test_compression')) + #suite.addTest(test.test_ssl.ThreadedTests('test_compression_disabled')) + #suite.addTest(test.test_ssl.ThreadedTests('test_crl_check')) + #suite.addTest(test.test_ssl.ThreadedTests('test_default_ciphers')) + #suite.addTest(test.test_ssl.ThreadedTests('test_default_ecdh_curve')) + #suite.addTest(test.test_ssl.ThreadedTests('test_dh_params')) + #suite.addTest(test.test_ssl.ThreadedTests('test_do_handshake_enotconn')) + #suite.addTest(test.test_ssl.ThreadedTests('test_echo')) + #suite.addTest(test.test_ssl.ThreadedTests('test_empty_cert')) + #suite.addTest(test.test_ssl.ThreadedTests('test_getpeercert')) + #suite.addTest(test.test_ssl.ThreadedTests('test_getpeercert_enotconn')) + #suite.addTest(test.test_ssl.ThreadedTests('test_handshake_timeout')) + #suite.addTest(test.test_ssl.ThreadedTests('test_malformed_cert')) + #suite.addTest(test.test_ssl.ThreadedTests('test_malformed_key')) + #suite.addTest(test.test_ssl.ThreadedTests('test_nonexisting_cert')) + #suite.addTest(test.test_ssl.ThreadedTests('test_npn_protocols')) + #suite.addTest(test.test_ssl.ThreadedTests('test_protocol_sslv2')) + #suite.addTest(test.test_ssl.ThreadedTests('test_protocol_sslv23')) + #suite.addTest(test.test_ssl.ThreadedTests('test_protocol_sslv3')) + #suite.addTest(test.test_ssl.ThreadedTests('test_protocol_tlsv1')) + #suite.addTest(test.test_ssl.ThreadedTests('test_protocol_tlsv1_1')) + #suite.addTest(test.test_ssl.ThreadedTests('test_protocol_tlsv1_2')) + #suite.addTest(test.test_ssl.ThreadedTests('test_read_write_after_close_raises_valuerror')) + #suite.addTest(test.test_ssl.ThreadedTests('test_recv_send')) + #suite.addTest(test.test_ssl.ThreadedTests('test_rude_shutdown')) + #suite.addTest(test.test_ssl.ThreadedTests('test_selected_npn_protocol')) + #suite.addTest(test.test_ssl.ThreadedTests('test_server_accept')) + #suite.addTest(test.test_ssl.ThreadedTests('test_sni_callback')) + #suite.addTest(test.test_ssl.ThreadedTests('test_sni_callback_alert')) + #suite.addTest(test.test_ssl.ThreadedTests('test_sni_callback_raising')) + #suite.addTest(test.test_ssl.ThreadedTests('test_sni_callback_wrong_return_type')) + #suite.addTest(test.test_ssl.ThreadedTests('test_socketserver')) + #suite.addTest(test.test_ssl.ThreadedTests('test_starttls')) + #suite.addTest(test.test_ssl.ThreadedTests('test_tls_unique_channel_binding')) + return suite + + else: + return loader.loadTestsFromModule(test.test_ssl, pattern) + +run_test(__name__)