# HG changeset patch # User Edouard Tisserant # Date 1539880621 -7200 # Node ID 523559fe635257acbb239b70a77f7b8438c02c34 # Parent d8fb90a2e11fd354084e9f1928cfd26c4ca54347# Parent e927c101ce6d60e4f08c06b9fbfc89e3d0fa6e96 merge diff -r d8fb90a2e11f -r 523559fe6352 Beremiz_service.py --- a/Beremiz_service.py Wed Oct 03 00:05:32 2018 +0200 +++ b/Beremiz_service.py Thu Oct 18 18:37:01 2018 +0200 @@ -75,7 +75,7 @@ sys.exit(2) # default values -given_ip = None +interface = '' port = 3000 webport = 8009 wampsecret = None @@ -97,8 +97,10 @@ version() sys.exit() elif o == "-i": - if len(a.split(".")) == 4 or a == "localhost": - given_ip = a + if len(a.split(".")) == 4: + interface = a + elif a == "localhost": + interface = '127.0.0.1' else: usage() sys.exit() @@ -493,7 +495,7 @@ runtime.CreatePLCObjectSingleton( WorkingDir, argv, statuschange, evaluator, pyruntimevars) -pyroserver = Server(servicename, given_ip, port) +pyroserver = Server(servicename, interface, port) if havewx: taskbar_instance = BeremizTaskBarIcon(pyroserver) @@ -501,7 +503,7 @@ if havetwisted: if webport is not None: try: - website = NS.RegisterWebsite(webport) + website = NS.RegisterWebsite(interface, webport) pyruntimevars["website"] = website NS.SetServer(pyroserver) statuschange.append(NS.website_statuslistener_factory(website)) diff -r d8fb90a2e11f -r 523559fe6352 connectors/PYRO/PSK_Adapter.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/connectors/PYRO/PSK_Adapter.py Thu Oct 18 18:37:01 2018 +0200 @@ -0,0 +1,83 @@ +from __future__ import absolute_import +from __future__ import print_function + +import socket +import re +import sslpsk +import Pyro +from Pyro.core import PyroURI +from Pyro.protocol import _connect_socket,TCPConnection,PYROAdapter +from Pyro.errors import ConnectionDeniedError, ProtocolError +from Pyro.util import Log + +# +# The TLS-PSK adapter that handles SSL connections instead of regular sockets, +# but using Pre Shared Keys instead of Certificates +# +class PYROPSKAdapter(PYROAdapter): + # This is essentialy the same as in Pyro/protocol.py + # only raw_sock wrapping into sock through sslpsk.wrap_socket was added + # Pyro unfortunately doesn't allow cleaner customization + def bindToURI(self,URI): + with self.lock: # only 1 thread at a time can bind the URI + try: + self.URI=URI + + # This are the statements that differ from Pyro/protocol.py + raw_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + _connect_socket(raw_sock, URI.address, URI.port, self.timeout) + sock = sslpsk.wrap_socket( + raw_sock, psk=Pyro.config.PYROPSK, server_side=False, + ciphers="PSK-AES256-GCM-SHA384:PSK-AES256-CBC-SHA") + # all the rest is the same as in Pyro/protocol.py + + conn=TCPConnection(sock, sock.getpeername()) + # receive the authentication challenge string, and use that to build the actual identification string. + try: + authChallenge=self.recvAuthChallenge(conn) + except ProtocolError,x: + # check if we were denied + if hasattr(x,"partialMsg") and x.partialMsg[:len(self.denyMSG)]==self.denyMSG: + raise ConnectionDeniedError(Pyro.constants.deniedReasons[int(x.partialMsg[-1])]) + else: + raise + # reply with our ident token, generated from the ident passphrase and the challenge + msg = self._sendConnect(sock,self.newConnValidator.createAuthToken(self.ident, authChallenge, conn.addr, self.URI, None) ) + if msg==self.acceptMSG: + self.conn=conn + self.conn.connected=1 + Log.msg('PYROAdapter','connected to',str(URI)) + if URI.protocol=='PYROLOCPSK': + self.resolvePYROLOC_URI("PYROPSK") # updates self.URI + elif msg[:len(self.denyMSG)]==self.denyMSG: + try: + raise ConnectionDeniedError(Pyro.constants.deniedReasons[int(msg[-1])]) + except (KeyError,ValueError): + raise ConnectionDeniedError('invalid response') + except socket.error: + Log.msg('PYROAdapter','connection failed to URI',str(URI)) + raise ProtocolError('connection failed') + +_getProtocolAdapter = Pyro.protocol.getProtocolAdapter +def getProtocolAdapter(protocol): + if protocol in ('PYROPSK', 'PYROLOCPSK'): + return PYROPSKAdapter() + _getProtocolAdapter(protocol) + +Pyro.protocol.getProtocolAdapter = getProtocolAdapter + +_processStringURI = Pyro.core.processStringURI +def processStringURI(URI): + x=re.match(r'(?PPYROLOCPSK)://(?P[^\s:]+):?(?P\d+)?/(?P\S*)',URI) + if x: + protocol=x.group('protocol') + hostname=x.group('hostname') + port=x.group('port') + if port: + port=int(port) + else: + port=0 + name=x.group('name') + return PyroURI(hostname,name,port,protocol) + return _processStringURI(URI) +Pyro.core.processStringURI = processStringURI diff -r d8fb90a2e11f -r 523559fe6352 connectors/PYRO/__init__.py --- a/connectors/PYRO/__init__.py Wed Oct 03 00:05:32 2018 +0200 +++ b/connectors/PYRO/__init__.py Thu Oct 18 18:37:01 2018 +0200 @@ -36,8 +36,7 @@ import Pyro.util from Pyro.errors import PyroError - -service_type = '_PYRO._tcp.local.' +zeroconf_service_type = '_PYRO._tcp.local.' # this module attribute contains a list of DNS-SD (Zeroconf) service types # supported by this connector confnode. # @@ -53,43 +52,26 @@ servicetype, location = uri.split("://") if servicetype == "PYROS": - schemename = "PYROLOCSSL" - # Protect against name->IP substitution in Pyro3 - Pyro.config.PYRO_DNS_URI = True - # Beware Pyro lib need str path, not unicode - # don't rely on PYRO_STORAGE ! see documentation - Pyro.config.PYROSSL_CERTDIR = os.path.abspath(str(confnodesroot.ProjectPath) + '/certs') - if not os.path.exists(Pyro.config.PYROSSL_CERTDIR): + import connectors.PYRO.PSK_Adapter + schemename = "PYROLOCPSK" + url, ID = location.split('#') + # load PSK from project + secpath = os.path.join(str(confnodesroot.ProjectPath), 'psk', ID+'.secret') + if not os.path.exists(secpath): confnodesroot.logger.write_error( - 'Error : the directory %s is missing for SSL certificates (certs_dir).' - 'Please fix it in your project.\n' % Pyro.config.PYROSSL_CERTDIR) + 'Error: Pre-Shared-Key Secret in %s is missing!\n' % secpath) return None - else: - confnodesroot.logger.write(_("PYRO using certificates in '%s' \n") - % (Pyro.config.PYROSSL_CERTDIR)) - Pyro.config.PYROSSL_CERT = "client.crt" - Pyro.config.PYROSSL_KEY = "client.key" - - # Ugly Monkey Patching - def _gettimeout(self): - return self.timeout - - def _settimeout(self, timeout): - self.timeout = timeout - from M2Crypto.SSL import Connection # pylint: disable=import-error - Connection.timeout = None - Connection.gettimeout = _gettimeout - Connection.settimeout = _settimeout - # M2Crypto.SSL.Checker.WrongHost: Peer certificate commonName does not - # match host, expected 127.0.0.1, got server - Connection.clientPostConnectionCheck = None + Pyro.config.PYROPSK = (open(secpath).read(), ID) + # strip ID from URL, so that pyro can understand it. + location = url else: schemename = "PYROLOC" - if location.find(service_type) != -1: + + if location.find(zeroconf_service_type) != -1: try: from zeroconf import Zeroconf r = Zeroconf() - i = r.get_service_info(service_type, location) + i = r.get_service_info(zeroconf_service_type, location) if i is None: raise Exception("'%s' not found" % location) ip = str(socket.inet_ntoa(i.address)) @@ -161,3 +143,4 @@ return member return PyroProxyProxy() + diff -r d8fb90a2e11f -r 523559fe6352 connectors/__init__.py --- a/connectors/__init__.py Wed Oct 03 00:05:32 2018 +0200 +++ b/connectors/__init__.py Thu Oct 18 18:37:01 2018 +0200 @@ -32,7 +32,6 @@ _base_path = paths.AbsDir(__file__) - def _GetLocalConnectorClassFactory(name): return lambda: getattr(__import__(name, globals(), locals()), name + "_connector_factory") diff -r d8fb90a2e11f -r 523559fe6352 runtime/NevowServer.py --- a/runtime/NevowServer.py Wed Oct 03 00:05:32 2018 +0200 +++ b/runtime/NevowServer.py Thu Oct 18 18:37:01 2018 +0200 @@ -333,11 +333,11 @@ # print "We will be called back when the client disconnects" -def RegisterWebsite(port): +def RegisterWebsite(iface, port): website = WebInterface() site = appserver.NevowSite(website) - reactor.listenTCP(port, site) + reactor.listenTCP(port, site, interface=iface) print(_('HTTP interface port :'), port) return website diff -r d8fb90a2e11f -r 523559fe6352 runtime/PyroServer.py --- a/runtime/PyroServer.py Wed Oct 03 00:05:32 2018 +0200 +++ b/runtime/PyroServer.py Thu Oct 18 18:37:01 2018 +0200 @@ -30,9 +30,7 @@ def _to_be_published(self): return self.servicename is not None and \ - self.ip_addr is not None and \ - self.ip_addr != "localhost" and \ - self.ip_addr != "127.0.0.1" + self.ip_addr not in ["", "localhost", "127.0.0.1"] def PrintServerInfo(self): print(_("Pyro port :"), self.port)