@@ -229,6 +229,81 @@ def decompress(byts):
229229frame_header_v3 = struct .Struct ('>BhBi' )
230230
231231
232+ def _default_pyopenssl_ssl_method (ssl_module ):
233+ for method_name in ('TLS_CLIENT_METHOD' , 'TLS_METHOD' , 'TLSv1_2_METHOD' ):
234+ method = getattr (ssl_module , method_name , None )
235+ if method is not None :
236+ return method
237+ raise ImportError ('pyOpenSSL does not expose a secure TLS client method' )
238+
239+
240+ def _pyopenssl_ssl_method_from_stdlib (ssl_module , ssl_version ):
241+ if ssl_version is None :
242+ return _default_pyopenssl_ssl_method (ssl_module )
243+
244+ protocol_method_names = (
245+ ('PROTOCOL_TLS_CLIENT' , ('TLS_CLIENT_METHOD' , 'TLS_METHOD' , 'TLSv1_2_METHOD' )),
246+ ('PROTOCOL_TLS' , ('TLS_METHOD' , 'TLS_CLIENT_METHOD' , 'TLSv1_2_METHOD' )),
247+ ('PROTOCOL_SSLv23' , ('TLS_METHOD' , 'TLS_CLIENT_METHOD' , 'TLSv1_2_METHOD' )),
248+ ('PROTOCOL_TLSv1_2' , ('TLSv1_2_METHOD' ,)),
249+ ('PROTOCOL_TLSv1_1' , ('TLSv1_1_METHOD' ,)),
250+ ('PROTOCOL_TLSv1' , ('TLSv1_METHOD' ,)),
251+ )
252+ for protocol_name , method_names in protocol_method_names :
253+ protocol = getattr (ssl , protocol_name , None )
254+ if (protocol is not None and
255+ ssl_version .__class__ is protocol .__class__ and
256+ ssl_version == protocol ):
257+ for method_name in method_names :
258+ method = getattr (ssl_module , method_name , None )
259+ if method is not None :
260+ return method
261+ raise ImportError ('pyOpenSSL does not expose a method for %s' % (protocol_name ,))
262+
263+ return ssl_version
264+
265+
266+ def _pyopenssl_verify_mode_from_cert_reqs (ssl_module , cert_reqs ):
267+ if cert_reqs is None :
268+ return None
269+ if cert_reqs .__class__ is not type (ssl .CERT_REQUIRED ):
270+ return cert_reqs
271+ if cert_reqs == ssl .CERT_NONE :
272+ return ssl_module .VERIFY_NONE
273+ if cert_reqs in (ssl .CERT_OPTIONAL , ssl .CERT_REQUIRED ):
274+ return ssl_module .VERIFY_PEER
275+ return cert_reqs
276+
277+
278+ def _build_pyopenssl_context_from_options (ssl_module , ssl_options ):
279+ ssl_options = ssl_options or {}
280+ context = ssl_module .Context (
281+ _pyopenssl_ssl_method_from_stdlib (ssl_module , ssl_options .get ('ssl_version' , None ))
282+ )
283+ if 'certfile' in ssl_options :
284+ context .use_certificate_file (ssl_options ['certfile' ])
285+ if 'keyfile' in ssl_options :
286+ context .use_privatekey_file (ssl_options ['keyfile' ])
287+ if 'ca_certs' in ssl_options :
288+ context .load_verify_locations (ssl_options ['ca_certs' ])
289+ cert_reqs = _pyopenssl_verify_mode_from_cert_reqs (
290+ ssl_module , ssl_options .get ('cert_reqs' , None ))
291+ if cert_reqs is None :
292+ cert_reqs = (ssl_module .VERIFY_PEER
293+ if (ssl_options .get ('ca_certs' , None ) or ssl_options .get ('check_hostname' , False ))
294+ else ssl_module .VERIFY_NONE )
295+ context .set_verify (
296+ cert_reqs ,
297+ callback = lambda _connection , _x509 , _errnum , _errdepth , ok : ok
298+ )
299+ ciphers = ssl_options .get ('ciphers' , None )
300+ if ciphers :
301+ if isinstance (ciphers , str ):
302+ ciphers = ciphers .encode ('ascii' )
303+ context .set_cipher_list (ciphers )
304+ return context
305+
306+
232307class EndPoint (object ):
233308 """
234309 Represents the information to connect to a cassandra node.
0 commit comments