diff --git a/synapse/config/tls.py b/synapse/config/tls.py
index f0014902da..5e4ed8289d 100644
--- a/synapse/config/tls.py
+++ b/synapse/config/tls.py
@@ -19,6 +19,8 @@ import warnings
from datetime import datetime
from hashlib import sha256
+from twisted.internet._sslverify import trustRootFromCertificates, Certificate
+
import six
from unpaddedbase64 import encode_base64
@@ -70,6 +72,37 @@ class TlsConfig(Config):
self.tls_fingerprints = list(self._original_tls_fingerprints)
+ # List of custom certificate authorities for TLS verification
+ self.federation_custom_ca_list = config.get(
+ "federation_custom_ca_list", [],
+ )
+
+ # Read in the CA certificates
+ cert_contents = []
+ try:
+ for ca_file in self.federation_custom_ca_list:
+ logger.debug("Reading custom CA certificate file: %s", ca_file)
+ with open(ca_file, 'rb') as f:
+ cert_contents.append(ca_file.read())
+ except:
+ logger.exception("Failed to read custom CA certificate off disk!")
+ raise
+
+ # Parse the CA certificates
+ certs = []
+ try:
+ for cert in certs:
+ logger.debug("Parsing custom CA certificate file: %s", ca_file)
+ cert_base = Certificate.loadPEM(content)
+ certs.append(cert_base)
+
+ trust_root = trustRootFromCertificates(certs)
+ except:
+ logger.exception("Failed to parse custom CA certificate off disk!")
+ raise
+
+ self.federation_custom_ca_list = trust_root
+
# 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
@@ -192,6 +225,16 @@ class TlsConfig(Config):
#
#tls_private_key_path: "%(tls_private_key_path)s"
+ # List of custom certificate authorities for federation traffic.
+ #
+ # Note that this list will replace those that are provided by your
+ # operating environment. Certificates must be in PEM format.
+ #
+ #federation_custom_ca_list:
+ # - myca1.pem
+ # - myca2.pem
+ # - myca3.pem
+
# ACME support: This will configure Synapse to request a valid TLS certificate
# for your configured `server_name` via Let's Encrypt.
#
diff --git a/synapse/crypto/context_factory.py b/synapse/crypto/context_factory.py
index b99159dbbd..7f747cd55a 100644
--- a/synapse/crypto/context_factory.py
+++ b/synapse/crypto/context_factory.py
@@ -128,7 +128,10 @@ class ClientTLSOptionsFactory(object):
def __init__(self, config):
# We don't use config options yet
- self._options_validate = CertificateOptions(verify=True)
+ self._options_validate = CertificateOptions(
+ # This option implies verify=True
+ trustRoot=config.federation_custom_ca_list,
+ )
self._options_novalidate = CertificateOptions(verify=False)
def get_options(self, host, config):
|