def setUp(self): """ Create a L{PantheonHTTPChecker} pointed at a mock authentication service with some simple site and user information. """ self.site = 'example.com' self.cwd = '/some/path' self.uid = 1542 self.username = '******' self.password = '******' keyString = FilePath(__file__).sibling('id_rsa').getContent() self.privateKey = Key.fromString(keyString) caKeyString = FilePath(__file__).sibling('cakey.pem').getContent() self.caKey = KeyPair.load(caKeyString, FILETYPE_PEM) caCertString = FilePath(__file__).sibling('cacert.pem').getContent() self.caCert = PrivateCertificate.load( caCertString, self.caKey, FILETYPE_PEM) self.resource = MockPantheonAuthResource( sites={self.site: [self.username]}, authorizations={self.site: dict(cwd=self.cwd, uid=self.uid)}, passwords={self.username: self.password}, keys={self.username: self.privateKey}, ) self.server = MockPantheonAuthServer( reactor, self.resource, self.caCert) self.server.startService() self.addCleanup(self.server.stopService)
def get_context_factory(cert_path, pkey_path): """OpenSSL context factory. Generates an OpenSSL context factory using Twisted's CertificateOptions class. This will keep a server cipher order. Args: cert_path (string): The path to the certificate file pkey_path (string): The path to the private key file Returns: twisted.internet.ssl.CertificateOptions: An OpenSSL context factory """ with open(cert_path) as cert: certificate = Certificate.loadPEM(cert.read()).original with open(pkey_path) as pkey: private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original ciphers = AcceptableCiphers.fromOpenSSLCipherString(TLS_CIPHERS) cert_options = CertificateOptions( privateKey=private_key, certificate=certificate, raiseMinimumTo=TLSVersion.TLSv1_2, acceptableCiphers=ciphers, ) ctx = cert_options.getContext() ctx.use_certificate_chain_file(cert_path) ctx.set_options(SSL_OP_NO_RENEGOTIATION) return cert_options
def getServerContext(self): """ Return a new SSL context suitable for use in a test server. """ pem = self._pem.getContent() cert = PrivateCertificate.load( pem, KeyPair.load(pem, FILETYPE_PEM), FILETYPE_PEM) return cert.options()
def getServerContext(self): """ Return a new SSL context suitable for use in a test server. """ cert = PrivateCertificate.load( self._certificateText, KeyPair.load(self._privateKeyText, FILETYPE_PEM), FILETYPE_PEM) return cert.options()
def getServerContext(self): """ Return a new SSL context suitable for use in a test server. """ pem = self._pem.getContent() cert = PrivateCertificate.load( pem, KeyPair.load(pem, FILETYPE_PEM), FILETYPE_PEM) return cert.options()
def getServerContext(self): """ Return a new SSL context suitable for use in a test server. """ cert = PrivateCertificate.load( self._certificateText, KeyPair.load(self._privateKeyText, FILETYPE_PEM), FILETYPE_PEM) return cert.options()
def start_ssl(self): log.debug("Enabling SSL with PKey: %s, Cert: %s", self.pkey, self.cert) check_ssl_keys() with open(configmanager.get_config_dir(self.cert)) as cert: certificate = Certificate.loadPEM(cert.read()).original with open(configmanager.get_config_dir(self.pkey)) as pkey: private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original options = CertificateOptions(privateKey=private_key, certificate=certificate, method=SSL.SSLv23_METHOD) options.getContext().set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3) self.socket = reactor.listenSSL(self.port, self.site, options) log.info("Serving on %s:%s view at https://127.0.0.1:%s", "0.0.0.0", self.port, self.port)
def _create_tls_client_context(config, cbdir, log): """ Create a CertificateOptions object for use with TLS listening endpoints. """ # server hostname: The expected name of the remote host. hostname = config['hostname'] # explicit trust (certificate) root ca_certs = None if 'ca_certificates' in config: log.info("TLS client using explicit trust ({cnt_certs} certificates)", cnt_certs=len(config['ca_certificates'])) ca_certs = [] for cert_fname in [os.path.abspath(os.path.join(cbdir, x)) for x in (config['ca_certificates'])]: cert = crypto.load_certificate( crypto.FILETYPE_PEM, six.u(open(cert_fname, 'r').read()) ) log.info("TLS client trust root CA certificate loaded from '{fname}'", fname=cert_fname) ca_certs.append(cert) ca_certs = OpenSSLCertificateAuthorities(ca_certs) else: log.info("TLS client using platform trust") # client key/cert to use client_cert = None if 'key' in config: if 'certificate' not in config: raise Exception('TLS client key present, but certificate missing') key_fname = os.path.abspath(os.path.join(cbdir, config['key'])) with open(key_fname, 'r') as f: private_key = KeyPair.load(f.read(), format=crypto.FILETYPE_PEM) log.info("Loaded client TLS key from '{key_fname}'", key_fname=key_fname) cert_fname = os.path.abspath(os.path.join(cbdir, config['certificate'])) with open(cert_fname, 'r') as f: cert = Certificate.loadPEM(f.read(),) log.info("Loaded client TLS certificate from '{cert_fname}' (cn='{cert_cn}', sha256={cert_sha256}..)", cert_fname=cert_fname, cert_cn=cert.getSubject().CN, cert_sha256=cert.digest('sha256')[:12]) client_cert = PrivateCertificate.fromCertificateAndKeyPair(cert, private_key) else: if 'certificate' in config: log.warn('TLS client certificate present, but key is missing') # create TLS client context ctx = optionsForClientTLS(hostname, trustRoot=ca_certs, clientCertificate=client_cert) return ctx
def _create_tls_client_context(config, cbdir, log): """ Create a CertificateOptions object for use with TLS listening endpoints. """ # server hostname: The expected name of the remote host. hostname = config['hostname'] # explicit trust (certificate) root ca_certs = None if 'ca_certificates' in config: log.info("TLS client using explicit trust ({cnt_certs} certificates)", cnt_certs=len(config['ca_certificates'])) ca_certs = [] for cert_fname in [os.path.abspath(os.path.join(cbdir, x)) for x in (config['ca_certificates'])]: cert = crypto.load_certificate( crypto.FILETYPE_PEM, six.u(open(cert_fname, 'r').read()) ) log.info("TLS client trust root CA certificate loaded from '{fname}'", fname=cert_fname) ca_certs.append(cert) ca_certs = OpenSSLCertificateAuthorities(ca_certs) else: log.info("TLS client using platform trust") # client key/cert to use client_cert = None if 'key' in config: if 'certificate' not in config: raise Exception('TLS client key present, but certificate missing') key_fname = os.path.abspath(os.path.join(cbdir, config['key'])) with open(key_fname, 'r') as f: private_key = KeyPair.load(f.read(), format=crypto.FILETYPE_PEM) log.info("Loaded client TLS key from '{key_fname}'", key_fname=key_fname) cert_fname = os.path.abspath(os.path.join(cbdir, config['certificate'])) with open(cert_fname, 'r') as f: cert = Certificate.loadPEM(f.read(),) log.info("Loaded client TLS certificate from '{cert_fname}' (cn='{cert_cn}', sha256={cert_sha256}..)", cert_fname=cert_fname, cert_cn=cert.getSubject().CN, cert_sha256=cert.digest('sha256')[:12]) client_cert = PrivateCertificate.fromCertificateAndKeyPair(cert, private_key) else: if 'certificate' in config: log.warn('TLS client certificate present, but key is missing') # create TLS client context ctx = optionsForClientTLS(hostname, trustRoot=ca_certs, clientCertificate=client_cert) return ctx
def from_path(cls, path): """ :param FilePath path: Directory where private key and certificate are stored. """ if not path.isdir(): raise PathError( b"Path {path} is not a directory.".format(path=path.path) ) certPath = path.child(certificate_filename) keyPath = path.child(key_filename) if not certPath.isfile(): raise PathError( b"Certificate file {path} does not exist.".format( path=certPath.path) ) if not keyPath.isfile(): raise PathError( b"Private key file {path} does not exist.".format( path=keyPath.path) ) try: certFile = certPath.open() except IOError: raise PathError( (b"Certificate file {path} could not be opened. " b"Check file permissions.").format( path=certPath.path) ) try: keyFile = keyPath.open() except IOError: raise PathError( (b"Private key file {path} could not be opened. " b"Check file permissions.").format( path=keyPath.path) ) certificate = Certificate.load( certFile.read(), format=crypto.FILETYPE_PEM) keypair = FlockerKeyPair( keypair=KeyPair.load(keyFile.read(), format=crypto.FILETYPE_PEM) ) return cls(path=path, certificate=certificate, keypair=keypair)
def start_ssl(self): log.debug("Enabling SSL with PKey: %s, Cert: %s", self.pkey, self.cert) check_ssl_keys() with open(configmanager.get_config_dir(self.cert)) as cert: certificate = Certificate.loadPEM(cert.read()).original with open(configmanager.get_config_dir(self.pkey)) as pkey: private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original options = CertificateOptions(privateKey=private_key, certificate=certificate, method=SSL.SSLv23_METHOD) ctx = options.getContext() ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3) ctx.use_certificate_chain_file(configmanager.get_config_dir(self.cert)) self.socket = reactor.listenSSL(self.port, self.site, options, interface=self.interface) log.info("Serving on %s:%s view at https://%s:%s", self.interface, self.port, self.interface, self.port)
def start_ssl(self): check_ssl_keys() log.debug('Enabling SSL with PKey: %s, Cert: %s', self.pkey, self.cert) with open(configmanager.get_config_dir(self.cert)) as cert: certificate = Certificate.loadPEM(cert.read()).original with open(configmanager.get_config_dir(self.pkey)) as pkey: private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original options = CertificateOptions(privateKey=private_key, certificate=certificate, method=SSL.SSLv23_METHOD) ctx = options.getContext() ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3) ctx.use_certificate_chain_file(configmanager.get_config_dir(self.cert)) self.socket = reactor.listenSSL(self.port, self.site, options, interface=self.interface) ip = self.socket.getHost().host ip = '[%s]' % ip if is_ipv6(ip) else ip log.info('Serving at https://%s:%s%s', ip, self.port, self.base)
def load_key_file(path): """ Load a private key from a specified path. :param FilePath path: Absolute path to certificate file. :return: A ``ComparableKeyPair`` instance representing the parsed key data. """ try: key_file = path.open() except IOError as e: code, failure = e raise PathError(b"Private key file could not be opened.", e.filename, code, failure) keypair = ComparableKeyPair( keypair=KeyPair.load(key_file.read(), format=crypto.FILETYPE_PEM)) return keypair
def objectsFromPEM(pemdata): """ Load some objects from a PEM. """ certificates = [] keys = [] for line in pemdata.split("\n"): if line.startswith('-----BEGIN'): if 'CERTIFICATE' in line: blobs = certificates else: blobs = keys blobs.append('') blobs[-1] += line blobs[-1] += '\n' keys = [KeyPair.load(key, FILETYPE_PEM) for key in keys] certificates = [ Certificate.loadPEM(certificate) for certificate in certificates ] return PEMObjects(keys=keys, certificates=certificates)
def objectsFromPEM(pemdata): """ Load some objects from a PEM. """ certificates = [] keys = [] blobs = [b""] for line in pemdata.split(b"\n"): if line.startswith(b'-----BEGIN'): if b'CERTIFICATE' in line: blobs = certificates else: blobs = keys blobs.append(b'') blobs[-1] += line blobs[-1] += b'\n' keys = [KeyPair.load(key, FILETYPE_PEM) for key in keys] certificates = [Certificate.loadPEM(certificate) for certificate in certificates] return PEMObjects(keys=keys, certificates=certificates)
def load_key_file(path): """ Load a private key from a specified path. :param FilePath path: Absolute path to certificate file. :return: A ``ComparableKeyPair`` instance representing the parsed key data. """ try: key_file = path.open() except IOError as e: code, failure = e raise PathError( b"Private key file could not be opened.", e.filename, code, failure ) keypair = ComparableKeyPair( keypair=KeyPair.load(key_file.read(), format=crypto.FILETYPE_PEM) ) return keypair
def load_certificate_from_path(path, key_filename, cert_filename): """ Load a certificate and keypair from a specified path. :param FilePath path: Directory where certificate and key files are stored. :param bytes key_filename: The file name of the private key. :param bytes cert_filename: The file name of the certificate. :return: A ``tuple`` containing the loaded key and certificate instances. """ certPath = path.child(cert_filename) keyPath = path.child(key_filename) try: certFile = certPath.open() except IOError as e: code, failure = e raise PathError( b"Certificate file could not be opened.", e.filename, code, failure ) try: keyFile = keyPath.open() except IOError as e: code, failure = e raise PathError( b"Private key file could not be opened.", e.filename, code, failure ) certificate = Certificate.load( certFile.read(), format=crypto.FILETYPE_PEM) keypair = ComparableKeyPair( keypair=KeyPair.load(keyFile.read(), format=crypto.FILETYPE_PEM) ) return (keypair, certificate)
def load_certificate_from_path(path, key_filename, cert_filename): """ Load a certificate and keypair from a specified path. :param FilePath path: Directory where certificate and key files are stored. :param bytes key_filename: The file name of the private key. :param bytes cert_filename: The file name of the certificate. :return: A ``tuple`` containing the loaded key and certificate instances. """ certPath = path.child(cert_filename) keyPath = path.child(key_filename) try: certFile = certPath.open() except IOError as e: code, failure = e raise PathError( b"Certificate file could not be opened.", e.filename, code, failure ) try: keyFile = keyPath.open() except IOError as e: code, failure = e raise PathError( b"Private key file could not be opened.", e.filename, code, failure ) certificate = Certificate.load( certFile.read(), format=crypto.FILETYPE_PEM) keypair = ComparableKeyPair( keypair=KeyPair.load(keyFile.read(), format=crypto.FILETYPE_PEM) ) return (keypair, certificate)
def start_ssl(self): check_ssl_keys() log.debug('Enabling SSL with PKey: %s, Cert: %s', self.pkey, self.cert) with open(configmanager.get_config_dir(self.cert)) as cert: certificate = Certificate.loadPEM(cert.read()).original with open(configmanager.get_config_dir(self.pkey)) as pkey: private_key = KeyPair.load(pkey.read(), FILETYPE_PEM).original options = CertificateOptions(privateKey=private_key, certificate=certificate, method=SSL.SSLv23_METHOD) ctx = options.getContext() ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3) ctx.use_certificate_chain_file(configmanager.get_config_dir(self.cert)) self.socket = reactor.listenSSL(self.port, self.site, options, interface=self.interface) ip = self.socket.getHost().host ip = '[%s]' % ip if is_ipv6(ip) else ip log.info('Serving at https://%s:%s%s', ip, self.port, self.base)
def _create_tls_server_context(config, cbdir, log): """ Create a CertificateOptions object for use with TLS listening endpoints. """ # server private key key_filepath = abspath(join(cbdir, config['key'])) log.info("Loading server TLS key from {key_filepath}", key_filepath=key_filepath) with open(key_filepath) as key_file: # server certificate (but only the server cert, no chain certs) cert_filepath = abspath(join(cbdir, config['certificate'])) log.info("Loading server TLS certificate from {cert_filepath}", cert_filepath=cert_filepath) with open(cert_filepath) as cert_file: key = KeyPair.load(key_file.read(), crypto.FILETYPE_PEM).original cert = Certificate.loadPEM(cert_file.read()).original # list of certificates that complete your verification chain extra_certs = None if 'chain_certificates' in config: extra_certs = [] for fname in config['chain_certificates']: extra_cert_filepath = abspath(join(cbdir, fname)) with open(extra_cert_filepath, 'r') as f: extra_certs.append(Certificate.loadPEM(f.read()).original) log.info("Loading server TLS chain certificate from {extra_cert_filepath}", extra_cert_filepath=extra_cert_filepath) # list of certificate authority certificate objects to use to verify the peer's certificate ca_certs = None if 'ca_certificates' in config: ca_certs = [] for fname in config['ca_certificates']: ca_cert_filepath = abspath(join(cbdir, fname)) with open(ca_cert_filepath, 'r') as f: ca_certs.append(Certificate.loadPEM(f.read()).original) log.info("Loading server TLS CA certificate from {ca_cert_filepath}", ca_cert_filepath=ca_cert_filepath) # ciphers we accept # # We prefer to make every single cipher (6 in total) _explicit_ (to reduce chances either we or the pattern-matching # language inside OpenSSL messes up) and drop support for Windows XP (we do WebSocket anyway). # # We don't use AES256 and SHA384, to reduce number of ciphers and since the additional # security gain seems not worth the additional performance drain. # # We also don't use ECDSA, since EC certificates a rare in the wild. # # The effective list of ciphers determined from an OpenSSL cipher string: # # openssl ciphers -v 'ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:' # # References: # # * https://www.ssllabs.com/ssltest/analyze.html?d=myserver.com # * http://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ # * http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT # * https://wiki.mozilla.org/Talk:Security/Server_Side_TLS # if 'ciphers' in config: log.info("Using explicit TLS ciphers from config") crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString(config['ciphers']) else: log.info("Using secure default TLS ciphers") crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString( # AEAD modes (GCM) # 'ECDHE-ECDSA-AES128-GCM-SHA256:' 'ECDHE-RSA-AES128-GCM-SHA256:' # 'ECDHE-ECDSA-AES256-GCM-SHA384:' # 'ECDHE-RSA-AES256-GCM-SHA384:' 'DHE-RSA-AES128-GCM-SHA256:' # 'DHE-RSA-AES256-GCM-SHA384:' # CBC modes 'ECDHE-RSA-AES128-SHA256:' 'DHE-RSA-AES128-SHA256:' 'ECDHE-RSA-AES128-SHA:' 'DHE-RSA-AES128-SHA:' ) # DH modes require a parameter file if 'dhparam' in config: dhpath = FilePath(abspath(join(cbdir, config['dhparam']))) dh_params = DiffieHellmanParameters.fromFile(dhpath) else: dh_params = None log.warn("No OpenSSL DH parameter file set - DH cipher modes will be deactive!") # create a TLS context factory # see: https://twistedmatrix.com/documents/current/api/twisted.internet.ssl.CertificateOptions.html ctx = CertificateOptions( privateKey=key, certificate=cert, extraCertChain=extra_certs, verify=(ca_certs is not None), caCerts=ca_certs, dhParameters=dh_params, acceptableCiphers=crossbar_ciphers, # TLS hardening method=TLSv1_2_METHOD, enableSingleUseKeys=True, enableSessions=False, enableSessionTickets=False, fixBrokenPeers=False, ) # Without a curve being set, ECDH won't be available even if listed # in acceptable ciphers! # # The curves available in OpenSSL can be listed: # # openssl ecparam -list_curves # # prime256v1: X9.62/SECG curve over a 256 bit prime field # # This is elliptic curve "NIST P-256" from here # http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf # # This seems to be the most widely used curve # # http://crypto.stackexchange.com/questions/11310/with-openssl-and-ecdhe-how-to-show-the-actual-curve-being-used # # and researchers think it is "ok" (other than wrt timing attacks etc) # # https://twitter.com/hyperelliptic/status/394258454342148096 # if ctx._ecCurve is None: log.warn("No OpenSSL elliptic curve set - EC cipher modes will be deactive!") else: if ctx._ecCurve.snName != "prime256v1": log.info("OpenSSL is using elliptic curve {curve}", curve=ctx._ecCurve.snName) else: log.info("OpenSSL is using elliptic curve prime256v1 (NIST P-256)") return ctx
def _create_tls_server_context(config, cbdir, log): """ Create a CertificateOptions object for use with TLS listening endpoints. """ # server private key key_filepath = abspath(join(cbdir, config['key'])) log.info("Loading server TLS key from {key_filepath}", key_filepath=key_filepath) with open(key_filepath) as key_file: # server certificate (but only the server cert, no chain certs) cert_filepath = abspath(join(cbdir, config['certificate'])) log.info("Loading server TLS certificate from {cert_filepath}", cert_filepath=cert_filepath) with open(cert_filepath) as cert_file: key = KeyPair.load(key_file.read(), crypto.FILETYPE_PEM).original cert = Certificate.loadPEM(cert_file.read()).original # list of certificates that complete your verification chain extra_certs = None if 'chain_certificates' in config: extra_certs = [] for fname in config['chain_certificates']: extra_cert_filepath = abspath(join(cbdir, fname)) with open(extra_cert_filepath, 'r') as f: extra_certs.append(Certificate.loadPEM(f.read()).original) log.info( "Loading server TLS chain certificate from {extra_cert_filepath}", extra_cert_filepath=extra_cert_filepath) # list of certificate authority certificate objects to use to verify the peer's certificate ca_certs = None if 'ca_certificates' in config: ca_certs = [] for fname in config['ca_certificates']: ca_cert_filepath = abspath(join(cbdir, fname)) with open(ca_cert_filepath, 'r') as f: ca_certs.append(Certificate.loadPEM(f.read()).original) log.info( "Loading server TLS CA certificate from {ca_cert_filepath}", ca_cert_filepath=ca_cert_filepath) # ciphers we accept # # We prefer to make every single cipher (6 in total) _explicit_ (to reduce chances either we or the pattern-matching # language inside OpenSSL messes up) and drop support for Windows XP (we do WebSocket anyway). # # We don't use AES256 and SHA384, to reduce number of ciphers and since the additional # security gain seems not worth the additional performance drain. # # We also don't use ECDSA, since EC certificates a rare in the wild. # # The effective list of ciphers determined from an OpenSSL cipher string: # # openssl ciphers -v 'ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:' # # References: # # * https://www.ssllabs.com/ssltest/analyze.html?d=myserver.com # * http://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ # * http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT # * https://wiki.mozilla.org/Talk:Security/Server_Side_TLS # if 'ciphers' in config: log.info("Using explicit TLS ciphers from config") crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString( config['ciphers']) else: log.info("Using secure default TLS ciphers") crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString( # AEAD modes (GCM) # 'ECDHE-ECDSA-AES128-GCM-SHA256:' 'ECDHE-RSA-AES128-GCM-SHA256:' # 'ECDHE-ECDSA-AES256-GCM-SHA384:' # 'ECDHE-RSA-AES256-GCM-SHA384:' 'DHE-RSA-AES128-GCM-SHA256:' # 'DHE-RSA-AES256-GCM-SHA384:' # CBC modes 'ECDHE-RSA-AES128-SHA256:' 'DHE-RSA-AES128-SHA256:' 'ECDHE-RSA-AES128-SHA:' 'DHE-RSA-AES128-SHA:') # DH modes require a parameter file if 'dhparam' in config: dhpath = FilePath(abspath(join(cbdir, config['dhparam']))) dh_params = DiffieHellmanParameters.fromFile(dhpath) else: dh_params = None log.warn( "No OpenSSL DH parameter file set - DH cipher modes will be deactive!" ) ctx = CertificateOptions( privateKey=key, certificate=cert, extraCertChain=extra_certs, verify=(ca_certs is not None), caCerts=ca_certs, dhParameters=dh_params, acceptableCiphers=crossbar_ciphers, # Disable SSLv3 and TLSv1 -- only allow TLSv1.1 or higher # # We are using Twisted private stuff (from twisted.internet._sslverify import TLSVersion), # as OpenSSL.SSL.TLSv1_1_METHOD wont work: # # [ERROR] File "../twisted/internet/_sslverify.py", line 1530, in __init__ # if raiseMinimumTo > self._defaultMinimumTLSVersion: # builtins.TypeError: '>' not supported between instances of 'int' and 'NamedConstant' # raiseMinimumTo=TLSVersion.TLSv1_1, # TLS hardening enableSingleUseKeys=True, enableSessions=False, enableSessionTickets=False, fixBrokenPeers=False, ) # Without a curve being set, ECDH won't be available even if listed # in acceptable ciphers! # # The curves available in OpenSSL can be listed: # # openssl ecparam -list_curves # # prime256v1: X9.62/SECG curve over a 256 bit prime field # # This is elliptic curve "NIST P-256" from here # http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf # # This seems to be the most widely used curve # # http://crypto.stackexchange.com/questions/11310/with-openssl-and-ecdhe-how-to-show-the-actual-curve-being-used # # and researchers think it is "ok" (other than wrt timing attacks etc) # # https://twitter.com/hyperelliptic/status/394258454342148096 # if False: # FIXME: this doesn't work anymore with Twisted 18.4. (there now seems more complex machinery # in self._ecChooser) if ctx._ecCurve is None: log.warn( "No OpenSSL elliptic curve set - EC cipher modes will be deactive!" ) else: if ctx._ecCurve.snName != "prime256v1": log.info("OpenSSL is using elliptic curve {curve}", curve=ctx._ecCurve.snName) else: log.info( "OpenSSL is using elliptic curve prime256v1 (NIST P-256)") return ctx
def create_connecting_endpoint_from_config(config, cbdir, reactor): """ Create a Twisted stream client endpoint from a Crossbar.io transport configuration. See: https://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IStreamClientEndpoint.html :param config: The transport configuration. :type config: dict :param cbdir: Crossbar.io node directory (we need this for Unix domain socket paths and TLS key/certificates). :type cbdir: str :param reactor: The reactor to use for endpoint creation. :type reactor: obj :returns obj -- An instance implementing IStreamClientEndpoint """ endpoint = None log = make_logger() # a TCP endpoint # if config['type'] == 'tcp': # the TCP protocol version (v4 or v6) # version = int(config.get('version', 4)) # the host to connect to # host = str(config['host']) # the port to connect to # port = int(config['port']) # connection timeout in seconds # timeout = int(config.get('timeout', 10)) if 'tls' in config: if _HAS_TLS: # if the config specified any CA certificates, we use those (only!) if 'ca_certificates' in config['tls']: ca_certs = [] for cert_fname in config['tls']['ca_certificates']: cert = crypto.load_certificate( crypto.FILETYPE_PEM, six.u(open(cert_fname, 'r').read())) log.info("Loaded CA certificate '{fname}'", fname=cert_fname) ca_certs.append(cert) client_cert = None if 'key' in config['tls']: with open(config['tls']['certificate'], 'r') as f: cert = Certificate.loadPEM(f.read(), ) log.info( "{fname}: CN={subj.CN}, sha={sha}", fname=config['tls']['certificate'], subj=cert.getSubject(), sha=cert.digest('sha'), ) with open(config['tls']['key'], 'r') as f: private_key = KeyPair.load( f.read(), format=crypto.FILETYPE_PEM, ) log.info( "{fname}: {key}", fname=config['tls']['key'], key=private_key.inspect(), ) client_cert = PrivateCertificate.fromCertificateAndKeyPair( cert, private_key) # XXX OpenSSLCertificateAuthorities is a "private" # class, in _sslverify, so we shouldn't really be # using it. However, while you can pass a single # Certificate as trustRoot= there's no way to pass # multiple ones. # XXX ...but maybe the config should only allow # the user to configure a single cert to trust # here anyway? options = optionsForClientTLS( config['tls']['hostname'], trustRoot=OpenSSLCertificateAuthorities(ca_certs), clientCertificate=client_cert, ) else: options = optionsForClientTLS(config['tls']['hostname']) # create a TLS client endpoint # if version == 4: endpoint = SSL4ClientEndpoint( reactor, host, port, options, timeout=timeout, ) elif version == 6: raise Exception("TLS on IPv6 not implemented") else: raise Exception( "invalid TCP protocol version {}".format(version)) else: raise Exception( "TLS transport requested, but TLS packages not available:\n{}" .format(_LACKS_TLS_MSG)) else: # create a non-TLS client endpoint # if version == 4: endpoint = TCP4ClientEndpoint(reactor, host, port, timeout=timeout) elif version == 6: endpoint = TCP6ClientEndpoint(reactor, host, port, timeout=timeout) else: raise Exception( "invalid TCP protocol version {}".format(version)) # a Unix Domain Socket endpoint # elif config['type'] == 'unix': # the path # path = abspath(join(cbdir, config['path'])) # connection timeout in seconds # timeout = int(config.get('timeout', 10)) # create the endpoint # endpoint = UNIXClientEndpoint(reactor, path, timeout=timeout) else: raise Exception("invalid endpoint type '{}'".format(config['type'])) return endpoint
def certoptions_factory(cert_file=None, cert_key=None, cert_ca=None): """ Factory pour un gestionnaire de paramètre de contextes SSL. @param cert_file: Emplacement du fichier du certificat client à présenter au serveur lors de la connexion, si souhaité. @type cert_file: C{str} @param cert_key: Emplacement de la clé privée correspondant au certificat spécifié par le paramètre C{cert_file} si celui-ci ne contient pas déjà la clé privée. @type cert_key: C{str} @param cert_ca: Liste des emplacements des certificats des autorités de confiance. @type cert_ca: C{list} @return: Instance contenant les réglages qui seront appliqués lors de la création du contexte SSL. @rtype: L{CertificateOptions} """ # Construction des objets associés à la gestion des certificats. # Tout d'abord, est-ce qu'on a un certificat client ? if cert_file: if cert_key: # Le certificat et la clé privée sont # dans 2 fichiers distincts. cert_handle = file(cert_file, 'r') pkey_handle = file(cert_key, 'r') try: cert = PrivateCertificate.fromCertificateAndKeyPair( Certificate.loadPEM(cert_handle.read()), KeyPair.load( pkey_handle.read(), crypto.FILETYPE_PEM ) ) finally: cert_handle.close() pkey_handle.close() else: # Le fichier contient à la fois # le certificat et sa clé privée. cert_handle = file(cert_file, 'r') try: cert = PrivateCertificate.loadPEM( cert_handle.read()) finally: cert_handle.close() # Construction de la liste des CA de confiance. cert_ca_objects = [] if cert_ca: # Une ou plusieurs CA ont été données en paramètre. for ca in cert_ca: ca_handle = file(ca, 'r') try: cert_ca_objects.append(Certificate.loadPEM( ca_handle.read())) finally: ca_handle.close() # Application des CA au certificat client. if cert_file: return cert.options(*cert_ca_objects) # Ou création d'un contexte qui ne valide le certificat du serveur # que si des CA ont été spécifiées. return CertificateOptions( method=SSL.SSLv23_METHOD, # SSLv2, SSLv3 ou TLSv1. verify=bool(cert_ca_objects), # Uniquement s'il y a des CAs. caCerts=[auth.original for auth in cert_ca_objects], requireCertificate=True, )
def create_listening_endpoint_from_config(config, cbdir, reactor): """ Create a Twisted stream server endpoint from a Crossbar.io transport configuration. See: https://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IStreamServerEndpoint.html :param config: The transport configuration. :type config: dict :param cbdir: Crossbar.io node directory (we need this for TLS key/certificates). :type cbdir: str :param reactor: The reactor to use for endpoint creation. :type reactor: obj :returns obj -- An instance implementing IStreamServerEndpoint """ log = make_logger() endpoint = None # a TCP endpoint # if config['type'] == 'tcp': # the TCP protocol version (v4 or v6) # version = int(config.get('version', 4)) # the listening port # if type(config['port']) is six.text_type: # read port from environment variable .. try: port = int(environ[config['port'][1:]]) except Exception as e: print( "Could not read listening port from env var: {}".format(e)) raise e else: port = config['port'] # the listening interface # interface = str(config.get('interface', '').strip()) # the TCP accept queue depth # backlog = int(config.get('backlog', 50)) if 'tls' in config: if _HAS_TLS: key_filepath = abspath(join(cbdir, config['tls']['key'])) cert_filepath = abspath( join(cbdir, config['tls']['certificate'])) with open(key_filepath) as key_file: with open(cert_filepath) as cert_file: if 'dhparam' in config['tls']: dhpath = FilePath( abspath(join(cbdir, config['tls']['dhparam']))) dh_params = DiffieHellmanParameters.fromFile( dhpath) else: # XXX won't be doing ANY EDH # curves... maybe make dhparam required? # or do "whatever tlxctx was doing" dh_params = None log.warn( "OpenSSL DH modes not active (no 'dhparam')") # create a TLS context factory # key = key_file.read() cert = cert_file.read() ca_certs = None if 'ca_certificates' in config['tls']: ca_certs = [] for fname in config['tls']['ca_certificates']: with open(fname, 'r') as f: ca_certs.append( Certificate.loadPEM(f.read()).original) crossbar_ciphers = AcceptableCiphers.fromOpenSSLCipherString( 'ECDHE-RSA-AES128-GCM-SHA256:' 'DHE-RSA-AES128-GCM-SHA256:' 'ECDHE-RSA-AES128-SHA256:' 'DHE-RSA-AES128-SHA256:' 'ECDHE-RSA-AES128-SHA:' 'DHE-RSA-AES128-SHA') ctx = CertificateOptions( privateKey=KeyPair.load( key, crypto.FILETYPE_PEM).original, certificate=Certificate.loadPEM(cert).original, verify=(ca_certs is not None), caCerts=ca_certs, dhParameters=dh_params, acceptableCiphers=crossbar_ciphers, ) if ctx._ecCurve is None: log.warn( "OpenSSL failed to set ECDH default curve") else: log.info( "Ok, OpenSSL is using ECDH elliptic curve {curve}", curve=ctx._ecCurve.snName, ) # create a TLS server endpoint # if version == 4: endpoint = SSL4ServerEndpoint(reactor, port, ctx, backlog=backlog, interface=interface) elif version == 6: raise Exception("TLS on IPv6 not implemented") else: raise Exception( "invalid TCP protocol version {}".format(version)) else: raise Exception( "TLS transport requested, but TLS packages not available:\n{}" .format(_LACKS_TLS_MSG)) else: # create a non-TLS server endpoint # if version == 4: endpoint = TCP4ServerEndpoint(reactor, port, backlog=backlog, interface=interface) elif version == 6: endpoint = TCP6ServerEndpoint(reactor, port, backlog=backlog, interface=interface) else: raise Exception( "invalid TCP protocol version {}".format(version)) # a Unix Domain Socket endpoint # elif config['type'] == 'unix': # the accept queue depth # backlog = int(config.get('backlog', 50)) # the path # path = FilePath(join(cbdir, config['path'])) # if there is already something there, delete it. # if path.exists(): log.info(("{path} exists, attempting to remove before using as a " "UNIX socket"), path=path) path.remove() # create the endpoint # endpoint = UNIXServerEndpoint(reactor, path.path, backlog=backlog) else: raise Exception("invalid endpoint type '{}'".format(config['type'])) return endpoint