[tbb-dev] Tor Browser TorLauncher Proposal

Matthew Finkel matthew.finkel at gmail.com
Wed Jan 10 15:10:21 UTC 2018


Hi All,

Apologies for the delay in sending this. Attached (or below) is the
proposal for migrating the TorLauncher legacy extension to
WebExtension. The main problem with directly moving TorLauncher to
using WebExtensions is the two Extensions APIs are not 1-to-1. There
was significant functionality previously available that is not available
with WebExtensions. In particular these involve launching a child
process and controlling it. This is a primary objective of TorLauncher,
so we needed an alternative.

As a result, this proposal takes a mixed approach. Part of the
functionality of TorLauncher will remain as an extension and the
remaining functionality will be directly implemented into Tor Browser.

>From the mobile/Android perspective, TorLauncher is a strange
requirement at this moment. On Android, Orbot controls and configures
tor, and external Apps cannot configure tor which is the purpose of
TorLauncher. In the future, we may prefer another design and
integration, providing a better user experience.

Although the proposal is long, it is mostly documenting the extension's
existing functionality.

Thanks,
Matt
-------------- next part --------------
Author: Matthew Finkel

0. Motivation

  As of Firefox 57, only extensions developed using WebExtensions are
  supported. As a result, the TorLauncher extension must be ported.
  The main objectives of TorLauncher are providing the User with an
  interactive interface for configuring tor and acting as a tor
  controller so tor may be configured as needed for the user.

  Although porting TorLauncher so it only uses the WebExtensions API
  is mostly possible, integrating some of the current functionality
  into Tor Browser may be easier and provide for a better user
  experience.

  This proposal describes TorLauncher's use case and how we can continue
  providing a uniform bootstrapping/loading user experience across all
  platforms and projects/products (Tor {Browser,Birdy,Messenger}).

1. Functionality

  Currently TorLauncher provides the following functionality:
    - Detects operating system platform
    - Constructs command line and execute tor as background process
    - Sets browser as controlling process of tor
    - Shows network settings wizard when networking and/or
      configuration issue is detected
    - Provides user interface for configuring bridges, proxy, and
      informing tor it is behind a fascist firewall
    - Shows the user tor's bootstrapping status as a progress bar
    - Provides "Copy Tor Log to Clipboard"
    - Connects to tor's control socket
    - Exports some tor controller functionality as a service within XPCOM
    - Retrieves bootstrapping progress via "GETINFO status/bootstrap-phase"
    - Buffers tor client log messages via "SETEVENTS STATUS_CLIENT NOTICE WARN ERR"
    - Monitors bootstrapping progress via events
    - Provides accessor and mutator of tor configuration via getconf/setconf

  Some of these points are redundant, but they give insight into how
  the extension works from different perspectives.

2. Back End

  The TorLauncher extension can be divided into two parts. As the first
  part, we can consider the back-end functionality the extension
  provides. The tor controller and tor process manager can be
  re-implemented in C++. The controller can be written as a network
  protocol service under netwerk/protocol/. The tor process can be
  managed by a class under security/.
  
  TorLauncher currently provides a XPCOM service for the tor
  controller using the contract ID
  "@torproject.org/torlauncher-protocol-service;1". Instead, now we
  can present the tor controller as a XPCOM service using the
  contract ID "@torproject.org/network/protocol/torcontroller;1".
  Ideally, this controller can be implemented in a child process and
  sandboxed, but that requires additional investigation and design.

3. Front End

  The second part of TorLauncher's functionality is providing a
  front-end user interface. The TorLauncher extension can be modified
  so it continues providing the user interface of the network settings
  and wizard using the WebExtension API. This will give us continued
  consistency across Windows, OSX, and Unix, but we will need a new UI
  for Android.
  
  Although the UI could be implemented directly as a widget for
  Tor Browser on desktop, using an extension provides easy code re-use
  across projects. Any UI changes directly in Tor Browser will likely
  require duplicaating or reimplementing in Mail/Messanger.
  
  On Android, we need a new mobile-friendly UI in any case (POE? [0]).
  How we integrate this with Orbot will be extremely important. We will
  use an Intent listener, and receive status messages from Orbot, but
  any tor configuration changes must be made using Orbot. This is the
  current state of implementation in Orfox. Therefore, on Android
  TorLauncher is not directly useful.

4. Mobile Questions

  Should we propose improvements/changes of Orbot so (trusted) external
  Apps can send Controller messages via intent?

  Should we launch our own tor service and fully control it rather than
  rely on another app?

5. Security Considerations

  Is there a way Tor Browser can further restrict access to a XPCOM
  service? Firefox's sandboxing makes difficult unprivileged access to
  internal services, but this risk remains when Tor Browser runs as a
  single process.

  As mentioned earlier, sandboxing the controller and process manager
  into a sandboxed-child process would provide additional assurance the
  tor process would not reveal private information if a vulnerability
  is found in the Browser.

  What are the implications of the browser having access to the full
  circuit information, including the User's guard?

6. Proposed TorController Contract

  TorController::GetControlSocket()
    - Return an object containing the Control socket information, as
      appropriate: Unix Domain Socket file path, hostname/IP address,
      and TCP port number.
  TorController::GetSOCKSSocket()
    - Return an object containing the SOCKS socket information, as
      appropriate: Unix Domain Socket file path, hostname/IP address,
      and TCP port number.
  TorController::GetControlPassword()
    - Return the password or, if requested, the hash of the
      password, or null if the password is null
  TorController::UnescapeString()
    - Nearly same implementation as TorUnescapeString() below.
      Return an error on failure (malformed string)

  Additional abstractions should be added at the public interface. We
  can re-use the below Interface, and replace the first five methods
  defined below with the four methods above. This new controller can be
  implemented within the TorController class and renaming the below
  functions by delete the "Tor" namespace prefix.
  
  We should enumerate all GETCONF and SETCONF use cases and limit the
  public Interface for only this functionality.

  Below there are public JS properties, these should be encapsulated
  within getter/setter methods.

7. Existing TorLauncher Contract

  The TorLauncher service contract currently provides the following
  interfaces, the new implemenation may use this as a reference:

    Protocol:
      Providing: nsISupports, nsIFactory, nsIObserver, nsIClassInfo
      property TorLogHasWarnOrErr
        - true if the log messages we have captured contain WARN or ERR

      TorGetControlIPCFile()
        - Return a copy of the Unix Domain file path if defined,
          otherwise return undefined
      TorGetControlPort()
        - Return the control port number, or null if using IPC file
      TorGetPassword()
        - Return the password or, if requested, the hash of the
          password, or null if the password is null
      TorGetSOCKSPortInfo()
        - Returns an object containing the SOCKS Port information, or
          null if not defined. The object defined keys: ipcFile, host,
          and port.
      TorUnescapeString()
        - Return a string after:
            stripping '"' as the first and last characters
            reinterpretting '\r', '\n', '\t'
            converting hex and octal values into decimal
            stripping one '\' before any other character
          Throws Error on failure (malformed string)
      TorEscapeString()
        - Return a string after escaping:
            character sequences:
              '\' -> '\\'
              '\\' -> '\\\\'
              '\r' -> '\\r'
              '\n' -> '\\n'
              '\t' -> '\\t'
            UTF-8 characters as a \xHH hex sequence
      TorGetConf()
        - Send GETCONF command, return original result on failure,
          and returns parsed reply object on success.
            Result object:
            {
              statusCode: 0,
              lineArray: [],
              _parseError: false
            }
      TorGetConfStr()
        - Same as TorGetConf() but set the retVal key in the reply
          object as the GETCONF reply status value or the provided
          default
      TorGetConfBool()
        - Same as TorGetConf() but set retVal as boolean true if the
          first non-status-ok response line is "1", else return false.
          Return the provided default value if Tor is currently using
          its default configuration for this config.
      TorSetConf()
        - Send SETCONF command where the input is an object with keys
          defining the config option, and the key's value is the new
          configuration. The value may be a string, a string array,
          or a boolean value. On failure return null, else return the
          reponse object.
      TorSetConfWithReply()
        - Same as TorSetConf() but return a boolean value indicating
          success or failure. On failure, return an object a key named
          "details" that is a string with an error message.
      TorRetrieveBootstrapStatus()
        - Send "GETCONF status/bootstrap-phase" command. Return null.
          Send a "TorBootstrapStatus" notification if the command
          returns successful.
      TorSendCommand()
        - Send the provided command, and return the received response
      TorCommandSucceeded()
        - Return a boolean value of true if the reply is not null and
          the status code was 250 (OK).
      TorCleanupConnection()
        - Call during browser shutdown, it closes the
          connections and it terminates event monitoring.
      TorStartEventMonitor()
        - Begin event monitoring by sending the SETEVENTS commnd
          "SETEVENTS STATUS_CLIENT NOTICE WARN ERR"
      TorGetLog()
        - Return the captured log messages as a text string. Return
          the number of log line if a non-null object is passed-in as
          a parameter.
      TorHaveControlConnection()
        - Return boolean true if a control connection is established.
          Creates a new control connection is a valid connection does
          not exist.

    Process:
      property TorProcessStatus
        - An "enum" defining the current status of the Tor process
          One of: Unknkown, Starting, Running, Exited
      property TorIsBootstrapDone
        - A boolean value notating bootstrapping is complete
      property TorBootstrapErrorOccurred
        - A boolean value notating an error occurred during bootstrap.

      TorStartAndControlTor()
        - Start Tor, notice when the process successfully started,
          launch the network settings wizard if needed.
      TorClearBootstrapError()
        - Clear (set as false or null) the state variables indicating
          an error occurred during bootstrap.


More information about the tbb-dev mailing list