# HG changeset patch # User Edouard Tisserant # Date 1539613619 -7200 # Node ID 84b3cc18893b01bf24a9e3937830eadbb212c1da # Parent bef2b4b87370eecea8c3f861d116cb920bd1e033 Replaced PYROSSL with PYROPSK. Secrets are files named $ID.secret in project's /psk directory. Connect with URI formated PYROPSK://host[:port]#ID diff -r bef2b4b87370 -r 84b3cc18893b connectors/PYRO/PSK_Adapter.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/connectors/PYRO/PSK_Adapter.py Mon Oct 15 16:26:59 2018 +0200 @@ -0,0 +1,62 @@ + +import sslpsk +import Pyro +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) + # 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=='PYROLOC': + self.resolvePYROLOC_URI("PYRO") # 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 + diff -r bef2b4b87370 -r 84b3cc18893b connectors/PYRO/__init__.py --- a/connectors/PYRO/__init__.py Mon Oct 15 15:27:47 2018 +0200 +++ b/connectors/PYRO/__init__.py Mon Oct 15 16:26:59 2018 +0200 @@ -36,7 +36,6 @@ import Pyro.util from Pyro.errors import PyroError - service_type = '_PYRO._tcp.local.' # this module attribute contains a list of DNS-SD (Zeroconf) service types # supported by this connector confnode. @@ -53,38 +52,19 @@ 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" + urlpath, 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() else: schemename = "PYROLOC" + if location.find(service_type) != -1: try: from zeroconf import Zeroconf @@ -161,3 +141,4 @@ return member return PyroProxyProxy() + diff -r bef2b4b87370 -r 84b3cc18893b connectors/__init__.py --- a/connectors/__init__.py Mon Oct 15 15:27:47 2018 +0200 +++ b/connectors/__init__.py Mon Oct 15 16:26:59 2018 +0200 @@ -32,7 +32,6 @@ _base_path = paths.AbsDir(__file__) - def _GetLocalConnectorClassFactory(name): return lambda: getattr(__import__(name, globals(), locals()), name + "_connector_factory")