Пример #1
0
    def creatorForNetloc(self, hostname, port):
        certificateOptions = CertificateOptions(
            trustRoot=self._trustRoot)

        return PermissiveClientTLSOptions(
            hostname.decode("ascii"),
            certificateOptions.getContext())
Пример #2
0
    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)
Пример #3
0
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())
Пример #4
0
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 creatorForNetloc(self, hostname, port):
        certificateOptions = CertificateOptions(
            trustRoot=self._trustRoot)

        return PermissiveClientTLSOptions(
            hostname.decode("ascii"),
            certificateOptions.getContext())
Пример #6
0
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())
Пример #7
0
 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)
Пример #8
0
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)
Пример #9
0
    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())
Пример #10
0
    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)
Пример #11
0
    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())
Пример #12
0
    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)
Пример #13
0
    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())
Пример #14
0
    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,
        )
Пример #15
0
    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())
Пример #16
0
 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)
Пример #17
0
    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)
Пример #18
0
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
Пример #19
0
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
Пример #20
0
    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)
Пример #21
0
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)
Пример #22
0
    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)
Пример #23
0
class MyWebClientContextFactory(object):

    def __init__(self):
        self._options = CertificateOptions()

    def getContext(self, hostname, port):
        return self._options.getContext()
Пример #24
0
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
Пример #25
0
    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)
Пример #26
0
 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
Пример #27
0
    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
Пример #28
0
    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)
Пример #29
0
 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
Пример #30
0
 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
     )
Пример #31
0
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)
Пример #32
0
 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())
Пример #33
0
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()
        )
Пример #34
0
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())
Пример #35
0
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)
Пример #36
0
 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))
Пример #37
0
 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
     )
Пример #38
0
    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
Пример #39
0
    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
Пример #40
0
    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)
Пример #41
0
 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)))
Пример #42
0
    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)
Пример #43
0
        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)))
Пример #44
0
 def __init__(self, **kwargs):
     CertificateOptions.__init__(self, **kwargs)
Пример #45
0
 def getContext(self, hostname, port):
     return CertificateOptions.getContext(self)
Пример #46
0
 def __init__(self, clientCert=None):
     if clientCert is None:
         options = CertificateOptions()
     else:
         options = clientCert.options()
     self._ctx = options.getContext()
Пример #47
0
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
Пример #48
0
 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
Пример #49
0
 def getContext(self, hostname, port):
     opts = CertificateOptions(verify=True, caCerts=[self._cacert])
     return opts.getContext()
Пример #50
0
 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
Пример #51
0
 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
Пример #52
0
 def __init__(self, torproject_pem):
     CertificateOptions.__init__(self)
     self.torproject_ca = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, open(torproject_pem, 'r').read())
Пример #53
0
 def __init__(self):
     self._options = CertificateOptions()