StemPortPlugin.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import logging
  2. import traceback
  3. import socket
  4. import stem
  5. from stem import Signal
  6. from stem.control import Controller
  7. from stem.socket import ControlPort
  8. from Plugin import PluginManager
  9. from Config import config
  10. from Debug import Debug
  11. if config.tor != "disable":
  12. from gevent import monkey
  13. monkey.patch_time()
  14. monkey.patch_socket(dns=False)
  15. monkey.patch_thread()
  16. print("Stem Port Plugin: modules are patched.")
  17. else:
  18. print("Stem Port Plugin: Tor mode disabled. Module patching skipped.")
  19. class PatchedControlPort(ControlPort):
  20. def _make_socket(self):
  21. try:
  22. if "socket_noproxy" in dir(socket): # Socket proxy-patched, use non-proxy one
  23. control_socket = socket.socket_noproxy(socket.AF_INET, socket.SOCK_STREAM)
  24. else:
  25. control_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  26. # TODO: repeated code - consider making a separate method
  27. control_socket.connect((self._control_addr, self._control_port))
  28. return control_socket
  29. except socket.error as exc:
  30. raise stem.SocketError(exc)
  31. def from_port(address = '127.0.0.1', port = 'default'):
  32. import stem.connection
  33. if not stem.util.connection.is_valid_ipv4_address(address):
  34. raise ValueError('Invalid IP address: %s' % address)
  35. elif port != 'default' and not stem.util.connection.is_valid_port(port):
  36. raise ValueError('Invalid port: %s' % port)
  37. if port == 'default':
  38. raise ValueError('Must specify a port')
  39. else:
  40. control_port = PatchedControlPort(address, port)
  41. return Controller(control_port)
  42. @PluginManager.registerTo("TorManager")
  43. class TorManagerPlugin(object):
  44. def connectController(self):
  45. self.log.info("Authenticate using Stem... %s:%s" % (self.ip, self.port))
  46. try:
  47. with self.lock:
  48. if config.tor_password:
  49. controller = from_port(port=self.port, password=config.tor_password)
  50. else:
  51. controller = from_port(port=self.port)
  52. controller.authenticate()
  53. self.controller = controller
  54. self.status = "Connected (via Stem)"
  55. except Exception as err:
  56. print("\n")
  57. traceback.print_exc()
  58. print("\n")
  59. self.controller = None
  60. self.status = "Error (%s)" % err
  61. self.log.error("Tor stem connect error: %s" % Debug.formatException(err))
  62. return self.controller
  63. def disconnect(self):
  64. self.controller.close()
  65. self.controller = None
  66. def resetCircuits(self):
  67. try:
  68. self.controller.signal(Signal.NEWNYM)
  69. except Exception as err:
  70. self.status = "Stem reset circuits error (%s)" % err
  71. self.log.error("Stem reset circuits error: %s" % err)
  72. def makeOnionAndKey(self):
  73. try:
  74. service = self.controller.create_ephemeral_hidden_service(
  75. {self.fileserver_port: self.fileserver_port},
  76. await_publication = False
  77. )
  78. if service.private_key_type != "RSA1024":
  79. raise Exception("ZeroNet doesn't support crypto " + service.private_key_type)
  80. self.log.debug("Stem created %s.onion (async descriptor publication)" % service.service_id)
  81. return (service.service_id, service.private_key)
  82. except Exception as err:
  83. self.status = "AddOnion error (Stem: %s)" % err
  84. self.log.error("Failed to create hidden service with Stem: " + err)
  85. return False
  86. def delOnion(self, address):
  87. try:
  88. self.controller.remove_ephemeral_hidden_service(address)
  89. return True
  90. except Exception as err:
  91. self.status = "DelOnion error (Stem: %s)" % err
  92. self.log.error("Stem failed to delete %s.onion: %s" % (address, err))
  93. self.disconnect() # Why?
  94. return False
  95. def request(self, cmd):
  96. with self.lock:
  97. if not self.enabled:
  98. return False
  99. else:
  100. self.log.error("[WARNING] StemPort self.request should not be called")
  101. return ""
  102. def send(self, cmd, conn=None):
  103. self.log.error("[WARNING] StemPort self.send should not be called")
  104. return ""