From 5c89b4ec55bc7ebe799da296e01544a5bcdc4250 Mon Sep 17 00:00:00 2001
From: Antoine Pitrou <solipsis@pitrou.net>
Date: Sun, 11 Nov 2012 01:25:36 +0100
Subject: Issue #16357: fix calling accept() on a SSLSocket created through
 SSLContext.wrap_socket(). Original patch by Jeff McNeil.

---
 Lib/ssl.py           | 15 +++++----------
 Lib/test/test_ssl.py | 36 ++++++++++++++++++++++++++++++++++++
 Misc/NEWS            |  3 +++
 3 files changed, 44 insertions(+), 10 deletions(-)

diff --git a/Lib/ssl.py b/Lib/ssl.py
index 8137231..e901b64 100644
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -491,16 +491,11 @@ class SSLSocket(socket):
         SSL channel, and the address of the remote client."""
 
         newsock, addr = socket.accept(self)
-        return (SSLSocket(sock=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),
-                addr)
+        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 __del__(self):
         # sys.stderr.write("__del__ on %s\n" % repr(self))
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index d4c5e63..2f0b3e6 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -1610,6 +1610,42 @@ 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():
+                nonlocal remote, peer
+                server.listen(5)
+                # Block on the accept and wait on the connection to close.
+                evt.set()
+                remote, peer = server.accept()
+                remote.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()
+            # Sanity checks.
+            self.assertIsInstance(remote, ssl.SSLSocket)
+            self.assertEqual(peer, client_addr)
+
         def test_default_ciphers(self):
             context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
             try:
diff --git a/Misc/NEWS b/Misc/NEWS
index 6cfa567..b035e24 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -159,6 +159,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #16357: fix calling accept() on a SSLSocket created through
+  SSLContext.wrap_socket().  Original patch by Jeff McNeil.
+
 - Issue #16350: zlib.Decompress.decompress() now accumulates data from
   successive calls after EOF in unused_data, instead of only saving the argument
   to the last call. Patch by Serhiy Storchaka.
-- 
cgit v0.12

