@@ -223,10 +223,17 @@ class TCPConnector(BaseConnector):
223223 """
224224
225225 def __init__ (self , * args , verify_ssl = True ,
226- resolve = False , family = socket .AF_INET , ** kwargs ):
226+ resolve = False , family = socket .AF_INET , ssl_context = None ,
227+ ** kwargs ):
228+ if not verify_ssl and ssl_context is not None :
229+ raise ValueError (
230+ "Either disable ssl certificate validation by "
231+ "verify_ssl=False or specify ssl_context, not both." )
232+
227233 super ().__init__ (* args , ** kwargs )
228234
229235 self ._verify_ssl = verify_ssl
236+ self ._ssl_context = ssl_context
230237 self ._family = family
231238 self ._resolve = resolve
232239 self ._resolved_hosts = {}
@@ -236,6 +243,33 @@ def verify_ssl(self):
236243 """Do check for ssl certifications?"""
237244 return self ._verify_ssl
238245
246+ @property
247+ def ssl_context (self ):
248+ """SSLContext instance for https requests.
249+
250+ Lazy property, creates context on demand.
251+ """
252+ if self ._ssl_context is None :
253+ if not self ._verify_ssl :
254+ sslcontext = ssl .SSLContext (ssl .PROTOCOL_SSLv23 )
255+ sslcontext .options |= ssl .OP_NO_SSLv2
256+ sslcontext .options |= ssl .OP_NO_SSLv3
257+ sslcontext .options |= getattr (ssl , "OP_NO_COMPRESSION" , 0 )
258+ sslcontext .set_default_verify_paths ()
259+ elif hasattr (ssl , 'create_default_context' ):
260+ # Python 3.4+
261+ sslcontext = ssl .create_default_context ()
262+ else : # pragma: no cover
263+ # Fallback for Python 3.3.
264+ sslcontext = ssl .SSLContext (ssl .PROTOCOL_SSLv23 )
265+ sslcontext .options |= ssl .OP_NO_SSLv2
266+ sslcontext .options |= ssl .OP_NO_SSLv3
267+ sslcontext .options |= getattr (ssl , "OP_NO_COMPRESSION" , 0 )
268+ sslcontext .set_default_verify_paths ()
269+ sslcontext .verify_mode = ssl .CERT_REQUIRED
270+ self ._ssl_context = sslcontext
271+ return self ._ssl_context
272+
239273 @property
240274 def family (self ):
241275 """Socket family like AF_INET."""
@@ -288,11 +322,10 @@ def _create_connection(self, req, **kwargs):
288322
289323 Has same keyword arguments as BaseEventLoop.create_connection.
290324 """
291- sslcontext = req .ssl
292- if req .ssl and not self ._verify_ssl :
293- sslcontext = ssl .SSLContext (ssl .PROTOCOL_SSLv23 )
294- sslcontext .options |= ssl .OP_NO_SSLv2
295- sslcontext .set_default_verify_paths ()
325+ if req .ssl :
326+ sslcontext = self .ssl_context
327+ else :
328+ sslcontext = None
296329
297330 hosts = yield from self ._resolve_host (req .host , req .port )
298331
0 commit comments