summary refs log tree commit diff
path: root/synapse/rest/register.py
diff options
context:
space:
mode:
authorErik Johnston <erik@matrix.org>2014-09-25 18:21:00 +0100
committerErik Johnston <erik@matrix.org>2014-09-25 18:21:00 +0100
commit697f6714a4c65cec6019231a7bac84e1b544c42d (patch)
tree8693ec59f906c076abb534f01c32573619bf7c8c /synapse/rest/register.py
parentBump versions and changelog (diff)
parentJust use a yaml list for turn servers (diff)
downloadsynapse-697f6714a4c65cec6019231a7bac84e1b544c42d.tar.xz
Merge branch 'release-v0.3.4' of github.com:matrix-org/synapse v0.3.4
Diffstat (limited to 'synapse/rest/register.py')
-rw-r--r--synapse/rest/register.py53
1 files changed, 48 insertions, 5 deletions
diff --git a/synapse/rest/register.py b/synapse/rest/register.py
index af528a44f6..4935e323d9 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
@@ -28,6 +30,16 @@ import urllib
 logger = logging.getLogger(__name__)
 
 
+# We ought to be using hmac.compare_digest() but on older pythons it doesn't
+# exist. It's a _really minor_ security flaw to use plain string comparison
+# because the timing attack is so obscured by all the other code here it's
+# unlikely to make much difference
+if hasattr(hmac, "compare_digest"):
+    compare_digest = hmac.compare_digest
+else:
+    compare_digest = lambda a, b: a == b
+
+
 class RegisterRestServlet(RestServlet):
     """Handles registration with the home server.
 
@@ -142,6 +154,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 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 +210,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 +234,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)