Skip to content

Commit 258eea1

Browse files
authored
Merge pull request #6 from chaen/convertExceptions
Convert SSL.SSLError to ssl.SSLError and close connection on error
2 parents 4cfd4c0 + 9edd45f commit 258eea1

File tree

1 file changed

+50
-47
lines changed

1 file changed

+50
-47
lines changed

tornado_m2crypto/m2iostream.py

Lines changed: 50 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,11 @@ def get(self):
8585
import errno
8686
import os
8787
import socket
88+
import ssl
8889

8990
from tornado_m2crypto.m2netutil import m2_wrap_socket
9091

91-
from tornado.iostream import SSLIOStream, _ERRNO_WOULDBLOCK,IOStream
92+
from tornado.iostream import SSLIOStream, _ERRNO_WOULDBLOCK, IOStream
9293
from tornado.log import gen_log
9394

9495
from M2Crypto import m2, SSL, Err
@@ -116,27 +117,27 @@ class M2IOStream(SSLIOStream):
116117
"""
117118

118119
def __init__(self, *args, **kwargs):
119-
pass
120+
pass
120121

121122
def initialize(self, *args, **kwargs):
122123
"""The ``ssl_options`` keyword argument may either be an
123124
`~M2Crypto.SSL.SSLContext` object or a dictionary of keywords arguments (see `~m2netutil.ssl_options_to_m2_context`.)
124125
"""
125-
self._ssl_options = kwargs.pop('ssl_options', _client_m2_ssl_defaults)
126+
self._ssl_options = kwargs.pop("ssl_options", _client_m2_ssl_defaults)
126127

127-
if kwargs.pop('create_context_on_init', False):
128-
server_side = kwargs.pop('server_side', False)
129-
do_handshake_on_connect = kwargs.pop('do_handshake_on_connect', False)
128+
if kwargs.pop("create_context_on_init", False):
129+
server_side = kwargs.pop("server_side", False)
130+
do_handshake_on_connect = kwargs.pop("do_handshake_on_connect", False)
130131
connection = args[0]
131-
self.socket = m2_wrap_socket(connection,
132-
self._ssl_options,
133-
server_side = server_side,
134-
do_handshake_on_connect=do_handshake_on_connect)
132+
self.socket = m2_wrap_socket(
133+
connection,
134+
self._ssl_options,
135+
server_side=server_side,
136+
do_handshake_on_connect=do_handshake_on_connect,
137+
)
135138

136139
args = (self.socket,) + args[1:]
137140

138-
139-
140141
IOStream.__init__(self, *args, **kwargs)
141142
self._done_setup = False
142143
self._ssl_accepting = True
@@ -156,7 +157,6 @@ def initialize(self, *args, **kwargs):
156157
# _handle_events.
157158
self._add_io_state(self.io_loop.WRITE)
158159

159-
160160
def _do_ssl_handshake(self):
161161
try:
162162
self._handshake_reading = False
@@ -172,31 +172,35 @@ def _do_ssl_handshake(self):
172172
self._done_setup = True
173173
# Actual accept/connect logic
174174
if self.socket.server_side:
175-
res = self.socket.accept_ssl()
175+
res = self.socket.accept_ssl()
176176
else:
177-
res = self.socket.connect_ssl()
177+
res = self.socket.connect_ssl()
178178
if res == 0:
179179
# TODO: We should somehow get SSL_WANT_READ/WRITE here
180180
# and then set the correct flag, although it does
181181
# work as long as one of them gets set
182182
self._handshake_reading = True
183-
#self._handshake_writing = True
183+
# self._handshake_writing = True
184184
return
185185
if res < 0:
186186
err_num = self.socket.ssl_get_error(res)
187187
gen_log.error("Err: %s" % err_num)
188188
gen_log.error("Err Str: %s" % Err.get_error_reason(err_num))
189189
return self.close()
190-
except SSL.SSLError as e:
191-
raise
190+
except SSL.SSLError as err:
191+
try:
192+
peer = self.socket.getpeername()
193+
except Exception:
194+
peer = "(not connected)"
195+
gen_log.warning("SSL Error on %s %s: %s", self.socket.fileno(), peer, err)
196+
return self.close(exc_info=err)
192197
except socket.error as err:
193198
gen_log.error("Socket error!")
194199
# Some port scans (e.g. nmap in -sT mode) have been known
195200
# to cause do_handshake to raise EBADF and ENOTCONN, so make
196201
# those errors quiet as well.
197202
# https://groups.google.com/forum/?fromgroups#!topic/python-tornado/ApucKJat1_0
198-
if (self._is_connreset(err) or
199-
err.args[0] in (errno.EBADF, errno.ENOTCONN)):
203+
if self._is_connreset(err) or err.args[0] in (errno.EBADF, errno.ENOTCONN):
200204
return self.close(exc_info=err)
201205
raise
202206
except AttributeError as err:
@@ -217,19 +221,18 @@ def close_fd(self):
217221
self.socket.shutdown(socket.SHUT_RDWR)
218222
super(M2IOStream, self).close_fd()
219223

220-
221224
def _verify_cert(self, peercert):
222225
"""Returns True if peercert is valid according to the configured
223226
validation mode and hostname.
224227
"""
225-
checker = getattr(self.socket, 'postConnectionCheck',
226-
self.socket.serverPostConnectionCheck)
228+
checker = getattr(
229+
self.socket, "postConnectionCheck", self.socket.serverPostConnectionCheck
230+
)
227231
addr = self.socket.socket.getpeername()[0]
228232
if checker and not checker(self.socket.get_peer_cert(), addr):
229233
return False
230234
return True
231235

232-
233236
def _handle_connect(self):
234237
# Call the superclass method to check for errors.
235238
self._handle_connect_super()
@@ -248,30 +251,30 @@ def _handle_connect(self):
248251
self.io_loop.remove_handler(self.socket)
249252
old_state = self._state
250253
self._state = None
251-
self.socket = m2_wrap_socket(self.socket, self._ssl_options,
252-
server_hostname=self._server_hostname)
254+
self.socket = m2_wrap_socket(
255+
self.socket, self._ssl_options, server_hostname=self._server_hostname
256+
)
253257
self._add_io_state(old_state)
254258

255-
256259
def write_to_fd(self, data):
257260

258261
try:
259262
res = self.socket.send(data)
260263
if res < 0:
261264

262-
err = self.socket.ssl_get_error( res)
263-
# if the error is try again, let's do it !
264-
if err == SSL.m2.ssl_error_want_write:
265-
return 0
265+
err = self.socket.ssl_get_error(res)
266+
# if the error is try again, let's do it !
267+
if err == SSL.m2.ssl_error_want_write:
268+
return 0
266269

267-
# Now this is is clearly not correct.
268-
# We get error "1 (ssl_error_ssl)" but the calling function (_handle_write)
269-
# is handling exception. So we might have to throw instead
270-
# of returning 0
271-
if res == -1:
272-
#return 0
273-
raise socket.error(errno.EWOULDBLOCK, "Fix me please")
274-
raise Exception()
270+
# Now this is is clearly not correct.
271+
# We get error "1 (ssl_error_ssl)" but the calling function (_handle_write)
272+
# is handling exception. So we might have to throw instead
273+
# of returning 0
274+
if res == -1:
275+
# return 0
276+
raise socket.error(errno.EWOULDBLOCK, "Fix me please")
277+
raise Exception()
275278

276279
return res
277280
finally:
@@ -302,8 +305,7 @@ def read_from_fd(self, buf):
302305
if e.args[0] == m2.ssl_error_want_read:
303306
return None
304307
else:
305-
306-
raise
308+
raise ssl.SSLError(*e.args)
307309
except socket.error as e:
308310
if e.args[0] in _ERRNO_WOULDBLOCK:
309311
return None
@@ -314,7 +316,7 @@ def read_from_fd(self, buf):
314316

315317
# Do inherit because there is no such error in M2Crpto
316318
def _is_connreset(self, e):
317-
return IOStream._is_connreset(self, e)
319+
return IOStream._is_connreset(self, e)
318320

319321
def _handle_connect_super(self):
320322
# Work around a bug where M2Crypto passes None as last argument to
@@ -327,9 +329,12 @@ def _handle_connect_super(self):
327329
# in that case a connection failure would be handled by the
328330
# error path in _handle_events instead of here.
329331
if self._connect_future is None:
330-
gen_log.warning("Connect error on fd %s: %s",
331-
self.socket.fileno(), errno.errorcode[err])
332-
gen_log.warning( "Close connect error!")
332+
gen_log.warning(
333+
"Connect error on fd %s: %s",
334+
self.socket.fileno(),
335+
errno.errorcode[err],
336+
)
337+
gen_log.warning("Close connect error!")
333338
self.close()
334339
return
335340
if self._connect_callback is not None:
@@ -342,7 +347,6 @@ def _handle_connect_super(self):
342347
future.set_result(self)
343348
self._connecting = False
344349

345-
346350
def get_ssl_certificate(self, **kwargs):
347351
"""Returns the client's SSL certificate, if any.
348352
@@ -364,7 +368,6 @@ def get_ssl_certificate(self, **kwargs):
364368
"""
365369
return self.socket.get_peer_cert()
366370

367-
368371
def get_ssl_certificate_chain(self, **kwargs):
369372
"""Returns the client's SSL certificate chain, if any.
370373
(Note that the chain does not contains the certificate itself !)

0 commit comments

Comments
 (0)