URI: 
       tnetwork: validate server peers sent by main server - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 21e637f5438e32dd0f6fdae17b0c908c5ab4d24b
   DIR parent 6d1acc929ad77c7ead58489c7db78b446c240aa8
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Wed, 13 May 2020 19:28:35 +0200
       
       network: validate server peers sent by main server
       
       Data returned by the main server for request "server.peers.subscribe"
       is of course untrusted input. Previously if it contained e.g. invalid port numbers
       or IP addresses, it could kill the whole network taskgroup.
       (this might have only affected master and not released versions,
       which would only raise exceptions once the client actually tried to connect to an invalid host/port)
       
       Diffstat:
         M electrum/network.py                 |       6 +++++-
       
       1 file changed, 5 insertions(+), 1 deletion(-)
       ---
   DIR diff --git a/electrum/network.py b/electrum/network.py
       t@@ -77,7 +77,9 @@ NUM_RECENT_SERVERS = 20
        
        
        def parse_servers(result: Sequence[Tuple[str, str, List[str]]]) -> Dict[str, dict]:
       -    """ parse servers list into dict format"""
       +    """Convert servers list (from protocol method "server.peers.subscribe") into dict format.
       +    Also validate values, such as IP addresses and ports.
       +    """
            servers = {}
            for item in result:
                host = item[1]
       t@@ -89,6 +91,7 @@ def parse_servers(result: Sequence[Tuple[str, str, List[str]]]) -> Dict[str, dic
                        if re.match(r"[st]\d*", v):
                            protocol, port = v[0], v[1:]
                            if port == '': port = constants.net.DEFAULT_PORTS[protocol]
       +                    ServerAddr(host, port, protocol=protocol)  # check if raises
                            out[protocol] = port
                        elif re.match("v(.?)+", v):
                            version = v[1:]
       t@@ -431,6 +434,7 @@ class Network(Logger, NetworkRetryManager[ServerAddr]):
                    random.shuffle(server_peers)
                    max_accepted_peers = len(constants.net.DEFAULT_SERVERS) + NUM_RECENT_SERVERS
                    server_peers = server_peers[:max_accepted_peers]
       +            # note that 'parse_servers' also validates the data (which is untrusted input!)
                    self.server_peers = parse_servers(server_peers)
                    self.notify('servers')
                async def get_relay_fee():