2018-10-26 13:05:22 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright 2015, 2016 OpenMarket Ltd
|
|
|
|
# Copyright 2018 New Vector
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
import getpass
|
|
|
|
import hashlib
|
|
|
|
import hmac
|
|
|
|
import logging
|
|
|
|
import sys
|
|
|
|
|
|
|
|
import requests as _requests
|
|
|
|
import yaml
|
|
|
|
|
|
|
|
|
|
|
|
def request_registration(
|
|
|
|
user,
|
|
|
|
password,
|
|
|
|
server_location,
|
|
|
|
shared_secret,
|
|
|
|
admin=False,
|
2018-12-14 19:20:59 +01:00
|
|
|
user_type=None,
|
2018-10-26 13:05:22 +02:00
|
|
|
requests=_requests,
|
|
|
|
_print=print,
|
|
|
|
exit=sys.exit,
|
|
|
|
):
|
|
|
|
|
|
|
|
url = "%s/_matrix/client/r0/admin/register" % (server_location,)
|
|
|
|
|
|
|
|
# Get the nonce
|
|
|
|
r = requests.get(url, verify=False)
|
|
|
|
|
2019-01-30 11:53:17 +01:00
|
|
|
if r.status_code != 200:
|
2018-10-26 13:05:22 +02:00
|
|
|
_print("ERROR! Received %d %s" % (r.status_code, r.reason))
|
|
|
|
if 400 <= r.status_code < 500:
|
|
|
|
try:
|
|
|
|
_print(r.json()["error"])
|
|
|
|
except Exception:
|
|
|
|
pass
|
|
|
|
return exit(1)
|
|
|
|
|
|
|
|
nonce = r.json()["nonce"]
|
|
|
|
|
2019-06-20 11:32:02 +02:00
|
|
|
mac = hmac.new(key=shared_secret.encode("utf8"), digestmod=hashlib.sha1)
|
2018-10-26 13:05:22 +02:00
|
|
|
|
2019-06-20 11:32:02 +02:00
|
|
|
mac.update(nonce.encode("utf8"))
|
2018-10-26 13:05:22 +02:00
|
|
|
mac.update(b"\x00")
|
2019-06-20 11:32:02 +02:00
|
|
|
mac.update(user.encode("utf8"))
|
2018-10-26 13:05:22 +02:00
|
|
|
mac.update(b"\x00")
|
2019-06-20 11:32:02 +02:00
|
|
|
mac.update(password.encode("utf8"))
|
2018-10-26 13:05:22 +02:00
|
|
|
mac.update(b"\x00")
|
|
|
|
mac.update(b"admin" if admin else b"notadmin")
|
2018-12-14 19:20:59 +01:00
|
|
|
if user_type:
|
|
|
|
mac.update(b"\x00")
|
2019-06-20 11:32:02 +02:00
|
|
|
mac.update(user_type.encode("utf8"))
|
2018-10-26 13:05:22 +02:00
|
|
|
|
|
|
|
mac = mac.hexdigest()
|
|
|
|
|
|
|
|
data = {
|
|
|
|
"nonce": nonce,
|
|
|
|
"username": user,
|
|
|
|
"password": password,
|
|
|
|
"mac": mac,
|
|
|
|
"admin": admin,
|
2018-12-14 19:20:59 +01:00
|
|
|
"user_type": user_type,
|
2018-10-26 13:05:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
_print("Sending registration request...")
|
|
|
|
r = requests.post(url, json=data, verify=False)
|
|
|
|
|
2019-01-30 11:53:17 +01:00
|
|
|
if r.status_code != 200:
|
2018-10-26 13:05:22 +02:00
|
|
|
_print("ERROR! Received %d %s" % (r.status_code, r.reason))
|
|
|
|
if 400 <= r.status_code < 500:
|
|
|
|
try:
|
|
|
|
_print(r.json()["error"])
|
|
|
|
except Exception:
|
|
|
|
pass
|
|
|
|
return exit(1)
|
|
|
|
|
|
|
|
_print("Success!")
|
|
|
|
|
|
|
|
|
2018-12-14 19:20:59 +01:00
|
|
|
def register_new_user(user, password, server_location, shared_secret, admin, user_type):
|
2018-10-26 13:05:22 +02:00
|
|
|
if not user:
|
|
|
|
try:
|
|
|
|
default_user = getpass.getuser()
|
|
|
|
except Exception:
|
|
|
|
default_user = None
|
|
|
|
|
|
|
|
if default_user:
|
|
|
|
user = input("New user localpart [%s]: " % (default_user,))
|
|
|
|
if not user:
|
|
|
|
user = default_user
|
|
|
|
else:
|
|
|
|
user = input("New user localpart: ")
|
|
|
|
|
|
|
|
if not user:
|
|
|
|
print("Invalid user name")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if not password:
|
|
|
|
password = getpass.getpass("Password: ")
|
|
|
|
|
|
|
|
if not password:
|
|
|
|
print("Password cannot be blank.")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
confirm_password = getpass.getpass("Confirm password: ")
|
|
|
|
|
|
|
|
if password != confirm_password:
|
|
|
|
print("Passwords do not match")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if admin is None:
|
|
|
|
admin = input("Make admin [no]: ")
|
|
|
|
if admin in ("y", "yes", "true"):
|
|
|
|
admin = True
|
|
|
|
else:
|
|
|
|
admin = False
|
|
|
|
|
2019-06-20 11:32:02 +02:00
|
|
|
request_registration(
|
|
|
|
user, password, server_location, shared_secret, bool(admin), user_type
|
|
|
|
)
|
2018-10-26 13:05:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
|
|
|
logging.captureWarnings(True)
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser(
|
2019-11-12 14:08:12 +01:00
|
|
|
description="Used to register new users with a given homeserver when"
|
|
|
|
" registration has been disabled. The homeserver must be"
|
2018-10-26 13:05:22 +02:00
|
|
|
" configured with the 'registration_shared_secret' option"
|
|
|
|
" set."
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"-u",
|
|
|
|
"--user",
|
|
|
|
default=None,
|
|
|
|
help="Local part of the new user. Will prompt if omitted.",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"-p",
|
|
|
|
"--password",
|
|
|
|
default=None,
|
|
|
|
help="New password for user. Will prompt if omitted.",
|
|
|
|
)
|
2018-12-14 19:20:59 +01:00
|
|
|
parser.add_argument(
|
|
|
|
"-t",
|
|
|
|
"--user_type",
|
|
|
|
default=None,
|
|
|
|
help="User type as specified in synapse.api.constants.UserTypes",
|
|
|
|
)
|
2018-10-26 13:05:22 +02:00
|
|
|
admin_group = parser.add_mutually_exclusive_group()
|
|
|
|
admin_group.add_argument(
|
|
|
|
"-a",
|
|
|
|
"--admin",
|
|
|
|
action="store_true",
|
|
|
|
help=(
|
|
|
|
"Register new user as an admin. "
|
|
|
|
"Will prompt if --no-admin is not set either."
|
|
|
|
),
|
|
|
|
)
|
|
|
|
admin_group.add_argument(
|
|
|
|
"--no-admin",
|
|
|
|
action="store_true",
|
|
|
|
help=(
|
|
|
|
"Register new user as a regular user. "
|
|
|
|
"Will prompt if --admin is not set either."
|
|
|
|
),
|
|
|
|
)
|
|
|
|
|
|
|
|
group = parser.add_mutually_exclusive_group(required=True)
|
|
|
|
group.add_argument(
|
|
|
|
"-c",
|
|
|
|
"--config",
|
2019-06-20 11:32:02 +02:00
|
|
|
type=argparse.FileType("r"),
|
2018-10-26 13:05:22 +02:00
|
|
|
help="Path to server config file. Used to read in shared secret.",
|
|
|
|
)
|
|
|
|
|
|
|
|
group.add_argument(
|
|
|
|
"-k", "--shared-secret", help="Shared secret as defined in server config file."
|
|
|
|
)
|
|
|
|
|
|
|
|
parser.add_argument(
|
|
|
|
"server_url",
|
|
|
|
default="https://localhost:8448",
|
2019-06-20 11:32:02 +02:00
|
|
|
nargs="?",
|
2019-11-12 14:08:12 +01:00
|
|
|
help="URL to use to talk to the homeserver. Defaults to "
|
2018-10-26 13:05:22 +02:00
|
|
|
" 'https://localhost:8448'.",
|
|
|
|
)
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
if "config" in args and args.config:
|
|
|
|
config = yaml.safe_load(args.config)
|
|
|
|
secret = config.get("registration_shared_secret", None)
|
|
|
|
if not secret:
|
|
|
|
print("No 'registration_shared_secret' defined in config.")
|
|
|
|
sys.exit(1)
|
|
|
|
else:
|
|
|
|
secret = args.shared_secret
|
|
|
|
|
|
|
|
admin = None
|
|
|
|
if args.admin or args.no_admin:
|
|
|
|
admin = args.admin
|
|
|
|
|
2019-06-20 11:32:02 +02:00
|
|
|
register_new_user(
|
|
|
|
args.user, args.password, args.server_url, secret, admin, args.user_type
|
|
|
|
)
|
2018-10-26 13:05:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|