commit 90d39dab97309e0498e447d28cef1bd0b87aad86 Author: kudrom kudrom@riseup.net Date: Thu Aug 7 00:45:44 2014 +0200
Fixed bug 11858: ooni might not look at requiresTor? --- ooni/director.py | 12 ++++--- ooni/oonicli.py | 25 +++++++------ ooni/settings.py | 82 +++++++++++++++++++++---------------------- ooni/tests/test_settings.py | 77 ++++++++++++++++++++++------------------ 4 files changed, 104 insertions(+), 92 deletions(-)
diff --git a/ooni/director.py b/ooni/director.py index d48c18f..18b7cb2 100644 --- a/ooni/director.py +++ b/ooni/director.py @@ -122,11 +122,13 @@ class Director(object): def start(self, start_tor=False): self.netTests = self.getNetTests()
- if config.advanced.start_tor and start_tor: - yield self.startTor() - elif config.tor.control_port: - log.msg("Connecting to Tor Control Port...") - yield self.getTorState() + if start_tor: + yield config.check_tor() + if config.advanced.start_tor: + yield self.startTor() + elif config.tor.control_port: + log.msg("Connecting to Tor Control Port...") + yield self.getTorState()
if config.global_options['no-geoip']: aux = [False] diff --git a/ooni/oonicli.py b/ooni/oonicli.py index cd9f4a9..cfc7ddc 100644 --- a/ooni/oonicli.py +++ b/ooni/oonicli.py @@ -111,13 +111,10 @@ def runWithDirector(logging=True, start_tor=True): config.global_options = global_options config.set_paths() config.initialize_ooni_home() - d = config.read_config_file(check_incoherences=True) - - @d.addErrback - def shutdown(failure): - failure.trap(errors.ConfigFileIncoherent) - log.err("Shutting down until ooniprobe.conf is coherent.") - reactor.callWhenRunning(reactor.stop) + try: + config.read_config_file(check_incoherences=True) + except errors.ConfigFileIncoherent: + sys.exit(6)
if global_options['verbose']: config.advanced.debug = True @@ -176,11 +173,11 @@ def runWithDirector(logging=True, start_tor=True):
deck = Deck() deck.bouncer = global_options['bouncer'] - start_tor = deck.requiresTor + conditions_to_start_tor = [False] if global_options['bouncer']: - start_tor = True + conditions_to_start_tor.append(True) if global_options['collector']: - start_tor = True + conditions_to_start_tor.append(True)
try: if global_options['testdeck']: @@ -207,6 +204,8 @@ def runWithDirector(logging=True, start_tor=True): log.err(e) sys.exit(5)
+ conditions_to_start_tor.append(deck.requiresTor) + start_tor = any(conditions_to_start_tor) d = director.start(start_tor=start_tor)
def setup_nettest(_): @@ -223,7 +222,8 @@ def runWithDirector(logging=True, start_tor=True): errors.CouldNotFindTestHelper, errors.CouldNotFindTestCollector, errors.ProbeIPUnknown, - errors.InvalidInputFile) + errors.InvalidInputFile, + errors.ConfigFileIncoherent)
if isinstance(failure.value, errors.TorNotRunning): log.err("Tor does not appear to be running") @@ -260,6 +260,9 @@ def runWithDirector(logging=True, start_tor=True): elif isinstance(failure.value, errors.InvalidInputFile): log.err("Invalid input file "%s"" % failure.value)
+ elif isinstance(failure.value, errors.ConfigFileIncoherent): + log.err("Incoherent config file") + if config.advanced.debug: log.exception(failure)
diff --git a/ooni/settings.py b/ooni/settings.py index cbf96cb..6f95536 100644 --- a/ooni/settings.py +++ b/ooni/settings.py @@ -99,7 +99,6 @@ class OConfig(object): else: w.write(line)
- @defer.inlineCallbacks def read_config_file(self, check_incoherences=False): if not os.path.exists(self.config_file): print "Configuration file does not exist." @@ -116,61 +115,60 @@ class OConfig(object): getattr(self, setting)[k] = v self.set_paths()
- # The incoherent checks must be performed after OConfig is in a valid state to runWithDirector if check_incoherences: - coherent = yield self.check_incoherences(configuration) - if not coherent: - raise errors.ConfigFileIncoherent + self.check_incoherences(configuration)
- @defer.inlineCallbacks def check_incoherences(self, configuration): incoherent = [] - deferreds = []
- if not configuration['advanced']['start_tor']: - if not 'socks_port' in configuration['tor']: + if configuration['advanced']['interface'] != 'auto' and configuration['advanced']['interface'] not in get_if_list(): + incoherent.append('advanced:interface') + + self.log_incoherences(incoherent) + + def log_incoherences(self, incoherences): + if len(incoherences) > 0: + if len(incoherences) > 1: + incoherent_pretty = ", ".join(incoherences[:-1]) + ' and ' + incoherences[-1] + else: + incoherent_pretty = incoherences[0] + log.err("You must set properly %s in %s." % (incoherent_pretty, self.config_file)) + raise errors.ConfigFileIncoherent + + @defer.inlineCallbacks + def check_tor(self): + """ + Called only when we must start tor by director.start + """ + incoherent = [] + d = defer.Deferred() + + if not self.advanced.start_tor: + if self.tor.socks_port is None: incoherent.append('tor:socks_port') - if not 'control_port' in configuration['tor']: + if self.tor.control_port is None: incoherent.append('tor:control_port') - if 'socks_port' in configuration['tor'] and 'control_port' in configuration['tor']: + if self.tor.socks_port is not None and self.tor.control_port is not None: # Check if tor is listening in these ports - @defer.inlineCallbacks - def cb(state): - timeout_call.cancel() - result = yield state.protocol.get_info("net/listeners/socks") - if result["net/listeners/socks"].split(':')[1] != str(configuration['tor']['socks_port']): - incoherent.append('tor:socks_port') - - def err(failure): - incoherent.append('tor:socks_port') - if timeout_call.active: - timeout_call.cancel() - def timeout(): incoherent.append('tor:control_port') if not d.called: d.errback()
- connection = TCP4ClientEndpoint(reactor, "localhost", configuration['tor']['control_port']) - d = txtorcon.build_tor_connection(connection) - d.addCallback(cb) - d.addErrback(err) - deferreds.append(d) + connection = TCP4ClientEndpoint(reactor, "localhost", self.tor.control_port) timeout_call = reactor.callLater(30, timeout) - - if configuration['advanced']['interface'] != 'auto' and configuration['advanced']['interface'] not in get_if_list(): - incoherent.append('advanced:interface') - - deferred_list = defer.DeferredList(deferreds) - yield deferred_list - if len(incoherent) > 0: - if len(incoherent) > 1: - incoherent_pretty = ", ".join(incoherent[:-1]) + ' and ' + incoherent[-1] - else: - incoherent_pretty = incoherent[0] - log.err("You must set properly %s in %s." % (incoherent_pretty, self.config_file)) - defer.returnValue(False) - defer.returnValue(True) + try: + d = txtorcon.build_tor_connection(connection) + state = yield d + result = yield state.protocol.get_info("net/listeners/socks") + if result["net/listeners/socks"].split(':')[1] != str(self.tor.socks_port): + incoherent.append('tor:socks_port') + except Exception: + incoherent.append('tor:socks_port') + finally: + if timeout_call.active: + timeout_call.cancel() + self.log_incoherences(incoherent)
def generate_pcap_filename(self, testDetails): test_name, start_time = testDetails['test_name'], testDetails['start_time'] diff --git a/ooni/tests/test_settings.py b/ooni/tests/test_settings.py index b28c1b2..efde7b4 100644 --- a/ooni/tests/test_settings.py +++ b/ooni/tests/test_settings.py @@ -7,10 +7,13 @@ from scapy.all import get_if_list import txtorcon
from ooni.settings import OConfig +from ooni import errors +from bases import ConfigTestCase
-class TestSettings(unittest.TestCase): +class TestSettings(ConfigTestCase): def setUp(self): + super(ConfigTestCase, self).setUp() self.conf = OConfig() self.configuration = {'advanced': {'interface': 'auto', 'start_tor': True}, @@ -19,6 +22,7 @@ class TestSettings(unittest.TestCase): self.tor_protocol = None
def tearDown(self): + super(ConfigTestCase, self).tearDown() if self.silly_listener is not None: self.silly_listener.stopListening()
@@ -29,8 +33,8 @@ class TestSettings(unittest.TestCase): print '%s %s' % (prog, summary)
config = txtorcon.TorConfig() - config.SocksPort = self.configuration['tor']['socks_port'] - config.ControlPort = self.configuration['tor']['control_port'] + config.SocksPort = self.conf.tor.socks_port + config.ControlPort = self.conf.tor.control_port d = txtorcon.launch_tor(config, reactor, progress_updates=progress) return d
@@ -42,33 +46,39 @@ class TestSettings(unittest.TestCase): class SillyFactory(Factory): protocol = SillyProtocol
- self.silly_listener = reactor.listenTCP(self.configuration['tor']['socks_port'], SillyFactory()) + self.silly_listener = reactor.listenTCP(self.conf.tor.socks_port, SillyFactory())
- @defer.inlineCallbacks def test_vanilla_configuration(self): - ret = yield self.conf.check_incoherences(self.configuration) - self.assertEqual(ret, True) + self.conf.check_incoherences(self.configuration)
@defer.inlineCallbacks - def test_check_incoherences_start_tor_missing_options(self): - self.configuration['advanced']['start_tor'] = False - ret = yield self.conf.check_incoherences(self.configuration) - self.assertEqual(ret, False) - self.configuration['tor'] = {'socks_port': 9999} - ret = yield self.conf.check_incoherences(self.configuration) - self.assertEqual(ret, False) - self.configuration['tor']['control_port'] = 9998 - ret = yield self.conf.check_incoherences(self.configuration) - self.assertEqual(ret, False) + def test_check_tor_missing_options(self): + self.conf.advanced.start_tor = False + try: + yield self.conf.check_tor() + except errors.ConfigFileIncoherent: + pass + + self.conf.tor.socks_port = 9999 + try: + yield self.conf.check_tor() + except errors.ConfigFileIncoherent: + pass + + self.conf.tor.socks_port = None + self.conf.tor.control_port = 9998 + try: + yield self.conf.check_tor() + except errors.ConfigFileIncoherent: + pass
@defer.inlineCallbacks - def test_check_incoherences_start_tor_correct(self): - self.configuration['advanced']['start_tor'] = False - self.configuration['tor'] = {'socks_port': 9999} - self.configuration['tor']['control_port'] = 9998 + def test_check_tor_correct(self): + self.conf.advanced.start_tor = False + self.conf.tor.socks_port = 9999 + self.conf.tor.control_port = 9998 self.tor_process = yield self.run_tor() - ret = yield self.conf.check_incoherences(self.configuration) - self.assertEqual(ret, True) + yield self.conf.check_incoherences(self.configuration) self.tor_process.transport.signalProcess('TERM')
d = defer.Deferred() @@ -76,20 +86,19 @@ class TestSettings(unittest.TestCase): yield d
@defer.inlineCallbacks - def test_check_incoherences_start_tor_silly_listener(self): - self.configuration['advanced']['start_tor'] = False - self.configuration['tor'] = {'socks_port': 9999} - self.configuration['tor']['control_port'] = 9998 + def test_check_tor_silly_listener(self): + self.conf.advanced.start_tor = False + self.conf.tor.socks_port = 9999 + self.conf.tor.control_port = 9998 self.run_silly_server() - ret = yield self.conf.check_incoherences(self.configuration) - self.assertEqual(ret, False) + try: + yield self.conf.check_tor() + except errors.ConfigFileIncoherent: + pass
- @defer.inlineCallbacks def test_check_incoherences_interface(self): self.configuration['advanced']['interface'] = 'funky' - ret = yield self.conf.check_incoherences(self.configuration) - self.assertEqual(ret, False) + self.assertRaises(errors.ConfigFileIncoherent, self.conf.check_incoherences, self.configuration)
self.configuration['advanced']['interface'] = random.choice(get_if_list()) - ret = yield self.conf.check_incoherences(self.configuration) - self.assertEqual(ret, True) + self.conf.check_incoherences(self.configuration)
tor-commits@lists.torproject.org