Add --salt to server. If no room control salt specified, generate random 10-char string and let admin know

This commit is contained in:
Et0h 2014-11-02 11:00:44 +00:00
parent e3d204aeb3
commit 09df507235
5 changed files with 40 additions and 27 deletions

View File

@ -1,7 +1,5 @@
import hashlib import hashlib
import os.path import os.path
import random
import string
import time import time
import re import re
from twisted.internet.protocol import ClientFactory from twisted.internet.protocol import ClientFactory
@ -447,7 +445,8 @@ class SyncplayClient(object):
@requireMinServerVersion("1.3.0") @requireMinServerVersion("1.3.0")
def createControlledRoom(self, roomName): def createControlledRoom(self, roomName):
controlPassword = RoomPasswordGenerator.generate_password() controlPassword = utils.RandomStringGenerator.generate_room_
password()
self.ui.showMessage(u"Attempting to create controlled room '{}' with password '{}'...".format(roomName, controlPassword)) self.ui.showMessage(u"Attempting to create controlled room '{}' with password '{}'...".format(roomName, controlPassword))
self.lastControlPasswordAttempt = controlPassword self.lastControlPasswordAttempt = controlPassword
self._protocol.requestControlledRoom(roomName, controlPassword) self._protocol.requestControlledRoom(roomName, controlPassword)
@ -772,20 +771,4 @@ class UiManager(object):
def drop(self): def drop(self):
self.__ui.drop() self.__ui.drop()
class RoomPasswordGenerator(object):
@staticmethod
def generate_password():
parts = (
RoomPasswordGenerator._get_random_letters(2),
RoomPasswordGenerator._get_random_numbers(3),
RoomPasswordGenerator._get_random_numbers(3)
)
return "{}-{}-{}".format(*parts)
@staticmethod
def _get_random_letters(quantity):
return ''.join(random.choice(string.ascii_uppercase) for _ in xrange(quantity))
@staticmethod
def _get_random_numbers(quantity):
return ''.join(random.choice(string.digits) for _ in xrange(quantity))

View File

@ -254,6 +254,7 @@ en = {
"welcome-server-notification" : "Welcome to Syncplay server, ver. {0}", # version "welcome-server-notification" : "Welcome to Syncplay server, ver. {0}", # version
"client-connected-room-server-notification" : "{0}({2}) connected to room '{1}'", # username, host, room "client-connected-room-server-notification" : "{0}({2}) connected to room '{1}'", # username, host, room
"client-left-server-notification" : "{0} left server", # name "client-left-server-notification" : "{0} left server", # name
"no-salt-notification" : "PLEASE NOTE: To allow room control passwords generated by this server instance to still work when the server is restarted, please add the following command line argument when running the Syncplay server in the future: --salt {}", #Salt
# Server arguments # Server arguments
@ -262,11 +263,10 @@ en = {
"server-port-argument" : 'server TCP port', "server-port-argument" : 'server TCP port',
"server-password-argument" : 'server password', "server-password-argument" : 'server password',
"server-isolate-room-argument" : 'should rooms be isolated?', "server-isolate-room-argument" : 'should rooms be isolated?',
"server-salt-argument" : "random string used to generate controlled room passwords",
"server-motd-argument": "path to file from which motd will be fetched", "server-motd-argument": "path to file from which motd will be fetched",
"server-messed-up-motd-unescaped-placeholders": "Message of the Day has unescaped placeholders. All $ signs should be doubled ($$).", "server-messed-up-motd-unescaped-placeholders": "Message of the Day has unescaped placeholders. All $ signs should be doubled ($$).",
"server-messed-up-motd-too-long": "Message of the Day is too long - maximum of {} chars, {} given.", "server-messed-up-motd-too-long": "Message of the Day is too long - maximum of {} chars, {} given.",
"server-irc-verbose": "Should server actively report changes in rooms",
"server-irc-config": "Path to irc bot config files",
# Server errors # Server errors
"unknown-command-server-error" : "Unknown command {}", # message "unknown-command-server-error" : "Unknown command {}", # message

View File

@ -11,16 +11,18 @@ import codecs
import os import os
from string import Template from string import Template
import argparse import argparse
from syncplay.utils import RoomPasswordProvider, NotControlledRoom from syncplay.utils import RoomPasswordProvider, NotControlledRoom, RandomStringGenerator
class SyncFactory(Factory): class SyncFactory(Factory):
def __init__(self, password='', motdFilePath=None, isolateRooms=False): def __init__(self, password='', motdFilePath=None, isolateRooms=False, salt=None):
print getMessage("welcome-server-notification").format(syncplay.version) print getMessage("welcome-server-notification").format(syncplay.version)
if password: if password:
password = hashlib.md5(password).hexdigest() password = hashlib.md5(password).hexdigest()
self.password = password self.password = password
# TODO: Make salt come from more reasonable place if salt is None:
self._salt = str(random.random()) salt = RandomStringGenerator.generate_server_salt()
print getMessage("no-salt-notification").format(salt)
self._salt = salt
self._motdFilePath = motdFilePath self._motdFilePath = motdFilePath
if not isolateRooms: if not isolateRooms:
self._roomManager = RoomManager() self._roomManager = RoomManager()
@ -420,4 +422,5 @@ class ConfigurationGetter(object):
self._argparser.add_argument('--port', metavar='port', type=str, nargs='?', help=getMessage("server-port-argument")) self._argparser.add_argument('--port', metavar='port', type=str, nargs='?', help=getMessage("server-port-argument"))
self._argparser.add_argument('--password', metavar='password', type=str, nargs='?', help=getMessage("server-password-argument")) self._argparser.add_argument('--password', metavar='password', type=str, nargs='?', help=getMessage("server-password-argument"))
self._argparser.add_argument('--isolate-rooms', action='store_true', help=getMessage("server-isolate-room-argument")) self._argparser.add_argument('--isolate-rooms', action='store_true', help=getMessage("server-isolate-room-argument"))
self._argparser.add_argument('--salt', metavar='salt', type=str, nargs='?', help=getMessage("server-salt-argument"))
self._argparser.add_argument('--motd-file', metavar='file', type=str, nargs='?', help=getMessage("server-motd-argument")) self._argparser.add_argument('--motd-file', metavar='file', type=str, nargs='?', help=getMessage("server-motd-argument"))

View File

@ -7,6 +7,8 @@ import sys
import os import os
import itertools import itertools
import hashlib import hashlib
import random
import string
def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None): def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None):
"""Retry calling the decorated function using an exponential backoff. """Retry calling the decorated function using an exponential backoff.
@ -241,5 +243,30 @@ class RoomPasswordProvider(object):
provisionalHash = hashlib.sha256(roomName + salt).hexdigest() provisionalHash = hashlib.sha256(roomName + salt).hexdigest()
return hashlib.sha1(provisionalHash + salt + password).hexdigest()[:12].upper() return hashlib.sha1(provisionalHash + salt + password).hexdigest()[:12].upper()
class RandomStringGenerator(object):
@staticmethod
def generate_room_password():
parts = (
RandomStringGenerator._get_random_letters(2),
RandomStringGenerator._get_random_numbers(3),
RandomStringGenerator._get_random_numbers(3)
)
return "{}-{}-{}".format(*parts)
@staticmethod
def generate_server_salt():
parts = (
RandomStringGenerator._get_random_letters(10),
)
return "{}".format(*parts)
@staticmethod
def _get_random_letters(quantity):
return ''.join(random.choice(string.ascii_uppercase) for _ in xrange(quantity))
@staticmethod
def _get_random_numbers(quantity):
return ''.join(random.choice(string.digits) for _ in xrange(quantity))
class NotControlledRoom(Exception): class NotControlledRoom(Exception):
pass pass

View File

@ -20,5 +20,5 @@ if __name__ == '__main__':
argsGetter = ConfigurationGetter() argsGetter = ConfigurationGetter()
args = argsGetter.getConfiguration() args = argsGetter.getConfiguration()
reactor.listenTCP(int(args.port), SyncFactory(args.password, args.motd_file, args.isolate_rooms)) reactor.listenTCP(int(args.port), SyncFactory(args.password, args.motd_file, args.isolate_rooms, args.salt))
reactor.run() reactor.run()