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

This commit is contained in:
Paul "LeoNerd" Evans 2014-09-23 15:58:44 +01:00
parent 537c7e1137
commit c03176af59

View file

@ -21,6 +21,8 @@ from synapse.api.constants import LoginType
from base import RestServlet, client_path_pattern from base import RestServlet, client_path_pattern
import synapse.util.stringutils as stringutils import synapse.util.stringutils as stringutils
from hashlib import sha1
import hmac
import json import json
import logging import logging
import urllib import urllib
@ -142,7 +144,7 @@ class RegisterRestServlet(RestServlet):
if not self.hs.config.enable_registration_captcha: if not self.hs.config.enable_registration_captcha:
raise SynapseError(400, "Captcha not required.") 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 session[LoginType.RECAPTCHA] = True # mark captcha as done
self._save_session(session) self._save_session(session)
@ -151,14 +153,27 @@ class RegisterRestServlet(RestServlet):
}) })
@defer.inlineCallbacks @defer.inlineCallbacks
def _check_recaptcha(self, request, register_json): def _check_recaptcha(self, request, register_json, session):
if "captcha_bypass_secret" in register_json: if ("captcha_bypass_hmac" in register_json and
if (self.hs.config.captcha_bypass_secret and
register_json["captcha_bypass_secret"] ==
self.hs.config.captcha_bypass_secret): 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) defer.returnValue(None)
else: else:
raise SynapseError(400, "Captcha bypass secret incorrect", raise SynapseError(400, "Captcha bypass HMAC incorrect",
errcode=Codes.CAPTCHA_NEEDED) errcode=Codes.CAPTCHA_NEEDED)
challenge = None challenge = None
@ -209,6 +224,10 @@ class RegisterRestServlet(RestServlet):
# captcha should've been done by this stage! # captcha should've been done by this stage!
raise SynapseError(400, "Captcha is required.") 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") password = register_json["password"].encode("utf-8")
desired_user_id = (register_json["user"].encode("utf-8") if "user" desired_user_id = (register_json["user"].encode("utf-8") if "user"
in register_json else None) in register_json else None)