# HG changeset patch # User Edouard Tisserant # Date 1540304360 -7200 # Node ID 33a0dbabccd3b7c169472abb12fa4ab589072ee7 # Parent 7ce4e5cf63395e86de2a194de6f00ee1142fd590 Runtime : Ensure that a random PSK secret compatible with stunnel is generated if -s commandline switch is used. Stunnel service is restarted after generation, using spawn_subprocess. TODO : give stunnel restart command as a commandline parameter. diff -r 7ce4e5cf6339 -r 33a0dbabccd3 Beremiz_service.py --- a/Beremiz_service.py Tue Oct 23 16:13:34 2018 +0200 +++ b/Beremiz_service.py Tue Oct 23 16:19:20 2018 +0200 @@ -50,7 +50,7 @@ print(""" Usage of Beremiz PLC execution service :\n %s {[-n servicename] [-i IP] [-p port] [-x enabletaskbar] [-a autostart]|-h|--help} working_dir - -n zeroconf service name (default:disabled) + -n service name (default:None, zeroconf discovery disabled) -i IP address of interface to bind to (default:localhost) -p port number default:3000 -h print this help text and quit @@ -59,7 +59,7 @@ -t enable/disable Twisted web interface (0:disable 1:enable) (default:1) -w web server port or "off" to disable web server (default:8009) -c WAMP client config file (can be overriden by wampconf.json in project) - -s WAMP client secret, given as a file (can be overriden by wamp.secret in project) + -s PSK secret path (default:PSK disabled) -e python extension (absolute path .py) working_dir - directory where are stored PLC files @@ -78,7 +78,7 @@ interface = '' port = 3000 webport = 8009 -wampsecret = None +pskpath = None wampconf = None servicename = None autostart = False @@ -120,7 +120,7 @@ elif o == "-c": wampconf = None if a == "off" else a elif o == "-s": - wampsecret = None if a == "off" else a + pskpath = None if a == "off" else a elif o == "-e": fnameanddirname = list(os.path.split(os.path.realpath(a))) fnameanddirname.reverse() @@ -489,6 +489,12 @@ sys.path.append(extension_folder) execfile(os.path.join(extension_folder, extention_file), locals()) +# Service name is used as an ID for stunnel's PSK +# Some extension may set 'servicename' to a computed ID or Serial Number +# instead of using commandline '-n' +if servicename is not None and pskpath is not None: + from runtime.Stunnel import ensurepsk + ensurepsk(servicename, pskpath) runtime.CreatePLCObjectSingleton( WorkingDir, argv, statuschange, evaluator, pyruntimevars) @@ -511,7 +517,7 @@ if havewamp: try: WC.SetServer(pyroserver) - WC.RegisterWampClient(wampconf, wampsecret) + WC.RegisterWampClient(wampconf, pskpath) WC.RegisterWebSettings(NS) except Exception: LogMessageAndException(_("WAMP client startup failed. ")) diff -r 7ce4e5cf6339 -r 33a0dbabccd3 runtime/Stunnel.py --- a/runtime/Stunnel.py Tue Oct 23 16:13:34 2018 +0200 +++ b/runtime/Stunnel.py Tue Oct 23 16:19:20 2018 +0200 @@ -1,10 +1,21 @@ import os -from binascii import hexlify +#from binascii import hexlify +from runtime.spawn_subprocess import call restart_stunnel_cmdline = ["/etc/init.d/S50stunnel","restart"] +# stunnel takes no encoding for psk, so we try to lose minimum entropy +# by using all possible chars except '\0\n\r' (checked stunnel parser to be sure) +translator = ''.join([(lambda c: '#' if c in '\0\n\r' else c)(chr(i)) for i in xrange(256)]) + def pskgen(ID, pskpath): - secretstring = hexlify(os.urandom(256)) + secret = os.urandom(256) # 2048 bits is still safe nowadays + + # following makes 512 length string, rejected by stunnel + # using binascii hexlify loses 50% entropy + # secretstring = hexlify(secret) + + secretstring = secret.translate(translator) pskstring = ID+":"+secretstring with open(pskpath, 'w') as f: f.write(pskstring) @@ -14,5 +25,5 @@ # check if already there if not os.path.exists(pskpath): # create if needed - pskgen(IS, pskpath) + pskgen(ID, pskpath)