diff options
-rw-r--r-- | changelog.d/4642.feature | 1 | ||||
-rw-r--r-- | changelog.d/4652.feature | 1 | ||||
-rw-r--r-- | changelog.d/4666.feature | 2 | ||||
-rw-r--r-- | changelog.d/4670.feature | 1 | ||||
-rw-r--r-- | changelog.d/4674.feature | 1 | ||||
-rw-r--r-- | docs/workers.rst | 3 | ||||
-rw-r--r-- | synapse/app/client_reader.py | 2 | ||||
-rw-r--r-- | synapse/config/tls.py | 15 | ||||
-rw-r--r-- | synapse/crypto/context_factory.py | 14 | ||||
-rw-r--r-- | synapse/handlers/acme.py | 9 | ||||
-rw-r--r-- | synapse/handlers/room.py | 22 | ||||
-rw-r--r-- | synapse/storage/registration.py | 82 |
12 files changed, 98 insertions, 55 deletions
diff --git a/changelog.d/4642.feature b/changelog.d/4642.feature new file mode 100644 index 0000000000..bfbf95bcbb --- /dev/null +++ b/changelog.d/4642.feature @@ -0,0 +1 @@ +Transfer bans on room upgrade. \ No newline at end of file diff --git a/changelog.d/4652.feature b/changelog.d/4652.feature new file mode 100644 index 0000000000..ebe6880b21 --- /dev/null +++ b/changelog.d/4652.feature @@ -0,0 +1 @@ +Support .well-known delegation when issuing certificates through ACME. diff --git a/changelog.d/4666.feature b/changelog.d/4666.feature index 421060f9f9..b3a3915eb0 100644 --- a/changelog.d/4666.feature +++ b/changelog.d/4666.feature @@ -1 +1 @@ -Allow registration to be handled by a worker instance. +Allow registration and login to be handled by a worker instance. diff --git a/changelog.d/4670.feature b/changelog.d/4670.feature new file mode 100644 index 0000000000..b3a3915eb0 --- /dev/null +++ b/changelog.d/4670.feature @@ -0,0 +1 @@ +Allow registration and login to be handled by a worker instance. diff --git a/changelog.d/4674.feature b/changelog.d/4674.feature new file mode 100644 index 0000000000..84630bb201 --- /dev/null +++ b/changelog.d/4674.feature @@ -0,0 +1 @@ +Reduce the overhead of creating outbound federation connections over TLS by caching the TLS client options. diff --git a/docs/workers.rst b/docs/workers.rst index 6ce7d88c11..3ba5879f76 100644 --- a/docs/workers.rst +++ b/docs/workers.rst @@ -222,11 +222,12 @@ following regular expressions:: ^/_matrix/client/(api/v1|r0|unstable)/rooms/.*/context/.*$ ^/_matrix/client/(api/v1|r0|unstable)/rooms/.*/members$ ^/_matrix/client/(api/v1|r0|unstable)/rooms/.*/state$ + ^/_matrix/client/(api/v1|r0|unstable)/login$ Additionally, the following REST endpoints can be handled, but all requests must be routed to the same instance:: - ^/_matrix/client/(api/v1|r0|unstable)/register$ + ^/_matrix/client/(r0|unstable)/register$ ``synapse.app.user_dir`` diff --git a/synapse/app/client_reader.py b/synapse/app/client_reader.py index 9250b6c239..043b48f8f3 100644 --- a/synapse/app/client_reader.py +++ b/synapse/app/client_reader.py @@ -40,6 +40,7 @@ from synapse.replication.slave.storage.registration import SlavedRegistrationSto from synapse.replication.slave.storage.room import RoomStore from synapse.replication.slave.storage.transactions import SlavedTransactionStore from synapse.replication.tcp.client import ReplicationClientHandler +from synapse.rest.client.v1.login import LoginRestServlet from synapse.rest.client.v1.room import ( JoinedRoomMemberListRestServlet, PublicRoomListRestServlet, @@ -94,6 +95,7 @@ class ClientReaderServer(HomeServer): RoomStateRestServlet(self).register(resource) RoomEventContextServlet(self).register(resource) RegisterRestServlet(self).register(resource) + LoginRestServlet(self).register(resource) resources.update({ "/_matrix/client/r0": resource, diff --git a/synapse/config/tls.py b/synapse/config/tls.py index 5fb3486db1..38425bb056 100644 --- a/synapse/config/tls.py +++ b/synapse/config/tls.py @@ -42,6 +42,7 @@ class TlsConfig(Config): 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")) @@ -229,6 +230,20 @@ class TlsConfig(Config): # # reprovision_threshold: 30 + # The domain that the certificate should be for. Normally this + # should be the same as your Matrix domain (i.e., 'server_name'), but, + # by putting a file at 'https://<server_name>/.well-known/matrix/server', + # you can delegate incoming traffic to another server. If you do that, + # you should give the target of the delegation here. + # + # For example: if your 'server_name' is 'example.com', but + # 'https://example.com/.well-known/matrix/server' delegates to + # 'matrix.example.com', you should put 'matrix.example.com' here. + # + # If not set, defaults to your 'server_name'. + # + # domain: matrix.example.com + # 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 diff --git a/synapse/crypto/context_factory.py b/synapse/crypto/context_factory.py index 85f2848fb1..49cbc7098f 100644 --- a/synapse/crypto/context_factory.py +++ b/synapse/crypto/context_factory.py @@ -1,4 +1,5 @@ # Copyright 2014-2016 OpenMarket Ltd +# Copyright 2019 New Vector Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,6 +12,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + import logging from zope.interface import implementer @@ -105,9 +107,7 @@ class ClientTLSOptions(object): self._hostnameBytes = _idnaBytes(hostname) self._sendSNI = True - ctx.set_info_callback( - _tolerateErrors(self._identityVerifyingInfoCallback) - ) + ctx.set_info_callback(_tolerateErrors(self._identityVerifyingInfoCallback)) def clientConnectionForTLS(self, tlsProtocol): context = self._ctx @@ -128,10 +128,8 @@ class ClientTLSOptionsFactory(object): def __init__(self, config): # We don't use config options yet - pass + self._options = CertificateOptions(verify=False) def get_options(self, host): - return ClientTLSOptions( - host, - CertificateOptions(verify=False).getContext() - ) + # Use _makeContext so that we get a fresh OpenSSL CTX each time. + return ClientTLSOptions(host, self._options._makeContext()) diff --git a/synapse/handlers/acme.py b/synapse/handlers/acme.py index dd0b217965..813777bf18 100644 --- a/synapse/handlers/acme.py +++ b/synapse/handlers/acme.py @@ -56,6 +56,7 @@ class AcmeHandler(object): def __init__(self, hs): self.hs = hs self.reactor = hs.get_reactor() + self._acme_domain = hs.config.acme_domain @defer.inlineCallbacks def start_listening(self): @@ -123,15 +124,15 @@ class AcmeHandler(object): @defer.inlineCallbacks def provision_certificate(self): - logger.warning("Reprovisioning %s", self.hs.hostname) + logger.warning("Reprovisioning %s", self._acme_domain) try: - yield self._issuer.issue_cert(self.hs.hostname) + yield self._issuer.issue_cert(self._acme_domain) except Exception: logger.exception("Fail!") raise - logger.warning("Reprovisioned %s, saving.", self.hs.hostname) - cert_chain = self._store.certs[self.hs.hostname] + logger.warning("Reprovisioned %s, saving.", self._acme_domain) + cert_chain = self._store.certs[self._acme_domain] try: with open(self.hs.config.tls_private_key_file, "wb") as private_key_file: diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index f9af1f0046..67b15697fd 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -311,6 +311,28 @@ class RoomCreationHandler(BaseHandler): creation_content=creation_content, ) + # Transfer membership events + old_room_member_state_ids = yield self.store.get_filtered_current_state_ids( + old_room_id, StateFilter.from_types([(EventTypes.Member, None)]), + ) + + # map from event_id to BaseEvent + old_room_member_state_events = yield self.store.get_events( + old_room_member_state_ids.values(), + ) + for k, old_event in iteritems(old_room_member_state_events): + # Only transfer ban events + if ("membership" in old_event.content and + old_event.content["membership"] == "ban"): + yield self.room_member_handler.update_membership( + requester, + UserID.from_string(old_event['state_key']), + new_room_id, + "ban", + ratelimit=False, + content=old_event.content, + ) + # XXX invites/joins # XXX 3pid invites diff --git a/synapse/storage/registration.py b/synapse/storage/registration.py index 3bc5def48e..9b9572890b 100644 --- a/synapse/storage/registration.py +++ b/synapse/storage/registration.py @@ -254,6 +254,47 @@ class RegistrationWorkerStore(SQLBaseStore): defer.returnValue(ret["guest_access_token"]) defer.returnValue(None) + @defer.inlineCallbacks + def get_user_id_by_threepid(self, medium, address): + """Returns user id from threepid + + Args: + medium (str): threepid medium e.g. email + address (str): threepid address e.g. me@example.com + + Returns: + Deferred[str|None]: user id or None if no user id/threepid mapping exists + """ + user_id = yield self.runInteraction( + "get_user_id_by_threepid", self.get_user_id_by_threepid_txn, + medium, address + ) + defer.returnValue(user_id) + + def get_user_id_by_threepid_txn(self, txn, medium, address): + """Returns user id from threepid + + Args: + txn (cursor): + medium (str): threepid medium e.g. email + address (str): threepid address e.g. me@example.com + + Returns: + str|None: user id or None if no user id/threepid mapping exists + """ + ret = self._simple_select_one_txn( + txn, + "user_threepids", + { + "medium": medium, + "address": address + }, + ['user_id'], True + ) + if ret: + return ret['user_id'] + return None + class RegistrationStore(RegistrationWorkerStore, background_updates.BackgroundUpdateStore): @@ -613,47 +654,6 @@ class RegistrationStore(RegistrationWorkerStore, ) defer.returnValue(ret) - @defer.inlineCallbacks - def get_user_id_by_threepid(self, medium, address): - """Returns user id from threepid - - Args: - medium (str): threepid medium e.g. email - address (str): threepid address e.g. me@example.com - - Returns: - Deferred[str|None]: user id or None if no user id/threepid mapping exists - """ - user_id = yield self.runInteraction( - "get_user_id_by_threepid", self.get_user_id_by_threepid_txn, - medium, address - ) - defer.returnValue(user_id) - - def get_user_id_by_threepid_txn(self, txn, medium, address): - """Returns user id from threepid - - Args: - txn (cursor): - medium (str): threepid medium e.g. email - address (str): threepid address e.g. me@example.com - - Returns: - str|None: user id or None if no user id/threepid mapping exists - """ - ret = self._simple_select_one_txn( - txn, - "user_threepids", - { - "medium": medium, - "address": address - }, - ['user_id'], True - ) - if ret: - return ret['user_id'] - return None - def user_delete_threepid(self, user_id, medium, address): return self._simple_delete( "user_threepids", |