def creatorForNetloc(self, hostname, port): certificateOptions = CertificateOptions( trustRoot=self._trustRoot) return PermissiveClientTLSOptions( hostname.decode("ascii"), certificateOptions.getContext())
def __init__(self, config): self._config = config # Check if we're using a custom list of a CA certificates trust_root = config.federation_ca_trust_root if trust_root is None: # Use CA root certs provided by OpenSSL trust_root = platformTrust() # "insecurelyLowerMinimumTo" is the argument that will go lower than # Twisted's default, which is why it is marked as "insecure" (since # Twisted's defaults are reasonably secure). But, since Twisted is # moving to TLS 1.2 by default, we want to respect the config option if # it is set to 1.0 (which the alternate option, raiseMinimumTo, will not # let us do). minTLS = _TLS_VERSION_MAP[config.federation_client_minimum_tls_version] self._verify_ssl = CertificateOptions(trustRoot=trust_root, insecurelyLowerMinimumTo=minTLS) self._verify_ssl_context = self._verify_ssl.getContext() self._verify_ssl_context.set_info_callback(self._context_info_cb) self._no_verify_ssl = CertificateOptions( insecurelyLowerMinimumTo=minTLS) self._no_verify_ssl_context = self._no_verify_ssl.getContext() self._no_verify_ssl_context.set_info_callback(self._context_info_cb)
class ClientTLSOptionsFactory(object): """Factory for Twisted ClientTLSOptions that are used to make connections to remote servers for federation.""" def __init__(self, config): self._config = config self._options_noverify = CertificateOptions() # Check if we're using a custom list of a CA certificates trust_root = config.federation_ca_trust_root if trust_root is None: # Use CA root certs provided by OpenSSL trust_root = platformTrust() self._options_verify = CertificateOptions(trustRoot=trust_root) def get_options(self, host): # Use _makeContext so that we get a fresh OpenSSL CTX each time. # Check if certificate verification has been enabled should_verify = self._config.federation_verify_certificates # Check if we've disabled certificate verification for this host if should_verify: for regex in self._config.federation_certificate_verification_whitelist: if regex.match(host): should_verify = False break if should_verify: return ClientTLSOptions(host, self._options_verify._makeContext()) return ClientTLSOptionsNoVerify(host, self._options_noverify._makeContext())
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 __init__(self, mapping): self.mapping = mapping self._negotiationDataForContext = collections.defaultdict( _NegotiationData) try: self.context = self.mapping['DEFAULT'].getContext() except KeyError: self.context = CertificateOptions().getContext() self.context.set_tlsext_servername_callback(self.selectContext)
class ClientTLSOptionsFactory(object): """Factory for Twisted SSLClientConnectionCreators that are used to make connections to remote servers for federation. Uses one of two OpenSSL context objects for all connections, depending on whether we should do SSL certificate verification. get_options decides whether we should do SSL certificate verification and constructs an SSLClientConnectionCreator factory accordingly. """ def __init__(self, config): self._config = config # Check if we're using a custom list of a CA certificates trust_root = config.federation_ca_trust_root if trust_root is None: # Use CA root certs provided by OpenSSL trust_root = platformTrust() self._verify_ssl_context = CertificateOptions( trustRoot=trust_root).getContext() self._verify_ssl_context.set_info_callback(self._context_info_cb) self._no_verify_ssl_context = CertificateOptions().getContext() self._no_verify_ssl_context.set_info_callback(self._context_info_cb) def get_options(self, host): # Check if certificate verification has been enabled should_verify = self._config.federation_verify_certificates # Check if we've disabled certificate verification for this host if should_verify: for regex in self._config.federation_certificate_verification_whitelist: if regex.match(host): should_verify = False break ssl_context = (self._verify_ssl_context if should_verify else self._no_verify_ssl_context) return SSLClientConnectionCreator(host, ssl_context, should_verify) @staticmethod def _context_info_cb(ssl_connection, where, ret): """The 'information callback' for our openssl context object.""" # we assume that the app_data on the connection object has been set to # a TLSMemoryBIOProtocol object. (This is done by SSLClientConnectionCreator) tls_protocol = ssl_connection.get_app_data() try: # ... we further assume that SSLClientConnectionCreator has set the # '_synapse_tls_verifier' attribute to a ConnectionVerifier object. tls_protocol._synapse_tls_verifier.verify_context_info_cb( ssl_connection, where) except: # noqa: E722, taken from the twisted implementation logger.exception("Error during info_callback") f = Failure() tls_protocol.failVerification(f)
def test_snimap_default(self): """ SNIMap preferentially loads the DEFAULT value from the mapping if it's present. """ options = CertificateOptions() mapping = {'DEFAULT': options} sni_map = SNIMap(mapping) conn = sni_map.serverConnectionForTLS(protocol.Protocol()) self.assertIs(conn.get_context()._obj, options.getContext())
def __init__(self, config): self._config = config self._options_noverify = CertificateOptions() # Check if we're using a custom list of a CA certificates trust_root = config.federation_ca_trust_root if trust_root is None: # Use CA root certs provided by OpenSSL trust_root = platformTrust() self._options_verify = CertificateOptions(trustRoot=trust_root)
def test_snimap_makes_its_own_defaults(self): """ If passed a mapping without a DEFAULT key, SNIMap will make its own default context. """ options = CertificateOptions() mapping = {'example.com': options} sni_map = SNIMap(mapping) conn = sni_map.serverConnectionForTLS(protocol.Protocol()) self.assertIsNot(conn.get_context(), options.getContext()) self.assertIsNotNone(conn.get_context())
def __init__(self, settings, crawler=None): self.crawler = crawler self.default_maxsize = settings.getint('DOWNLOAD_MAXSIZE') self.default_warnsize = settings.getint('DOWNLOAD_WARNSIZE') self.fail_on_dataloss = settings.getbool('DOWNLOAD_FAIL_ON_DATALOSS') self.context_factory = CertificateOptions( verify=False, raiseMinimumTo=TLSVersion.TLSv1_2, fixBrokenPeers=True, )
def setUp(self): """ Set up client and server SSL contexts for use later. """ self.sKey, self.sCert = makeCertificate(O="Server Test Certificate", CN="server") self.cKey, self.cCert = makeCertificate(O="Client Test Certificate", CN="client") self.serverSSLContext = CertificateOptions(privateKey=self.sKey, certificate=self.sCert, requireCertificate=False) self.clientSSLContext = CertificateOptions(requireCertificate=False)
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)
class SNIMap(object): def __init__(self, mapping): self.mapping = mapping self._negotiationDataForContext = collections.defaultdict( _NegotiationData ) try: self.context = self.mapping['DEFAULT'].getContext() except KeyError: self.context = CertificateOptions().getContext() self.context.set_tlsext_servername_callback( self.selectContext ) def selectContext(self, connection): oldContext = connection.get_context() newContext = self.mapping[connection.get_servername()].getContext() negotiationData = self._negotiationDataForContext[oldContext] negotiationData.negotiateNPN(newContext) negotiationData.negotiateALPN(newContext) connection.set_context(newContext) def serverConnectionForTLS(self, protocol): """ Construct an OpenSSL server connection. @param protocol: The protocol initiating a TLS connection. @type protocol: L{TLSMemoryBIOProtocol} @return: a connection @rtype: L{OpenSSL.SSL.Connection} """ conn = Connection(self.context, None) return _ConnectionProxy(conn, self) def _npnAdvertiseCallbackForContext(self, context, callback): self._negotiationDataForContext[context].npnAdvertiseCallback = ( callback ) def _npnSelectCallbackForContext(self, context, callback): self._negotiationDataForContext[context].npnSelectCallback = callback def _alpnSelectCallbackForContext(self, context, callback): self._negotiationDataForContext[context].alpnSelectCallback = callback def _alpnProtocolsForContext(self, context, protocols): self._negotiationDataForContext[context].alpnProtocols = protocols
def __init__(self, config): self._config = config # Check if we're using a custom list of a CA certificates trust_root = config.federation_ca_trust_root if trust_root is None: # Use CA root certs provided by OpenSSL trust_root = platformTrust() self._verify_ssl_context = CertificateOptions( trustRoot=trust_root).getContext() self._verify_ssl_context.set_info_callback(self._context_info_cb) self._no_verify_ssl_context = CertificateOptions().getContext() self._no_verify_ssl_context.set_info_callback(self._context_info_cb)
class RegularPolicyForHTTPS: """Factory for Twisted SSLClientConnectionCreators that are used to make connections to remote servers, for other than federation. Always uses the same OpenSSL context object, which uses the default OpenSSL CA trust root. """ def __init__(self): trust_root = platformTrust() self._ssl_context = CertificateOptions( trustRoot=trust_root).getContext() self._ssl_context.set_info_callback(_context_info_cb) def creatorForNetloc(self, hostname, port): return SSLClientConnectionCreator(hostname, self._ssl_context, True)
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)
class MyWebClientContextFactory(object): def __init__(self): self._options = CertificateOptions() def getContext(self, hostname, port): return self._options.getContext()
class GeminiDownloadHandler: """ Scrapy download handler for gemini:// scheme URLs. This implementation is *heavily* based on scrapy's HTTP 1.1 and telnet handlers as references. I did, however, make several attempts to simplify the code and use idiomatic twisted patterns. Some integrity checks had to be removed since gemini does not use a Content-Length or checksum. Since scrapy is built around HTTP requests/responses, this code will take the gemini response and generate a pseudo-HTTP response with an equivalent status code and headers. This is necessary to retain compatibility with most of the library's middleware. """ lazy = False def __init__(self, settings, crawler=None): self.crawler = crawler self.default_maxsize = settings.getint('DOWNLOAD_MAXSIZE') self.default_warnsize = settings.getint('DOWNLOAD_WARNSIZE') self.fail_on_dataloss = settings.getbool('DOWNLOAD_FAIL_ON_DATALOSS') self.context_factory = CertificateOptions( verify=False, raiseMinimumTo=TLSVersion.TLSv1_2, fixBrokenPeers=True, ) @classmethod def from_crawler(cls, crawler): return cls(crawler.settings, crawler) def download_request(self, request, spider): bindaddress = request.meta.get('bindaddress') timeout = request.meta.get('download_timeout') maxsize = getattr(spider, 'download_maxsize', self.default_maxsize) warnsize = getattr(spider, 'download_warnsize', self.default_warnsize) parts = urlparse(request.url) remote_host = bindaddress or parts.hostname remote_port = parts.port or 1965 hostname = HostnameEndpoint(reactor, remote_host, remote_port) # The recommended helper method for this (optionsForClientTLS) does not # allow setting up a client context that accepts unverified certificates. # So we are forced to use the private ClientTLSOptions method instead. options = ScrapyClientTLSOptions(remote_host, self.context_factory.getContext()) # noinspection PyTypeChecker endpoint = wrapClientTLS(options, hostname) logger.debug(f"Creating download request for {request.url}") protocol = GeminiClientProtocol(request, maxsize, warnsize, timeout) # If the connection fails (DNS lookup, etc.) propagate the error so # that scrapy knows the request has completed. connected = connectProtocol(endpoint, protocol) connected.addErrback(protocol.finished.errback) return protocol.finished
def __init__(self): # Use CA root certs provided by OpenSSL trust_root = platformTrust() # "insecurelyLowerMinimumTo" is the argument that will go lower than # Twisted's default, which is why it is marked as "insecure" (since # Twisted's defaults are reasonably secure). But, since Twisted is # moving to TLS 1.2 by default, we want to respect the config option if # it is set to 1.0 (which the alternate option, raiseMinimumTo, will not # let us do). minTLS = TLSVersion.TLSv1_2 self._verify_ssl = CertificateOptions(trustRoot=trust_root, insecurelyLowerMinimumTo=minTLS) self._verify_ssl_context = self._verify_ssl.getContext() self._verify_ssl_context.set_info_callback(self._context_info_cb)
def getContext(self, host, port): ctx = CertificateOptions.getContext(self) ctx.set_verify_depth(0) ctx.set_verify( OpenSSL.SSL.VERIFY_PEER | OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT, self.verifyHostname) return ctx
def getContext(self) -> SSL.Context: def always_validate(conn, cert, errno, depth, preverify_ok): # This function is called to validate the certificate received by # the other end. OpenSSL calls it multiple times, for each errno # for each certificate. # We do not care about certificate authorities or revocation # lists, we just want to know that the certificate has a valid # signature and follow the chain back to one which is # self-signed. We need to protect against forged signatures, but # not the usual TLS concerns about invalid CAs or revoked # certificates. things_are_ok = ( _OPENSSL.X509_V_OK, _OPENSSL.X509_V_ERR_CERT_NOT_YET_VALID, _OPENSSL.X509_V_ERR_CERT_HAS_EXPIRED, _OPENSSL.X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, _OPENSSL.X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, ) # TODO can we do this once instead of multiple times? if errno in things_are_ok and timing_safe_compare( get_spki_hash(cert.to_cryptography()), self.expected_spki_hash): return 1 # TODO: log the details of the error, because otherwise they get # lost in the PyOpenSSL exception that will eventually be raised # (possibly OpenSSL.SSL.Error: certificate verify failed) return 0 ctx = CertificateOptions.getContext(self) # VERIFY_PEER means we ask the the other end for their certificate. ctx.set_verify(SSL.VERIFY_PEER, always_validate) return ctx
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 getContextFactory(self): if SSL is None: raise RuntimeError("No SSL support: you need to install OpenSSL.") cert = PrivateCertificate.loadPEM(self.certificatePath.open().read()) certOpts = CertificateOptions(cert.privateKey.original, cert.original, requireCertificate=False, method=SSL.SSLv23_METHOD) return certOpts
def __init__(self, mapping): self.mapping = mapping try: self.context = self.mapping['DEFAULT'].getContext() except KeyError: self.context = CertificateOptions().getContext() self.context.set_tlsext_servername_callback( self.selectContext )
def createCertOptions(server): pk = None cert = None if server.cert: pc = PrivateCertificate.loadPEM(open(server.cert,"rb").read()) pk = pc.privateKey.original cert = pc.original tr = platformTrust() if server.verify else None return CertificateOptions(privateKey=pk, certificate=cert, trustRoot=tr)
def __init__(self): self.running = False # open/create poloniex database, ticker collection/table self.db = MongoClient().poloniex['ticker'] # thread namespace self._appProcess = None self._appRunner = ApplicationRunner(u"wss://api.poloniex.com:443", u"realm1", ssl=CertificateOptions())
class SNIMap(ContextFactory, object): def __init__(self, mapping): self.mapping = mapping try: self.context = self.mapping['DEFAULT'].getContext() except KeyError: self.context = CertificateOptions().getContext() self.context.set_tlsext_servername_callback( self.selectContext ) def getContext(self): return self.context def selectContext(self, connection): connection.set_context( self.mapping[connection.get_servername()] .getContext() )
class ClientTLSOptionsFactory(object): """Factory for Twisted ClientTLSOptions that are used to make connections to remote servers for federation.""" def __init__(self, config): # We don't use config options yet self._options = CertificateOptions(verify=False) def get_options(self, host): # Use _makeContext so that we get a fresh OpenSSL CTX each time. return ClientTLSOptions(host, self._options._makeContext())
class ClientTLSOptionsFactory(object): """Factory for Twisted SSLClientConnectionCreators that are used to make connections to remote servers for federation. Uses one of two OpenSSL context objects for all connections, depending on whether we should do SSL certificate verification. get_options decides whether we should do SSL certificate verification and constructs an SSLClientConnectionCreator factory accordingly. """ def __init__(self): # Use CA root certs provided by OpenSSL trust_root = platformTrust() # "insecurelyLowerMinimumTo" is the argument that will go lower than # Twisted's default, which is why it is marked as "insecure" (since # Twisted's defaults are reasonably secure). But, since Twisted is # moving to TLS 1.2 by default, we want to respect the config option if # it is set to 1.0 (which the alternate option, raiseMinimumTo, will not # let us do). minTLS = TLSVersion.TLSv1_2 self._verify_ssl = CertificateOptions( trustRoot=trust_root, insecurelyLowerMinimumTo=minTLS ) self._verify_ssl_context = self._verify_ssl.getContext() self._verify_ssl_context.set_info_callback(self._context_info_cb) def get_options(self, host): ssl_context = self._verify_ssl_context return SSLClientConnectionCreator(host, ssl_context) @staticmethod def _context_info_cb(ssl_connection, where, ret): """The 'information callback' for our openssl context object.""" # we assume that the app_data on the connection object has been set to # a TLSMemoryBIOProtocol object. (This is done by SSLClientConnectionCreator) tls_protocol = ssl_connection.get_app_data() try: # ... we further assume that SSLClientConnectionCreator has set the # '_synapse_tls_verifier' attribute to a ConnectionVerifier object. tls_protocol._synapse_tls_verifier.verify_context_info_cb( ssl_connection, where ) except: # noqa: E722, taken from the twisted implementation logger.exception("Error during info_callback") f = Failure() tls_protocol.failVerification(f) def creatorForNetloc(self, hostname, port): """Implements the IPolicyForHTTPS interace so that this can be passed directly to agents. """ return self.get_options(hostname)
def start_responding(self, server_name, challenge, response): """ Put a context into the mapping. """ server_name = response.z_domain.decode('ascii') cert, pkey = generate_tls_sni_01_cert( server_name, _generate_private_key=self._generate_private_key) server_name = server_name.encode('utf-8') self._challenge_options[server_name] = CertificateOptions( certificate=cert_cryptography_to_pyopenssl(cert), privateKey=key_cryptography_to_pyopenssl(pkey))
def __init__(self, mapping): self.mapping = mapping self._negotiationDataForContext = collections.defaultdict( _NegotiationData ) try: self.context = self.mapping['DEFAULT'].getContext() except KeyError: self.context = CertificateOptions().getContext() self.context.set_tlsext_servername_callback( self.selectContext )
def getContext(self): ctx = CertificateOptions.getContext(self) # VERIFY_PEER means we ask the the other end for their certificate. # not adding VERIFY_FAIL_IF_NO_PEER_CERT means it's ok if they don't # give us one (i.e. if an anonymous client connects to an # authenticated server). I don't know what VERIFY_CLIENT_ONCE does. ctx.set_verify(SSL.VERIFY_PEER | #SSL.VERIFY_FAIL_IF_NO_PEER_CERT | SSL.VERIFY_CLIENT_ONCE, alwaysValidate) return ctx
def getContext(self): ctx = CertificateOptions.getContext(self) # VERIFY_PEER means we ask the the other end for their certificate. # not adding VERIFY_FAIL_IF_NO_PEER_CERT means it's ok if they don't # give us one (i.e. if an anonymous client connects to an # authenticated server). I don't know what VERIFY_CLIENT_ONCE does. ctx.set_verify( SSL.VERIFY_PEER | #SSL.VERIFY_FAIL_IF_NO_PEER_CERT | SSL.VERIFY_CLIENT_ONCE, alwaysValidate) return ctx
def getCertificateOptions(self): from OpenSSL import crypto v1 = crypto.load_privatekey( crypto.FILETYPE_PEM, open('/Users/wupeiqi/client.key.unsecure', mode='r').read()) v2 = crypto.load_certificate( crypto.FILETYPE_PEM, open('/Users/wupeiqi/client.pem', mode='r').read()) return CertificateOptions( privateKey=v1, # pKey对象 certificate=v2, # X509对象 verify=False, method=getattr(self, 'method', getattr(self, '_ssl_method', None)))
def _default_options(self, trust_root): """ Construct a ``CertificateOptions`` that exposes this credential's certificate and keypair. :param trust_root: Trust root to pass to ``CertificateOptions``. :return: ``CertificateOptions`` instance with CA validation configured. """ key = self.credential.keypair.keypair.original certificate = self.credential.certificate.original return CertificateOptions( privateKey=key, certificate=certificate, trustRoot=trust_root)
def getCertificateOptions(self): # setting verify=True will require you to provide CAs # to verify against; in other words: it's not that simple # backward-compatible SSL/TLS method: # # * this will respect `method` attribute in often recommended # `ScrapyClientContextFactory` subclass # (https://github.com/scrapy/scrapy/issues/1429#issuecomment-131782133) # # * getattr() for `_ssl_method` attribute for context factories # not calling super(..., self).__init__ return CertificateOptions(verify=False, method=getattr(self, 'method', getattr(self, '_ssl_method', None)))
def __init__(self, **kwargs): CertificateOptions.__init__(self, **kwargs)
def getContext(self, hostname, port): return CertificateOptions.getContext(self)
def __init__(self, clientCert=None): if clientCert is None: options = CertificateOptions() else: options = clientCert.options() self._ctx = options.getContext()
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, # TLS hardening enableSingleUseKeys=True, enableSessions=False, enableSessionTickets=False, fixBrokenPeers=False, ) # Disable SSLv3 and TLSv1 -- only do 1.1+ ctx._options = ctx._options | OP_NO_SSLv3 | OP_NO_TLSv1 # 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 getContext(self, host, port): ctx = CertificateOptions.getContext(self) ctx.set_verify_depth(0) ctx.set_verify(OpenSSL.SSL.VERIFY_PEER | OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT, self.verifyHostname) return ctx
def getContext(self, hostname, port): opts = CertificateOptions(verify=True, caCerts=[self._cacert]) return opts.getContext()
def _makeContext(self): context = CertificateOptions._makeContext(self) context.set_verify( SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, self.verify_callback) return context
def __init__(self, host, caCerts=None): if caCerts is None: caCerts = get_global_ca_certs() CertificateOptions.__init__(self, verify=True, caCerts=caCerts) self.host = host
def __init__(self, torproject_pem): CertificateOptions.__init__(self) self.torproject_ca = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, open(torproject_pem, 'r').read())
def __init__(self): self._options = CertificateOptions()