Address changes. Make federation_domain_whitelist not None

This commit is contained in:
Andrew Morgan 2019-04-02 18:10:13 +01:00
parent a8adde0624
commit e083ae39cd
9 changed files with 40 additions and 53 deletions

View file

@ -111,13 +111,11 @@ class ServerConfig(Config):
self.admin_contact = config.get("admin_contact", None) self.admin_contact = config.get("admin_contact", None)
# FIXME: federation_domain_whitelist needs sytests # FIXME: federation_domain_whitelist needs sytests
self.federation_domain_whitelist = None self.federation_domain_whitelist = {}
federation_domain_whitelist = config.get( federation_domain_whitelist = config.get(
"federation_domain_whitelist", None "federation_domain_whitelist", [],
) )
# turn the whitelist into a hash for speed of lookup # turn the whitelist into a hash for speed of lookup
if federation_domain_whitelist is not None:
self.federation_domain_whitelist = {}
for domain in federation_domain_whitelist: for domain in federation_domain_whitelist:
self.federation_domain_whitelist[domain] = True self.federation_domain_whitelist[domain] = True

View file

@ -77,14 +77,12 @@ class TlsConfig(Config):
) )
# Whitelist of domains to not verify certificates for # Whitelist of domains to not verify certificates for
self.federation_certificate_verification_whitelist = None self.federation_certificate_verification_whitelist = {}
federation_certificate_verification_whitelist = config.get( federation_certificate_verification_whitelist = config.get(
"federation_certificate_verification_whitelist", None "federation_certificate_verification_whitelist", [],
) )
# Store whitelisted domains in a hash for fast lookup # Store whitelisted domains in a hash for fast lookup
if federation_certificate_verification_whitelist is not None:
self.federation_certificate_verification_whitelist = {}
for domain in federation_certificate_verification_whitelist: for domain in federation_certificate_verification_whitelist:
self.federation_certificate_verification_whitelist[domain] = True self.federation_certificate_verification_whitelist[domain] = True
@ -102,7 +100,7 @@ class TlsConfig(Config):
with open(ca_file, 'rb') as f: with open(ca_file, 'rb') as f:
content = f.read() content = f.read()
except Exception: except Exception:
logger.exception("Failed to read custom CA certificate off disk!") logger.fatal("Failed to read custom CA certificate off disk!")
raise raise
# Parse the CA certificates # Parse the CA certificates
@ -110,10 +108,9 @@ class TlsConfig(Config):
cert_base = Certificate.loadPEM(content) cert_base = Certificate.loadPEM(content)
certs.append(cert_base) certs.append(cert_base)
except Exception: except Exception:
logger.exception("Failed to parse custom CA certificate off disk!") logger.fatal("Failed to parse custom CA certificate off disk!")
raise raise
if len(certs) > 0:
self.federation_custom_ca_list = trustRootFromCertificates(certs) self.federation_custom_ca_list = trustRootFromCertificates(certs)
# This config option applies to non-federation HTTP clients # This config option applies to non-federation HTTP clients
@ -146,14 +143,12 @@ class TlsConfig(Config):
with open(self.tls_certificate_file, 'rb') as f: with open(self.tls_certificate_file, 'rb') as f:
cert_pem = f.read() cert_pem = f.read()
except Exception: except Exception:
logger.exception("Failed to read existing certificate off disk!") logger.fatal("Failed to read existing certificate off disk!")
raise
try: try:
tls_certificate = crypto.load_certificate(crypto.FILETYPE_PEM, cert_pem) tls_certificate = crypto.load_certificate(crypto.FILETYPE_PEM, cert_pem)
except Exception: except Exception:
logger.exception("Failed to parse existing certificate off disk!") logger.fatal("Failed to parse existing certificate off disk!")
raise
if not allow_self_signed: if not allow_self_signed:
if tls_certificate.get_subject() == tls_certificate.get_issuer(): if tls_certificate.get_subject() == tls_certificate.get_issuer():
@ -240,10 +235,18 @@ class TlsConfig(Config):
# Whether to verify TLS certificates when sending federation traffic. # Whether to verify TLS certificates when sending federation traffic.
# #
# This currently defaults to `false`, however this will change in
# Synapse 1.0 when valid federation certificates will be required.
#
#federation_verify_certificates: true #federation_verify_certificates: true
# Prevent federation certificate validation on the following whitelist # Skip federation certificate validation on the following whitelist of
# of domains. Only effective if federation_verify_certicates is true. # domains.
#
# Note that this should only be used within the context of private
# federation as it will otherwise break things.
#
# Only effective if federation_verify_certicates is `true`.
# #
#federation_certificate_validation_whitelist: #federation_certificate_validation_whitelist:
# - lon.example.com # - lon.example.com

View file

@ -18,7 +18,10 @@ import logging
from zope.interface import implementer from zope.interface import implementer
from OpenSSL import SSL, crypto from OpenSSL import SSL, crypto
from twisted.internet._sslverify import OpenSSLCertificateAuthorities, _defaultCurveName from twisted.internet._sslverify import (
ClientTLSOptions as ClientTLSOptionsVerify,
_defaultCurveName,
)
from twisted.internet.abstract import isIPAddress, isIPv6Address from twisted.internet.abstract import isIPAddress, isIPv6Address
from twisted.internet.interfaces import IOpenSSLClientConnectionCreator from twisted.internet.interfaces import IOpenSSLClientConnectionCreator
from twisted.internet.ssl import CertificateOptions, ContextFactory, platformTrust from twisted.internet.ssl import CertificateOptions, ContextFactory, platformTrust
@ -132,7 +135,7 @@ class ClientTLSOptionsFactory(object):
self._options_novalidate = CertificateOptions() self._options_novalidate = CertificateOptions()
# Check if we're using a custom list of a CA certificates # Check if we're using a custom list of a CA certificates
if isinstance(config.federation_custom_ca_list, OpenSSLCertificateAuthorities): if config.federation_custom_ca_list is not None:
self._options_validate = CertificateOptions( self._options_validate = CertificateOptions(
# Use custom CA trusted root certs # Use custom CA trusted root certs
trustRoot=config.federation_custom_ca_list, trustRoot=config.federation_custom_ca_list,
@ -152,7 +155,7 @@ class ClientTLSOptionsFactory(object):
if (self._config.federation_verify_certificates and if (self._config.federation_verify_certificates and
host not in self._config.federation_certificate_validation_whitelist): host not in self._config.federation_certificate_validation_whitelist):
# Require verification # Require verification
return ClientTLSOptions(host, self._options_validate._makeContext()) return ClientTLSOptionsVerify(host, self._options_validate._makeContext())
# Otherwise don't require verification # Otherwise don't require verification
return ClientTLSOptions(host, self._options_novalidate._makeContext()) return ClientTLSOptions(host, self._options_novalidate._makeContext())

View file

@ -127,10 +127,7 @@ class Authenticator(object):
json_request["origin"] = origin json_request["origin"] = origin
json_request["signatures"].setdefault(origin, {})[key] = sig json_request["signatures"].setdefault(origin, {})[key] = sig
if ( if (origin not in self.federation_domain_whitelist):
self.federation_domain_whitelist is not None and
origin not in self.federation_domain_whitelist
):
raise FederationDeniedError(origin) raise FederationDeniedError(origin)
if not json_request["signatures"]: if not json_request["signatures"]:

View file

@ -177,7 +177,6 @@ class MatrixFederationHttpClient(object):
self.agent = MatrixFederationAgent( self.agent = MatrixFederationAgent(
hs.get_reactor(), hs.get_reactor(),
tls_client_options_factory, tls_client_options_factory,
hs.config,
) )
self.clock = hs.get_clock() self.clock = hs.get_clock()
self._store = hs.get_datastore() self._store = hs.get_datastore()
@ -284,10 +283,7 @@ class MatrixFederationHttpClient(object):
else: else:
_sec_timeout = self.default_timeout _sec_timeout = self.default_timeout
if ( if (request.destination not in self.hs.config.federation_domain_whitelist):
self.hs.config.federation_domain_whitelist is not None and
request.destination not in self.hs.config.federation_domain_whitelist
):
raise FederationDeniedError(request.destination) raise FederationDeniedError(request.destination)
limiter = yield synapse.util.retryutils.get_retry_limiter( limiter = yield synapse.util.retryutils.get_retry_limiter(

View file

@ -139,10 +139,7 @@ class RemoteKey(Resource):
store_queries = [] store_queries = []
for server_name, key_ids in query.items(): for server_name, key_ids in query.items():
if ( if (server_name not in self.federation_domain_whitelist):
self.federation_domain_whitelist is not None and
server_name not in self.federation_domain_whitelist
):
logger.debug("Federation denied with %s", server_name) logger.debug("Federation denied with %s", server_name)
continue continue

View file

@ -231,10 +231,7 @@ class MediaRepository(object):
Deferred: Resolves once a response has successfully been written Deferred: Resolves once a response has successfully been written
to request to request
""" """
if ( if (server_name not in self.federation_domain_whitelist):
self.federation_domain_whitelist is not None and
server_name not in self.federation_domain_whitelist
):
raise FederationDeniedError(server_name) raise FederationDeniedError(server_name)
self.mark_recently_accessed(server_name, media_id) self.mark_recently_accessed(server_name, media_id)
@ -271,10 +268,7 @@ class MediaRepository(object):
Returns: Returns:
Deferred[dict]: The media_info of the file Deferred[dict]: The media_info of the file
""" """
if ( if (server_name not in self.federation_domain_whitelist):
self.federation_domain_whitelist is not None and
server_name not in self.federation_domain_whitelist
):
raise FederationDeniedError(server_name) raise FederationDeniedError(server_name)
# We linearize here to ensure that we don't try and download remote # We linearize here to ensure that we don't try and download remote

View file

@ -39,6 +39,7 @@ from synapse.util.logcontext import LoggingContext
from tests.http import ServerTLSContext from tests.http import ServerTLSContext
from tests.server import FakeTransport, ThreadedMemoryReactorClock from tests.server import FakeTransport, ThreadedMemoryReactorClock
from tests.unittest import TestCase from tests.unittest import TestCase
from tests.utils import default_config
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -49,16 +50,11 @@ class MatrixFederationAgentTests(TestCase):
self.mock_resolver = Mock() self.mock_resolver = Mock()
config = Mock()
config.federation_custom_ca_list = None
config.federation_verify_certificates = False
config.federation_certificate_validation_whitelist = []
self.well_known_cache = TTLCache("test_cache", timer=self.reactor.seconds) self.well_known_cache = TTLCache("test_cache", timer=self.reactor.seconds)
self.agent = MatrixFederationAgent( self.agent = MatrixFederationAgent(
reactor=self.reactor, reactor=self.reactor,
tls_client_options_factory=ClientTLSOptionsFactory(config), tls_client_options_factory=ClientTLSOptionsFactory(default_config()),
_well_known_tls_policy=TrustingTLSPolicyForHTTPS(), _well_known_tls_policy=TrustingTLSPolicyForHTTPS(),
_srv_resolver=self.mock_resolver, _srv_resolver=self.mock_resolver,
_well_known_cache=self.well_known_cache, _well_known_cache=self.well_known_cache,

View file

@ -136,7 +136,10 @@ def default_config(name):
config.worker_app = None config.worker_app = None
config.email_enable_notifs = False config.email_enable_notifs = False
config.block_non_admin_invites = False config.block_non_admin_invites = False
config.federation_domain_whitelist = None config.federation_domain_whitelist = []
config.federation_certificate_verification_whitelist = []
config.federation_custom_ca_list = []
config.federation_verify_certificates = False
config.federation_rc_reject_limit = 10 config.federation_rc_reject_limit = 10
config.federation_rc_sleep_limit = 10 config.federation_rc_sleep_limit = 10
config.federation_rc_sleep_delay = 100 config.federation_rc_sleep_delay = 100