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