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
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
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
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
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
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