Re: [Tails-dev] Tor Launcher as a standalone XUL app in Tail…

Delete this message

Reply to this message
Author: anonym
Date:  
To: The Tails public development discussion list
CC: Mike Perry, Mark Smith, Kathleen Brade
Subject: Re: [Tails-dev] Tor Launcher as a standalone XUL app in Tails [Was: Tor Launcher extension]
11/02/14 20:17, Mark Smith wrote:
> On 2/11/14, 11:23 AM, anonym wrote:
>> 11/02/14 02:37, anonym wrote:
>> # Tor Launcher in Tails
>>
>> All in all, not much is necessary to make Tor Launcher able to *only*
>> control (as opposed to "own", i.e. control + "Tor is started by the
>> controller, and Tor exits with the controller") a system-wide Tor
>> instance:
>>
>>      src/application.ini                         |   13 +++++++++++++
>>      src/chrome/locale/en/torlauncher.properties |    1 +
>>      src/components/tl-process.js                |   32
>> ++++++++++++++++++++++++++------
>>      3 files changed, 40 insertions(+), 6 deletions(-)

>
> Thanks for working on this.


Thank you for providing an alternative to the now-abandoned Vidalia! And
sorry for thinking that "Mark" was a mistaken "Mike" in my first post in
this thread -- I just didn't see any mention of Mark in the Git history. :S

>> See attached files for a POC.
>>
>> Essentially what my changes do is to separate the "starting Tor" and
>> "control Tor" code, and skip the former if
>> `extensions.torlauncher.start_tor` is `false`, or if `TOR_SKIP_LAUNCH`
>> is `1`. The old behaviour of those options is to do absolutely nothing
>> w.r.t. starting/communicating with Tor, so I suppose they were only
>> used for debugging. IMHO this new behaviour is better than introducing
>> `TOR_CONFIGURE_ONLY`, as suggested. If the old behaviour is still
>> needed we can instead introduce a new option, like `IGNORE_TOR` or
>> whatever.
>
> I think we need to preserve the existing behavior. There are people who
> are using TOR_SKIP_LAUNCH and the extensions.torlauncher.start_tor
> preference, and I don't think we should break things for them.


What use cases are they trying to achieve by using Tor Launcher like
that? Is it for just starting the browser in the TBB by making Tor
Launcher do (more or less) nothing?

> We picked the name TOR_CONFIGURE_ONLY for the new behavior because we
> thought Tor Launcher would need to exit the browser after the settings
> wizard finished. If that is not the case, a name like TOR_CONTROL_ONLY
> would be better.


Sorry, but I don't understand the "exit the browser [...]" part. In the
way we intend to use the Tor Launcher in Tails there will be no browser
as it will run as a standalone XUL application.

>> ...
>> We can skip the `TOR_SKIP_LAUNCH` and `TOR_CONTROL_PORT` environment
>> variables by instead using the corresponding settings in `prefs.js`,
>> but there is no option corresponding to `TOR_CONTROL_COOKIE_AUTH_FILE`
>> although a `extensions.torlauncher.control_cookie_path` should be easy
>> to add. This is only relevant if we prefer to use proper settings
>> instead of environment variables.
>
> Is there an advantage to avoiding environment variables? They are
> already implemented and they work ;)


Not really. In fact it may just increase our maintenance burden since
keeping our own `prefs.js` will also require us to keep it in-sync with
your upstream changes.

>> # Problem: settings persistence with a system-wide Tor setup
>>
>> In Vidalia, settings configured by the user (like `bridge ...`,
>> `HTTPProxy ...`, etc) persist by being saved in Vidalia's config
>> (well, I think Vidalia first tries to write the settings to torrc via
>> `SAVECONF` and falls back to this if it fails, which it does in
>> Tails), and they are restored as soon as Vidalia establishes control
>> of Tor. In Tails' current, experimental bridge mode, the obvious race
>> condition is dealt with by adding an invalid bridge, which effectively
>> emulated the `DisableNetwork` option (in combination with our custom
>> Vidalia patches).
>>
>> In Tor Launcher, settings configured by the user are saved directly in
>> torrc (via `SAVECONF`), which doesn't fit very well in the Tails
>> context. With my changes applied, the changes are simply lost whenever
>> Tor restarts, which will happened for a number of reasons, e.g. for
>> each new network connection.
>>
>> This is a fundamental issue that my changes doesn't currently deal
>> with, and I'm unsure how to proceed. Below are some thoughts on our
>> options:
>> ...
>
> I admit that I do not understand everything about the Tails
> architecture. It sounds like users can write to the browser's (or
> XULRunner's) prefs.js but not to torrc? Is this restriction present to
> improve security or for a different reason?


In order to lessen the damage possible by compromising certain users we
do (at least) the following:

* The system-wide Tor process runs under the `debian-tor` user.

* The torrc used by Tor is only writeable by `root`.

* Tor controllers are run under yet another user (currently called
`vidalia` since that's our current controller).

> When we designed Tor Launcher, we tried hard to only have Tor settings
> stored in one place (torrc). I don't like the idea of "caching" all of
> the Tor settings as Tor Launcher preferences, but maybe that is the only
> viable solution given your architecture.


I understand this, and I think the Vidalia developers suffered a bit
from supporting that.

Something we Tails developers may want consider is to make torrc
writeable by the `debian-tor` user; if we do, then `SAVECONF` will work
and we can use Tor Launcher as is (w.r.t. configuration persistence).
Without putting too much thought into this I'm not even sure if that
would make anything worse than the current situation. After all, if the
`debian-tor` user is compromised, it can reconfigure Tor in whatever way
it want via the control port (or socket) instead of torrc. A simple
script could be left running that would compromise new Tor processes in
case it's restarted, so there's not even that benefit with this separation.

>> ...
>> If we can agree on what the right thing to do with all this is, and I
>> haven't missed anything big, I feel confident that we can drop Vidalia
>> and have bridge mode implemented using Tor Launcher in Tails 0.23.
>
> Kathy and I will need to review your patches in more detail, but one
> comment is that I don't think Tor Launcher should open the network
> settings wizard whenever DisableNetwork=1. In fact, to support PTs we


[Sorry, what do you means with "PTs"?]

> are adding a "Use Default Bridges" option which will require that Tor
> Launcher always start Tor with DisableNetwork=1 (so that the correct
> bridge configuration can be set before Tor touches the network).


I don't understand how that additional condition will cause problems for
you in this situation. You have to show the network settings so this
soon-to-be "Use Default Bridges" option can be selected, right?

By the way, why would you *always* have to start Tor with
`DisableNetwork=1` with this new option? You only have to keep
`DisableNetwork=1` until bridges have been added and SAVECONF:ed into
torrc, as that's sufficient for preventing connections to the public Tor
network.

Perhaps I just don't understand what exactly this new option is supposed
to do (?).

> Can you instead ensure that the extensions.torlauncher.prompt_at_startup
> pref is set to 'true' before starting Tor Launcher?


I suppose so. Adding the `FORCE_SHOW_NET_CONFIG` environment variable I
suggested would be even easier to work with. At least it'll make it
possible for us to let our users change Tor network settings during the
same Tails session.

Attached is a new set of patches that probably are closer to something
we can agree upon (that's not to say that they're final), and that will
add everything we need in Tails *if* we change it so that the Tor
process user (i.e. `debian-tor`) can write to torrc. I've tested them
briefly in that Tails context, and it seems to work fine.

Cheers!

From 91a3ba2a9b8aa1e0f635fb74b4b32443d84a62ef Mon Sep 17 00:00:00 2001
From: Tails developers <amnesia@???>
Date: Tue, 11 Feb 2014 00:02:22 +0100
Subject: [PATCH 1/4] Generate application.ini suitable for standalone XUL.

When running `make package` that is.
---
 Makefile           |    7 ++++++-
 application.ini.in |   13 +++++++++++++
 2 files changed, 19 insertions(+), 1 deletion(-)
 create mode 100644 application.ini.in


diff --git a/Makefile b/Makefile
index 9c3e853..7519f71 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,8 @@
### See src/LICENSE for licensing information.

 EXT_NAME=tor-launcher
-XPI_NAME:=$(shell echo "$(EXT_NAME)-`grep em:version src/install.rdf | sed -e 's/[<>]/    /g' | cut -f3`.xpi")
+VERSION:=`grep em:version src/install.rdf | sed -e 's/[<>]/    /g' | cut -f3`
+XPI_NAME:=$(shell echo "$(EXT_NAME)-$(VERSION).xpi")


AVAIL_TARGETS=help package clean

@@ -20,11 +21,15 @@ help:

 package:    clean
     @mkdir -p pkg
+    @cp "application.ini.in" "src/application.ini"
+    @sed -i "s/__VERSION__/$(VERSION)/" "src/application.ini"
+    @sed -i "s/__DATE__/`date '+%Y%m%d'`/" "src/application.ini"
     @(cd src; $(ZIP) -X9r "../pkg/$(XPI_NAME)" ./ -x "*.diff")
     @echo "Created package pkg/$(XPI_NAME)"


 clean:
     @rm -f "pkg/$(XPI_NAME)"
+    @rm -f "src/application.ini"


 zip:
     @TMPFILE=/tmp/$(EXT_NAME)-`date '+%Y-%m-%d-%s'`.zip;                     \
diff --git a/application.ini.in b/application.ini.in
new file mode 100644
index 0000000..d655a6e
--- /dev/null
+++ b/application.ini.in
@@ -0,0 +1,13 @@
+[App]
+Vendor=TorProject
+Name=TorLauncher
+Version=__VERSION__
+BuildID=__DATE__
+ID=tor-launcher@???
+
+[Gecko]
+MinVersion=17.0.0
+MaxVersion=*.*.*
+
+[Shell]
+Icon=icon.png
-- 
1.7.10.4


From 0225fec6a38c7ae0bb483afcc28e459e072ddcb7 Mon Sep 17 00:00:00 2001
From: Tails developers <amnesia@???>
Date: Mon, 17 Feb 2014 20:20:28 +0100
Subject: [PATCH 2/4] Split Tor process starting code from control code.

---
 src/chrome/locale/en/torlauncher.properties |    1 +
 src/components/tl-process.js                |   29 ++++++++++++++++++++++-----
 2 files changed, 25 insertions(+), 5 deletions(-)


diff --git a/src/chrome/locale/en/torlauncher.properties b/src/chrome/locale/en/torlauncher.properties
index 483ce43..1221701 100644
--- a/src/chrome/locale/en/torlauncher.properties
+++ b/src/chrome/locale/en/torlauncher.properties
@@ -7,6 +7,7 @@ torlauncher.tor_exited=Tor unexpectedly exited.
torlauncher.please_restart_app=Please restart this application.
torlauncher.tor_controlconn_failed=Could not connect to Tor control port.
torlauncher.tor_failed_to_start=Tor failed to start.
+torlauncher.tor_control_failed=Failed to take control of Tor.
torlauncher.tor_bootstrap_failed=Tor failed to establish a Tor network connection.\n\n%S

 torlauncher.unable_to_start_tor=Unable to start Tor.\n\n%S
diff --git a/src/components/tl-process.js b/src/components/tl-process.js
index 660588d..f04e1e8 100644
--- a/src/components/tl-process.js
+++ b/src/components/tl-process.js
@@ -88,9 +88,13 @@ TorProcessService.prototype =
       this.mObsSvc.addObserver(this, kOpenNetworkSettingsTopic, false);
       this.mObsSvc.addObserver(this, kUserQuitTopic, false);
       this.mObsSvc.addObserver(this, kBootstrapStatusTopic, false);
+      this.mTorProcessStatus = this.kStatusUnknown;


       if (TorLauncherUtil.shouldStartAndOwnTor)
+      {
         this._startTor();
+        this._controlTor();
+      }
     }
     else if ("quit-application-granted" == aTopic)
     {
@@ -261,8 +265,6 @@ TorProcessService.prototype =
   // Private Methods /////////////////////////////////////////////////////////
   _startTor: function()
   {
-    this.mTorProcessStatus = this.kStatusUnknown;
-
     var isInitialBootstrap =
                      TorLauncherUtil.getBoolPref(this.kPrefPromptAtStartup);


@@ -340,7 +342,24 @@ TorProcessService.prototype =
       p.runwAsync(args, args.length, this, false);
       this.mTorProcess = p;
       this.mTorProcessStartTime = Date.now();
+    }
+    catch (e)
+    {
+      this.mTorProcessStatus = this.kStatusExited;
+      var s = TorLauncherUtil.getLocalizedString("tor_failed_to_start");
+      TorLauncherUtil.showAlert(null, s);
+      TorLauncherLogger.safelog(4, "_startTor error: ", e);
+    }
+  }, // _startTor()
+
+
+  _controlTor: function()
+  {
+    var isInitialBootstrap =
+          TorLauncherUtil.getBoolPref(this.kPrefPromptAtStartup);


+    try
+    {
       this._monitorTorProcessStartup();


       if (isInitialBootstrap)
@@ -378,11 +397,11 @@ TorProcessService.prototype =
     catch (e)
     {
       this.mTorProcessStatus = this.kStatusExited;
-      var s = TorLauncherUtil.getLocalizedString("tor_failed_to_start");
+      var s = TorLauncherUtil.getLocalizedString("tor_control_failed");
       TorLauncherUtil.showAlert(null, s);
-      TorLauncherLogger.safelog(4, "_startTor error: ", e);
+      TorLauncherLogger.safelog(4, "_controlTor error: ", e);
     }
-  }, // _startTor()
+  }, // controlTor()


_monitorTorProcessStartup: function()
{
--
1.7.10.4

From 6249f6eac2dd80621009267b3a1e87d72140d6c5 Mon Sep 17 00:00:00 2001
From: Tails developers <amnesia@???>
Date: Mon, 17 Feb 2014 20:22:29 +0100
Subject: [PATCH 3/4] If TOR_CONFIGURE_ONLY=1, only configure Tor.

This option only prevents Tor Launcher from starting a Tor process (so
it's not the same as TOR_SKIP_LAUNCH, which prevents configuration as
well). This option is intended for situations where Tor Launcher is
supposed to configure a system-wide Tor instance.
---
 src/components/tl-process.js  |    5 ++++-
 src/components/tl-protocol.js |    3 ++-
 src/modules/tl-util.jsm       |   16 ++++++++++++++++
 3 files changed, 22 insertions(+), 2 deletions(-)


diff --git a/src/components/tl-process.js b/src/components/tl-process.js
index f04e1e8..efd1875 100644
--- a/src/components/tl-process.js
+++ b/src/components/tl-process.js
@@ -90,7 +90,10 @@ TorProcessService.prototype =
       this.mObsSvc.addObserver(this, kBootstrapStatusTopic, false);
       this.mTorProcessStatus = this.kStatusUnknown;


-      if (TorLauncherUtil.shouldStartAndOwnTor)
+      if (TorLauncherUtil.shouldOnlyConfigureTor)
+      {
+        this._controlTor();
+      } else if (TorLauncherUtil.shouldStartAndOwnTor)
       {
         this._startTor();
         this._controlTor();
diff --git a/src/components/tl-protocol.js b/src/components/tl-protocol.js
index 72530ea..e73f2e9 100644
--- a/src/components/tl-protocol.js
+++ b/src/components/tl-protocol.js
@@ -568,7 +568,8 @@ TorProtocolService.prototype =
         return null;
       }


-      if (!aIsEventConnection && TorLauncherUtil.shouldStartAndOwnTor)
+      if (!aIsEventConnection && TorLauncherUtil.shouldStartAndOwnTor &&
+          !TorLauncherUtil.shouldOnlyConfigureTor)
       {
         // Try to become the primary controller (TAKEOWNERSHIP).
         reply = this._sendCommand(conn, "TAKEOWNERSHIP", null);
diff --git a/src/modules/tl-util.jsm b/src/modules/tl-util.jsm
index e6298e8..f6ac77b 100644
--- a/src/modules/tl-util.jsm
+++ b/src/modules/tl-util.jsm
@@ -155,6 +155,22 @@ let TorLauncherUtil =  // Public


     return this.getBoolPref(kPrefStartTor, true);
   },
+
+
+  get shouldOnlyConfigureTor()
+  {
+    try
+    {
+      const kEnvOnlyConfigureTor = "TOR_CONFIGURE_ONLY";
+
+      var env = Cc["@mozilla.org/process/environment;1"]
+                  .getService(Ci.nsIEnvironment);
+      if (env.exists(kEnvOnlyConfigureTor))
+        return ("1" == env.get(kEnvOnlyConfigureTor));
+    } catch(e) {}
+
+    return false
+  },
 };



--
1.7.10.4

From 1c9de42102b3a8ba4f9285394f381669a97ffee3 Mon Sep 17 00:00:00 2001
From: Tails developers <amnesia@???>
Date: Mon, 17 Feb 2014 20:36:20 +0100
Subject: [PATCH 4/4] If FORCE_SHOW_NET_CONFIG=1, always show network
settings.

---
 src/components/tl-process.js |    2 +-
 src/modules/tl-util.jsm      |   15 +++++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)


diff --git a/src/components/tl-process.js b/src/components/tl-process.js
index efd1875..8dd8ccc 100644
--- a/src/components/tl-process.js
+++ b/src/components/tl-process.js
@@ -365,7 +365,7 @@ TorProcessService.prototype =
     {
       this._monitorTorProcessStartup();


-      if (isInitialBootstrap)
+      if (isInitialBootstrap || TorLauncherUtil.forceShowNetworkSettings)
       {
         if (this.mProtocolSvc)
           this._openNetworkSettings(true); // Blocks until dialog is closed.
diff --git a/src/modules/tl-util.jsm b/src/modules/tl-util.jsm
index f6ac77b..1d5fa8c 100644
--- a/src/modules/tl-util.jsm
+++ b/src/modules/tl-util.jsm
@@ -171,6 +171,21 @@ let TorLauncherUtil =  // Public


     return false
   },
+
+  get forceShowNetworkSettings()
+  {
+    try
+    {
+      const kEnvForceShowNetConfig = "FORCE_SHOW_NET_CONFIG";
+
+      var env = Cc["@mozilla.org/process/environment;1"]
+                  .getService(Ci.nsIEnvironment);
+      if (env.exists(kEnvForceShowNetConfig))
+        return ("1" == env.get(kEnvForceShowNetConfig));
+    } catch(e) {}
+
+    return false
+  },
 };



--
1.7.10.4