register_new_matrix_user 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Copyright 2015, 2016 OpenMarket Ltd
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. import argparse
  17. import getpass
  18. import hashlib
  19. import hmac
  20. import json
  21. import sys
  22. import urllib2
  23. import yaml
  24. def request_registration(user, password, server_location, shared_secret, admin=False):
  25. req = urllib2.Request(
  26. "%s/_matrix/client/r0/admin/register" % (server_location,),
  27. headers={'Content-Type': 'application/json'}
  28. )
  29. try:
  30. if sys.version_info[:3] >= (2, 7, 9):
  31. # As of version 2.7.9, urllib2 now checks SSL certs
  32. import ssl
  33. f = urllib2.urlopen(req, context=ssl.SSLContext(ssl.PROTOCOL_SSLv23))
  34. else:
  35. f = urllib2.urlopen(req)
  36. body = f.read()
  37. f.close()
  38. nonce = json.loads(body)["nonce"]
  39. except urllib2.HTTPError as e:
  40. print "ERROR! Received %d %s" % (e.code, e.reason,)
  41. if 400 <= e.code < 500:
  42. if e.info().type == "application/json":
  43. resp = json.load(e)
  44. if "error" in resp:
  45. print resp["error"]
  46. sys.exit(1)
  47. mac = hmac.new(
  48. key=shared_secret,
  49. digestmod=hashlib.sha1,
  50. )
  51. mac.update(nonce)
  52. mac.update("\x00")
  53. mac.update(user)
  54. mac.update("\x00")
  55. mac.update(password)
  56. mac.update("\x00")
  57. mac.update("admin" if admin else "notadmin")
  58. mac = mac.hexdigest()
  59. data = {
  60. "nonce": nonce,
  61. "username": user,
  62. "password": password,
  63. "mac": mac,
  64. "admin": admin,
  65. }
  66. server_location = server_location.rstrip("/")
  67. print "Sending registration request..."
  68. req = urllib2.Request(
  69. "%s/_matrix/client/r0/admin/register" % (server_location,),
  70. data=json.dumps(data),
  71. headers={'Content-Type': 'application/json'}
  72. )
  73. try:
  74. if sys.version_info[:3] >= (2, 7, 9):
  75. # As of version 2.7.9, urllib2 now checks SSL certs
  76. import ssl
  77. f = urllib2.urlopen(req, context=ssl.SSLContext(ssl.PROTOCOL_SSLv23))
  78. else:
  79. f = urllib2.urlopen(req)
  80. f.read()
  81. f.close()
  82. print "Success."
  83. except urllib2.HTTPError as e:
  84. print "ERROR! Received %d %s" % (e.code, e.reason,)
  85. if 400 <= e.code < 500:
  86. if e.info().type == "application/json":
  87. resp = json.load(e)
  88. if "error" in resp:
  89. print resp["error"]
  90. sys.exit(1)
  91. def register_new_user(user, password, server_location, shared_secret, admin):
  92. if not user:
  93. try:
  94. default_user = getpass.getuser()
  95. except:
  96. default_user = None
  97. if default_user:
  98. user = raw_input("New user localpart [%s]: " % (default_user,))
  99. if not user:
  100. user = default_user
  101. else:
  102. user = raw_input("New user localpart: ")
  103. if not user:
  104. print "Invalid user name"
  105. sys.exit(1)
  106. if not password:
  107. password = getpass.getpass("Password: ")
  108. if not password:
  109. print "Password cannot be blank."
  110. sys.exit(1)
  111. confirm_password = getpass.getpass("Confirm password: ")
  112. if password != confirm_password:
  113. print "Passwords do not match"
  114. sys.exit(1)
  115. if not admin:
  116. admin = raw_input("Make admin [no]: ")
  117. if admin in ("y", "yes", "true"):
  118. admin = True
  119. else:
  120. admin = False
  121. request_registration(user, password, server_location, shared_secret, bool(admin))
  122. if __name__ == "__main__":
  123. parser = argparse.ArgumentParser(
  124. description="Used to register new users with a given home server when"
  125. " registration has been disabled. The home server must be"
  126. " configured with the 'registration_shared_secret' option"
  127. " set.",
  128. )
  129. parser.add_argument(
  130. "-u", "--user",
  131. default=None,
  132. help="Local part of the new user. Will prompt if omitted.",
  133. )
  134. parser.add_argument(
  135. "-p", "--password",
  136. default=None,
  137. help="New password for user. Will prompt if omitted.",
  138. )
  139. parser.add_argument(
  140. "-a", "--admin",
  141. action="store_true",
  142. help="Register new user as an admin. Will prompt if omitted.",
  143. )
  144. group = parser.add_mutually_exclusive_group(required=True)
  145. group.add_argument(
  146. "-c", "--config",
  147. type=argparse.FileType('r'),
  148. help="Path to server config file. Used to read in shared secret.",
  149. )
  150. group.add_argument(
  151. "-k", "--shared-secret",
  152. help="Shared secret as defined in server config file.",
  153. )
  154. parser.add_argument(
  155. "server_url",
  156. default="https://localhost:8448",
  157. nargs='?',
  158. help="URL to use to talk to the home server. Defaults to "
  159. " 'https://localhost:8448'.",
  160. )
  161. args = parser.parse_args()
  162. if "config" in args and args.config:
  163. config = yaml.safe_load(args.config)
  164. secret = config.get("registration_shared_secret", None)
  165. if not secret:
  166. print "No 'registration_shared_secret' defined in config."
  167. sys.exit(1)
  168. else:
  169. secret = args.shared_secret
  170. register_new_user(args.user, args.password, args.server_url, secret, args.admin)