proxy.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #!/usr/bin/env python3
  2. #
  3. # MMGen Wallet, a terminal-based cryptocurrency wallet
  4. # Copyright (C)2013-2025 The MMGen Project <mmgen@tuta.io>
  5. # Licensed under the GNU General Public License, Version 3:
  6. # https://www.gnu.org/licenses
  7. # Public project repositories:
  8. # https://github.com/mmgen/mmgen-wallet
  9. # https://gitlab.com/mmgen/mmgen-wallet
  10. """
  11. test.cmdtest_d.include.proxy: SSH SOCKS proxy runner for the cmdtest.py test suite
  12. """
  13. import sys, atexit
  14. from subprocess import run, PIPE
  15. from mmgen.util import msg, die, fmt
  16. from mmgen.util2 import port_in_use
  17. from ...include.common import omsg
  18. class TestProxy:
  19. port = 49237
  20. no_ssh_errmsg = """
  21. The SSH daemon must be running and listening on localhost in order to test
  22. XMR TX relaying via SOCKS proxy. If sshd is not running, please start it.
  23. Otherwise, add the line 'ListenAddress 127.0.0.1' to your sshd_config, and
  24. then restart the daemon.
  25. """
  26. bad_perm_errmsg = """
  27. In order to test XMR TX relaying via SOCKS proxy, it’s desirable to enable
  28. SSH to localhost without a password, which is not currently supported by
  29. your configuration. Your possible courses of action:
  30. 1. Continue by answering 'y' at this prompt, and enter your system password
  31. at the following prompt;
  32. 2. Exit the test here, add your user SSH public key to your user
  33. 'authorized_keys' file, and restart the test; or
  34. 3. Exit the test here, start the SSH SOCKS proxy manually by entering the
  35. following command, and restart the test:
  36. {}
  37. """
  38. need_start_errmsg = """
  39. Please start the SSH SOCKS proxy by entering the following command:
  40. {}
  41. Then restart the test.
  42. """
  43. def kill_proxy(self, args):
  44. if sys.platform in ('linux', 'darwin'):
  45. omsg(f'Stopping SSH SOCKS server at localhost:{self.port}')
  46. cmd = ['pkill', '-f', ' '.join(args)]
  47. run(cmd)
  48. def __init__(self, test_group, cfg):
  49. if test_group and test_group.is_helper:
  50. return
  51. def start_proxy():
  52. run(a + b2)
  53. omsg(f'SSH SOCKS server started, listening at localhost:{self.port}')
  54. a = ['ssh', '-x', '-o', 'ExitOnForwardFailure=True', '-D', f'localhost:{self.port}']
  55. b0 = ['-o', 'PasswordAuthentication=False']
  56. b1 = ['localhost', 'true']
  57. b2 = ['-fN', '-E', 'txrelay-proxy.debug', 'localhost']
  58. if port_in_use(self.port):
  59. omsg(f'Port {self.port} already in use. Assuming SSH SOCKS server is running')
  60. else:
  61. cp = run(a + b0 + b1, stdout=PIPE, stderr=PIPE, text=True)
  62. if cp.stderr:
  63. omsg(cp.stderr)
  64. if cp.returncode == 0:
  65. start_proxy()
  66. elif 'onnection refused' in cp.stderr:
  67. die(2, fmt(self.no_ssh_errmsg, indent=' '))
  68. elif 'ermission denied' in cp.stderr:
  69. msg(fmt(self.bad_perm_errmsg.format(' '.join(a + b2)), indent=' ', strip_char='\t'))
  70. from mmgen.ui import keypress_confirm
  71. keypress_confirm(cfg, 'Continue?', do_exit=True)
  72. start_proxy()
  73. else:
  74. die(2, fmt(self.need_start_errmsg.format(' '.join(a + b2)), indent=' '))
  75. if test_group is None:
  76. self.kill_proxy(a + b2)
  77. elif not hasattr(test_group.tr, 'proxy_stop_registered'):
  78. atexit.unregister(self.kill_proxy)
  79. atexit.register(self.kill_proxy, a + b2)
  80. test_group.tr.proxy_stop_registered = True