[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [ooni-probe/master] * Fixes #6968, #6971
commit fef162fe803fad2ff7eab45d321baf1086f6c980
Author: Isis Lovecruft <isis@xxxxxxxxxxxxxx>
Date: Tue Sep 25 00:07:54 2012 +0000
* Fixes #6968, #6971
* Found bug: first bridge doesn't get tested #6970
* I'm trying to use trac more to keep other people up-to-date, in case that
wasn't obviously. I hate Trac like nobody's business.
---
ooni/plugins/bridget.py | 201 +++++++++++++++++++++++++---------------------
ooni/utils/onion.py | 38 +++++++---
2 files changed, 137 insertions(+), 102 deletions(-)
diff --git a/ooni/plugins/bridget.py b/ooni/plugins/bridget.py
index cd7ba4e..83c9ed6 100644
--- a/ooni/plugins/bridget.py
+++ b/ooni/plugins/bridget.py
@@ -66,33 +66,43 @@ class PTNotFoundException(Exception):
return sys.exit()
class ValueChecker(object):
- def port_check(self, number):
+ def port_check(self, port):
"""Check that given ports are in the allowed range."""
- number = int(number)
- if number not in range(1024, 65535):
+ port = int(port)
+ if port not in range(1024, 65535):
raise ValueError("Port out of range")
+ log.err()
sock_check, ctrl_check = port_check, port_check
allowed = "must be between 1024 and 65535."
sock_check.coerceDoc = "Port to use for Tor's SocksPort, " +allowed
ctrl_check.coerceDoc = "Port to use for Tor's ControlPort, " +allowed
- def uid_check(pluggable_transport):
- """Check that we're not root when trying to use pluggable transports."""
+ def uid_check(self, pluggable_transport):
+ """
+ Check that we're not root when trying to use pluggable transports. If
+ we are, setuid to normal user (1000) if we're running on a posix-based
+ system, and if we're Windows just tell the user that we can't be run
+ as root with the specified options and then exit.
+ """
uid, gid = os.getuid(), os.getgid()
if uid == 0 and gid == 0:
log.msg("Error: Running bridget as root with transports not allowed.")
+ if os.name == 'posix':
log.msg("Dropping privileges to normal user...")
os.setgid(1000)
os.setuid(1000)
+ else:
+ sys.exit(0)
- def dir_check(d):
+ def dir_check(self, d):
"""Check that the given directory exists."""
- if not os.isdir(d):
+ if not os.path.isdir(d):
raise ValueError("%s doesn't exist, or has wrong permissions" % d)
- def file_check(f):
- if not os.isfile(f):
+ def file_check(self, f):
+ """Check that the given file exists."""
+ if not os.path.isfile(f):
raise ValueError("%s does not exist, or has wrong permissions" % f)
class RandomPortException(Exception):
@@ -121,8 +131,9 @@ class TxtorconImportError(ImportError):
class BridgetArgs(usage.Options):
"""Commandline options."""
+ global vc
vc = ValueChecker()
-
+
optParameters = [
['bridges', 'b', None,
'File listing bridge IP:ORPorts to test'],
@@ -227,6 +238,17 @@ class BridgetTest(OONITest):
else:
lst.append(line.replace('\n',''))
+ def __parse_data_dir__(data_dir):
+ if data_dir.startswith('~'):
+ data_dir = os.path.expanduser(data_dir)
+ elif data_dir.startswith('/'):
+ data_dir = os.path.join(os.getcwd(), data_dir)
+ elif data_dir.startswith('./'):
+ data_dir = os.path.abspath(data_dir)
+ else:
+ data_dir = os.path.join(os.getcwd(), data_dir)
+ return data_dir
+
if self.local_options:
try:
from ooni.lib.txtorcon import TorConfig
@@ -258,17 +280,18 @@ class BridgetTest(OONITest):
if options['torpath']:
self.tor_binary = options['torpath']
- if self.local_options['datadir']:
- self.data_directory = local_options['datadir']
+ if options['datadir']:
+ self.data_directory = __parse_data_dir__(options['datadir'])
else:
self.data_directory = None
if options['transport']:
self.use_pt = True
- log.msg("Using ClientTransportPlugin %s" % options['transport'])
+ log.msg("Using ClientTransportPlugin %s"
+ % options['transport'])
[self.pt_type, pt_exec] = options['transport'].split(' ', 1)
- ## ClientTransportPlugin transport exec path-to-binary [options]
+ ## ClientTransportPlugin transport exec pathtobinary [options]
## XXX we need a better way to deal with all PTs
if self.pt_type == "obfs2":
config.ClientTransportPlugin = self.pt_type + " " + pt_exec
@@ -355,6 +378,7 @@ class BridgetTest(OONITest):
log.err(tie)
sys.exit()
+ '''
## XXX qu'est-que fuck? ou est utiliser ce fonction?
def bootstrap(ctrl):
"""
@@ -364,6 +388,7 @@ class BridgetTest(OONITest):
conf = TorConfig(ctrl)
conf.post_bootstrap.addCallback(setup_done).addErrback(setup_fail)
log.msg("Tor process connected, bootstrapping ...")
+ '''
@defer.inlineCallbacks
def reconfigure_bridge(state, bridge, use_pt=False, pt_type=None):
@@ -385,13 +410,19 @@ class BridgetTest(OONITest):
raise PTNotFoundException
controller_response = reset_tor.callback
+ controller_response.addCallback(reconfigure_done,
+ bridge,
+ reachable)
+ controller_response.addErrback(reconfigure_fail,
+ bridge,
+ reachable)
#if not controller_response:
# defer.returnValue((state.callback, None))
#else:
# defer.returnValue((state.callback, controller_response))
if controller_response == 'OK':
- defer.returnValue((state.callback, controller_response))
+ defer.returnValue((state, controller_response))
else:
log.msg("TorControlProtocol responded with error:\n%s"
% controller_response)
@@ -400,11 +431,16 @@ class BridgetTest(OONITest):
except Exception, e:
log.msg("Reconfiguring torrc with Bridge line %s failed:\n%s"
% (bridge, e))
+ defer.returnValue((state.callback, e))
- def reconfigure_fail(state, bridge, bad):
+ def reconfigure_done(response, bridge, reachable):
+ log.msg("Reconfiguring with 'Bridge %s' successful" % bridge)
+ reachable.append(bridge)
+
+ def reconfigure_fail(response, bridge, unreachable):
log.msg("Reconfiguring TorConfig with parameters %s failed"
% state)
- bad.append(bridge)
+ unreachable.append(bridge)
@defer.inlineCallbacks
def remove_public_relays(state, bridges):
@@ -423,7 +459,7 @@ class BridgetTest(OONITest):
% node)
bridges.remove(line)
except ValueError, ve:
- log.err(ve)
+ log.debug(ve)
if len(both) > 0:
try:
@@ -447,23 +483,6 @@ class BridgetTest(OONITest):
raise NotImplemented
#attacher.extend_circuit
- #def state_complete(state, bridge_list=None, relay_list=None):
- # """Called when we've got a TorState."""
- # log.msg("We've completely booted up a Tor version %s at PID %d"
- # % (state.protocol.version, state.tor_pid))
- #
- # log.msg("This Tor has the following %d Circuits:"
- # % len(state.circuits))
- # for circ in state.circuits.values():
- # log.msg("%s" % circ)
- #
- # if bridge_list is not None and relay_list is None:
- # return state, bridge_list
- # elif bridge_list is None and relay_list is not None:
- # raise NotImplemented
- # else:
- # return state, None
-
def state_attach(state, path):
log.msg("Setting up custom circuit builder...")
attacher = CustomCircuit(state)
@@ -488,50 +507,65 @@ class BridgetTest(OONITest):
log.msg("Bridget: initiating test ... ")
+ #defer.setDebugging(True)
if self.bridges_remaining() > 0:
- for self.current_bridge in self.bridges:
- #self.current_bridge = bridge
+ if not 'Bridge' in self.config.config:
+ self.config.Bridge = self.bridges.pop()
+
+ ## Necessary for avoiding starting several processes:
+ self.config.save()
+ assert self.config.config.has_key('Bridge'), "NO BRIDGE"
+
+ state = start_tor(self.reactor, self.config, self.control_port,
+ self.tor_binary, self.data_directory)
+ #state.addCallback(remove_public_relays, self.bridges)
+ #state.callback
+ #rm_public_relays = defer.Deferred()
+ #rm_public_relays.addCallback(remove_public_relays,
+ # self.bridges)
+ #state.chainDeferred(rm_public_relays)
+ #state = defer.DeferredList([state])
+ from ooni.utils.onion import __setup_done__, __setup_fail__
+ state.addCallback(__setup_done__)
+ state.addErrback(__setup_fail__)
- if not self.config.config.has_key('Bridge'):
- self.config.Bridge = self.current_bridge
- state = start_tor(self.reactor,
- self.config,
- self.control_port,
- self.tor_binary,
- self.data_directory)
- state.addCallback(remove_public_relays, self.bridges)
- else:
- log.msg("We now have %d untested bridges..."
- % self.bridges_remaining())
- reconf = defer.Deferred()
- reconf.addCallback(reconfigure_bridge, state,
- self.current_bridge, self.use_pt,
- self.pt_type)
- reconf.addErrback(reconfigure_fail, state,
- self.current_bridge, self.bridges_down)
- state.chainDeferred(reconf)
- state.callback(controller_response)
- #all = []
- #reconf = reconfigure_bridge(state, self.current_bridge,
- # self.use_pt, self.pt_type)
- #reconf.addCallback(reconfigure_done)
- #reconf.addErrback(reconfigure_fail)
- #state.DeferredList(all)
-
- if self.relays_remaining() != 0:
- state.chainDeferred()
-
+ ## XXX Should do something like: if state.iscomplete
+ #if 'Bridge' in self.config.config:
+ if state and 'Bridge' in self.config.config:
+ all = []
+ for bridge in self.bridges:
+ self.current_bridge = bridge
+ log.msg("We now have %d untested bridges..."
+ % self.bridges_remaining())
+ #reconf = defer.Deferred()
+ #reconf.addCallback(reconfigure_bridge, state,
+ # self.current_bridge, self.use_pt,
+ # self.pt_type)
+ #reconf.addErrback(reconfigure_fail, state,
+ # self.current_bridge, self.bridges_down)
+ #state.chainDeferred(reconf)
+ #state.callback
+
+ reconf = reconfigure_bridge(state,
+ self.current_bridge,
+ self.use_pt,
+ self.pt_type)
+ all.append(reconf)
+ state.chainDeferred(defer.DeferredList(all))
+ #state.addCallback(defer.DeferredList(all))
+
+ if self.relays_remaining() > 0:
while self.relays_remaining() >= 3:
#path = list(self.relays.pop() for i in range(3))
- #log.msg("Trying path %s" % '->'.join(map(lambda node: node, path)))
+ #log.msg("Trying path %s" % '->'.join(map(lambda node:
+ # node, path)))
self.current_relay = self.relays.pop()
for circ in state.circuits.values():
for node in circ.path:
if node == self.current_relay:
self.relays_up.append(self.current_relay)
-
if len(circ.path) < 3:
try:
parameters = (state.attacher, circ,
@@ -545,32 +579,15 @@ class BridgetTest(OONITest):
else:
continue
- return state
+ #return state
## still need to attach attacher to state
## then build circuits
- ## XXX see txtorcon.TorControlProtocol.add_event_listener we
- ## may not need full CustomCircuit class
- ## o if bridges and relays, use one bridge then build a circuit
- ## from three relays
- ## o if bridges only, try one bridge at a time, but don't build
- ## circuits, just return
- ## o if relays only, build circuits from relays
- #else:
- # try:
- # state.addCallback(reconfigure_bridge, self.current_bridge,
- # self.use_pt, self.pt_type)
- # state.addErrback(reconfigure_fail)
- # except TimeoutError:
- # log.msg("Adding %s to unreachable bridges..."
- # % self.current_bridge)
- # self.bridges_down.append(self.current_bridge)
- # else:
- # log.msg("Adding %s to reachable bridges..."
- # % self.current_bridge)
- # self.bridges_up.append(self.current_bridge)
-
- #reactor.run()
+
+ reactor.run()
+
+ def control(self, experiment_result, args):
+ experiment_result.callback
## So that getPlugins() can register the Test:
bridget = BridgetTest(None, None, None)
@@ -585,6 +602,6 @@ bridget = BridgetTest(None, None, None)
## x check if bridges are public relays
## o take bridge_desc file as input, also be able to give same
## format as output
-## x Add assychronous timout for deferred, so that we don't wait
+## x Add asynchronous timeout for deferred, so that we don't wait
## forever for bridges that don't work.
## o Add mechanism for testing through another host
diff --git a/ooni/utils/onion.py b/ooni/utils/onion.py
index 46373b4..08f27d4 100644
--- a/ooni/utils/onion.py
+++ b/ooni/utils/onion.py
@@ -17,7 +17,9 @@
import random
from ooni.lib.txtorcon import CircuitListenerMixin, IStreamAttacher
+from ooni.lib.txtorcon import TorState
from ooni.utils import log
+from twisted.internet import defer
from zope.interface import implements
@@ -50,7 +52,7 @@ def __state_complete__(state, bridge_list=None, relay_list=None):
return state, None
def __updates__(_progress, _tag, _summary):
- log.msg("%d%%: %s", _progress, _summary)
+ log.msg("%d%%: %s" % (_progress, _summary))
def write_torrc(conf, data_dir=None):
"""
@@ -98,6 +100,7 @@ def delete_files_or_dirs(delete_list):
except OSError:
rmtree(temp, ignore_errors=True)
+@xxxxxxxxxxxxxxxxxxxxx
def start_tor(reactor, config, control_port, tor_binary, data_dir,
report=None, progress=__updates__, process_cb=__setup_done__,
process_eb=__setup_fail__):
@@ -162,18 +165,17 @@ def start_tor(reactor, config, control_port, tor_binary, data_dir,
connection_creator = partial(end_point.connect, TorProtocolFactory())
process_protocol = TorProcessProtocol(connection_creator, progress)
process_protocol.to_delete = to_delete
- process_protocol.addCallback(process_cb)
- process_protocol.addErrback(process_eb)
reactor.addSystemEventTrigger('before', 'shutdown',
partial(delete_files_or_dirs, to_delete))
try:
- transport = reactor.spawnProcess(process_protocol,
- tor_binary,
- args=(tor_binary,'-f',torrc),
- env={'HOME': data_dir},
- path=data_dir)
- transport.closeStdin()
+ transport = yield reactor.spawnProcess(process_protocol,
+ tor_binary,
+ args=(tor_binary,'-f',torrc),
+ env={'HOME': data_dir},
+ path=data_dir)
+ if transport:
+ transport.closeStdin()
except RuntimeError as e:
log.err("Starting Tor failed: %s" % e)
process_protocol.connected_cb.errback(e)
@@ -182,7 +184,23 @@ def start_tor(reactor, config, control_port, tor_binary, data_dir,
log.err("Running bridget on Windows requires pywin32: %s" % url)
process_protocol.connected_cb.errback(e)
- return process_protocol.connected_cb ## new defer.Deferred()
+ #proc_proto = process_protocol.connected_cb
+ #proc_proto.addCallback(process_cb)
+ #proc_proto.addErrback(process_eb)
+ #
+ #d = yield process_protocol.connected_cb.addCallback(
+ # process_cb).addErrback(
+ # process_eb)
+ #d = yield process_protocol.connected_cb
+ #d.addCallback(process_cb)
+ #d.addErrback(process_eb)
+ #
+ #defer.returnValue(d)
+
+ d = yield process_protocol.connected_cb
+ defer.returnValue(d)
+
+ #return process_protocol.connected_cb.addCallback(process_cb).addErrback(process_eb)
class CustomCircuit(CircuitListenerMixin):
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits