summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaul "LeoNerd" Evans <paul@matrix.org>2014-09-23 15:58:44 +0100
committerPaul "LeoNerd" Evans <paul@matrix.org>2014-09-23 15:58:44 +0100
commitc03176af59adfe0d60ffd8beb8bf262b4563d20b (patch)
tree4da3a30d07d9acffbf863e859550703ba9a47c34
parentConfig values are almost never 'None', but they might be empty string. Detect... (diff)
downloadsynapse-c03176af59adfe0d60ffd8beb8bf262b4563d20b.tar.xz
Send an HMAC(SHA1) protecting the User ID for the ReCAPTCHA bypass, rather than simply the secret itself, so it's useless if that HMAC leaks
-rw-r--r--synapse/rest/register.py33
1 files changed, 26 insertions, 7 deletions
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)