diff --git a/synapse/rest/register.py b/synapse/rest/register.py index 66cef26ada..14d1ab018e 100644 --- a/synapse/rest/register.py +++ b/synapse/rest/register.py @@ -21,6 +21,8 @@ from synapse.api.constants import LoginType from base import RestServlet, client_path_pattern import synapse.util.stringutils as stringutils +from hashlib import sha1 +import hmac import json import logging import urllib @@ -142,7 +144,7 @@ class RegisterRestServlet(RestServlet): if not self.hs.config.enable_registration_captcha: raise SynapseError(400, "Captcha not required.") - yield self._check_recaptcha(request, register_json) + yield self._check_recaptcha(request, register_json, session) session[LoginType.RECAPTCHA] = True # mark captcha as done self._save_session(session) @@ -151,14 +153,27 @@ class RegisterRestServlet(RestServlet): }) @defer.inlineCallbacks - def _check_recaptcha(self, request, register_json): - if "captcha_bypass_secret" in register_json: - if (self.hs.config.captcha_bypass_secret and - register_json["captcha_bypass_secret"] == - self.hs.config.captcha_bypass_secret): + def _check_recaptcha(self, request, register_json, session): + if ("captcha_bypass_hmac" in register_json and + self.hs.config.captcha_bypass_secret): + if "user" not in register_json: + raise SynapseError(400, "Captcha bypass needs 'user'") + + want = hmac.new( + key=self.hs.config.captcha_bypass_secret, + msg=register_json["user"], + digestmod=sha1, + ).hexdigest() + + # str() because otherwise hmac complains that 'unicode' does not + # have the buffer interface + got = str(register_json["captcha_bypass_hmac"]) + + if hmac.compare_digest(want, got): + session["user"] = register_json["user"] defer.returnValue(None) else: - raise SynapseError(400, "Captcha bypass secret incorrect", + raise SynapseError(400, "Captcha bypass HMAC incorrect", errcode=Codes.CAPTCHA_NEEDED) challenge = None @@ -209,6 +224,10 @@ class RegisterRestServlet(RestServlet): # captcha should've been done by this stage! raise SynapseError(400, "Captcha is required.") + if ("user" in session and "user" in register_json and + session["user"] != register_json["user"]): + raise SynapseError(400, "Cannot change user ID during registration") + password = register_json["password"].encode("utf-8") desired_user_id = (register_json["user"].encode("utf-8") if "user" in register_json else None)