Beispiel #1
0
    def test_launch_root_changes_tmp_ownership(self, chown, euid, _pwd, _sys):
        _pwd.return_value = 1000
        _sys.platform = 'linux2'
        euid.return_value = 0
        reactor = Mock()
        directlyProvides(reactor, IReactorCore)

        # note! we're providing enough options here that we react the
        # "chown" before any 'yield' statements in launch, so we don't
        # actually have to wait for it... a little rickety, though :/
        launch(reactor,
               tor_binary='/bin/echo',
               user='******',
               socks_port='1234')
        self.assertEqual(1, chown.call_count)
Beispiel #2
0
    def _test_tor_connection_default_control_port(self):
        """
        Confirm a default control-port is set if not user-supplied.
        """
        class Connector:
            def __call__(self, proto, trans):
                proto._set_valid_events('STATUS_CLIENT')
                proto.makeConnection(trans)
                proto.post_bootstrap.callback(proto)
                return proto.post_bootstrap

        def on_protocol(proto):
            proto.outReceived(b'Bootstrapped 90%\n')
            proto.outReceived(b'Bootstrapped 100%\n')

        trans = FakeProcessTransport()
        trans.protocol = self.protocol
        creator = functools.partial(Connector(), self.protocol, self.transport)
        tor = yield launch(
            FakeReactor(self, trans, on_protocol, [9052]),
            connection_creator=creator,
            tor_binary='/bin/echo',
            socks_port=1234,
        )

        self.assertEqual(tor.config.ControlPort, 9052)
Beispiel #3
0
    def test_launch_with_timeout(self):
        # XXX not entirely sure what this was/is supposed to be
        # testing, but it covers an extra 7 lines of code??
        timeout = 5

        def connector(proto, trans):
            proto._set_valid_events('STATUS_CLIENT')
            proto.makeConnection(trans)
            proto.post_bootstrap.callback(proto)
            return proto.post_bootstrap

        def on_protocol(proto):
            proto.outReceived(b'Bootstrapped 100%\n')

        trans = FakeProcessTransportNeverBootstraps()
        trans.protocol = self.protocol
        creator = functools.partial(connector, Mock(), Mock())
        react = FakeReactor(self, trans, on_protocol, [1234, 9052])

        with self.assertRaises(RuntimeError) as ctx:
            d = launch(react,
                       connection_creator=creator,
                       timeout=timeout,
                       tor_binary='/bin/echo')
            # FakeReactor is a task.Clock subclass and +1 just to be sure
            react.advance(timeout + 1)
            yield d
        self.assertTrue('timeout while launching Tor' in str(ctx.exception))
        # could/should just use return from this to do asserts?
        self.flushLoggedErrors(RuntimeError)
Beispiel #4
0
    def test_launch_timeout_exception(self):
        """
        we provide a timeout, and it expires
        """
        trans = Mock()
        trans.signalProcess = Mock(side_effect=error.ProcessExitedAlready)
        trans.loseConnection = Mock()
        on_proto = Mock()
        react = FakeReactor(self, trans, on_proto, [1234])

        def creator():
            return defer.succeed(Mock())

        d = launch(
            reactor=react,
            tor_binary='/bin/echo',
            socks_port=1234,
            timeout=10,
            connection_creator=creator,
        )
        react.advance(12)
        self.assertTrue(trans.loseConnection.called)
        with self.assertRaises(RuntimeError) as ctx:
            yield d
        self.assertTrue("timeout while launching" in str(ctx.exception))
Beispiel #5
0
    def test_successful_launch_tcp_control(self, ftb):
        """
        full end-to-end test of a launch, faking things out at a "lower
        level" than most of the other tests
        """
        trans = FakeProcessTransport()

        def on_protocol(proto):
            pass

        reactor = FakeReactor(self, trans, on_protocol, [1, 2, 3])

        def connect_tcp(host, port, factory, timeout=0, bindAddress=None):
            addr = Mock()
            factory.doStart()
            proto = factory.buildProtocol(addr)
            tpp = proto._wrappedProtocol
            tpp.add_event_listener = self._fake_event_listener
            tpp.queue_command = self._fake_queue
            proto.makeConnection(Mock())
            return proto

        reactor.connectTCP = connect_tcp

        config = TorConfig()

        tor = yield launch(reactor,
                           _tor_config=config,
                           control_port='1234',
                           timeout=30)
        self.assertTrue(isinstance(tor, Tor))
Beispiel #6
0
    def test_no_tor_binary(self, ftb):
        self.transport = proto_helpers.StringTransport()

        class Connector:
            def __call__(self, proto, trans):
                proto._set_valid_events('STATUS_CLIENT')
                proto.makeConnection(trans)
                proto.post_bootstrap.callback(proto)
                return proto.post_bootstrap

        self.protocol = FakeControlProtocol([])
        trans = Mock()
        trans.protocol = self.protocol
        creator = functools.partial(Connector(), self.protocol, self.transport)
        reactor = Mock()
        directlyProvides(reactor, IReactorCore)
        try:
            yield launch(
                reactor,
                connection_creator=creator
            )
            self.fail()

        except TorNotFound:
            pass  # success!
Beispiel #7
0
    def test_tor_produces_stderr_output(self):
        def connector(proto, trans):
            proto._set_valid_events('STATUS_CLIENT')
            proto.makeConnection(trans)
            proto.post_bootstrap.callback(proto)
            return proto.post_bootstrap

        def on_protocol(proto):
            proto.errReceived('Something went horribly wrong!\n')

        trans = FakeProcessTransport()
        trans.protocol = Mock()
        fakeout = StringIO()
        fakeerr = StringIO()
        creator = functools.partial(connector, Mock(), Mock())
        try:
            yield launch(
                FakeReactor(self, trans, on_protocol, [1234, 9052]),
                connection_creator=creator,
                tor_binary='/bin/echo',
                stdout=fakeout,
                stderr=fakeerr,
            )
            self.fail()  # should't get callback
        except RuntimeError as e:
            self.assertEqual('', fakeout.getvalue())
            self.assertEqual('Something went horribly wrong!\n',
                             fakeerr.getvalue())
            self.assertTrue('Something went horribly wrong!' in str(e))
Beispiel #8
0
    def test_no_tor_binary(self, ftb):
        self.transport = proto_helpers.StringTransport()

        class Connector:
            def __call__(self, proto, trans):
                proto._set_valid_events('STATUS_CLIENT')
                proto.makeConnection(trans)
                proto.post_bootstrap.callback(proto)
                return proto.post_bootstrap

        self.protocol = FakeControlProtocol([])
        trans = Mock()
        trans.protocol = self.protocol
        creator = functools.partial(Connector(), self.protocol, self.transport)
        reactor = Mock()
        directlyProvides(reactor, IReactorCore)
        try:
            yield launch(
                reactor,
                connection_creator=creator
            )
            self.fail()

        except TorNotFound:
            pass  # success!
Beispiel #9
0
    def test_tor_connection_fails(self, ftb):
        trans = FakeProcessTransport()

        def on_protocol(proto):
            proto.outReceived(b'Bootstrapped 100%\n')

        reactor = FakeReactor(self, trans, on_protocol, [1, 2, 3])

        fails = ['one']

        def connect_tcp(host, port, factory, timeout=0, bindAddress=None):
            if len(fails):
                fails.pop()
                raise error.CannotListenError('on-purpose-error', None, None)

            addr = Mock()
            factory.doStart()
            proto = factory.buildProtocol(addr)
            tpp = proto._wrappedProtocol

            def fake_event_listener(what, cb):
                if what == 'STATUS_CLIENT':
                    # should ignore non-BOOTSTRAP messages
                    cb('STATUS_CLIENT not-bootstrap')
                    cb('STATUS_CLIENT BOOTSTRAP PROGRESS=100 TAG=foo SUMMARY=bar'
                       )
                return defer.succeed(None)

            tpp.add_event_listener = fake_event_listener

            def fake_queue(cmd):
                if cmd.split()[0] == 'PROTOCOLINFO':
                    return defer.succeed('AUTH METHODS=NULL')
                elif cmd == 'GETINFO config/names':
                    return defer.succeed('config/names=')
                elif cmd == 'GETINFO signal/names':
                    return defer.succeed('signal/names=')
                elif cmd == 'GETINFO version':
                    return defer.succeed('version=0.1.2.3')
                elif cmd == 'GETINFO events/names':
                    return defer.succeed('events/names=STATUS_CLIENT')
                elif cmd == 'GETINFO config/defaults':
                    return defer.succeed('config/defaults=')
                return defer.succeed(None)

            tpp.queue_command = fake_queue
            proto.makeConnection(Mock())
            return proto

        reactor.connectTCP = connect_tcp
        config = TorConfig()

        tor = yield launch(reactor,
                           _tor_config=config,
                           control_port='1234',
                           timeout=30)
        errs = self.flushLoggedErrors()
        self.assertTrue(isinstance(tor, Tor))
        self.assertEqual(1, len(errs))
Beispiel #10
0
 def test_launch_wrong_stdout(self):
     try:
         yield launch(
             FakeReactor(self, Mock(), Mock()),
             stdout=object(),
             tor_binary='/bin/echo',
         )
         self.fail("Should have thrown an error")
     except RuntimeError as e:
         self.assertTrue("file-like object needed" in str(e).lower())
Beispiel #11
0
 def test_launch_tor_unix_controlport_no_directory(self):
     reactor = FakeReactor(self, Mock(), None, [9050])
     with self.assertRaises(ValueError) as ctx:
         socket_file = '/does/not/exist'
         yield launch(
             reactor,
             control_port="unix:{}".format(socket_file),
             tor_binary="/bin/echo",
             stdout=Mock(),
             stderr=Mock(),
         )
     self.assertTrue("must exist" in str(ctx.exception))
Beispiel #12
0
 def test_launch_tor_unix_controlport_wrong_perms(self):
     reactor = FakeReactor(self, Mock(), None, [9050])
     with self.assertRaises(ValueError) as ctx:
         with TempDir() as tmp:
             tmpdir = str(tmp)
             os.chmod(tmpdir, 0o0777)
             socket_file = join(tmpdir, 'socket_test')
             yield launch(
                 reactor,
                 control_port="unix:{}".format(socket_file),
                 tor_binary="/bin/echo",
                 stdout=Mock(),
                 stderr=Mock(),
             )
     self.assertTrue(
         "must only be readable by the user" in str(ctx.exception))
Beispiel #13
0
def main(reactor):
    # note that you can pass a few options as kwargs
    # (e.g. data_directory=, or socks_port= ). For other torrc
    # changes, see below.
    tor = yield txtorcon.launch(
        reactor,
        data_directory="./tordata",
        stdout=sys.stdout,
        socks_port='unix:/tmp/tor2/socks',
    )
    # tor = yield txtorcon.connect(
    #     reactor,
    #     clientFromString(reactor, "unix:/var/run/tor/control"),
    # )
    print("Connected to Tor version '{}'".format(tor.protocol.version))

    config = yield tor.get_config()
    state = yield tor.create_state()
    # or state = yield txtorcon.TorState.from_protocol(tor.protocol)

    print("This Tor has PID {}".format(state.tor_pid))
    print("This Tor has the following {} Circuits:".format(len(
        state.circuits)))
    for c in state.circuits.values():
        print("  {}".format(c))

    endpoint_d = config.socks_endpoint(reactor, u'unix:/tmp/tor2/socks')
    agent = tor.web_agent(socks_endpoint=endpoint_d)
    uri = b'https://www.torproject.org'
    print("Downloading {}".format(uri))
    resp = yield agent.request(b'GET', uri)
    print("Response has {} bytes".format(resp.length))
    body = yield readBody(resp)
    print("received body ({} bytes)".format(len(body)))
    print("{}\n[...]\n{}\n".format(body[:200], body[-200:]))

    # SOCKSPort is 'really' a list of SOCKS ports in Tor now, so we
    # have to set it to a list ... :/
    print("Changing our config (SOCKSPort=9876)")
    # config.SOCKSPort = ['unix:/tmp/foo/bar']
    config.SOCKSPort = ['9876']
    yield config.save()

    print("Querying to see it changed:")
    socksport = yield tor.protocol.get_conf("SOCKSPort")
    print("SOCKSPort", socksport)
Beispiel #14
0
    def test_launch_timeout_process_exits(self):
        # cover the "one more edge case" where we get a processEnded()
        # but we've already "done" a timeout.
        trans = Mock()
        trans.signalProcess = Mock()
        trans.loseConnection = Mock()

        class MyFakeReactor(FakeReactor):
            def spawnProcess(self,
                             processprotocol,
                             bin,
                             args,
                             env,
                             path,
                             uid=None,
                             gid=None,
                             usePTY=None,
                             childFDs=None):
                self.protocol = processprotocol
                self.protocol.makeConnection(self.transport)
                self.transport.process_protocol = processprotocol
                self.on_protocol(self.protocol)

                status = Mock()
                status.value.exitCode = None
                processprotocol.processEnded(status)
                return self.transport

        react = MyFakeReactor(self, trans, Mock(), [1234, 9052])

        d = launch(
            reactor=react,
            tor_binary='/bin/echo',
            timeout=10,
            data_directory='/dev/null',
        )
        react.advance(20)

        try:
            yield d
        except RuntimeError as e:
            self.assertTrue("Tor was killed" in str(e))

        errs = self.flushLoggedErrors(RuntimeError)
        self.assertEqual(1, len(errs))
        self.assertTrue("Tor was killed" in str(errs[0]))
Beispiel #15
0
def main(reactor):
    # note that you can pass a few options as kwargs
    # (e.g. data_directory=, or socks_port= ). For other torrc
    # changes, see below.
    tor = yield txtorcon.launch(
        reactor,
        data_directory="./tordata",
        stdout=sys.stdout,
        socks_port='unix:/tmp/tor2/socks',
    )
    # tor = yield txtorcon.connect(
    #     reactor,
    #     clientFromString(reactor, "unix:/var/run/tor/control"),
    # )
    print("Connected to Tor version '{}'".format(tor.protocol.version))

    config = yield tor.get_config()
    state = yield tor.create_state()
    # or state = yield txtorcon.TorState.from_protocol(tor.protocol)

    print("This Tor has PID {}".format(state.tor_pid))
    print("This Tor has the following {} Circuits:".format(len(state.circuits)))
    for c in state.circuits.values():
        print("  {}".format(c))

    endpoint_d = config.socks_endpoint(reactor, u'unix:/tmp/tor2/socks')
    agent = tor.web_agent(socks_endpoint=endpoint_d)
    uri = b'https://www.torproject.org'
    print("Downloading {}".format(uri))
    resp = yield agent.request(b'GET', uri)
    print("Response has {} bytes".format(resp.length))
    body = yield readBody(resp)
    print("received body ({} bytes)".format(len(body)))
    print("{}\n[...]\n{}\n".format(body[:200], body[-200:]))

    # SOCKSPort is 'really' a list of SOCKS ports in Tor now, so we
    # have to set it to a list ... :/
    print("Changing our config (SOCKSPort=9876)")
    # config.SOCKSPort = ['unix:/tmp/foo/bar']
    config.SOCKSPort = ['9876']
    yield config.save()

    print("Querying to see it changed:")
    socksport = yield tor.protocol.get_conf("SOCKSPort")
    print("SOCKSPort", socksport)
Beispiel #16
0
    def test_launch_fails(self, ftb):
        trans = FakeProcessTransport()

        def on_proto(protocol):
            protocol.processEnded(
                Failure(error.ProcessTerminated(12, None, 'statusFIXME')))

        reactor = FakeReactor(self, trans, on_proto, [1234, 9052])

        try:
            yield launch(reactor)
            self.fail("Should fail")
        except RuntimeError:
            pass

        errs = self.flushLoggedErrors(RuntimeError)
        self.assertEqual(1, len(errs))
        self.assertTrue("Tor exited with error-code 12" in str(errs[0]))
def main(reactor):
    # we must have a directory owned by us with 0700 permissions to
    # contain our Unix sockets or Tor is sad.
    tmp = tempfile.mkdtemp()
    reactor.addSystemEventTrigger(
        'after',
        'shutdown',
        shutil.rmtree,
        tmp,
    )

    control_path = join(tmp, 'control_socket')
    socks_path = join(tmp, 'socks')
    # note that you can pass a few options as kwargs
    # (e.g. data_directory=, or socks_port= ). For other torrc
    # changes, see below.
    tor = yield txtorcon.launch(
        reactor,
        data_directory="./tordata",
        stdout=sys.stdout,
        control_port='unix:{}'.format(control_path),
        socks_port='unix:{}'.format(socks_path),
    )
    print("Connected to Tor version '{}'".format(tor.protocol.version))

    state = yield tor.create_state()

    print("This Tor has PID {}".format(state.tor_pid))
    print("This Tor has the following {} Circuits:".format(len(
        state.circuits)))
    for c in state.circuits.values():
        print("  {}".format(c))

    config = yield tor.get_config()
    socks_ep = config.create_socks_endpoint(reactor,
                                            u'unix:{}'.format(socks_path))
    agent = tor.web_agent(socks_endpoint=socks_ep)
    uri = b'https://www.torproject.org'
    print("Downloading {} via Unix socket".format(uri))
    resp = yield agent.request(b'GET', uri)
    print("Response has {} bytes".format(resp.length))
    body = yield readBody(resp)
    print("received body ({} bytes)".format(len(body)))
    print("{}\n[...]\n{}\n".format(body[:200], body[-200:]))
Beispiel #18
0
    def test_tor_connection_user_data_dir(self):
        """
        Test that we don't delete a user-supplied data directory.
        """

        config = TorConfig()
        config.OrPort = 1234

        class Connector:
            def __call__(self, proto, trans):
                proto._set_valid_events('STATUS_CLIENT')
                proto.makeConnection(trans)
                proto.post_bootstrap.callback(proto)
                return proto.post_bootstrap

        def on_protocol(proto):
            proto.outReceived(b'Bootstrapped 90%\n')

        with TempDir() as tmp:
            my_dir = str(tmp)
            config.DataDirectory = my_dir
            trans = FakeProcessTransport()
            trans.protocol = self.protocol
            creator = functools.partial(Connector(), self.protocol,
                                        self.transport)
            d = launch(
                FakeReactor(self, trans, on_protocol, [1234, 9051]),
                connection_creator=creator,
                tor_binary='/bin/echo',
                data_directory=my_dir,
                control_port=0,
            )

            def still_have_data_dir(tor, tester):
                tor._process_protocol.cleanup(
                )  # FIXME? not really unit-testy as this is sort of internal function
                tester.assertTrue(os.path.exists(my_dir))

            d.addCallback(still_have_data_dir, self)
            d.addErrback(self.fail)
            return d
Beispiel #19
0
def main(reactor):
    def update(percent, tag, summary):
        print("{}%: {}".format(int(percent), summary))

    tor = yield txtorcon.launch(
        reactor,
        progress_updates=update,
        data_directory='./tordata',
    )

    print("Tor started: {}".format(tor))

    # make a request via Tor
    resp = yield treq.get(
        'https://www.torproject.org:443',
        agent=tor.web_agent(),
    )

    print("Retrieving {} bytes".format(resp.length))
    data = yield resp.text()
    print("Got {} bytes:\n{}\n[...]{}".format(
        len(data),
        data[:120],
        data[-120:],
    ))

    # create a new circuit
    print("creating circuit")
    state = yield tor.create_state()
    circ = yield state.build_circuit()
    yield circ.when_built()
    print("  path: {}".format(" -> ".join([r.ip for r in circ.path])))

    # make a request via our new circuit
    print("Downloading meejah's public key...")
    resp = yield treq.get(
        'https://meejah.ca/meejah.asc',
        agent=circ.web_agent(reactor, tor.config.socks_endpoint(reactor)),
    )
    data = yield resp.text()
    print(data)
def main(reactor):
    # we must have a directory owned by us with 0700 permissions to
    # contain our Unix sockets or Tor is sad.
    tmp = tempfile.mkdtemp()
    reactor.addSystemEventTrigger(
        'after', 'shutdown',
        shutil.rmtree, tmp,
    )

    control_path = join(tmp, 'control_socket')
    socks_path = join(tmp, 'socks')
    # note that you can pass a few options as kwargs
    # (e.g. data_directory=, or socks_port= ). For other torrc
    # changes, see below.
    tor = yield txtorcon.launch(
        reactor,
        data_directory="./tordata",
        stdout=sys.stdout,
        control_port='unix:{}'.format(control_path),
        socks_port='unix:{}'.format(socks_path),
    )
    print("Connected to Tor version '{}'".format(tor.protocol.version))

    state = yield tor.create_state()

    print("This Tor has PID {}".format(state.tor_pid))
    print("This Tor has the following {} Circuits:".format(len(state.circuits)))
    for c in state.circuits.values():
        print("  {}".format(c))

    config = yield tor.get_config()
    socks_ep = config.create_socks_endpoint(reactor, u'unix:{}'.format(socks_path))
    agent = tor.web_agent(socks_endpoint=socks_ep)
    uri = b'https://www.torproject.org'
    print("Downloading {} via Unix socket".format(uri))
    resp = yield agent.request(b'GET', uri)
    print("Response has {} bytes".format(resp.length))
    body = yield readBody(resp)
    print("received body ({} bytes)".format(len(body)))
    print("{}\n[...]\n{}\n".format(body[:200], body[-200:]))
Beispiel #21
0
    def test_launch_tor_unix_controlport(self):
        trans = FakeProcessTransport()
        trans.protocol = self.protocol
        self.protocol.post_bootstrap.callback(self.protocol)
        self.protocol._set_valid_events("STATUS_CLIENT")
        self.protocol.add_event_listener = self._fake_event_listener
        self.protocol.queue_command = self._fake_queue

        def on_protocol(proto):
            proto.outReceived(b'Bootstrapped 90%\n')

        # launch() auto-discovers a SOCKS port
        reactor = FakeReactor(self, trans, on_protocol, [9050])
        reactor.connectUNIX = Mock()
        # prepare a suitable directory for tor unix socket
        with TempDir() as tmp:
            tmpdir = str(tmp)
            os.chmod(tmpdir, 0o0700)
            socket_file = join(tmpdir, 'test_socket_file')
            with patch('txtorcon.controller.UNIXClientEndpoint') as uce:
                endpoint = Mock()
                endpoint.connect = Mock(
                    return_value=defer.succeed(self.protocol))
                uce.return_value = endpoint

                yield launch(
                    reactor,
                    control_port="unix:{}".format(socket_file),
                    tor_binary="/bin/echo",
                    stdout=Mock(),
                    stderr=Mock(),
                )

        self.assertTrue(endpoint.connect.called)
        self.assertTrue(uce.called)
        self.assertEqual(
            socket_file,
            uce.mock_calls[0][1][1],
        )
Beispiel #22
0
    def test_successful_launch(self, tpp, ftb):
        trans = FakeProcessTransport()
        reactor = FakeReactor(self, trans, lambda p: None, [1, 2, 3])
        config = TorConfig()

        def boot(arg=None):
            config.post_bootstrap.callback(config)

        config.__dict__['bootstrap'] = Mock(side_effect=boot)
        config.__dict__['attach_protocol'] = Mock(
            return_value=defer.succeed(None))

        def foo(*args, **kw):
            rtn = Mock()
            rtn.post_bootstrap = defer.succeed(None)
            rtn.when_connected = Mock(return_value=defer.succeed(rtn))
            return rtn

        tpp.side_effect = foo

        tor = yield launch(reactor, _tor_config=config)
        self.assertTrue(isinstance(tor, Tor))
Beispiel #23
0
    def _test_tor_connection_user_control_port(self):
        """
        Confirm we use a user-supplied control-port properly
        """

        config = TorConfig()
        config.OrPort = 1234
        config.ControlPort = 4321

        class Connector:
            def __call__(self, proto, trans):
                proto._set_valid_events('STATUS_CLIENT')
                proto.makeConnection(trans)
                proto.post_bootstrap.callback(proto)
                return proto.post_bootstrap

        def on_protocol(proto):
            proto.outReceived(b'Bootstrapped 90%\n')
            proto.outReceived(b'Bootstrapped 100%\n')

        trans = FakeProcessTransport()
        trans.protocol = self.protocol
        creator = functools.partial(Connector(), self.protocol, self.transport)
        d = launch(
            FakeReactor(self, trans, on_protocol, [9052]),
            connection_creator=creator,
            tor_binary='/bin/echo',
            socks_port=1234,
        )

        def check_control_port(proto, tester):
            # we just want to ensure launch() didn't mess with
            # the controlport we set
            tester.assertEquals(config.ControlPort, 4321)

        d.addCallback(check_control_port, self)
        d.addErrback(self.fail)
        return d
Beispiel #24
0
    def test_launch_no_control_port(self):
        '''
        See Issue #80. This allows you to launch tor with a TorConfig
        with ControlPort=0 in case you don't want a control connection
        at all. In this case you get back a TorProcessProtocol and you
        own both pieces. (i.e. you have to kill it yourself).
        '''

        trans = FakeProcessTransportNoProtocol()
        trans.protocol = self.protocol

        def creator(*args, **kw):
            print("Bad: connection creator called")
            self.fail()

        def on_protocol(proto):
            self.process_proto = proto
            proto.outReceived(b'Bootstrapped 90%\n')
            proto.outReceived(b'Bootstrapped 100%\n')

        reactor = FakeReactor(self, trans, on_protocol, [9052, 9999])

        tor = yield launch(
            reactor=reactor,
            connection_creator=creator,
            tor_binary='/bin/echo',
            socks_port=1234,
            control_port=0,
        )
        self.assertEqual(tor._process_protocol, self.process_proto)
        d = tor.quit()
        reactor.advance(0)
        yield d
        errs = self.flushLoggedErrors()
        self.assertEqual(1, len(errs))
        self.assertTrue("Tor was killed" in str(errs[0]))
Beispiel #25
0
def get_tor(reactor, launch_tor=False, tor_control_port=None,
            timing=None, stderr=sys.stderr):
    """
    If launch_tor=True, I will try to launch a new Tor process, ask it
    for its SOCKS and control ports, and use those for outbound
    connections (and inbound onion-service listeners, if necessary).

    Otherwise if tor_control_port is provided, I will attempt to connect
    to an existing Tor's control port at the endpoint it specifies.  I'll
    ask that Tor for its SOCKS port.

    With no arguments, I will try to connect to an existing Tor's control
    port at the usual places: [unix:/var/run/tor/control,
    tcp:127.0.0.1:9051, tcp:127.0.0.1:9151].  If any are successful, I'll
    ask that Tor for its SOCKS port.  If none are successful, I'll
    attempt to do SOCKS to the usual places: [tcp:127.0.0.1:9050,
    tcp:127.0.0.1:9150].

    If I am unable to make a SOCKS connection, the initial connection to
    the Rendezvous Server will fail, and the program will terminate.

    Control-port connections can only succeed if I can authenticate (by
    reading a cookie file named by the Tor process), so the current user
    must have permission to read that file (either they started Tor, e.g.
    TorBrowser, or they are in a unix group that's been given access,
    e.g. debian-tor).
    """
    # rationale: launching a new Tor takes a long time, so only do it if
    # the user specifically asks for it with --launch-tor. Using an
    # existing Tor should be much faster, but still requires general
    # permission via --tor.

    if not txtorcon:
        raise errors.NoTorError()

    if not isinstance(launch_tor, bool): # note: False is int
        raise TypeError("launch_tor= must be boolean")
    if not isinstance(tor_control_port, (type(""), type(None))):
        raise TypeError("tor_control_port= must be str or None")
    assert tor_control_port != ""
    if launch_tor and tor_control_port is not None:
        raise ValueError("cannot combine --launch-tor and --tor-control-port=")
    timing = timing or DebugTiming()

    # Connect to an existing Tor, or create a new one. If we need to
    # launch an onion service, then we need a working control port (and
    # authentication cookie). If we're only acting as a client, we don't
    # need the control port.

    if launch_tor:
        print(" launching a new Tor process, this may take a while..",
              file=stderr)
        with timing.add("launch tor"):
            tor = yield txtorcon.launch(reactor,
                                        #data_directory=,
                                        #tor_binary=,
                                        )
    elif tor_control_port:
        with timing.add("find tor"):
            control_ep = clientFromString(reactor, tor_control_port)
            tor = yield txtorcon.connect(reactor, control_ep) # might raise
            print(" using Tor via control port at %s" % tor_control_port,
                  file=stderr)
    else:
        # Let txtorcon look through a list of usual places. If that fails,
        # we'll arrange to attempt the default SOCKS port
        with timing.add("find tor"):
            try:
                tor = yield txtorcon.connect(reactor)
                print(" using Tor via default control port", file=stderr)
            except Exception:
                # TODO: make this more specific. I think connect() is
                # likely to throw a reactor.connectTCP -type error, like
                # ConnectionFailed or ConnectionRefused or something
                print(" unable to find default Tor control port, using SOCKS",
                      file=stderr)
                tor = SocksOnlyTor(reactor)
    directlyProvides(tor, _interfaces.ITorManager)
    returnValue(tor)
Beispiel #26
0
def get_tor(reactor,
            launch_tor=False,
            tor_control_port=None,
            timing=None,
            stderr=sys.stderr):
    """
    If launch_tor=True, I will try to launch a new Tor process, ask it
    for its SOCKS and control ports, and use those for outbound
    connections (and inbound onion-service listeners, if necessary).

    Otherwise if tor_control_port is provided, I will attempt to connect
    to an existing Tor's control port at the endpoint it specifies.  I'll
    ask that Tor for its SOCKS port.

    With no arguments, I will try to connect to an existing Tor's control
    port at the usual places: [unix:/var/run/tor/control,
    tcp:127.0.0.1:9051, tcp:127.0.0.1:9151].  If any are successful, I'll
    ask that Tor for its SOCKS port.  If none are successful, I'll
    attempt to do SOCKS to the usual places: [tcp:127.0.0.1:9050,
    tcp:127.0.0.1:9150].

    If I am unable to make a SOCKS connection, the initial connection to
    the Rendezvous Server will fail, and the program will terminate.

    Control-port connections can only succeed if I can authenticate (by
    reading a cookie file named by the Tor process), so the current user
    must have permission to read that file (either they started Tor, e.g.
    TorBrowser, or they are in a unix group that's been given access,
    e.g. debian-tor).
    """
    # rationale: launching a new Tor takes a long time, so only do it if
    # the user specifically asks for it with --launch-tor. Using an
    # existing Tor should be much faster, but still requires general
    # permission via --tor.

    if not txtorcon:
        raise errors.NoTorError()

    if not isinstance(launch_tor, bool):  # note: False is int
        raise TypeError("launch_tor= must be boolean")
    if not isinstance(tor_control_port, (type(""), type(None))):
        raise TypeError("tor_control_port= must be str or None")
    assert tor_control_port != ""
    if launch_tor and tor_control_port is not None:
        raise ValueError("cannot combine --launch-tor and --tor-control-port=")
    timing = timing or DebugTiming()

    # Connect to an existing Tor, or create a new one. If we need to
    # launch an onion service, then we need a working control port (and
    # authentication cookie). If we're only acting as a client, we don't
    # need the control port.

    if launch_tor:
        print(" launching a new Tor process, this may take a while..",
              file=stderr)
        with timing.add("launch tor"):
            tor = yield txtorcon.launch(reactor,
                                        #data_directory=,
                                        #tor_binary=,
                                        )
    elif tor_control_port:
        with timing.add("find tor"):
            control_ep = clientFromString(reactor, tor_control_port)
            tor = yield txtorcon.connect(reactor, control_ep)  # might raise
            print(" using Tor via control port at %s" % tor_control_port,
                  file=stderr)
    else:
        # Let txtorcon look through a list of usual places. If that fails,
        # we'll arrange to attempt the default SOCKS port
        with timing.add("find tor"):
            try:
                tor = yield txtorcon.connect(reactor)
                print(" using Tor via default control port", file=stderr)
            except Exception:
                # TODO: make this more specific. I think connect() is
                # likely to throw a reactor.connectTCP -type error, like
                # ConnectionFailed or ConnectionRefused or something
                print(" unable to find default Tor control port, using SOCKS",
                      file=stderr)
                tor = SocksOnlyTor(reactor)
    directlyProvides(tor, _interfaces.ITorManager)
    returnValue(tor)
Beispiel #27
0
 def test_launch_no_ireactorcore(self):
     try:
         yield launch(None)
         self.fail("should get exception")
     except ValueError as e:
         self.assertTrue("provide IReactorCore" in str(e))