forked from MirrorHub/synapse
Synapse 1.13.0rc3 (2020-05-18)
Bugfixes: - Hash passwords as early as possible during registration. #7523 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEF3tZXk38tRDFVnUIM/xY9qcRMEgFAl7CpGYACgkQM/xY9qcR MEhVixAAk2hDWVXxbGzUk2LmfiIsFA2eV55sw+VqEw0eRfe1d/mP6aH75VmTt3pw IymZUVxDXdbTnPNPw+ldyGhzu9C6JJjXnNRBZnIkR5vcSbWsV0mPl/qHFu/4FnZI m4Nj1Sx3sG0CyNDpWjVrzTW6SbDX9J68DXbLwnNTSX3KPa7gNn6TUmFfKzlrNI23 pPmD+EITYMn/H9HOhxhTzq//Ja7UOViAKQ0q4N2I4GxmLP6ufx9P3s5FG/oJqA+H Pka2+9JnfHq2Ze22CoDcg8q5f5MgVkQzGeir0ZsGJwJqOYjeTmbCvD3T/RYWO5g+ ZghON3tsMQmdzUQqGRxcn/YLOZY9ZqrX2kBf5E6Wapwj9MfKg2ToLZM4yrWN0+RX KDuWaKXYtkSQCo1nDS2KooVMWjGNZautWWnHzZ0KNQCIkxVpGC234JYI685grKXb dg7R41kdXI7NJzqS4iM1fxXoLx64fpoREa/pbLF6VeLaYXBlzMjfhiIx2pQBN3L/ q/y3ftev9VCp+2wPxiKUkiC4Sh7dgWUzNuyHU+4lsPUbI1H/MN5dN2ryObdEGWc/ 5YU3tv2MTQJ7jECHR+/fastnG+5d2kVm/FK+zVhG17JvA2VmDaLnSde+mzGbsO1N gIUx5VrTEP7y0tC8C/VgbS3c2KqCSOopqd3j2slLLrtQlXM71VE= =lpDI -----END PGP SIGNATURE----- Merge tag 'v1.13.0rc3' into develop Synapse 1.13.0rc3 (2020-05-18) Bugfixes: - Hash passwords as early as possible during registration. #7523
This commit is contained in:
commit
ee421e5244
5 changed files with 40 additions and 32 deletions
|
@ -1,3 +1,12 @@
|
||||||
|
Synapse 1.13.0rc3 (2020-05-18)
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Hash passwords as early as possible during registration. ([\#7523](https://github.com/matrix-org/synapse/issues/7523))
|
||||||
|
|
||||||
|
|
||||||
Synapse 1.13.0rc2 (2020-05-14)
|
Synapse 1.13.0rc2 (2020-05-14)
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
__version__ = "1.13.0rc2"
|
__version__ = "1.13.0rc3"
|
||||||
|
|
||||||
if bool(os.environ.get("SYNAPSE_TEST_PATCH_LOG_CONTEXTS", False)):
|
if bool(os.environ.get("SYNAPSE_TEST_PATCH_LOG_CONTEXTS", False)):
|
||||||
# We import here so that we don't have to install a bunch of deps when
|
# We import here so that we don't have to install a bunch of deps when
|
||||||
|
|
|
@ -132,7 +132,7 @@ class RegistrationHandler(BaseHandler):
|
||||||
def register_user(
|
def register_user(
|
||||||
self,
|
self,
|
||||||
localpart=None,
|
localpart=None,
|
||||||
password=None,
|
password_hash=None,
|
||||||
guest_access_token=None,
|
guest_access_token=None,
|
||||||
make_guest=False,
|
make_guest=False,
|
||||||
admin=False,
|
admin=False,
|
||||||
|
@ -147,7 +147,7 @@ class RegistrationHandler(BaseHandler):
|
||||||
Args:
|
Args:
|
||||||
localpart: The local part of the user ID to register. If None,
|
localpart: The local part of the user ID to register. If None,
|
||||||
one will be generated.
|
one will be generated.
|
||||||
password (unicode): The password to assign to this user so they can
|
password_hash (str|None): The hashed password to assign to this user so they can
|
||||||
login again. This can be None which means they cannot login again
|
login again. This can be None which means they cannot login again
|
||||||
via a password (e.g. the user is an application service user).
|
via a password (e.g. the user is an application service user).
|
||||||
user_type (str|None): type of user. One of the values from
|
user_type (str|None): type of user. One of the values from
|
||||||
|
@ -164,11 +164,6 @@ class RegistrationHandler(BaseHandler):
|
||||||
yield self.check_registration_ratelimit(address)
|
yield self.check_registration_ratelimit(address)
|
||||||
|
|
||||||
yield self.auth.check_auth_blocking(threepid=threepid)
|
yield self.auth.check_auth_blocking(threepid=threepid)
|
||||||
password_hash = None
|
|
||||||
if password:
|
|
||||||
password_hash = yield defer.ensureDeferred(
|
|
||||||
self._auth_handler.hash(password)
|
|
||||||
)
|
|
||||||
|
|
||||||
if localpart is not None:
|
if localpart is not None:
|
||||||
yield self.check_username(localpart, guest_access_token=guest_access_token)
|
yield self.check_username(localpart, guest_access_token=guest_access_token)
|
||||||
|
|
|
@ -243,11 +243,11 @@ class UserRestServletV2(RestServlet):
|
||||||
|
|
||||||
else: # create user
|
else: # create user
|
||||||
password = body.get("password")
|
password = body.get("password")
|
||||||
if password is not None and (
|
password_hash = None
|
||||||
not isinstance(body["password"], text_type)
|
if password is not None:
|
||||||
or len(body["password"]) > 512
|
if not isinstance(password, text_type) or len(password) > 512:
|
||||||
):
|
raise SynapseError(400, "Invalid password")
|
||||||
raise SynapseError(400, "Invalid password")
|
password_hash = await self.auth_handler.hash(password)
|
||||||
|
|
||||||
admin = body.get("admin", None)
|
admin = body.get("admin", None)
|
||||||
user_type = body.get("user_type", None)
|
user_type = body.get("user_type", None)
|
||||||
|
@ -259,7 +259,7 @@ class UserRestServletV2(RestServlet):
|
||||||
|
|
||||||
user_id = await self.registration_handler.register_user(
|
user_id = await self.registration_handler.register_user(
|
||||||
localpart=target_user.localpart,
|
localpart=target_user.localpart,
|
||||||
password=password,
|
password_hash=password_hash,
|
||||||
admin=bool(admin),
|
admin=bool(admin),
|
||||||
default_display_name=displayname,
|
default_display_name=displayname,
|
||||||
user_type=user_type,
|
user_type=user_type,
|
||||||
|
@ -298,7 +298,7 @@ class UserRegisterServlet(RestServlet):
|
||||||
NONCE_TIMEOUT = 60
|
NONCE_TIMEOUT = 60
|
||||||
|
|
||||||
def __init__(self, hs):
|
def __init__(self, hs):
|
||||||
self.handlers = hs.get_handlers()
|
self.auth_handler = hs.get_auth_handler()
|
||||||
self.reactor = hs.get_reactor()
|
self.reactor = hs.get_reactor()
|
||||||
self.nonces = {}
|
self.nonces = {}
|
||||||
self.hs = hs
|
self.hs = hs
|
||||||
|
@ -362,16 +362,16 @@ class UserRegisterServlet(RestServlet):
|
||||||
400, "password must be specified", errcode=Codes.BAD_JSON
|
400, "password must be specified", errcode=Codes.BAD_JSON
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if (
|
password = body["password"]
|
||||||
not isinstance(body["password"], text_type)
|
if not isinstance(password, text_type) or len(password) > 512:
|
||||||
or len(body["password"]) > 512
|
|
||||||
):
|
|
||||||
raise SynapseError(400, "Invalid password")
|
raise SynapseError(400, "Invalid password")
|
||||||
|
|
||||||
password = body["password"].encode("utf-8")
|
password_bytes = password.encode("utf-8")
|
||||||
if b"\x00" in password:
|
if b"\x00" in password_bytes:
|
||||||
raise SynapseError(400, "Invalid password")
|
raise SynapseError(400, "Invalid password")
|
||||||
|
|
||||||
|
password_hash = await self.auth_handler.hash(password)
|
||||||
|
|
||||||
admin = body.get("admin", None)
|
admin = body.get("admin", None)
|
||||||
user_type = body.get("user_type", None)
|
user_type = body.get("user_type", None)
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ class UserRegisterServlet(RestServlet):
|
||||||
want_mac_builder.update(b"\x00")
|
want_mac_builder.update(b"\x00")
|
||||||
want_mac_builder.update(username)
|
want_mac_builder.update(username)
|
||||||
want_mac_builder.update(b"\x00")
|
want_mac_builder.update(b"\x00")
|
||||||
want_mac_builder.update(password)
|
want_mac_builder.update(password_bytes)
|
||||||
want_mac_builder.update(b"\x00")
|
want_mac_builder.update(b"\x00")
|
||||||
want_mac_builder.update(b"admin" if admin else b"notadmin")
|
want_mac_builder.update(b"admin" if admin else b"notadmin")
|
||||||
if user_type:
|
if user_type:
|
||||||
|
@ -407,7 +407,7 @@ class UserRegisterServlet(RestServlet):
|
||||||
|
|
||||||
user_id = await register.registration_handler.register_user(
|
user_id = await register.registration_handler.register_user(
|
||||||
localpart=body["username"].lower(),
|
localpart=body["username"].lower(),
|
||||||
password=body["password"],
|
password_hash=password_hash,
|
||||||
admin=bool(admin),
|
admin=bool(admin),
|
||||||
user_type=user_type,
|
user_type=user_type,
|
||||||
)
|
)
|
||||||
|
|
|
@ -426,12 +426,16 @@ class RegisterRestServlet(RestServlet):
|
||||||
# we do basic sanity checks here because the auth layer will store these
|
# we do basic sanity checks here because the auth layer will store these
|
||||||
# in sessions. Pull out the username/password provided to us.
|
# in sessions. Pull out the username/password provided to us.
|
||||||
if "password" in body:
|
if "password" in body:
|
||||||
if (
|
password = body.pop("password")
|
||||||
not isinstance(body["password"], string_types)
|
if not isinstance(password, string_types) or len(password) > 512:
|
||||||
or len(body["password"]) > 512
|
|
||||||
):
|
|
||||||
raise SynapseError(400, "Invalid password")
|
raise SynapseError(400, "Invalid password")
|
||||||
self.password_policy_handler.validate_password(body["password"])
|
self.password_policy_handler.validate_password(password)
|
||||||
|
|
||||||
|
# If the password is valid, hash it and store it back on the request.
|
||||||
|
# This ensures the hashed password is handled everywhere.
|
||||||
|
if "password_hash" in body:
|
||||||
|
raise SynapseError(400, "Unexpected property: password_hash")
|
||||||
|
body["password_hash"] = await self.auth_handler.hash(password)
|
||||||
|
|
||||||
desired_username = None
|
desired_username = None
|
||||||
if "username" in body:
|
if "username" in body:
|
||||||
|
@ -484,7 +488,7 @@ class RegisterRestServlet(RestServlet):
|
||||||
|
|
||||||
guest_access_token = body.get("guest_access_token", None)
|
guest_access_token = body.get("guest_access_token", None)
|
||||||
|
|
||||||
if "initial_device_display_name" in body and "password" not in body:
|
if "initial_device_display_name" in body and "password_hash" not in body:
|
||||||
# ignore 'initial_device_display_name' if sent without
|
# ignore 'initial_device_display_name' if sent without
|
||||||
# a password to work around a client bug where it sent
|
# a password to work around a client bug where it sent
|
||||||
# the 'initial_device_display_name' param alone, wiping out
|
# the 'initial_device_display_name' param alone, wiping out
|
||||||
|
@ -546,11 +550,11 @@ class RegisterRestServlet(RestServlet):
|
||||||
registered = False
|
registered = False
|
||||||
else:
|
else:
|
||||||
# NB: This may be from the auth handler and NOT from the POST
|
# NB: This may be from the auth handler and NOT from the POST
|
||||||
assert_params_in_dict(params, ["password"])
|
assert_params_in_dict(params, ["password_hash"])
|
||||||
|
|
||||||
desired_username = params.get("username", None)
|
desired_username = params.get("username", None)
|
||||||
guest_access_token = params.get("guest_access_token", None)
|
guest_access_token = params.get("guest_access_token", None)
|
||||||
new_password = params.get("password", None)
|
new_password_hash = params.get("password_hash", None)
|
||||||
|
|
||||||
if desired_username is not None:
|
if desired_username is not None:
|
||||||
desired_username = desired_username.lower()
|
desired_username = desired_username.lower()
|
||||||
|
@ -583,7 +587,7 @@ class RegisterRestServlet(RestServlet):
|
||||||
|
|
||||||
registered_user_id = await self.registration_handler.register_user(
|
registered_user_id = await self.registration_handler.register_user(
|
||||||
localpart=desired_username,
|
localpart=desired_username,
|
||||||
password=new_password,
|
password_hash=new_password_hash,
|
||||||
guest_access_token=guest_access_token,
|
guest_access_token=guest_access_token,
|
||||||
threepid=threepid,
|
threepid=threepid,
|
||||||
address=client_addr,
|
address=client_addr,
|
||||||
|
|
Loading…
Reference in a new issue