diff --git a/Lib/ssl.py b/Lib/ssl.py --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -62,8 +62,13 @@ import _ssl # if we can't im from _ssl import OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_INFO, OPENSSL_VERSION from _ssl import _SSLContext, SSLError from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED -from _ssl import (PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, +from _ssl import (PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1) +try: + from _ssl import PROTOCOL_SSLv2 + OPENSSL_NO_SSL2 = False +except ImportError: + OPENSSL_NO_SSL2 = True from _ssl import OP_ALL, OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_TLSv1 from _ssl import RAND_status, RAND_egd, RAND_add from _ssl import ( @@ -555,7 +560,7 @@ def get_protocol_name(protocol_code): return "TLSv1" elif protocol_code == PROTOCOL_SSLv23: return "SSLv23" - elif protocol_code == PROTOCOL_SSLv2: + elif (not OPENSSL_NO_SSL2) and protocol_code == PROTOCOL_SSLv2: return "SSLv2" elif protocol_code == PROTOCOL_SSLv3: return "SSLv3" 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 @@ -21,9 +21,11 @@ import functools ssl = support.import_module("ssl") PROTOCOLS = [ - ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, + ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1 ] +if hasattr(ssl, 'PROTOCOL_SSLv2'): + PROTOCOLS.append(ssl.PROTOCOL_SSLv2) HOST = support.HOST @@ -67,22 +69,25 @@ def no_sslv2_implies_sslv3_hello(): # Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2 def skip_if_broken_ubuntu_ssl(func): - @functools.wraps(func) - def f(*args, **kwargs): - try: - 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', '')): - raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour") - return func(*args, **kwargs) - return f + if hasattr(ssl, 'PROTOCOL_SSLv2'): + @functools.wraps(func) + def f(*args, **kwargs): + try: + 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', '')): + raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour") + return func(*args, **kwargs) + return f + else: + return func class BasicSocketTests(unittest.TestCase): def test_constants(self): - ssl.PROTOCOL_SSLv2 + #ssl.PROTOCOL_SSLv2 ssl.PROTOCOL_SSLv23 ssl.PROTOCOL_SSLv3 ssl.PROTOCOL_TLSv1 @@ -292,7 +297,8 @@ class ContextTests(unittest.TestCase): @skip_if_broken_ubuntu_ssl def test_constructor(self): - ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2) + if hasattr(ssl, 'PROTOCOL_SSLv2'): + ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv2) ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv3) ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) @@ -1186,6 +1192,8 @@ else: 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 support.verbose: @@ -1211,14 +1219,15 @@ else: """Connecting to an SSLv23 server with various client options""" if support.verbose: sys.stdout.write("\n") - try: - try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True) - except (ssl.SSLError, 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)) + if hasattr(ssl, 'PROTOCOL_SSLv2'): + try: + try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True) + except (ssl.SSLError, 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) @@ -1249,7 +1258,8 @@ else: 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_SSLv2, False) + 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) try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False) if no_sslv2_implies_sslv3_hello(): @@ -1265,7 +1275,8 @@ else: 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_SSLv2, False) + 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) diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -63,8 +63,10 @@ enum py_ssl_cert_requirements { }; enum py_ssl_version { +#ifndef OPENSSL_NO_SSL2 PY_SSL_VERSION_SSL2, - PY_SSL_VERSION_SSL3, +#endif + PY_SSL_VERSION_SSL3=1, PY_SSL_VERSION_SSL23, PY_SSL_VERSION_TLS1 }; @@ -1447,8 +1449,10 @@ context_new(PyTypeObject *type, PyObject ctx = SSL_CTX_new(TLSv1_method()); 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 @@ -2107,8 +2111,10 @@ PyInit__ssl(void) PY_SSL_CERT_REQUIRED); /* protocol versions */ +#ifndef OPENSSL_NO_SSL2 PyModule_AddIntConstant(m, "PROTOCOL_SSLv2", PY_SSL_VERSION_SSL2); +#endif PyModule_AddIntConstant(m, "PROTOCOL_SSLv3", PY_SSL_VERSION_SSL3); PyModule_AddIntConstant(m, "PROTOCOL_SSLv23",