diff --git a/changelog.d/12091.misc b/changelog.d/12091.misc new file mode 100644 index 000000000000..def44987b470 --- /dev/null +++ b/changelog.d/12091.misc @@ -0,0 +1 @@ +Refuse to start if registration is enabled without email, captcha, or token-based verification unless new config flag `enable_registration_without_verification` is set. diff --git a/demo/start.sh b/demo/start.sh index 55e69685e3c2..5a9972d24c2c 100755 --- a/demo/start.sh +++ b/demo/start.sh @@ -38,6 +38,7 @@ for port in 8080 8081 8082; do printf '\n\n# Customisation made by demo/start.sh\n\n' echo "public_baseurl: http://localhost:$port/" echo 'enable_registration: true' + echo 'enable_registration_without_verification: true' echo '' # Warning, this heredoc depends on the interaction of tabs and spaces. diff --git a/docs/sample_config.yaml b/docs/sample_config.yaml index d634fd8ff54c..ec5dd129faca 100644 --- a/docs/sample_config.yaml +++ b/docs/sample_config.yaml @@ -1212,10 +1212,18 @@ oembed: # Registration can be rate-limited using the parameters in the "Ratelimiting" # section of this file. -# Enable registration for new users. +# Enable registration for new users. Defaults to 'false'. It is highly recommended that if you enable registration, +# you use either captcha, email, or token-based verification to verify that new users are not bots. In order to enable registration +# without any verification, you must also set `enable_registration_without_verification`, found below. # #enable_registration: false +# Enable registration without email or captcha verification. Note: this option is *not* recommended, +# as registration without verification is a known vector for spam and abuse. Defaults to false. Has no effect +# unless `enable_registration` is also enabled. +# +#enable_registration_without_verification: true + # Time that a user's session remains valid for, after they log in. # # Note that this is not currently compatible with guest logins. diff --git a/docs/upgrade.md b/docs/upgrade.md index 95005962dc49..2f35d97a5398 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -87,6 +87,12 @@ process, for example: # Upgrading to v1.55.0 +## Open registration without verification is now disabled by default + +Synapse will refuse to start if registration is enabled without email, captcha, or token-based verification unless the new config +flag `enable_registration_without_verification` is set to "true". + + ## `synctl` script has been moved The `synctl` script diff --git a/synapse/app/homeserver.py b/synapse/app/homeserver.py index e4dc04c0b40f..bdf27bfa0e0b 100644 --- a/synapse/app/homeserver.py +++ b/synapse/app/homeserver.py @@ -348,6 +348,23 @@ def setup(config_options: List[str]) -> SynapseHomeServer: if config.server.gc_seconds: synapse.metrics.MIN_TIME_BETWEEN_GCS = config.server.gc_seconds + if ( + config.registration.enable_registration + and not config.registration.enable_registration_without_verification + ): + if ( + not config.captcha.enable_registration_captcha + and not config.registration.registrations_require_3pid + and not config.registration.registration_requires_token + ): + + raise ConfigError( + "You have enabled open registration without any verification. This is a known vector for " + "spam and abuse. If you would like to allow public registration, please consider adding email, " + "captcha, or token-based verification. Otherwise this check can be removed by setting the " + "`enable_registration_without_verification` config option to `true`." + ) + hs = SynapseHomeServer( config.server.server_name, config=config, diff --git a/synapse/config/registration.py b/synapse/config/registration.py index ea9b50fe97e4..40fb329a7fac 100644 --- a/synapse/config/registration.py +++ b/synapse/config/registration.py @@ -33,6 +33,10 @@ def read_config(self, config, **kwargs): str(config["disable_registration"]) ) + self.enable_registration_without_verification = strtobool( + str(config.get("enable_registration_without_verification", False)) + ) + self.registrations_require_3pid = config.get("registrations_require_3pid", []) self.allowed_local_3pids = config.get("allowed_local_3pids", []) self.enable_3pid_lookup = config.get("enable_3pid_lookup", True) @@ -207,10 +211,18 @@ def generate_config_section(self, generate_secrets=False, **kwargs): # Registration can be rate-limited using the parameters in the "Ratelimiting" # section of this file. - # Enable registration for new users. + # Enable registration for new users. Defaults to 'false'. It is highly recommended that if you enable registration, + # you use either captcha, email, or token-based verification to verify that new users are not bots. In order to enable registration + # without any verification, you must also set `enable_registration_without_verification`, found below. # #enable_registration: false + # Enable registration without email or captcha verification. Note: this option is *not* recommended, + # as registration without verification is a known vector for spam and abuse. Defaults to false. Has no effect + # unless `enable_registration` is also enabled. + # + #enable_registration_without_verification: true + # Time that a user's session remains valid for, after they log in. # # Note that this is not currently compatible with guest logins. diff --git a/tests/config/test_registration_config.py b/tests/config/test_registration_config.py index 17a84d20d811..2acdb6ac6161 100644 --- a/tests/config/test_registration_config.py +++ b/tests/config/test_registration_config.py @@ -11,14 +11,16 @@ # 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 synapse.app.homeserver from synapse.config import ConfigError from synapse.config.homeserver import HomeServerConfig -from tests.unittest import TestCase +from tests.config.utils import ConfigFileTestCase from tests.utils import default_config -class RegistrationConfigTestCase(TestCase): +class RegistrationConfigTestCase(ConfigFileTestCase): def test_session_lifetime_must_not_be_exceeded_by_smaller_lifetimes(self): """ session_lifetime should logically be larger than, or at least as large as, @@ -76,3 +78,19 @@ def test_session_lifetime_must_not_be_exceeded_by_smaller_lifetimes(self): HomeServerConfig().parse_config_dict( {"session_lifetime": "31m", "refresh_token_lifetime": "31m", **config_dict} ) + + def test_refuse_to_start_if_open_registration_and_no_verification(self): + self.generate_config() + self.add_lines_to_config( + [ + " ", + "enable_registration: true", + "registrations_require_3pid: []", + "enable_registration_captcha: false", + "registration_requires_token: false", + ] + ) + + # Test that allowing open registration without verification raises an error + with self.assertRaises(ConfigError): + synapse.app.homeserver.setup(["-c", self.config_file])