Ejemplo n.º 1
0
    def cacheContext(self):
        # Unfortunate code duplication.
        ctx = SSLContext(self.sslmethod)

        # Always disable SSLv2/SSLv3/Compression
        ctx.set_options(OP_NO_SSLv2)
        ctx.set_options(OP_NO_SSLv3)
        ctx.set_options(_OP_NO_COMPRESSION)

        if self.ciphers is not None:
            ctx.set_cipher_list(self.ciphers)
            ctx.set_options(OP_CIPHER_SERVER_PREFERENCE)

        if self.passwdCallback is not None:
            ctx.set_passwd_cb(self.passwdCallback)

        if self.keychainIdentity and hasattr(ctx, "use_keychain_identity"):
            ctx.use_keychain_identity(self.keychainIdentity)
        else:
            if self.certificateFileName:
                ctx.use_certificate_file(self.certificateFileName)
            if self.privateKeyFileName:
                ctx.use_privatekey_file(self.privateKeyFileName)
            if self.certificateChainFile:
                ctx.use_certificate_chain_file(self.certificateChainFile)

        verifyFlags = VERIFY_NONE
        if self.verifyClient:
            verifyFlags = VERIFY_PEER
            if self.requireClientCertificate:
                verifyFlags |= VERIFY_FAIL_IF_NO_PEER_CERT
            if self.verifyClientOnce:
                verifyFlags |= VERIFY_CLIENT_ONCE
            if self.clientCACertFileNames:
                store = ctx.get_cert_store()
                for cert in self.clientCACertFileNames:
                    with open(cert) as f:
                        certpem = f.read()
                    cert = Certificate.loadPEM(certpem)
                    store.add_cert(cert.original)
                    if self.sendCAsToClient:
                        ctx.add_client_ca(cert.original)

            # When a client certificate is used we also need to set a session context id
            # to avoid openssl SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED
            # errors
            ctx.set_session_id(str(uuid.uuid4()).replace("-", ""))

        # It'd be nice if pyOpenSSL let us pass None here for this behavior (as
        # the underlying OpenSSL API call allows NULL to be passed).  It
        # doesn't, so we'll supply a function which does the same thing.
        def _verifyCallback(conn, cert, errno, depth, preverify_ok):
            return preverify_ok

        ctx.set_verify(verifyFlags, _verifyCallback)

        if self.verifyClientDepth is not None:
            ctx.set_verify_depth(self.verifyClientDepth)

        self._context = ctx
Ejemplo n.º 2
0
    def creatorForNetloc(self, hostname, port):
        """
        Create a L{client connection creator
        <twisted.internet.interfaces.IOpenSSLClientConnectionCreator>} for a
        given network location.

        @param tls: The TLS protocol to create a connection for.
        @type tls: L{twisted.protocols.tls.TLSMemoryBIOProtocol}

        @param hostname: The hostname part of the URI.
        @type hostname: L{bytes}

        @param port: The port part of the URI.
        @type port: L{int}

        @return: a connection creator with appropriate verification
            restrictions set
        @rtype: L{client connection creator
            <twisted.internet.interfaces.IOpenSSLClientConnectionCreator>}
        """

        key_pair = KeyPair.load(self.key, format=FILETYPE_PEM)
        cert = PrivateCertificate.fromCertificateAndKeyPair(Certificate.loadPEM(self.crt), key_pair)

        authority = ssl.Certificate.loadPEM(self.ca)

        options = optionsForClientTLS(hostname.decode("ascii"), authority, clientCertificate=cert)

        # bypass hostname verification
        # options._identityVerifyingInfoCallback = self._identityVerifyingInfoCallback
        options._ctx.set_info_callback(
            _tolerateErrors(self._identityVerifyingInfoCallback)
        )
        return options
Ejemplo n.º 3
0
    def processPeerCertificate(self):
        # Look for SSL client cert
        if self._secure:
            try:
                self.peerCredentials = TLSCredentials(Certificate.peerFromTransport(self.transport))
            except CertificateError:
                pass

        self.peerCertificateCheck = True
Ejemplo n.º 4
0
    def processPeerCertificate(self):
        # Look for SSL client cert
        if self._secure:
            try:
                self.peerCredentials = TLSCredentials(
                    Certificate.peerFromTransport(self.transport))
            except CertificateError:
                pass

        self.peerCertificateCheck = True
Ejemplo n.º 5
0
    def read_config(self, config: dict, config_dir_path: str, **kwargs):

        acme_config = config.get("acme", None)
        if acme_config is None:
            acme_config = {}

        self.acme_enabled = acme_config.get("enabled", False)

        if self.acme_enabled:
            logger.warning(ACME_SUPPORT_ENABLED_WARN)

        # hyperlink complains on py2 if this is not a Unicode
        self.acme_url = str(
            acme_config.get("url",
                            "https://acme-v01.api.letsencrypt.org/directory"))
        self.acme_port = acme_config.get("port", 80)
        self.acme_bind_addresses = acme_config.get("bind_addresses",
                                                   ["::", "0.0.0.0"])
        self.acme_reprovision_threshold = acme_config.get(
            "reprovision_threshold", 30)
        self.acme_domain = acme_config.get("domain", config.get("server_name"))

        self.acme_account_key_file = self.abspath(
            acme_config.get("account_key_file",
                            config_dir_path + "/client.key"))

        self.tls_certificate_file = self.abspath(
            config.get("tls_certificate_path"))
        self.tls_private_key_file = self.abspath(
            config.get("tls_private_key_path"))

        if self.root.server.has_tls_listener():
            if not self.tls_certificate_file:
                raise ConfigError(
                    "tls_certificate_path must be specified if TLS-enabled listeners are "
                    "configured.")
            if not self.tls_private_key_file:
                raise ConfigError(
                    "tls_private_key_path must be specified if TLS-enabled listeners are "
                    "configured.")

        self._original_tls_fingerprints = config.get("tls_fingerprints", [])

        if self._original_tls_fingerprints is None:
            self._original_tls_fingerprints = []

        self.tls_fingerprints = list(self._original_tls_fingerprints)

        # Whether to verify certificates on outbound federation traffic
        self.federation_verify_certificates = config.get(
            "federation_verify_certificates", True)

        # Minimum TLS version to use for outbound federation traffic
        self.federation_client_minimum_tls_version = str(
            config.get("federation_client_minimum_tls_version", 1))

        if self.federation_client_minimum_tls_version not in [
                "1", "1.1", "1.2", "1.3"
        ]:
            raise ConfigError(
                "federation_client_minimum_tls_version must be one of: 1, 1.1, 1.2, 1.3"
            )

        # Prevent people shooting themselves in the foot here by setting it to
        # the biggest number blindly
        if self.federation_client_minimum_tls_version == "1.3":
            if getattr(SSL, "OP_NO_TLSv1_3", None) is None:
                raise ConfigError(
                    ("federation_client_minimum_tls_version cannot be 1.3, "
                     "your OpenSSL does not support it"))

        # Whitelist of domains to not verify certificates for
        fed_whitelist_entries = config.get(
            "federation_certificate_verification_whitelist", [])
        if fed_whitelist_entries is None:
            fed_whitelist_entries = []

        # Support globs (*) in whitelist values
        self.federation_certificate_verification_whitelist = [
        ]  # type: List[str]
        for entry in fed_whitelist_entries:
            try:
                entry_regex = glob_to_regex(
                    entry.encode("ascii").decode("ascii"))
            except UnicodeEncodeError:
                raise ConfigError(
                    "IDNA domain names are not allowed in the "
                    "federation_certificate_verification_whitelist: %s" %
                    (entry, ))

            # Convert globs to regex
            self.federation_certificate_verification_whitelist.append(
                entry_regex)

        # List of custom certificate authorities for federation traffic validation
        custom_ca_list = config.get("federation_custom_ca_list", None)

        # Read in and parse custom CA certificates
        self.federation_ca_trust_root = None
        if custom_ca_list is not None:
            if len(custom_ca_list) == 0:
                # A trustroot cannot be generated without any CA certificates.
                # Raise an error if this option has been specified without any
                # corresponding certificates.
                raise ConfigError(
                    "federation_custom_ca_list specified without "
                    "any certificate files")

            certs = []
            for ca_file in custom_ca_list:
                logger.debug("Reading custom CA certificate file: %s", ca_file)
                content = self.read_file(ca_file, "federation_custom_ca_list")

                # Parse the CA certificates
                try:
                    cert_base = Certificate.loadPEM(content)
                    certs.append(cert_base)
                except Exception as e:
                    raise ConfigError(
                        "Error parsing custom CA certificate file %s: %s" %
                        (ca_file, e))

            self.federation_ca_trust_root = trustRootFromCertificates(certs)

        # This config option applies to non-federation HTTP clients
        # (e.g. for talking to recaptcha, identity servers, and such)
        # It should never be used in production, and is intended for
        # use only when running tests.
        self.use_insecure_ssl_client_just_for_testing_do_not_use = config.get(
            "use_insecure_ssl_client_just_for_testing_do_not_use")

        self.tls_certificate = None
        self.tls_private_key = None
Ejemplo n.º 6
0
    def read_config(self, config):

        acme_config = config.get("acme", None)
        if acme_config is None:
            acme_config = {}

        self.acme_enabled = acme_config.get("enabled", False)

        # hyperlink complains on py2 if this is not a Unicode
        self.acme_url = six.text_type(acme_config.get(
            "url", u"https://acme-v01.api.letsencrypt.org/directory"
        ))
        self.acme_port = acme_config.get("port", 80)
        self.acme_bind_addresses = acme_config.get("bind_addresses", ['::', '0.0.0.0'])
        self.acme_reprovision_threshold = acme_config.get("reprovision_threshold", 30)
        self.acme_domain = acme_config.get("domain", config.get("server_name"))

        self.tls_certificate_file = self.abspath(config.get("tls_certificate_path"))
        self.tls_private_key_file = self.abspath(config.get("tls_private_key_path"))

        if self.has_tls_listener():
            if not self.tls_certificate_file:
                raise ConfigError(
                    "tls_certificate_path must be specified if TLS-enabled listeners are "
                    "configured."
                )
            if not self.tls_private_key_file:
                raise ConfigError(
                    "tls_private_key_path must be specified if TLS-enabled listeners are "
                    "configured."
                )

        self._original_tls_fingerprints = config.get("tls_fingerprints", [])

        if self._original_tls_fingerprints is None:
            self._original_tls_fingerprints = []

        self.tls_fingerprints = list(self._original_tls_fingerprints)

        # Whether to verify certificates on outbound federation traffic
        self.federation_verify_certificates = config.get(
            "federation_verify_certificates", True,
        )

        # Whitelist of domains to not verify certificates for
        fed_whitelist_entries = config.get(
            "federation_certificate_verification_whitelist", [],
        )

        # Support globs (*) in whitelist values
        self.federation_certificate_verification_whitelist = []
        for entry in fed_whitelist_entries:
            # Convert globs to regex
            entry_regex = glob_to_regex(entry)
            self.federation_certificate_verification_whitelist.append(entry_regex)

        # List of custom certificate authorities for federation traffic validation
        custom_ca_list = config.get(
            "federation_custom_ca_list", None,
        )

        # Read in and parse custom CA certificates
        self.federation_ca_trust_root = None
        if custom_ca_list is not None:
            if len(custom_ca_list) == 0:
                # A trustroot cannot be generated without any CA certificates.
                # Raise an error if this option has been specified without any
                # corresponding certificates.
                raise ConfigError("federation_custom_ca_list specified without "
                                  "any certificate files")

            certs = []
            for ca_file in custom_ca_list:
                logger.debug("Reading custom CA certificate file: %s", ca_file)
                content = self.read_file(ca_file, "federation_custom_ca_list")

                # Parse the CA certificates
                try:
                    cert_base = Certificate.loadPEM(content)
                    certs.append(cert_base)
                except Exception as e:
                    raise ConfigError("Error parsing custom CA certificate file %s: %s"
                                      % (ca_file, e))

            self.federation_ca_trust_root = trustRootFromCertificates(certs)

        # This config option applies to non-federation HTTP clients
        # (e.g. for talking to recaptcha, identity servers, and such)
        # It should never be used in production, and is intended for
        # use only when running tests.
        self.use_insecure_ssl_client_just_for_testing_do_not_use = config.get(
            "use_insecure_ssl_client_just_for_testing_do_not_use"
        )

        self.tls_certificate = None
        self.tls_private_key = None
Ejemplo n.º 7
0
    def read_config(self, config: JsonDict, **kwargs: Any) -> None:

        self.tls_certificate_file = self.abspath(config.get("tls_certificate_path"))
        self.tls_private_key_file = self.abspath(config.get("tls_private_key_path"))

        if self.root.server.has_tls_listener():
            if not self.tls_certificate_file:
                raise ConfigError(
                    "tls_certificate_path must be specified if TLS-enabled listeners are "
                    "configured."
                )
            if not self.tls_private_key_file:
                raise ConfigError(
                    "tls_private_key_path must be specified if TLS-enabled listeners are "
                    "configured."
                )

        # Whether to verify certificates on outbound federation traffic
        self.federation_verify_certificates = config.get(
            "federation_verify_certificates", True
        )

        # Minimum TLS version to use for outbound federation traffic
        self.federation_client_minimum_tls_version = str(
            config.get("federation_client_minimum_tls_version", 1)
        )

        if self.federation_client_minimum_tls_version not in ["1", "1.1", "1.2", "1.3"]:
            raise ConfigError(
                "federation_client_minimum_tls_version must be one of: 1, 1.1, 1.2, 1.3"
            )

        # Prevent people shooting themselves in the foot here by setting it to
        # the biggest number blindly
        if self.federation_client_minimum_tls_version == "1.3":
            if getattr(SSL, "OP_NO_TLSv1_3", None) is None:
                raise ConfigError(
                    "federation_client_minimum_tls_version cannot be 1.3, "
                    "your OpenSSL does not support it"
                )

        # Whitelist of domains to not verify certificates for
        fed_whitelist_entries = config.get(
            "federation_certificate_verification_whitelist", []
        )
        if fed_whitelist_entries is None:
            fed_whitelist_entries = []

        # Support globs (*) in whitelist values
        self.federation_certificate_verification_whitelist: List[Pattern] = []
        for entry in fed_whitelist_entries:
            try:
                entry_regex = glob_to_regex(entry.encode("ascii").decode("ascii"))
            except UnicodeEncodeError:
                raise ConfigError(
                    "IDNA domain names are not allowed in the "
                    "federation_certificate_verification_whitelist: %s" % (entry,)
                )

            # Convert globs to regex
            self.federation_certificate_verification_whitelist.append(entry_regex)

        # List of custom certificate authorities for federation traffic validation
        custom_ca_list = config.get("federation_custom_ca_list", None)

        # Read in and parse custom CA certificates
        self.federation_ca_trust_root = None
        if custom_ca_list is not None:
            if len(custom_ca_list) == 0:
                # A trustroot cannot be generated without any CA certificates.
                # Raise an error if this option has been specified without any
                # corresponding certificates.
                raise ConfigError(
                    "federation_custom_ca_list specified without "
                    "any certificate files"
                )

            certs = []
            for ca_file in custom_ca_list:
                logger.debug("Reading custom CA certificate file: %s", ca_file)
                content = self.read_file(ca_file, "federation_custom_ca_list")

                # Parse the CA certificates
                try:
                    cert_base = Certificate.loadPEM(content)
                    certs.append(cert_base)
                except Exception as e:
                    raise ConfigError(
                        "Error parsing custom CA certificate file %s: %s" % (ca_file, e)
                    )

            self.federation_ca_trust_root = trustRootFromCertificates(certs)

        # This config option applies to non-federation HTTP clients
        # (e.g. for talking to recaptcha, identity servers, and such)
        # It should never be used in production, and is intended for
        # use only when running tests.
        self.use_insecure_ssl_client_just_for_testing_do_not_use = config.get(
            "use_insecure_ssl_client_just_for_testing_do_not_use"
        )

        self.tls_certificate: Optional[crypto.X509] = None
        self.tls_private_key: Optional[crypto.PKey] = None
Ejemplo n.º 8
0
    def read_config(self, config):

        acme_config = config.get("acme", None)
        if acme_config is None:
            acme_config = {}

        self.acme_enabled = acme_config.get("enabled", False)

        # hyperlink complains on py2 if this is not a Unicode
        self.acme_url = six.text_type(acme_config.get(
            "url", u"https://acme-v01.api.letsencrypt.org/directory"
        ))
        self.acme_port = acme_config.get("port", 80)
        self.acme_bind_addresses = acme_config.get("bind_addresses", ['::', '0.0.0.0'])
        self.acme_reprovision_threshold = acme_config.get("reprovision_threshold", 30)
        self.acme_domain = acme_config.get("domain", config.get("server_name"))

        self.tls_certificate_file = self.abspath(config.get("tls_certificate_path"))
        self.tls_private_key_file = self.abspath(config.get("tls_private_key_path"))

        if self.has_tls_listener():
            if not self.tls_certificate_file:
                raise ConfigError(
                    "tls_certificate_path must be specified if TLS-enabled listeners are "
                    "configured."
                )
            if not self.tls_private_key_file:
                raise ConfigError(
                    "tls_private_key_path must be specified if TLS-enabled listeners are "
                    "configured."
                )

        self._original_tls_fingerprints = config.get("tls_fingerprints", [])

        if self._original_tls_fingerprints is None:
            self._original_tls_fingerprints = []

        self.tls_fingerprints = list(self._original_tls_fingerprints)

        # Whether to verify certificates on outbound federation traffic
        self.federation_verify_certificates = config.get(
            "federation_verify_certificates", False,
        )

        # Whitelist of domains to not verify certificates for
        fed_whitelist_entries = config.get(
            "federation_certificate_verification_whitelist", [],
        )

        # Support globs (*) in whitelist values
        self.federation_certificate_verification_whitelist = []
        for entry in fed_whitelist_entries:
            # Convert globs to regex
            entry_regex = glob_to_regex(entry)
            self.federation_certificate_verification_whitelist.append(entry_regex)

        # List of custom certificate authorities for federation traffic validation
        custom_ca_list = config.get(
            "federation_custom_ca_list", None,
        )

        # Read in and parse custom CA certificates
        self.federation_ca_trust_root = None
        if custom_ca_list is not None:
            if len(custom_ca_list) == 0:
                # A trustroot cannot be generated without any CA certificates.
                # Raise an error if this option has been specified without any
                # corresponding certificates.
                raise ConfigError("federation_custom_ca_list specified without "
                                  "any certificate files")

            certs = []
            for ca_file in custom_ca_list:
                logger.debug("Reading custom CA certificate file: %s", ca_file)
                content = self.read_file(ca_file)

                # Parse the CA certificates
                try:
                    cert_base = Certificate.loadPEM(content)
                    certs.append(cert_base)
                except Exception as e:
                    raise ConfigError("Error parsing custom CA certificate file %s: %s"
                                      % (ca_file, e))

            self.federation_ca_trust_root = trustRootFromCertificates(certs)

        # This config option applies to non-federation HTTP clients
        # (e.g. for talking to recaptcha, identity servers, and such)
        # It should never be used in production, and is intended for
        # use only when running tests.
        self.use_insecure_ssl_client_just_for_testing_do_not_use = config.get(
            "use_insecure_ssl_client_just_for_testing_do_not_use"
        )

        self.tls_certificate = None
        self.tls_private_key = None