Fix registering accounts with shared secret. Fixes #107

This commit is contained in:
Tulir Asokan 2021-06-11 10:55:51 +03:00
parent 92a14f20f6
commit 543f8dbf78
3 changed files with 30 additions and 30 deletions

View File

@ -22,7 +22,7 @@ import string
import hmac import hmac
from aiohttp import web from aiohttp import web
from mautrix.api import HTTPAPI, Path, Method from mautrix.api import HTTPAPI, Path, SynapseAdminPath, Method
from mautrix.errors import MatrixRequestError from mautrix.errors import MatrixRequestError
from .base import routes, get_config, get_loop from .base import routes, get_config, get_loop
@ -33,21 +33,6 @@ def registration_secrets() -> Dict[str, Dict[str, str]]:
return get_config()["registration_secrets"] return get_config()["registration_secrets"]
def generate_mac(secret: str, nonce: str, user: str, password: str, admin: bool = False, user_type: str = None):
mac = hmac.new(key=secret.encode("utf-8"), digestmod=hashlib.sha1)
mac.update(nonce.encode("utf-8"))
mac.update(b"\x00")
mac.update(user.encode("utf-8"))
mac.update(b"\x00")
mac.update(password.encode("utf-8"))
mac.update(b"\x00")
mac.update(b"admin" if admin else b"notadmin")
if user_type is not None:
mac.update(b"\x00")
mac.update(user_type.encode("utf8"))
return mac.hexdigest()
@routes.get("/client/auth/servers") @routes.get("/client/auth/servers")
async def get_registerable_servers(_: web.Request) -> web.Response: async def get_registerable_servers(_: web.Request) -> web.Response:
return web.json_response({key: value["url"] for key, value in registration_secrets().items()}) return web.json_response({key: value["url"] for key, value in registration_secrets().items()})
@ -82,25 +67,40 @@ async def read_client_auth_request(request: web.Request) -> Tuple[Optional[AuthR
return AuthRequestInfo(api, secret, username, password, user_type), None return AuthRequestInfo(api, secret, username, password, user_type), None
def generate_mac(secret: str, nonce: str, user: str, password: str, admin: bool = False,
user_type: str = None) -> str:
mac = hmac.new(key=secret.encode("utf-8"), digestmod=hashlib.sha1)
mac.update(nonce.encode("utf-8"))
mac.update(b"\x00")
mac.update(user.encode("utf-8"))
mac.update(b"\x00")
mac.update(password.encode("utf-8"))
mac.update(b"\x00")
mac.update(b"admin" if admin else b"notadmin")
if user_type is not None:
mac.update(b"\x00")
mac.update(user_type.encode("utf8"))
return mac.hexdigest()
@routes.post("/client/auth/{server}/register") @routes.post("/client/auth/{server}/register")
async def register(request: web.Request) -> web.Response: async def register(request: web.Request) -> web.Response:
info, err = await read_client_auth_request(request) info, err = await read_client_auth_request(request)
if err is not None: if err is not None:
return err return err
api, secret, username, password, user_type = info api, secret, username, password, user_type = info
res = await api.request(Method.GET, Path.admin.register) path = SynapseAdminPath.v1.register
nonce = res["nonce"] res = await api.request(Method.GET, path)
mac = generate_mac(secret, nonce, username, password, user_type=user_type) content = {
try: "nonce": res["nonce"],
return web.json_response(await api.request(Method.POST, Path.admin.register, content={
"nonce": nonce,
"username": username, "username": username,
"password": password, "password": password,
"admin": False, "admin": False,
"mac": mac, "mac": generate_mac(secret, res["nonce"], username, password, user_type=user_type),
# Older versions of synapse will ignore this field if it is None
"user_type": user_type, "user_type": user_type,
})) }
try:
return web.json_response(await api.request(Method.POST, path, content=content))
except MatrixRequestError as e: except MatrixRequestError as e:
return web.json_response({ return web.json_response({
"errcode": e.errcode, "errcode": e.errcode,

View File

@ -5,7 +5,7 @@
psycopg2-binary>=2,<3 psycopg2-binary>=2,<3
#/e2be #/e2be
asyncpg>=0.20,<0.23 asyncpg>=0.20,<0.24
python-olm>=3,<4 python-olm>=3,<4
pycryptodome>=3,<4 pycryptodome>=3,<4
unpaddedbase64>=1,<2 unpaddedbase64>=1,<2

View File

@ -1,4 +1,4 @@
mautrix>=0.9,<0.10 mautrix>=0.9.5,<0.10
aiohttp>=3,<4 aiohttp>=3,<4
yarl>=1,<2 yarl>=1,<2
SQLAlchemy>=1,<1.4 SQLAlchemy>=1,<1.4