Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Add config option for adding additional TLS fingerprints #1167

Merged
merged 3 commits into from
Oct 12, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions synapse/config/tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
import subprocess
import os

from hashlib import sha256
from unpaddedbase64 import encode_base64

GENERATE_DH_PARAMS = False


Expand All @@ -42,6 +45,19 @@ def read_config(self, config):
config.get("tls_dh_params_path"), "tls_dh_params"
)

self.tls_fingerprints = config["tls_fingerprints"]

# Check that our own certificate is included in the list of fingerprints
# and include it if it is not.
x509_certificate_bytes = crypto.dump_certificate(
crypto.FILETYPE_ASN1,
self.tls_certificate
)
sha256_fingerprint = encode_base64(sha256(x509_certificate_bytes).digest())
sha256_fingerprints = set(f["sha256"] for f in self.tls_fingerprints)
if sha256_fingerprint not in sha256_fingerprints:
self.tls_fingerprints.append({u"sha256": sha256_fingerprint})

# 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
Expand Down Expand Up @@ -73,6 +89,27 @@ def default_config(self, config_dir_path, server_name, **kwargs):

# Don't bind to the https port
no_tls: False

# List of allowed TLS fingerprints for this server to publish along
# with the signing keys for this server. Other matrix servers that
# make HTTPS requests to this server will check that the TLS
# certificates returned by this server match one of the fingerprints.
#
# Synapse automatically adds its the fingerprint of its own certificate
# to the list. So if federation traffic is handle directly by synapse
# then no modification to the list is required.
#
# If synapse is run behind a load balancer that handles the TLS then it
# will be necessary to add the fingerprints of the certificates used by
# the loadbalancers to this list if they are different to the one
# synapse is using.
#
# Homeservers are permitted to cache the list of TLS fingerprints
# returned in the key responses. It may be necessary to publish the
# fingerprints of a new certificate and wait for the caches on other
# servers to expire before deploying it.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This worries me a bit if we're not explicit about the cache invaliadtion timings

tls_fingerprints: []
#- {"sha256": "<base64_encoded_sha256_fingerprint>"}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a confusing way of giving an example, I was quite confused for a minute. Maybe:

tls_fingerprints: []
# tls_fingerprints: [{"sha256": "<base64_encoded_sha256_fingerprint>"}, ...]

""" % locals()

def read_tls_certificate(self, cert_path):
Expand Down
16 changes: 4 additions & 12 deletions synapse/rest/key/v2/local_key_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
from signedjson.sign import sign_json
from unpaddedbase64 import encode_base64
from canonicaljson import encode_canonical_json
from hashlib import sha256
from OpenSSL import crypto
import logging


Expand Down Expand Up @@ -49,7 +47,8 @@ class LocalKey(Resource):
"key": # base64 encoded NACL verification key.
}
}
"tls_certificate": # base64 ASN.1 DER encoded X.509 tls cert.
"tls_fingerprints": # Fingerprints of the TLS certs this server uses.
- {"sha256": "..."}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. This is JSON not yaml
  2. Are we actually changing the API here? Won't that affect when other servers look up keys?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We aren't changing the API. The comment is just a tiny bit out of date.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\o/

"signatures": {
"this.server.example.com": {
"algorithm:version": # NACL signature for this server
Expand Down Expand Up @@ -90,21 +89,14 @@ def response_json_object(self):
u"expired_ts": key.expired,
}

x509_certificate_bytes = crypto.dump_certificate(
crypto.FILETYPE_ASN1,
self.config.tls_certificate
)

sha256_fingerprint = sha256(x509_certificate_bytes).digest()
tls_fingerprints = self.config.tls_fingerprints

json_object = {
u"valid_until_ts": self.valid_until_ts,
u"server_name": self.config.server_name,
u"verify_keys": verify_keys,
u"old_verify_keys": old_verify_keys,
u"tls_fingerprints": [{
u"sha256": encode_base64(sha256_fingerprint),
}]
u"tls_fingerprints": tls_fingerprints,
}
for key in self.config.signing_key:
json_object = sign_json(
Expand Down