diff --git a/syncplay/client.py b/syncplay/client.py index 4242486..2d42674 100644 --- a/syncplay/client.py +++ b/syncplay/client.py @@ -1,7 +1,5 @@ import hashlib import os.path -import random -import string import time import re from twisted.internet.protocol import ClientFactory @@ -447,7 +445,8 @@ class SyncplayClient(object): @requireMinServerVersion("1.3.0") 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.lastControlPasswordAttempt = controlPassword self._protocol.requestControlledRoom(roomName, controlPassword) @@ -772,20 +771,4 @@ class UiManager(object): def drop(self): 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)) diff --git a/syncplay/messages.py b/syncplay/messages.py index 26992d7..b5ad9a6 100755 --- a/syncplay/messages.py +++ b/syncplay/messages.py @@ -254,6 +254,7 @@ en = { "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-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 @@ -262,11 +263,10 @@ en = { "server-port-argument" : 'server TCP port', "server-password-argument" : 'server password', "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-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-irc-verbose": "Should server actively report changes in rooms", - "server-irc-config": "Path to irc bot config files", # Server errors "unknown-command-server-error" : "Unknown command {}", # message diff --git a/syncplay/server.py b/syncplay/server.py index f586be3..f2cad52 100644 --- a/syncplay/server.py +++ b/syncplay/server.py @@ -11,16 +11,18 @@ import codecs import os from string import Template import argparse -from syncplay.utils import RoomPasswordProvider, NotControlledRoom +from syncplay.utils import RoomPasswordProvider, NotControlledRoom, RandomStringGenerator 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) if password: password = hashlib.md5(password).hexdigest() self.password = password - # TODO: Make salt come from more reasonable place - self._salt = str(random.random()) + if salt is None: + salt = RandomStringGenerator.generate_server_salt() + print getMessage("no-salt-notification").format(salt) + self._salt = salt self._motdFilePath = motdFilePath if not isolateRooms: 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('--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('--motd-file', metavar='file', type=str, nargs='?', help=getMessage("server-motd-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")) \ No newline at end of file diff --git a/syncplay/utils.py b/syncplay/utils.py index b1c52e7..9c2715d 100644 --- a/syncplay/utils.py +++ b/syncplay/utils.py @@ -7,6 +7,8 @@ import sys import os import itertools import hashlib +import random +import string def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None): """Retry calling the decorated function using an exponential backoff. @@ -241,5 +243,30 @@ class RoomPasswordProvider(object): provisionalHash = hashlib.sha256(roomName + salt).hexdigest() 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): pass \ No newline at end of file diff --git a/syncplayServer.py b/syncplayServer.py index 7b1faa1..c127fbf 100755 --- a/syncplayServer.py +++ b/syncplayServer.py @@ -20,5 +20,5 @@ if __name__ == '__main__': argsGetter = ConfigurationGetter() 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()