[Python-checkins] r80453 - in python/branches/release26-maint: Lib/ssl.py Lib/test/test_ssl.py Misc/NEWS Modules/_ssl.c
antoine.pitrou
python-checkins at python.org
Sat Apr 24 22:13:37 CEST 2010
Author: antoine.pitrou
Date: Sat Apr 24 22:13:37 2010
New Revision: 80453
Log:
Merged revisions 80451-80452 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r80451 | antoine.pitrou | 2010-04-24 21:57:01 +0200 (sam., 24 avril 2010) | 4 lines
The do_handshake() method of SSL objects now adjusts the blocking mode of
the SSL structure if necessary (as other methods already do).
........
r80452 | antoine.pitrou | 2010-04-24 22:04:58 +0200 (sam., 24 avril 2010) | 4 lines
Issue #5103: SSL handshake would ignore the socket timeout and block
indefinitely if the other end didn't respond.
........
Modified:
python/branches/release26-maint/ (props changed)
python/branches/release26-maint/Lib/ssl.py
python/branches/release26-maint/Lib/test/test_ssl.py
python/branches/release26-maint/Misc/NEWS
python/branches/release26-maint/Modules/_ssl.c
Modified: python/branches/release26-maint/Lib/ssl.py
==============================================================================
--- python/branches/release26-maint/Lib/ssl.py (original)
+++ python/branches/release26-maint/Lib/ssl.py Sat Apr 24 22:13:37 2010
@@ -113,12 +113,7 @@
keyfile, certfile,
cert_reqs, ssl_version, ca_certs)
if do_handshake_on_connect:
- timeout = self.gettimeout()
- try:
- self.settimeout(None)
- self.do_handshake()
- finally:
- self.settimeout(timeout)
+ self.do_handshake()
self.keyfile = keyfile
self.certfile = certfile
self.cert_reqs = cert_reqs
Modified: python/branches/release26-maint/Lib/test/test_ssl.py
==============================================================================
--- python/branches/release26-maint/Lib/test/test_ssl.py (original)
+++ python/branches/release26-maint/Lib/test/test_ssl.py Sat Apr 24 22:13:37 2010
@@ -457,7 +457,8 @@
asyncore.dispatcher_with_send.__init__(self, conn)
self.socket = ssl.wrap_socket(conn, server_side=True,
certfile=certfile,
- do_handshake_on_connect=True)
+ do_handshake_on_connect=False)
+ self._ssl_accepting = True
def readable(self):
if isinstance(self.socket, ssl.SSLSocket):
@@ -465,9 +466,28 @@
self.handle_read_event()
return True
+ 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()
+ raise
+ except socket.error, err:
+ if err.args[0] == errno.ECONNABORTED:
+ return self.handle_close()
+ else:
+ self._ssl_accepting = False
+
def handle_read(self):
- data = self.recv(1024)
- self.send(data.lower())
+ if self._ssl_accepting:
+ self._do_ssl_handshake()
+ else:
+ data = self.recv(1024)
+ self.send(data.lower())
def handle_close(self):
self.close()
@@ -1226,6 +1246,61 @@
server.stop()
server.join()
+ 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)
+ started = threading.Event()
+ finish = False
+
+ def serve():
+ server.listen(5)
+ started.set()
+ conns = []
+ while not finish:
+ r, w, e = select.select([server], [], [], 0.1)
+ if server in r:
+ # Let the socket hang around rather than having
+ # it closed by garbage collection.
+ conns.append(server.accept()[0])
+
+ t = threading.Thread(target=serve)
+ t.start()
+ started.wait()
+
+ try:
+ try:
+ c = socket.socket(socket.AF_INET)
+ c.settimeout(0.2)
+ c.connect((host, port))
+ # Will attempt handshake and time out
+ try:
+ ssl.wrap_socket(c)
+ except ssl.SSLError, e:
+ self.assertTrue("timed out" in str(e), str(e))
+ else:
+ self.fail("SSLError wasn't raised")
+ finally:
+ c.close()
+ try:
+ c = socket.socket(socket.AF_INET)
+ c.settimeout(0.2)
+ c = ssl.wrap_socket(c)
+ # Will attempt handshake and time out
+ try:
+ c.connect((host, port))
+ except ssl.SSLError, e:
+ self.assertTrue("timed out" in str(e), str(e))
+ else:
+ self.fail("SSLError wasn't raised")
+ finally:
+ c.close()
+ finally:
+ finish = True
+ t.join()
+ server.close()
+
def test_main(verbose=False):
if skip_expected:
Modified: python/branches/release26-maint/Misc/NEWS
==============================================================================
--- python/branches/release26-maint/Misc/NEWS (original)
+++ python/branches/release26-maint/Misc/NEWS Sat Apr 24 22:13:37 2010
@@ -33,6 +33,12 @@
Library
-------
+- Issue #5103: SSL handshake would ignore the socket timeout and block
+ indefinitely if the other end didn't respond.
+
+- The do_handshake() method of SSL objects now adjusts the blocking mode of
+ the SSL structure if necessary (as other methods already do).
+
- Issue #5238: Calling makefile() on an SSL object would prevent the
underlying socket from being closed until all objects get truely destroyed.
Modified: python/branches/release26-maint/Modules/_ssl.c
==============================================================================
--- python/branches/release26-maint/Modules/_ssl.c (original)
+++ python/branches/release26-maint/Modules/_ssl.c Sat Apr 24 22:13:37 2010
@@ -445,7 +445,12 @@
{
int ret;
int err;
- int sockstate;
+ int sockstate, nonblocking;
+
+ /* just in case the blocking state of the socket has been changed */
+ nonblocking = (self->Socket->sock_timeout >= 0.0);
+ BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking);
+ BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking);
/* Actually negotiate SSL connection */
/* XXX If SSL_do_handshake() returns 0, it's also a failure. */
More information about the Python-checkins
mailing list