Commit 553a894e authored by anonym's avatar anonym

Separate data (filters) out of tor-controlport-filter.

And while we're at it, allow multiple different filters, based on the
client's cmdline.
parent dec33fc1
---
- cmdline:
- '/usr/bin/python3 /usr/bin/onioncircuits'
commands:
GETINFO:
- 'version'
- 'circuit-status'
- 'stream-status'
- 'ns/id/[a-fA-F0-9]+'
- 'ip-to-country/\d+\.\d+\.\d+\.\d+'
GETCONF:
- 'usemicrodescriptors'
- '__owningcontrollerprocess'
---
- cmdline:
- '/usr/bin/python3 /usr/bin/onionshare'
- '/usr/bin/python3 /usr/bin/onionshare-gui'
commands:
GETINFO:
- 'version'
- 'onions/current'
GETCONF:
- '__owningcontrollerprocess'
ADD_ONION:
- 'NEW:BEST Port=80,176\d\d'
DEL_ONION:
- '.+'
events:
- 'HS_DESC'
- 'SIGNAL'
- 'CONF_CHANGED'
---
- cmdline:
- '/usr/local/lib/tor-browser/firefox -allow-remote --class Tor Browser'
commands:
SIGNAL:
- 'NEWNYM'
......@@ -15,6 +15,9 @@
import socketserver
import re
import psutil
import yaml
import glob
from stem.control import Controller, EventType
from stem import SocketError
......@@ -23,39 +26,13 @@ from stem import SocketError
# crash this filter proxy by sending infinitely long lines.
MAX_LINESIZE = 128
ALLOWED_COMMANDS = {
'GETINFO': [
'version',
'onions/current',
'circuit-status',
'stream-status',
'ip-to-country',
'ns/id/[a-fA-F0-9]+',
'ip-to-country/\d+\.\d+\.\d+\.\d+',
],
'GETCONF': [
'usemicrodescriptors',
'__owningcontrollerprocess',
],
'SIGNAL': ['NEWNYM'],
'ADD_ONION': ['NEW:BEST Port=80,176\d\d'],
'DEL_ONION': ['.+'],
}
ALLOWED_EVENTS = {
'HS_DESC': EventType.HS_DESC,
'SIGNAL': EventType.SIGNAL,
'CONF_CHANGED': EventType.CONF_CHANGED,
}
class UnexpectedAnswer(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return "[UnexpectedAnswer] " + self.msg
def handle_controlport_session(controller, readh, writeh):
def handle_controlport_session(controller, readh, writeh, allowed_commands, allowed_events):
def respond(line, raw = False):
writeh.write(bytes(line, 'ascii'))
if not raw: writeh.write(bytes("\r\n", 'ascii'))
......@@ -94,10 +71,10 @@ def handle_controlport_session(controller, readh, writeh):
events = line.split(' ')[1:]
if len(events) > 0:
for event in events:
if event in ALLOWED_EVENTS:
if event in allowed_events:
def event_cb(event):
respond(event.raw_content())
controller.add_event_listener(event_cb, ALLOWED_EVENTS[event])
controller.add_event_listener(event_cb, getattr(EventType, event))
subscribed_event_listeners.append(event_cb)
respond("250 OK")
else:
......@@ -110,7 +87,7 @@ def handle_controlport_session(controller, readh, writeh):
cmd_allowed = False
cmd, _, args = line.partition(' ')
cmd = cmd.upper()
allowed_args = ALLOWED_COMMANDS.get(cmd, [])
allowed_args = allowed_commands.get(cmd, [])
if any([re.match(regex + "$", args) for regex in allowed_args]):
response = controller.msg(line)
respond(response.raw_content(), raw = True)
......@@ -121,6 +98,13 @@ def handle_controlport_session(controller, readh, writeh):
class FilteredControlPortProxyHandler(socketserver.StreamRequestHandler):
def setup(self):
super(type(self), self).setup()
self.filters = []
for filter_file in glob.glob('/etc/tor-controlport-filter.d/*.yml'):
with open(filter_file, "rb") as fh:
self.filters += yaml.load(fh.read())
def connect_to_real_control_port(self):
# Read authentication cookie
with open("/var/run/tor/control.authcookie", "rb") as f:
......@@ -136,9 +120,15 @@ class FilteredControlPortProxyHandler(socketserver.StreamRequestHandler):
return controller
def handle(self):
client_conn = next(conn for conn in psutil.net_connections() if conn.laddr == self.client_address)
client_proc = psutil.Process(client_conn.pid)
client_cmdline = " ".join(client_proc.cmdline())
client_filter = next(filter for filter in self.filters if any([cmdline for cmdline in filter['cmdline'] if client_cmdline.startswith(cmdline)]))
allowed_commands = client_filter.get('commands', {})
allowed_events = client_filter.get('events', [])
controller = self.connect_to_real_control_port()
try:
handle_controlport_session(controller, self.rfile, self.wfile)
handle_controlport_session(controller, self.rfile, self.wfile, allowed_commands, allowed_events)
finally:
controller.close()
......
......@@ -404,3 +404,7 @@ python-qt4
# Provide gnome-open (used to open e.g. URLs in KeePassX, Icedove, Electrum...)
libgnome2-bin
# tor-controlport-filter
python3-psutil
python3-yaml
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment