diff --git a/eventlet/green/socket.py b/eventlet/green/socket.py index 0607346..8fa6566 100644 --- a/eventlet/green/socket.py +++ b/eventlet/green/socket.py @@ -4,6 +4,7 @@ for var in __socket.__all__: _fileobject = __socket._fileobject from eventlet.api import get_hub +from eventlet.util import wrap_ssl_obj from eventlet.greenio import GreenSocket as socket from eventlet.greenio import GreenSSL as _GreenSSL from eventlet.greenio import GreenSSLObject as _GreenSSLObject @@ -70,15 +71,4 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT): def ssl(sock, certificate=None, private_key=None): - from OpenSSL import SSL - context = SSL.Context(SSL.SSLv23_METHOD) - if certificate is not None: - context.use_certificate_file(certificate) - if private_key is not None: - context.use_privatekey_file(private_key) - context.set_verify(SSL.VERIFY_NONE, lambda *x: True) - - ## TODO only do this on client sockets? how? - connection = SSL.Connection(context, sock) - connection.set_connect_state() - return _GreenSSLObject(_GreenSSL(connection)) + return wrap_ssl_obj(sock, certificate, private_key) diff --git a/eventlet/greenio.py b/eventlet/greenio.py index 7ee58fb..38108fa 100644 --- a/eventlet/greenio.py +++ b/eventlet/greenio.py @@ -710,6 +710,10 @@ class GreenSSL(GreenSocket): return fn(*args, **kw) +def _convert_to_sslerror(ex): + """ Transliterates SSL.SysCallErrors to socket.sslerrors""" + return socket.sslerror((ex[0], ex[1])) + class GreenSSLObject(object): """ Wrapper object around the SSLObjects returned by socket.ssl, which have a slightly different interface from SSL.Connection objects. """ @@ -717,6 +721,10 @@ class GreenSSLObject(object): """ Should only be called by a 'green' socket.ssl """ assert(isinstance(green_ssl_obj, GreenSSL)) self.connection = green_ssl_obj + try: + self.connection.do_handshake() + except SSL.SysCallError, e: + raise _convert_to_sslerror(e) def read(self, n=None): """If n is provided, read n bytes from the SSL connection, otherwise read @@ -726,28 +734,31 @@ class GreenSSLObject(object): raise NotImplementedError("GreenSSLObject does not support "\ " unlimited reads until we hear of someone needing to use them.") else: - return self.connection.read(n) + try: + return self.connection.read(n) + except SSL.SysCallError, e: + raise _convert_to_sslerror(e) def write(self, s): """Writes the string s to the on the object's SSL connection. The return value is the number of bytes written. """ - return self.connection.write(s) + try: + return self.connection.write(s) + except SSL.SysCallError, e: + raise _convert_to_sslerror(e) def server(self): """ Returns a string describing the server's certificate. Useful for debugging purposes; do not parse the content of this string because its format can't be parsed unambiguously. """ - # NOTE: probably not the same as the real SSLObject, but, if someone actually - # uses this then we can fix it. - return str(self.connection.get_peer_certificate()) + return str(self.connection.get_peer_certificate().get_subject()) def issuer(self): """Returns a string describing the issuer of the server's certificate. Useful for debugging purposes; do not parse the content of this string because its format can't be parsed unambiguously.""" - # NOTE: probably not the same as the real SSLObject, but, if someone actually - # uses this then we can fix it. return str(self.connection.get_peer_certificate().get_issuer()) + def socketpair(*args): diff --git a/eventlet/util.py b/eventlet/util.py index c3b492c..1b59613 100644 --- a/eventlet/util.py +++ b/eventlet/util.py @@ -74,6 +74,13 @@ def wrap_ssl(sock, certificate=None, private_key=None): return greenio.GreenSSL(connection) +def wrap_ssl_obj(sock, certificate=None, private_key=None): + """ For 100% compatibility with the socket module, this wraps and handshakes an + open connection, returning a SSLObject.""" + from eventlet import greenio + wrapped = wrap_ssl(sock, certificate, private_key) + return greenio.GreenSSLObject(wrapped) + socket_already_wrapped = False def wrap_socket_with_coroutine_socket(use_thread_pool=True): global socket_already_wrapped @@ -86,10 +93,7 @@ def wrap_socket_with_coroutine_socket(use_thread_pool=True): socket.socket = new_socket # for 100% compatibility, return a GreenSSLObject - def new_ssl(sock, certificate=None, private_key=None): - wrapped = wrap_ssl(sock, certificate, private_key) - return greenio.GreenSSLObject(wrapped) - socket.ssl = new_ssl + socket.ssl = wrap_ssl_obj if use_thread_pool: from eventlet import tpool