ZeroNet/plugins/disabled-StemPort/StemPortPlugin.py

136 lines
4.3 KiB
Python

import logging
import traceback
import socket
import stem
from stem import Signal
from stem.control import Controller
from stem.socket import ControlPort
from Plugin import PluginManager
from Config import config
from Debug import Debug
if config.tor != "disable":
from gevent import monkey
monkey.patch_time()
monkey.patch_socket(dns=False)
monkey.patch_thread()
print("Stem Port Plugin: modules are patched.")
else:
print("Stem Port Plugin: Tor mode disabled. Module patching skipped.")
class PatchedControlPort(ControlPort):
def _make_socket(self):
try:
if "socket_noproxy" in dir(socket): # Socket proxy-patched, use non-proxy one
control_socket = socket.socket_noproxy(socket.AF_INET, socket.SOCK_STREAM)
else:
control_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# TODO: repeated code - consider making a separate method
control_socket.connect((self._control_addr, self._control_port))
return control_socket
except socket.error as exc:
raise stem.SocketError(exc)
def from_port(address = '127.0.0.1', port = 'default'):
import stem.connection
if not stem.util.connection.is_valid_ipv4_address(address):
raise ValueError('Invalid IP address: %s' % address)
elif port != 'default' and not stem.util.connection.is_valid_port(port):
raise ValueError('Invalid port: %s' % port)
if port == 'default':
raise ValueError('Must specify a port')
else:
control_port = PatchedControlPort(address, port)
return Controller(control_port)
@PluginManager.registerTo("TorManager")
class TorManagerPlugin(object):
def connectController(self):
self.log.info("Authenticate using Stem... %s:%s" % (self.ip, self.port))
try:
with self.lock:
if config.tor_password:
controller = from_port(port=self.port, password=config.tor_password)
else:
controller = from_port(port=self.port)
controller.authenticate()
self.controller = controller
self.status = "Connected (via Stem)"
except Exception as err:
print("\n")
traceback.print_exc()
print("\n")
self.controller = None
self.status = "Error (%s)" % err
self.log.error("Tor stem connect error: %s" % Debug.formatException(err))
return self.controller
def disconnect(self):
self.controller.close()
self.controller = None
def resetCircuits(self):
try:
self.controller.signal(Signal.NEWNYM)
except Exception as err:
self.status = "Stem reset circuits error (%s)" % err
self.log.error("Stem reset circuits error: %s" % err)
def makeOnionAndKey(self):
try:
service = self.controller.create_ephemeral_hidden_service(
{self.fileserver_port: self.fileserver_port},
await_publication = False
)
if service.private_key_type != "RSA1024":
raise Exception("ZeroNet doesn't support crypto " + service.private_key_type)
self.log.debug("Stem created %s.onion (async descriptor publication)" % service.service_id)
return (service.service_id, service.private_key)
except Exception as err:
self.status = "AddOnion error (Stem: %s)" % err
self.log.error("Failed to create hidden service with Stem: " + err)
return False
def delOnion(self, address):
try:
self.controller.remove_ephemeral_hidden_service(address)
return True
except Exception as err:
self.status = "DelOnion error (Stem: %s)" % err
self.log.error("Stem failed to delete %s.onion: %s" % (address, err))
self.disconnect() # Why?
return False
def request(self, cmd):
with self.lock:
if not self.enabled:
return False
else:
self.log.error("[WARNING] StemPort self.request should not be called")
return ""
def send(self, cmd, conn=None):
self.log.error("[WARNING] StemPort self.send should not be called")
return ""