Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 48dc27c

Browse files
author
Bill Janssen
committed
most recent changes to SSL module to support non-blocking sockets properly
1 parent a37d4c6 commit 48dc27c

2 files changed

Lines changed: 65 additions & 12 deletions

File tree

Doc/library/ssl.rst

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ Functions, Constants, and Exceptions
5151
network connection. This error is a subtype of :exc:`socket.error`, which
5252
in turn is a subtype of :exc:`IOError`.
5353

54-
.. function:: wrap_socket (sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version={see docs}, ca_certs=None)
54+
.. function:: wrap_socket (sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version={see docs}, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True)
5555

5656
Takes an instance ``sock`` of :class:`socket.socket`, and returns an instance of :class:`ssl.SSLSocket`, a subtype
5757
of :class:`socket.socket`, which wraps the underlying socket in an SSL context.
@@ -118,6 +118,18 @@ Functions, Constants, and Exceptions
118118
`*` In some older versions of OpenSSL (for instance, 0.9.7l on OS X 10.4),
119119
an SSLv2 client could not connect to an SSLv23 server.
120120

121+
The parameter ``do_handshake_on_connect`` specifies whether to do the SSL
122+
handshake automatically after doing a :meth:`socket.connect`, or whether the
123+
application program will call it explicitly, by invoking the :meth:`SSLSocket.do_handshake`
124+
method. Calling :meth:`SSLSocket.do_handshake` explicitly gives the program control over
125+
the blocking behavior of the socket I/O involved in the handshake.
126+
127+
The parameter ``suppress_ragged_eofs`` specifies how the :meth:`SSLSocket.read`
128+
method should signal unexpected EOF from the other end of the connection. If specified
129+
as :const:`True` (the default), it returns a normal EOF in response to unexpected
130+
EOF errors raised from the underlying socket; if :const:`False`, it will raise
131+
the exceptions back the caller.
132+
121133
.. function:: RAND_status()
122134

123135
Returns True if the SSL pseudo-random number generator has been
@@ -231,15 +243,41 @@ Functions, Constants, and Exceptions
231243
SSLSocket Objects
232244
-----------------
233245

234-
.. method:: SSLSocket.read([nbytes=1024])
246+
.. method:: SSLSocket.read(nbytes=1024, buffer=None)
235247

236248
Reads up to ``nbytes`` bytes from the SSL-encrypted channel and returns them.
249+
If the ``buffer`` is specified, it will attempt to read into the buffer
250+
the minimum of the size of the buffer and ``nbytes``, if that is specified.
251+
If no buffer is specified, an immutable buffer is allocated and returned
252+
with the data read from the socket.
237253

238254
.. method:: SSLSocket.write(data)
239255

240256
Writes the ``data`` to the other side of the connection, using the
241257
SSL channel to encrypt. Returns the number of bytes written.
242258

259+
.. method:: SSLSocket.do_handshake()
260+
261+
Performs the SSL setup handshake. If the socket is non-blocking,
262+
this method may raise :exc:`SSLError` with the value of the exception
263+
instance's ``args[0]``
264+
being either :const:`SSL_ERROR_WANT_READ` or
265+
:const:`SSL_ERROR_WANT_WRITE`, and should be called again until
266+
it stops raising those exceptions. Here's an example of how to do
267+
that::
268+
269+
while True:
270+
try:
271+
sock.do_handshake()
272+
break
273+
except ssl.SSLError as err:
274+
if err.args[0] == ssl.SSL_ERROR_WANT_READ:
275+
select.select([sock], [], [])
276+
elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
277+
select.select([], [sock], [])
278+
else:
279+
raise
280+
243281
.. method:: SSLSocket.getpeercert(binary_form=False)
244282

245283
If there is no certificate for the peer on the other end of the

Lib/ssl.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,20 @@ def __init__(self, sock=None, keyfile=None, certfile=None,
126126
keyfile, certfile,
127127
cert_reqs, ssl_version, ca_certs)
128128
if do_handshake_on_connect:
129+
timeout = self.gettimeout()
130+
if timeout == 0.0:
131+
# non-blocking
132+
raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets")
129133
self.do_handshake()
134+
130135
except socket_error as x:
131136
self.close()
132137
raise x
133138

134-
self._base = sock
139+
if sock and (self.fileno() != sock.fileno()):
140+
self._base = sock
141+
else:
142+
self._base = None
135143
self.keyfile = keyfile
136144
self.certfile = certfile
137145
self.cert_reqs = cert_reqs
@@ -148,7 +156,7 @@ def _checkClosed(self, msg=None):
148156
# raise an exception here if you wish to check for spurious closes
149157
pass
150158

151-
def read(self, len=1024, buffer=None):
159+
def read(self, len=None, buffer=None):
152160
"""Read up to LEN bytes and return them.
153161
Return zero-length string on EOF."""
154162

@@ -157,7 +165,7 @@ def read(self, len=1024, buffer=None):
157165
if buffer:
158166
return self._sslobj.read(buffer, len)
159167
else:
160-
return self._sslobj.read(len)
168+
return self._sslobj.read(len or 1024)
161169
except SSLError as x:
162170
if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:
163171
return b''
@@ -296,16 +304,18 @@ def _real_close(self):
296304
# self._closed = True
297305
if self._base:
298306
self._base.close()
299-
socket._real_close(self)
307+
socket.close(self)
300308

301-
def do_handshake(self):
309+
def do_handshake(self, block=False):
302310
"""Perform a TLS/SSL handshake."""
303311

312+
timeout = self.gettimeout()
304313
try:
314+
if timeout == 0.0 and block:
315+
self.settimeout(None)
305316
self._sslobj.do_handshake()
306-
except:
307-
self._sslobj = None
308-
raise
317+
finally:
318+
self.settimeout(timeout)
309319

310320
def connect(self, addr):
311321
"""Connects to remote ADDR, and then wraps the connection in
@@ -339,15 +349,20 @@ def accept(self):
339349
addr)
340350

341351

352+
def __del__(self):
353+
self._real_close()
354+
342355
def wrap_socket(sock, keyfile=None, certfile=None,
343356
server_side=False, cert_reqs=CERT_NONE,
344357
ssl_version=PROTOCOL_SSLv23, ca_certs=None,
345-
do_handshake_on_connect=True):
358+
do_handshake_on_connect=True,
359+
suppress_ragged_eofs=True):
346360

347361
return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile,
348362
server_side=server_side, cert_reqs=cert_reqs,
349363
ssl_version=ssl_version, ca_certs=ca_certs,
350-
do_handshake_on_connect=do_handshake_on_connect)
364+
do_handshake_on_connect=do_handshake_on_connect,
365+
suppress_ragged_eofs=suppress_ragged_eofs)
351366

352367
# some utility functions
353368

0 commit comments

Comments
 (0)