diff --git a/synapse/config/captcha.py b/synapse/config/captcha.py
index 8ebcfc3623..4ed9070b9e 100644
--- a/synapse/config/captcha.py
+++ b/synapse/config/captcha.py
@@ -24,6 +24,7 @@ class CaptchaConfig(Config):
self.captcha_ip_origin_is_x_forwarded = (
args.captcha_ip_origin_is_x_forwarded
)
+ self.captcha_bypass_secret = args.captcha_bypass_secret
@classmethod
def add_arguments(cls, parser):
@@ -43,4 +44,8 @@ class CaptchaConfig(Config):
"--captcha_ip_origin_is_x_forwarded", type=bool, default=False,
help="When checking captchas, use the X-Forwarded-For (XFF) header"
+ " as the client IP and not the actual client IP."
- )
\ No newline at end of file
+ )
+ group.add_argument(
+ "--captcha_bypass_secret", type=str,
+ help="A secret key used to bypass the captcha test entirely."
+ )
diff --git a/synapse/rest/register.py b/synapse/rest/register.py
index af528a44f6..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,6 +144,38 @@ class RegisterRestServlet(RestServlet):
if not self.hs.config.enable_registration_captcha:
raise SynapseError(400, "Captcha not required.")
+ yield self._check_recaptcha(request, register_json, session)
+
+ session[LoginType.RECAPTCHA] = True # mark captcha as done
+ self._save_session(session)
+ defer.returnValue({
+ "next": [LoginType.PASSWORD, LoginType.EMAIL_IDENTITY]
+ })
+
+ @defer.inlineCallbacks
+ 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 HMAC incorrect",
+ errcode=Codes.CAPTCHA_NEEDED)
+
challenge = None
user_response = None
try:
@@ -166,11 +200,6 @@ class RegisterRestServlet(RestServlet):
challenge,
user_response
)
- session[LoginType.RECAPTCHA] = True # mark captcha as done
- self._save_session(session)
- defer.returnValue({
- "next": [LoginType.PASSWORD, LoginType.EMAIL_IDENTITY]
- })
@defer.inlineCallbacks
def _do_email_identity(self, request, register_json, session):
@@ -195,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)
|