commit 818e4603d4d2a91f033b013db2b3dfecc5c99114 Author: Arturo Filastò hellais@torproject.org Date: Thu Aug 2 17:42:43 2012 +0200
* Fix some bugs in Daphn3 * Add more details to Test interface * Remove dead code in Reporting system * Make some changes to bridget --- bin/ooniprobe | 5 +- ooni/lib/Makefile | 4 ++ ooni/ooniprobe.py | 3 +- ooni/plugins/bridget.py | 10 +++- ooni/plugins/daphn3.py | 23 +++++------ ooni/plugoo/interface.py | 9 ++++ ooni/plugoo/reports.py | 93 +++------------------------------------------- ooni/plugoo/tests.py | 5 +- ooni/protocols/daphn3.py | 15 +++++-- 9 files changed, 56 insertions(+), 111 deletions(-)
diff --git a/bin/ooniprobe b/bin/ooniprobe index 505e1c2..5c87831 100755 --- a/bin/ooniprobe +++ b/bin/ooniprobe @@ -1,4 +1,5 @@ #!/bin/sh -ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )" +ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +echo $ROOT export PYTHONPATH=$PYTHONPATH:$ROOT -python $ROOT/ooni/ooniprobe.py +python $ROOT/ooni/ooniprobe.py $1 diff --git a/ooni/lib/Makefile b/ooni/lib/Makefile index 4cfbee3..3b0c922 100644 --- a/ooni/lib/Makefile +++ b/ooni/lib/Makefile @@ -12,6 +12,10 @@ txtorcon: mv txtorcon.git/txtorcon txtorcon rm -rf txtorcon.git
+clean: + rm -rf txtorcon + rm -rf txtraceroute.py + #txscapy: # echo "Processing dependency txscapy" # git clone https://github.com/hellais/txscapy.git txscapy.git diff --git a/ooni/ooniprobe.py b/ooni/ooniprobe.py index b75deca..2189ddb 100755 --- a/ooni/ooniprobe.py +++ b/ooni/ooniprobe.py @@ -84,7 +84,8 @@ def runTest(test, options, global_options, reactor=reactor): test.runTool() return
- if test.end: + if test.ended: + print "Ending because it's ended" return
wgen = work.WorkGenerator(test, diff --git a/ooni/plugins/bridget.py b/ooni/plugins/bridget.py index fa3cb67..22ff9a0 100644 --- a/ooni/plugins/bridget.py +++ b/ooni/plugins/bridget.py @@ -33,6 +33,7 @@ class bridgetTest(OONITest): from ooni.lib.txtorcon import DEFAULT_VALUE, launch_tor def updates(prog, tag, summary): log.msg("%d%%: %s" % (prog, summary)) + return
def setup_failed(args): log.msg("Setup Failed.") @@ -45,15 +46,18 @@ class bridgetTest(OONITest): return report
config = TorConfig() - config.SocksPort = 9999 - config.OrPort = 1234 + import random + config.SocksPort = random.randint(1024, 2**16) + config.ControlPort = random.randint(1024, 2**16) + if 'bridge' in args: config.UseBridges = 1 config.Bridge = args['bridge'] config.save() + print config.create_torrc() report = {'tor_config': config.config} log.msg("Starting Tor") - d = launch_tor(config, reactor, progress_updates=updates) + d = launch_tor(config, self.reactor, progress_updates=updates) d.addCallback(setup_complete) d.addErrback(setup_failed) return d diff --git a/ooni/plugins/daphn3.py b/ooni/plugins/daphn3.py index 6c1186e..091fe8a 100644 --- a/ooni/plugins/daphn3.py +++ b/ooni/plugins/daphn3.py @@ -16,31 +16,29 @@ from ooni.utils import log
class Daphn3ClientProtocol(daphn3.Daphn3Protocol): def connectionMade(self): - print "I have made a connection!" self.next_state()
- def connectionLost(self, reason): - pass - class Daphn3ClientFactory(protocol.ClientFactory): protocol = Daphn3ClientProtocol mutator = None steps = None test = None - report = reports.Report('daphn3', 'daphn3.yamlooni')
def buildProtocol(self, addr): p = self.protocol() - p.report = self.report p.factory = self + p.test = self.test + if self.steps: p.steps = self.steps
if not self.mutator: self.mutator = daphn3.Mutator(p.steps) + else: print "Moving on to next mutation" self.mutator.next() + p.mutator = self.mutator return p
@@ -48,6 +46,7 @@ class Daphn3ClientFactory(protocol.ClientFactory): print "We failed connecting the the OONIB" print "Cannot perform test. Perhaps it got blocked?" print "Please report this to tor-assistants@torproject.org" + self.test.result['error'] = ('Failed in connecting to OONIB', reason) self.test.end(d)
def clientConnectionLost(self, reason): @@ -108,15 +107,16 @@ class daphn3Test(OONITest): def control(self, exp_res, args): try: mutation = self.factory.mutator.get(0) + self.result['censored'] = False except: mutation = None - return {'mutation_number': args['mutation'], 'value': mutation} + + return {'mutation_number': args['mutation'], + 'value': mutation}
def _failure(self, *argc, **kw): - print "We failed connecting the the OONIB" - print "Cannot perform test. Perhaps it got blocked?" - print "Please report this to tor-assistants@torproject.org" - print "Traceback: %s %s" % (argc, kw) + self.result['censored'] = True + self.result['error'] = ('Failed in connecting', (argc, kw)) self.end()
def experiment(self, args): @@ -133,7 +133,6 @@ class daphn3Test(OONITest): d = endpoint.connect(self.factory) d.addErrback(self._failure) return d - #return endpoint.connect(Daphn3ClientFactory)
def load_assets(self): if not self.steps: diff --git a/ooni/plugoo/interface.py b/ooni/plugoo/interface.py index c3b3855..d00e70b 100644 --- a/ooni/plugoo/interface.py +++ b/ooni/plugoo/interface.py @@ -44,3 +44,12 @@ class ITest(Interface): If the test does not have any assets it should return an empty dict. """
+ def end(): + """ + This can be called at any time to terminate the execution of all of + these test instances. + + What this means is that no more test instances with new parameters will + be created. A report will be written. + """ + diff --git a/ooni/plugoo/reports.py b/ooni/plugoo/reports.py index 3a9c5d2..a543151 100644 --- a/ooni/plugoo/reports.py +++ b/ooni/plugoo/reports.py @@ -4,7 +4,7 @@ import os import yaml
import itertools -from ooni.utils import log, date +from ooni.utils import log, date, net
class Report: """This is the ooni-probe reporting mechanism. It allows @@ -46,10 +46,11 @@ class Report: header += "# %s\n\n" % pretty_date self._write_to_report(header) # XXX replace this with something proper + address = net.getClientAddress() test_details = {'start_time': str(date.now()), - 'asn': 'ASN-1234', + 'asn': address['asn'], 'test_name': self.testname, - 'addr': '1234'} + 'addr': address['ip']} self(test_details)
def _write_to_report(self, dump): @@ -73,98 +74,16 @@ class Report: This should be invoked every time you wish to write some data to the reporting system """ - #print "Writing report(s)" - #dump = '--- \n' dump = yaml.dump([data]) - #dump += yaml.dump(data) - self._write_to_report(dump)
- def file_report(self, data, file=None, mode='a+'): + def file_report(self, data): """ This reports to a file in YAML format """ - if not file: - file = self.file - with open(file, mode) as f: + with open(self.file, 'a+') as f: f.write(data)
- def tcp_report(self, data): - """ - This connect to the specified tcp server - and writes the data passed as argument. - """ - host, port = self.tcp.split(":") - tcp = socket.getprotobyname('tcp') - send_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, tcp) - try: - send_socket.connect((host, int(port))) - send_socket.send(data) - - except Exception, e: - raise e - - finally: - send_socket.close() - - - def scp_report(self, data, rfile=None, mode='a+'): - """ - Push data to the remote ssh server. - - :rfile the remote filename to write - :data the raw data content that should be written - :mode in what mode the file should be created - """ - if not rfile: - rfile = self.file - host, port = self.scp.split(":") - transport = paramiko.Transport((host, port)) - - # The remote path of the remote file to write - rfpath = os.path.join(self.config.ssh_rpath, rfile) - - try: - username = self.config.ssh_username - except: - raise "No username provided" - - # Load the local known host key file - transport.load_host_keys(os.path.expanduser("~/.ssh/known_hosts")) - - # We prefer to use an ssh keyfile fo authentication - if self.config.ssh_keyfile: - keyfile = os.path.expanduser(self.config.ssh_keyfile) - key = paramiko.RSAKey.from_private_key_file(keylocfile) - try: - transport.connect(username=username, pkey=key) - except Exception, e: - raise e - - # If not even a password is fine - elif self.config.ssh_password: - try: - transport.connect(username=username, password=self.config.ssh_password) - except Exception, e: - raise e - - # ... but no authentication, that is madness! - else: - raise "No key or password provided for ssh" - - sftp = paramiko.SFTPClient.from_transport(transport) - try: - sftp = ssh.open_sftp() - remote_file = sftp.file(rfile, mode) - remote_file.set_pipelined(True) - remote_file.write(data) - - except Exception, e: - raise e - sftp.close() - transport.close() - - def send_report(self, data, type): """ This sends the report using the diff --git a/ooni/plugoo/tests.py b/ooni/plugoo/tests.py index 482b8bc..7c190eb 100644 --- a/ooni/plugoo/tests.py +++ b/ooni/plugoo/tests.py @@ -26,6 +26,7 @@ class OONITest(object): blocking = False reactor = None tool = False + ended = False
def __init__(self, local_options, global_options, report, ooninet=None, reactor=None): @@ -65,7 +66,7 @@ class OONITest(object): """ self.ended = True
- def finished(self, control): + def finished(self, return_value): """ The Test has finished running, we must now calculate the test runtime and add all time data to the report. @@ -76,7 +77,7 @@ class OONITest(object): result['start_time'] = str(self.start_time) result['end_time'] = str(self.end_time) result['run_time'] = str(self.end_time - self.start_time) - result['control'] = control + result['return_value'] = return_value log.msg("FINISHED %s" % result) self.report(result) return result diff --git a/ooni/protocols/daphn3.py b/ooni/protocols/daphn3.py index d7471ab..7514a40 100644 --- a/ooni/protocols/daphn3.py +++ b/ooni/protocols/daphn3.py @@ -208,6 +208,8 @@ class Daphn3Protocol(protocol.Protocol): to_receive_data = 0 report = reports.Report('daphn3', 'daphn3.yamlooni')
+ test = None + def next_state(self): """ This is called once I have completed one step of the protocol and need @@ -267,10 +269,11 @@ class Daphn3Protocol(protocol.Protocol): print "The connection was closed because of %s" % report['reason'] print "State %s, Mutator %s" % (report['proto_state'], report['mutator_state']) + if self.test: + self.test.result['censored'] = True + self.test.result['state'] = report self.mutator.next()
- - def connectionLost(self, reason): """ The connection was closed. This may be because of a legittimate reason @@ -289,8 +292,12 @@ class Daphn3Protocol(protocol.Protocol): else: print "I have reached the end of the state machine" print "Censorship fingerprint bruteforced!" - report = {'mutator_state': self.mutator.state()} - self.report(report) + if self.test: + print "In the test thing" + self.test.result['censored'] = False + self.test.result['state'] = report + self.test.result['state_walk_finished'] = True + self.test.report(self.test.result) return
if reason.check(ConnectionDone):