33from eventlet .patcher import slurp_properties
44slurp_properties (__ssl , globals (), srckeys = dir (__ssl ))
55
6- import errno
7- import functools
86import sys
9-
107from eventlet import greenio , hubs
118from eventlet .greenio import (
129 set_nonblocking , GreenSocket , CONNECT_ERR , CONNECT_SUCCESS ,
1310)
1411from eventlet .hubs import trampoline , IOClosed
1512from eventlet .support import get_errno , PY33
1613import six
14+ from contextlib import contextmanager
15+
1716orig_socket = __import__ ('socket' )
1817socket = orig_socket .socket
1918timeout_exc = SSLError
2423
2524_original_sslsocket = __ssl .SSLSocket
2625_original_wrap_socket = __ssl .wrap_socket
26+ _original_sslcontext = getattr (__ssl , 'SSLContext' , None )
27+ _is_under_py_3_7 = sys .version_info < (3 , 7 )
28+
29+
30+ @contextmanager
31+ def _original_ssl_context (* args , ** kwargs ):
32+ tmp_sslcontext = _original_wrap_socket .__globals__ .get ('SSLContext' , None )
33+ tmp_sslsocket = _original_sslsocket ._create .__globals__ .get ('SSLSocket' , None )
34+ _original_sslsocket ._create .__globals__ ['SSLSocket' ] = _original_sslsocket
35+ _original_wrap_socket .__globals__ ['SSLContext' ] = _original_sslcontext
36+ try :
37+ yield
38+ finally :
39+ _original_wrap_socket .__globals__ ['SSLContext' ] = tmp_sslcontext
40+ _original_sslsocket ._create .__globals__ ['SSLSocket' ] = tmp_sslsocket
2741
2842
2943class GreenSSLSocket (_original_sslsocket ):
@@ -40,59 +54,56 @@ class GreenSSLSocket(_original_sslsocket):
4054 settimeout(), and to close/reopen the connection when a timeout
4155 occurs at an unexpected juncture in the code.
4256 """
57+ def __new__ (cls , sock = None , keyfile = None , certfile = None ,
58+ server_side = False , cert_reqs = CERT_NONE ,
59+ ssl_version = PROTOCOL_SSLv23 , ca_certs = None ,
60+ do_handshake_on_connect = True , * args , ** kw ):
61+ if _is_under_py_3_7 :
62+ return super (GreenSSLSocket , cls ).__new__ (cls )
63+ else :
64+ if not isinstance (sock , GreenSocket ):
65+ sock = GreenSocket (sock )
66+ with _original_ssl_context ():
67+ ret = _original_wrap_socket (
68+ sock = sock .fd ,
69+ keyfile = keyfile ,
70+ certfile = certfile ,
71+ server_side = server_side ,
72+ cert_reqs = cert_reqs ,
73+ ssl_version = ssl_version ,
74+ ca_certs = ca_certs ,
75+ do_handshake_on_connect = False ,
76+ * args , ** kw
77+ )
78+ ret .keyfile = keyfile
79+ ret .certfile = certfile
80+ ret .cert_reqs = cert_reqs
81+ ret .ssl_version = ssl_version
82+ ret .ca_certs = ca_certs
83+ ret .__class__ = GreenSSLSocket
84+ return ret
85+
4386 # we are inheriting from SSLSocket because its constructor calls
4487 # do_handshake whose behavior we wish to override
45-
4688 def __init__ (self , sock , keyfile = None , certfile = None ,
4789 server_side = False , cert_reqs = CERT_NONE ,
4890 ssl_version = PROTOCOL_SSLv23 , ca_certs = None ,
4991 do_handshake_on_connect = True , * args , ** kw ):
5092 if not isinstance (sock , GreenSocket ):
5193 sock = GreenSocket (sock )
52-
5394 self .act_non_blocking = sock .act_non_blocking
5495
5596 if six .PY2 :
5697 # On Python 2 SSLSocket constructor queries the timeout, it'd break without
5798 # this assignment
5899 self ._timeout = sock .gettimeout ()
59100
60- if sys .version_info >= (3 , 7 ):
61- # Monkey-patch the sslsocket so our modified self gets
62- # injected into its _create method.
63- def fake_new (self , cls , * args , ** kwargs ):
64- return self
65-
66- orig_new = _original_sslsocket .__new__
67- try :
68- _original_sslsocket .__new__ = fake_new .__get__ (self , GreenSSLSocket )
69-
70- self = _original_wrap_socket (
71- sock = sock .fd ,
72- keyfile = keyfile ,
73- certfile = certfile ,
74- server_side = server_side ,
75- cert_reqs = cert_reqs ,
76- ssl_version = ssl_version ,
77- ca_certs = ca_certs ,
78- do_handshake_on_connect = False ,
79- * args , ** kw
80- )
81- self .keyfile = keyfile
82- self .certfile = certfile
83- self .cert_reqs = cert_reqs
84- self .ssl_version = ssl_version
85- self .ca_certs = ca_certs
86- finally :
87- # Unpatch
88- _original_sslsocket .__new__ = orig_new
89- else :
101+ if _is_under_py_3_7 :
90102 # nonblocking socket handshaking on connect got disabled so let's pretend it's disabled
91103 # even when it's on
92104 super (GreenSSLSocket , self ).__init__ (
93105 sock .fd , keyfile , certfile , server_side , cert_reqs , ssl_version ,
94106 ca_certs , do_handshake_on_connect and six .PY2 , * args , ** kw )
95-
96107 # the superclass initializer trashes the methods so we remove
97108 # the local-object versions of them and let the actual class
98109 # methods shine through
@@ -354,7 +365,7 @@ def connect(self, addr):
354365 except NameError :
355366 self ._sslobj = sslobj
356367 else :
357- if sys . version_info < ( 3 , 7 ) :
368+ if _is_under_py_3_7 :
358369 self ._sslobj = SSLObject (sslobj , owner = self )
359370 else :
360371 self ._sslobj = sslobj
@@ -396,6 +407,7 @@ def accept(self):
396407 def dup (self ):
397408 raise NotImplementedError ("Can't dup an ssl object" )
398409
410+
399411SSLSocket = GreenSSLSocket
400412
401413
0 commit comments