sydent.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2014 OpenMarket Ltd
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import ConfigParser
  16. import logging
  17. import os
  18. import twisted.internet.reactor
  19. from twisted.python import log
  20. from db.sqlitedb import SqliteDatabase
  21. from http.httpcommon import SslComponents
  22. from http.httpserver import ClientApiHttpServer, ReplicationHttpsServer
  23. from http.httpsclient import ReplicationHttpsClient
  24. from http.servlets.blindlysignstuffservlet import BlindlySignStuffServlet
  25. from http.servlets.pubkeyservlets import EphemeralPubkeyIsValidServlet, PubkeyIsValidServlet
  26. from validators.emailvalidator import EmailValidator
  27. from validators.msisdnvalidator import MsisdnValidator
  28. from sign.ed25519 import SydentEd25519
  29. from http.servlets.emailservlet import EmailRequestCodeServlet, EmailValidateCodeServlet
  30. from http.servlets.msisdnservlet import MsisdnRequestCodeServlet, MsisdnValidateCodeServlet
  31. from http.servlets.lookupservlet import LookupServlet
  32. from http.servlets.bulklookupservlet import BulkLookupServlet
  33. from http.servlets.pubkeyservlets import Ed25519Servlet
  34. from http.servlets.threepidbindservlet import ThreePidBindServlet
  35. from http.servlets.replication import ReplicationPushServlet
  36. from http.servlets.getvalidated3pidservlet import GetValidated3pidServlet
  37. from http.servlets.store_invite_servlet import StoreInviteServlet
  38. from threepid.bind import ThreepidBinder
  39. from replication.pusher import Pusher
  40. logger = logging.getLogger(__name__)
  41. class Sydent:
  42. CONFIG_SECTIONS = ['general', 'db', 'http', 'email', 'crypto', 'sms']
  43. CONFIG_DEFAULTS = {
  44. # general
  45. 'server.name': '',
  46. 'log.path': '',
  47. 'pidfile.path': 'sydent.pid',
  48. # db
  49. 'db.file': 'sydent.db',
  50. # http
  51. 'clientapi.http.port': '8090',
  52. 'replication.https.certfile': '',
  53. 'replication.https.cacert': '', # This should only be used for testing
  54. 'replication.https.port': '4434',
  55. 'obey_x_forwarded_for': False,
  56. # email
  57. 'email.template': 'res/email.template',
  58. 'email.from': 'Sydent Validation <noreply@{hostname}>',
  59. 'email.subject': 'Your Validation Token',
  60. 'email.invite.subject': '%(sender_display_name)s has invited you to chat',
  61. 'email.smtphost': 'localhost',
  62. 'email.smtpport': '25',
  63. 'email.smtpusername': '',
  64. 'email.smtppassword': '',
  65. 'email.hostname': '',
  66. 'email.tlsmode': '0',
  67. # sms
  68. 'bodyTemplate': 'Your code is {token}',
  69. # crypto
  70. 'ed25519.signingkey': '',
  71. }
  72. def __init__(self):
  73. logger.info("Starting Sydent server")
  74. self.parse_config()
  75. logPath = self.cfg.get('general', "log.path")
  76. if logPath != '':
  77. logging.basicConfig(level=logging.INFO, filename=logPath)
  78. else:
  79. logging.basicConfig(level=logging.INFO, filename=logPath)
  80. self.pidfile = self.cfg.get('general', "pidfile.path");
  81. observer = log.PythonLoggingObserver()
  82. observer.start()
  83. self.db = SqliteDatabase(self).db
  84. self.server_name = self.cfg.get('general', 'server.name')
  85. if self.server_name == '':
  86. self.server_name = os.uname()[1]
  87. logger.warn(("You had not specified a server name. I have guessed that this server is called '%s' "
  88. + " and saved this in the config file. If this is incorrect, you should edit server.name in "
  89. + "the config file.") % (self.server_name,))
  90. self.cfg.set('general', 'server.name', self.server_name)
  91. self.save_config()
  92. self.validators = Validators()
  93. self.validators.email = EmailValidator(self)
  94. self.validators.msisdn = MsisdnValidator(self)
  95. self.keyring = Keyring()
  96. self.keyring.ed25519 = SydentEd25519(self).signing_key
  97. self.keyring.ed25519.alg = 'ed25519'
  98. self.servlets = Servlets()
  99. self.servlets.emailRequestCode = EmailRequestCodeServlet(self)
  100. self.servlets.emailValidate = EmailValidateCodeServlet(self)
  101. self.servlets.msisdnRequestCode = MsisdnRequestCodeServlet(self)
  102. self.servlets.msisdnValidate = MsisdnValidateCodeServlet(self)
  103. self.servlets.lookup = LookupServlet(self)
  104. self.servlets.bulk_lookup = BulkLookupServlet(self)
  105. self.servlets.pubkey_ed25519 = Ed25519Servlet(self)
  106. self.servlets.pubkeyIsValid = PubkeyIsValidServlet(self)
  107. self.servlets.ephemeralPubkeyIsValid = EphemeralPubkeyIsValidServlet(self)
  108. self.servlets.threepidBind = ThreePidBindServlet(self)
  109. self.servlets.replicationPush = ReplicationPushServlet(self)
  110. self.servlets.getValidated3pid = GetValidated3pidServlet(self)
  111. self.servlets.storeInviteServlet = StoreInviteServlet(self)
  112. self.servlets.blindlySignStuffServlet = BlindlySignStuffServlet(self)
  113. self.threepidBinder = ThreepidBinder(self)
  114. self.sslComponents = SslComponents(self)
  115. self.clientApiHttpServer = ClientApiHttpServer(self)
  116. self.replicationHttpsServer = ReplicationHttpsServer(self)
  117. self.replicationHttpsClient = ReplicationHttpsClient(self)
  118. self.pusher = Pusher(self)
  119. def parse_config(self):
  120. self.cfg = ConfigParser.SafeConfigParser(Sydent.CONFIG_DEFAULTS)
  121. for sect in Sydent.CONFIG_SECTIONS:
  122. try:
  123. self.cfg.add_section(sect)
  124. except ConfigParser.DuplicateSectionError:
  125. pass
  126. self.cfg.read("sydent.conf")
  127. def save_config(self):
  128. fp = open("sydent.conf", 'w')
  129. self.cfg.write(fp)
  130. fp.close()
  131. def run(self):
  132. self.clientApiHttpServer.setup()
  133. self.replicationHttpsServer.setup()
  134. self.pusher.setup()
  135. if self.pidfile:
  136. with open(self.pidfile, 'w') as pidfile:
  137. pidfile.write(str(os.getpid()) + "\n")
  138. twisted.internet.reactor.run()
  139. def ip_from_request(self, request):
  140. if (self.cfg.get('http', 'obey_x_forwarded_for') and
  141. request.requestHeaders.hasHeader("X-Forwarded-For")):
  142. return request.requestHeaders.getRawHeaders("X-Forwarded-For")[0]
  143. return request.getClientIP()
  144. class Validators:
  145. pass
  146. class Servlets:
  147. pass
  148. class Keyring:
  149. pass
  150. if __name__ == '__main__':
  151. syd = Sydent()
  152. syd.run()