cpython: 16c86a6bdbe2 (original) (raw)
--- 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
--- 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):
"""[](#l2.8)
Return a string identifying the protocol version used by the[](#l2.9)
current SSL channel, or None if there is no established channel.[](#l2.10)
"""[](#l2.11)
if self._sslobj is None:[](#l2.12)
return None[](#l2.13)
return self._sslobj.version()[](#l2.14)
+ def wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE,
--- 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()[](#l3.7)
'client_npn_protocol': s.selected_npn_protocol(),[](#l3.8)
'version': s.version(),[](#l3.9) })[](#l3.10) s.close()[](#l3.11) stats['server_npn_protocols'] = server.selected_protocols[](#l3.12)
@@ -1912,6 +1913,13 @@ else: def try_protocol_combo(server_protocol, client_protocol, expect_success, certsreqs=None, server_options=0, client_options=0):
"""[](#l3.17)
Try to SSL-connect using *client_protocol* to *server_protocol*.[](#l3.18)
If *expect_success* is true, assert that the connection succeeds,[](#l3.19)
if it's false, assert that the connection fails.[](#l3.20)
Also, if *expect_success* is a string, assert that it is the protocol[](#l3.21)
version actually used by the connection.[](#l3.22)
"""[](#l3.23) if certsreqs is None:[](#l3.24) certsreqs = ssl.CERT_NONE[](#l3.25) certtype = {[](#l3.26)
@@ -1941,8 +1949,8 @@ else: ctx.load_cert_chain(CERTFILE) ctx.load_verify_locations(CERTFILE) try:
server_params_test(client_context, server_context,[](#l3.31)
chatty=False, connectionchatty=False)[](#l3.32)
stats = server_params_test(client_context, server_context,[](#l3.33)
chatty=False, connectionchatty=False)[](#l3.34) # Protocol mismatch can result in either an SSLError, or a[](#l3.35) # "Connection reset by peer" error.[](#l3.36) except ssl.SSLError:[](#l3.37)
@@ -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[](#l3.42)
and expect_success != stats['version']):[](#l3.43)
raise AssertionError("version mismatch: expected %r, got %r"[](#l3.44)
% (expect_success, stats['version']))[](#l3.45)
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)[](#l3.53)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, 'SSLv3')[](#l3.54) try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True)[](#l3.55)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True)[](#l3.56)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1')[](#l3.57)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)[](#l3.59)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)[](#l3.60) try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_OPTIONAL)[](#l3.61)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)[](#l3.62)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)[](#l3.63)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)[](#l3.65)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)[](#l3.66) try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED)[](#l3.67)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)[](#l3.68)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)[](#l3.69)
# 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)[](#l3.77)
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL)[](#l3.78)
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED)[](#l3.79)
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')[](#l3.80)
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)[](#l3.81)
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)[](#l3.82) if hasattr(ssl, 'PROTOCOL_SSLv2'):[](#l3.83) try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)[](#l3.84) try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False,[](#l3.85)
@@ -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,[](#l3.90)
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, 'SSLv3',[](#l3.91) client_options=ssl.OP_NO_SSLv2)[](#l3.92)
@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)[](#l3.99)
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL)[](#l3.100)
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED)[](#l3.101)
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')[](#l3.102)
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)[](#l3.103)
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)[](#l3.104) if hasattr(ssl, 'PROTOCOL_SSLv2'):[](#l3.105) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)[](#l3.106) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)[](#l3.107)
@@ -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)[](#l3.112)
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')[](#l3.113) if hasattr(ssl, 'PROTOCOL_SSLv2'):[](#l3.114) try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)[](#l3.115) try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)[](#l3.116) try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv23, False,[](#l3.117) client_options=ssl.OP_NO_TLSv1_1)[](#l3.118)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, True)[](#l3.120)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')[](#l3.121) try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)[](#l3.122) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)[](#l3.123)
@@ -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,[](#l3.129)
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',[](#l3.130) server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,[](#l3.131) client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)[](#l3.132) if hasattr(ssl, 'PROTOCOL_SSLv2'):[](#l3.133)
@@ -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)[](#l3.138)
try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2')[](#l3.139) try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1, False)[](#l3.140) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_2, False)[](#l3.141) try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)[](#l3.142)
@@ -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):[](#l3.147)
"""[](#l3.148)
Basic tests for SSLSocket.version().[](#l3.149)
More tests are done in the test_protocol_*() methods.[](#l3.150)
"""[](#l3.151)
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)[](#l3.152)
with ThreadedEchoServer(CERTFILE,[](#l3.153)
ssl_version=ssl.PROTOCOL_TLSv1,[](#l3.154)
chatty=False) as server:[](#l3.155)
with closing(context.wrap_socket(socket.socket())) as s:[](#l3.156)
self.assertIs(s.version(), None)[](#l3.157)
s.connect((HOST, server.port))[](#l3.158)
self.assertEqual(s.version(), "TLSv1")[](#l3.159)
self.assertIs(s.version(), None)[](#l3.160)
+ @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
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -171,6 +171,7 @@ Windows -------
- Issue #22160: The bundled version of OpenSSL has been updated to 1.0.1i. +version in use. What's New in Python 2.7.8?
--- 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) +{
- if (self->ssl == NULL)
Py_RETURN_NONE;[](#l5.12)
- version = SSL_get_version(self->ssl);
- if (!strcmp(version, "unknown"))
Py_RETURN_NONE;[](#l5.15)
- 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},
#ifdef OPENSSL_NPN_NEGOTIATED {"selected_npn_protocol", (PyCFunction)PySSL_selected_npn_protocol, METH_NOARGS}, #endif