diff --git a/changelog.d/19585.misc b/changelog.d/19585.misc new file mode 100644 index 0000000000..621cf782f1 --- /dev/null +++ b/changelog.d/19585.misc @@ -0,0 +1 @@ +Prevent sending registration emails if registration is disabled. \ No newline at end of file diff --git a/synapse/rest/client/register.py b/synapse/rest/client/register.py index fdd2f1985a..73832ba7a8 100644 --- a/synapse/rest/client/register.py +++ b/synapse/rest/client/register.py @@ -86,6 +86,7 @@ class EmailRegisterRequestTokenRestServlet(RestServlet): self.server_name = hs.hostname self.identity_handler = hs.get_identity_handler() self.config = hs.config + self._registration_enabled = hs.config.registration.enable_registration if self.hs.config.email.can_verify_email: self.registration_mailer = Mailer( @@ -109,6 +110,14 @@ class EmailRegisterRequestTokenRestServlet(RestServlet): raise SynapseError( 400, "Email-based registration has been disabled on this server" ) + + if not self._registration_enabled: + raise SynapseError( + 403, + "Registration is disabled on this homeserver", + Codes.FORBIDDEN, + ) + body = parse_json_object_from_request(request) assert_params_in_dict(body, ["client_secret", "email", "send_attempt"]) diff --git a/tests/rest/client/test_register.py b/tests/rest/client/test_register.py index 2c0396a3de..f66c56a6b1 100644 --- a/tests/rest/client/test_register.py +++ b/tests/rest/client/test_register.py @@ -22,7 +22,7 @@ import datetime import importlib.resources as importlib_resources import os -from typing import Any +from typing import Any, cast from unittest.mock import AsyncMock from twisted.internet.testing import MemoryReactor @@ -66,6 +66,17 @@ class RegisterRestServletTestCase(unittest.HomeserverTestCase): hs.get_send_email_handler()._sendmail = AsyncMock() return hs + def _get_sendmail_mock(self) -> AsyncMock: + """ + Cast the homeserver's `_sendmail` object as an `AsyncMock`. + + `_sendmail` is an `AsyncMock` (see `make_homeserver`) but this type + information doesn't make it through the test harness. Thus we need to + cast the object again. + """ + sendmail = self.hs.get_send_email_handler()._sendmail + return cast(AsyncMock, sendmail) + def test_POST_appservice_registration_valid(self) -> None: user_id = "@as_user_kermit:test" as_token = "i_am_an_app_service" @@ -747,6 +758,33 @@ class RegisterRestServletTestCase(unittest.HomeserverTestCase): self.assertIsNotNone(channel.json_body.get("sid")) + @unittest.override_config( + { + "public_baseurl": "https://test_server", + "email": { + "smtp_host": "mail_server", + "smtp_port": 2525, + "notif_from": "sender@host", + }, + } + ) + def test_request_token_allowed_when_email_flow_is_advertised(self) -> None: + sendmail = self._get_sendmail_mock() + sendmail.reset_mock() + + channel = self.make_request( + "POST", + b"register/email/requestToken", + { + "client_secret": "foobar", + "email": "test@example.com", + "send_attempt": 1, + }, + ) + self.assertEqual(200, channel.code, channel.result) + self.assertIsNotNone(channel.json_body.get("sid")) + sendmail.assert_awaited_once() + @unittest.override_config( { "public_baseurl": "https://test_server",