network: split off proxy_user and proxy_pass from serialized proxy string and add separate cmdline params and config keys for them.
support parsing both old style mode:host:port:user:pass and new mode:host:port, where new form also accepts IPv6 addresses
This commit is contained in:
@@ -1563,11 +1563,20 @@ def add_network_options(parser):
|
|||||||
parser.add_argument("-f", "--serverfingerprint", dest=SimpleConfig.NETWORK_SERVERFINGERPRINT.key(), default=None,
|
parser.add_argument("-f", "--serverfingerprint", dest=SimpleConfig.NETWORK_SERVERFINGERPRINT.key(), default=None,
|
||||||
help="only allow connecting to servers with a matching SSL certificate SHA256 fingerprint. " +
|
help="only allow connecting to servers with a matching SSL certificate SHA256 fingerprint. " +
|
||||||
"To calculate this yourself: '$ openssl x509 -noout -fingerprint -sha256 -inform pem -in mycertfile.crt'. Enter as 64 hex chars.")
|
"To calculate this yourself: '$ openssl x509 -noout -fingerprint -sha256 -inform pem -in mycertfile.crt'. Enter as 64 hex chars.")
|
||||||
parser.add_argument("-1", "--oneserver", action="store_true", dest=SimpleConfig.NETWORK_ONESERVER.key(), default=None, help="connect to one server only")
|
parser.add_argument("-1", "--oneserver", action="store_true", dest=SimpleConfig.NETWORK_ONESERVER.key(), default=None,
|
||||||
parser.add_argument("-s", "--server", dest=SimpleConfig.NETWORK_SERVER.key(), default=None, help="set server host:port:protocol, where protocol is either t (tcp) or s (ssl)")
|
help="connect to one server only")
|
||||||
parser.add_argument("-p", "--proxy", dest=SimpleConfig.NETWORK_PROXY.key(), default=None, help="set proxy [type:]host[:port] (or 'none' to disable proxy), where type is socks4,socks5 or http")
|
parser.add_argument("-s", "--server", dest=SimpleConfig.NETWORK_SERVER.key(), default=None,
|
||||||
parser.add_argument("--noonion", action="store_true", dest=SimpleConfig.NETWORK_NOONION.key(), default=None, help="do not try to connect to onion servers")
|
help="set server host:port:protocol, where protocol is either t (tcp) or s (ssl)")
|
||||||
parser.add_argument("--skipmerklecheck", action="store_true", dest=SimpleConfig.NETWORK_SKIPMERKLECHECK.key(), default=None, help="Tolerate invalid merkle proofs from server")
|
parser.add_argument("-p", "--proxy", dest=SimpleConfig.NETWORK_PROXY.key(), default=None,
|
||||||
|
help="set proxy [type:]host:port (or 'none' to disable proxy), where type is socks4 or socks5")
|
||||||
|
parser.add_argument("--proxyuser", dest=SimpleConfig.NETWORK_PROXY_USER.key(), default=None,
|
||||||
|
help="set proxy username")
|
||||||
|
parser.add_argument("--proxypassword", dest=SimpleConfig.NETWORK_PROXY_PASSWORD.key(), default=None,
|
||||||
|
help="set proxy password")
|
||||||
|
parser.add_argument("--noonion", action="store_true", dest=SimpleConfig.NETWORK_NOONION.key(), default=None,
|
||||||
|
help="do not try to connect to onion servers")
|
||||||
|
parser.add_argument("--skipmerklecheck", action="store_true", dest=SimpleConfig.NETWORK_SKIPMERKLECHECK.key(), default=None,
|
||||||
|
help="Tolerate invalid merkle proofs from server")
|
||||||
|
|
||||||
def add_global_options(parser):
|
def add_global_options(parser):
|
||||||
group = parser.add_argument_group('global options')
|
group = parser.add_argument_group('global options')
|
||||||
|
|||||||
@@ -470,6 +470,8 @@ class ElectrumGui(BaseElectrumGui, EventListener):
|
|||||||
out = self.run_popup('', ['Transaction ID:', self.txid[self.pos]])
|
out = self.run_popup('', ['Transaction ID:', self.txid[self.pos]])
|
||||||
|
|
||||||
def edit_str(self, target, c, is_num=False):
|
def edit_str(self, target, c, is_num=False):
|
||||||
|
if target is None:
|
||||||
|
target = ''
|
||||||
# detect backspace
|
# detect backspace
|
||||||
cc = curses.unctrl(c).decode()
|
cc = curses.unctrl(c).decode()
|
||||||
if c in [8, 127, 263] and target:
|
if c in [8, 127, 263] and target:
|
||||||
@@ -721,10 +723,13 @@ class ElectrumGui(BaseElectrumGui, EventListener):
|
|||||||
proxy_config, auto_connect = net_params.proxy, net_params.auto_connect
|
proxy_config, auto_connect = net_params.proxy, net_params.auto_connect
|
||||||
srv = 'auto-connect' if auto_connect else str(self.network.default_server)
|
srv = 'auto-connect' if auto_connect else str(self.network.default_server)
|
||||||
out = self.run_dialog('Network', [
|
out = self.run_dialog('Network', [
|
||||||
{'label':'server', 'type':'str', 'value':srv},
|
{'label': 'server', 'type': 'str', 'value': srv},
|
||||||
{'label':'proxy', 'type':'str', 'value':self.config.NETWORK_PROXY},
|
{'label': 'proxy', 'type': 'str', 'value': self.config.NETWORK_PROXY},
|
||||||
], buttons = 1)
|
{'label': 'proxy user', 'type': 'str', 'value': self.config.NETWORK_PROXY_USER},
|
||||||
|
{'label': 'proxy pass', 'type': 'str', 'value': self.config.NETWORK_PROXY_PASSWORD},
|
||||||
|
], buttons=1)
|
||||||
if out:
|
if out:
|
||||||
|
self.show_message(repr(proxy_config))
|
||||||
if out.get('server'):
|
if out.get('server'):
|
||||||
server_str = out.get('server')
|
server_str = out.get('server')
|
||||||
auto_connect = server_str == 'auto-connect'
|
auto_connect = server_str == 'auto-connect'
|
||||||
@@ -734,11 +739,14 @@ class ElectrumGui(BaseElectrumGui, EventListener):
|
|||||||
except Exception:
|
except Exception:
|
||||||
self.show_message("Error:" + server_str + "\nIn doubt, type \"auto-connect\"")
|
self.show_message("Error:" + server_str + "\nIn doubt, type \"auto-connect\"")
|
||||||
return False
|
return False
|
||||||
if out.get('server') or out.get('proxy'):
|
if out.get('server') or out.get('proxy') or out.get('proxy user') or out.get('proxy pass'):
|
||||||
proxy = electrum.network.deserialize_proxy(out.get('proxy')) if out.get('proxy') else proxy_config
|
new_proxy_config = electrum.network.deserialize_proxy(out.get('proxy')) if out.get('proxy') else proxy_config
|
||||||
|
if new_proxy_config:
|
||||||
|
new_proxy_config['user'] = out.get('proxy user') if 'proxy user' in out else proxy_config['user']
|
||||||
|
new_proxy_config['pass'] = out.get('proxy pass') if 'proxy pass' in out else proxy_config['pass']
|
||||||
net_params = NetworkParameters(
|
net_params = NetworkParameters(
|
||||||
server=server_addr,
|
server=server_addr,
|
||||||
proxy=proxy,
|
proxy=new_proxy_config,
|
||||||
auto_connect=auto_connect)
|
auto_connect=auto_connect)
|
||||||
self.network.run_from_another_thread(self.network.set_parameters(net_params))
|
self.network.run_from_another_thread(self.network.set_parameters(net_params))
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import functools
|
|||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
|
|
||||||
import aiorpcx
|
import aiorpcx
|
||||||
from aiorpcx import ignore_after
|
from aiorpcx import ignore_after, NetAddress
|
||||||
from aiohttp import ClientResponse
|
from aiohttp import ClientResponse
|
||||||
|
|
||||||
from . import util
|
from . import util
|
||||||
@@ -168,35 +168,52 @@ proxy_modes = ['socks4', 'socks5']
|
|||||||
def serialize_proxy(p):
|
def serialize_proxy(p):
|
||||||
if not isinstance(p, dict):
|
if not isinstance(p, dict):
|
||||||
return None
|
return None
|
||||||
return ':'.join([p.get('mode'), p.get('host'), p.get('port'),
|
return ':'.join([p.get('mode'), p.get('host'), p.get('port')])
|
||||||
p.get('user', ''), p.get('password', '')])
|
|
||||||
|
|
||||||
|
|
||||||
def deserialize_proxy(s: Optional[str]) -> Optional[dict]:
|
def deserialize_proxy(s: Optional[str], user: str = None, password: str = None) -> Optional[dict]:
|
||||||
if not isinstance(s, str):
|
if not isinstance(s, str):
|
||||||
return None
|
return None
|
||||||
if s.lower() == 'none':
|
if s.lower() == 'none':
|
||||||
return None
|
return None
|
||||||
proxy = {"mode":"socks5", "host":"localhost"}
|
proxy = {"mode": "socks5", "host": "localhost"}
|
||||||
# FIXME raw IPv6 address fails here
|
|
||||||
args = s.split(':')
|
args = s.split(':')
|
||||||
n = 0
|
if args[0] in proxy_modes:
|
||||||
if proxy_modes.count(args[n]) == 1:
|
proxy['mode'] = args[0]
|
||||||
proxy["mode"] = args[n]
|
args = args[1:]
|
||||||
n += 1
|
|
||||||
if len(args) > n:
|
def is_valid_port(ps: str):
|
||||||
proxy["host"] = args[n]
|
try:
|
||||||
n += 1
|
assert 0 < int(ps) < 65535
|
||||||
if len(args) > n:
|
except (ValueError, AssertionError):
|
||||||
proxy["port"] = args[n]
|
return False
|
||||||
n += 1
|
return True
|
||||||
else:
|
|
||||||
proxy["port"] = "8080" if proxy["mode"] == "http" else "1080"
|
def is_valid_host(ph: str):
|
||||||
if len(args) > n:
|
try:
|
||||||
proxy["user"] = args[n]
|
NetAddress(ph, '1')
|
||||||
n += 1
|
except ValueError:
|
||||||
if len(args) > n:
|
return False
|
||||||
proxy["password"] = args[n]
|
return True
|
||||||
|
|
||||||
|
# detect migrate from old settings
|
||||||
|
if len(args) == 4 and is_valid_host(args[0]) and is_valid_port(args[1]): # host:port:user:pass,
|
||||||
|
proxy['host'] = args[0]
|
||||||
|
proxy['port'] = args[1]
|
||||||
|
proxy['user'] = args[2]
|
||||||
|
proxy['password'] = args[3]
|
||||||
|
return proxy
|
||||||
|
|
||||||
|
proxy['host'] = ':'.join(args[:-1])
|
||||||
|
proxy['port'] = args[-1]
|
||||||
|
|
||||||
|
if not is_valid_host(proxy['host']) or not is_valid_port(proxy['port']):
|
||||||
|
return None
|
||||||
|
|
||||||
|
proxy['user'] = user
|
||||||
|
proxy['password'] = password
|
||||||
|
|
||||||
return proxy
|
return proxy
|
||||||
|
|
||||||
|
|
||||||
@@ -496,7 +513,8 @@ class Network(Logger, NetworkRetryManager[ServerAddr]):
|
|||||||
def _init_parameters_from_config(self) -> None:
|
def _init_parameters_from_config(self) -> None:
|
||||||
self.auto_connect = self.config.NETWORK_AUTO_CONNECT
|
self.auto_connect = self.config.NETWORK_AUTO_CONNECT
|
||||||
self._set_default_server()
|
self._set_default_server()
|
||||||
self._set_proxy(deserialize_proxy(self.config.NETWORK_PROXY))
|
self._set_proxy(deserialize_proxy(self.config.NETWORK_PROXY, self.config.NETWORK_PROXY_USER,
|
||||||
|
self.config.NETWORK_PROXY_PASSWORD))
|
||||||
self._maybe_set_oneserver()
|
self._maybe_set_oneserver()
|
||||||
|
|
||||||
def get_donation_address(self):
|
def get_donation_address(self):
|
||||||
@@ -625,6 +643,8 @@ class Network(Logger, NetworkRetryManager[ServerAddr]):
|
|||||||
async def set_parameters(self, net_params: NetworkParameters):
|
async def set_parameters(self, net_params: NetworkParameters):
|
||||||
proxy = net_params.proxy
|
proxy = net_params.proxy
|
||||||
proxy_str = serialize_proxy(proxy)
|
proxy_str = serialize_proxy(proxy)
|
||||||
|
proxy_user = proxy['user'] if proxy else None
|
||||||
|
proxy_pass = proxy['password'] if proxy else None
|
||||||
server = net_params.server
|
server = net_params.server
|
||||||
# sanitize parameters
|
# sanitize parameters
|
||||||
try:
|
try:
|
||||||
@@ -636,10 +656,14 @@ class Network(Logger, NetworkRetryManager[ServerAddr]):
|
|||||||
self.config.NETWORK_AUTO_CONNECT = net_params.auto_connect
|
self.config.NETWORK_AUTO_CONNECT = net_params.auto_connect
|
||||||
self.config.NETWORK_ONESERVER = net_params.oneserver
|
self.config.NETWORK_ONESERVER = net_params.oneserver
|
||||||
self.config.NETWORK_PROXY = proxy_str
|
self.config.NETWORK_PROXY = proxy_str
|
||||||
|
self.config.NETWORK_PROXY_USER = proxy_user
|
||||||
|
self.config.NETWORK_PROXY_PASSWORD = proxy_pass
|
||||||
self.config.NETWORK_SERVER = str(server)
|
self.config.NETWORK_SERVER = str(server)
|
||||||
# abort if changes were not allowed by config
|
# abort if changes were not allowed by config
|
||||||
if self.config.NETWORK_SERVER != str(server) \
|
if self.config.NETWORK_SERVER != str(server) \
|
||||||
or self.config.NETWORK_PROXY != proxy_str \
|
or self.config.NETWORK_PROXY != proxy_str \
|
||||||
|
or self.config.NETWORK_PROXY_USER != proxy_user \
|
||||||
|
or self.config.NETWORK_PROXY_PASSWORD != proxy_pass \
|
||||||
or self.config.NETWORK_ONESERVER != net_params.oneserver:
|
or self.config.NETWORK_ONESERVER != net_params.oneserver:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -926,6 +926,8 @@ class SimpleConfig(Logger):
|
|||||||
NETWORK_AUTO_CONNECT = ConfigVar('auto_connect', default=True, type_=bool)
|
NETWORK_AUTO_CONNECT = ConfigVar('auto_connect', default=True, type_=bool)
|
||||||
NETWORK_ONESERVER = ConfigVar('oneserver', default=False, type_=bool)
|
NETWORK_ONESERVER = ConfigVar('oneserver', default=False, type_=bool)
|
||||||
NETWORK_PROXY = ConfigVar('proxy', default=None)
|
NETWORK_PROXY = ConfigVar('proxy', default=None)
|
||||||
|
NETWORK_PROXY_USER = ConfigVar('proxy_user', default=None)
|
||||||
|
NETWORK_PROXY_PASSWORD = ConfigVar('proxy_password', default=None)
|
||||||
NETWORK_SERVER = ConfigVar('server', default=None, type_=str)
|
NETWORK_SERVER = ConfigVar('server', default=None, type_=str)
|
||||||
NETWORK_NOONION = ConfigVar('noonion', default=False, type_=bool)
|
NETWORK_NOONION = ConfigVar('noonion', default=False, type_=bool)
|
||||||
NETWORK_OFFLINE = ConfigVar('offline', default=False, type_=bool)
|
NETWORK_OFFLINE = ConfigVar('offline', default=False, type_=bool)
|
||||||
|
|||||||
Reference in New Issue
Block a user