[tor-commits] [arm/release] Wizard hooks for configuring system wide torrc
atagar at torproject.org
atagar at torproject.org
Sun Sep 25 21:38:22 UTC 2011
commit ec49c74ba52d9410d6f108a4e76dfad063d40500
Author: Damian Johnson <atagar at torproject.org>
Date: Wed Jul 27 12:10:02 2011 -0700
Wizard hooks for configuring system wide torrc
Providing an option to apply the wizard config to the system wide torrc if
it's available (user has already done the --init prep).
---
src/cli/wizard.py | 98 +++++++++++++++++++++++++++++++++++++++++++++++------
src/settings.cfg | 4 ++
2 files changed, 91 insertions(+), 11 deletions(-)
diff --git a/src/cli/wizard.py b/src/cli/wizard.py
index 08e9d0b..31f2f70 100644
--- a/src/cli/wizard.py
+++ b/src/cli/wizard.py
@@ -24,7 +24,7 @@ TORRC_TEMPLATE = "resources/torrcTemplate.txt"
RelayType = enum.Enum("RESUME", "RELAY", "EXIT", "BRIDGE", "CLIENT")
# all options that can be configured
-Options = enum.Enum("DIVIDER", "CONTROL", "NICKNAME", "CONTACT", "NOTIFY", "BANDWIDTH", "LIMIT", "CLIENT", "LOWPORTS", "PORTFORWARD", "STARTUP", "RSHUTDOWN", "CSHUTDOWN", "NOTICE", "POLICY", "WEBSITES", "EMAIL", "IM", "MISC", "PLAINTEXT", "DISTRIBUTE", "BRIDGED", "BRIDGE1", "BRIDGE2", "BRIDGE3", "REUSE")
+Options = enum.Enum("DIVIDER", "CONTROL", "NICKNAME", "CONTACT", "NOTIFY", "BANDWIDTH", "LIMIT", "CLIENT", "LOWPORTS", "PORTFORWARD", "SYSTEM", "STARTUP", "RSHUTDOWN", "CSHUTDOWN", "NOTICE", "POLICY", "WEBSITES", "EMAIL", "IM", "MISC", "PLAINTEXT", "DISTRIBUTE", "BRIDGED", "BRIDGE1", "BRIDGE2", "BRIDGE3", "REUSE")
RelayOptions = {RelayType.RELAY: (Options.NICKNAME,
Options.CONTACT,
Options.NOTIFY,
@@ -34,7 +34,8 @@ RelayOptions = {RelayType.RELAY: (Options.NICKNAME,
Options.LOWPORTS,
Options.PORTFORWARD,
Options.STARTUP,
- Options.RSHUTDOWN),
+ Options.RSHUTDOWN,
+ Options.SYSTEM),
RelayType.EXIT: (Options.NICKNAME,
Options.CONTACT,
Options.NOTIFY,
@@ -45,6 +46,7 @@ RelayOptions = {RelayType.RELAY: (Options.NICKNAME,
Options.PORTFORWARD,
Options.STARTUP,
Options.RSHUTDOWN,
+ Options.SYSTEM,
Options.DIVIDER,
Options.NOTICE,
Options.POLICY,
@@ -60,13 +62,15 @@ RelayOptions = {RelayType.RELAY: (Options.NICKNAME,
Options.LOWPORTS,
Options.PORTFORWARD,
Options.STARTUP,
- Options.RSHUTDOWN),
+ Options.RSHUTDOWN,
+ Options.SYSTEM),
RelayType.CLIENT: (Options.BRIDGED,
Options.BRIDGE1,
Options.BRIDGE2,
Options.BRIDGE3,
Options.REUSE,
- Options.CSHUTDOWN)}
+ Options.CSHUTDOWN,
+ Options.SYSTEM)}
# option sets
CUSTOM_POLICIES = (Options.WEBSITES, Options.EMAIL, Options.IM, Options.MISC, Options.PLAINTEXT)
@@ -95,6 +99,12 @@ VERSION_REQUIREMENTS = {Options.PORTFORWARD: "0.2.3.1-alpha"}
TOR_DEFAULTS = {Options.BANDWIDTH: "5 MB",
Options.REUSE: "10 minutes"}
+# path for the torrc to be placed if replacing the torrc for the system wide
+# tor instance
+SYSTEM_DROP_PATH = "/var/lib/tor-arm/torrc"
+OVERRIDE_SCRIPT = "/usr/share/arm/resources/torrcOverride/override.py"
+OVERRIDE_SETUID_SCRIPT = "/usr/bin/torrc-override"
+
CONFIG = {"wizard.message.role": "",
"wizard.message.relay": "",
"wizard.message.exit": "",
@@ -306,6 +316,13 @@ def showWizard():
if not sysTools.isAvailable("tor-fw-helper"):
disabledOpt.append(Options.PORTFORWARD)
+ # If we haven't run 'resources/torrcOverride/override.py --init' or lack
+ # permissions then we aren't able to deal with the system wide tor instance.
+ # Also drop the optoin if we aren't installed since override.py won't be at
+ # the expected path.
+ if not os.path.exists(SYSTEM_DROP_PATH) or not os.path.exists(OVERRIDE_SCRIPT):
+ disabledOpt.append(Options.SYSTEM)
+
while True:
if relayType == None:
selection = promptRelayType(relaySelection)
@@ -331,16 +348,26 @@ def showWizard():
if confirmationSelection == NEXT:
log.log(log.INFO, "Writing torrc to '%s':\n%s" % (torrcLocation, generatedTorrc))
+ isSystemReplace = not Options.SYSTEM in disabledOpt and config[Options.SYSTEM].getValue()
+ if isSystemReplace: torrcLocation = SYSTEM_DROP_PATH
+
# if the torrc already exists then save it to a _bak file
isBackedUp = False
if os.path.exists(torrcLocation):
- shutil.copy(torrcLocation, torrcLocation + "_bak")
- isBackedUp = True
+ try:
+ shutil.copy(torrcLocation, torrcLocation + "_bak")
+ isBackedUp = True
+ except IOError, exc:
+ log.log(log.WARN, "Unable to backup the torrc: %s" % exc)
# writes the torrc contents
- torrcFile = open(torrcLocation, "w")
- torrcFile.write(generatedTorrc)
- torrcFile.close()
+ try:
+ torrcFile = open(torrcLocation, "w")
+ torrcFile.write(generatedTorrc)
+ torrcFile.close()
+ except IOError, exc:
+ log.log(log.ERR, "Unable to make torrc: %s" % exc)
+ break
# logs where we placed the torrc
msg = "Tor configuration placed at '%s'" % torrcLocation
@@ -367,7 +394,53 @@ def showWizard():
msg = "Exit notice placed at '%s/index.html'. Some of the sections are specific to US relay operators so please change the \"FIXME\" sections if this is inappropriate." % dst
log.log(log.NOTICE, msg)
- if manager.isTorrcAvailable():
+ runCommand, exitCode = None, 1
+
+ if isSystemReplace:
+ # running override.py needs root so...
+ # - if running as root (bad user, no biscuit!) then run it directly
+ # - if the setuid binary is available at '/usr/bin/torrc-override'
+ # then use that
+ # - attempt sudo in case passwordless sudo is available
+ # - if all of the above fail then log instructions
+
+ if os.geteuid() == 0: runCommand = OVERRIDE_SCRIPT
+ elif os.path.exists(OVERRIDE_SETUID_SCRIPT): runCommand = OVERRIDE_SETUID_SCRIPT
+ else:
+ # The -n argument to sudo is *supposed* to be available starting
+ # with 1.7.0 [1] however this is a dirty lie (Ubuntu 9.10 uses
+ # 1.7.0 and even has the option in its man page, but it doesn't
+ # work). Instead checking for version 1.7.1.
+ #
+ # [1] http://www.sudo.ws/pipermail/sudo-users/2009-January/003889.html
+
+ sudoVersionResult = sysTools.call("sudo -V")
+
+ # version output looks like "Sudo version 1.7.2p7"
+ if len(sudoVersionResult) == 1 and sudoVersionResult.count(" ") >= 2:
+ versionNum = 0
+
+ for comp in sudoVersionResult[0].split(" ")[2].split("."):
+ if comp and comp[0].isdigit():
+ versionNum = (10 * versionNum) + int(comp)
+ else:
+ # invalid format
+ log.log(log.INFO, "Unrecognized sudo version string: %s" % sudoVersionResult[0])
+ versionNum = 0
+ break
+
+ if versionNum >= 171:
+ runCommand = "sudo -n %s" % OVERRIDE_SCRIPT
+ else:
+ log.log(log.INFO, "Insufficient sudo version for the -n argument")
+
+ if runCommand: exitCode = os.system("%s > /dev/null 2>&1" % runCommand)
+
+ if exitCode != 0:
+ msg = "Tor needs root permissions to replace the system wide torrc. To continue...\n- open another terminal\n- run \"sudo %s\"\n- press 'x' here to tell tor to reload" % OVERRIDE_SCRIPT
+ log.log(log.NOTICE, msg)
+ else: torTools.getConn().reload()
+ elif manager.isTorrcAvailable():
# If we're connected to a managed instance then just need to
# issue a sighup to pick up the new settings. Otherwise starts
# a new tor instance.
@@ -603,9 +676,12 @@ def getTorrc(relayType, config, disabledOpt):
dataDir = cli.controller.getController().getDataDirectory()
templateOptions["NOTICE_PATH"] = "%sexitNotice/index.html" % dataDir
templateOptions["LOG_ENTRY"] = "notice file %stor_log" % dataDir
- templateOptions["DATA_DIR"] = "%stor_data" % dataDir
templateOptions["USERNAME"] = getpass.getuser()
+ # using custom data directory, unless this is for a system wide instance
+ if not config[Options.SYSTEM].getValue() or Options.SYSTEM in disabledOpt:
+ templateOptions["DATA_DIR"] = "%stor_data" % dataDir
+
policyCategories = []
if not config[Options.POLICY].getValue():
policyCategories = ["web", "mail", "im", "misc"]
diff --git a/src/settings.cfg b/src/settings.cfg
index 750ae9e..9154ed5 100644
--- a/src/settings.cfg
+++ b/src/settings.cfg
@@ -354,6 +354,7 @@ wizard.toggle Portforward => Enabled, Disabled
wizard.toggle Startup => Yes, No
wizard.toggle Rshutdown => Yes, No
wizard.toggle Cshutdown => Yes, No
+wizard.toggle System => Yes, No
wizard.toggle Notice => Yes, No
wizard.toggle Policy => Custom, Default
wizard.toggle Websites => Allow, Block
@@ -383,6 +384,7 @@ wizard.default Bandwidth => 5 MB/s
wizard.default Startup => true
wizard.default Rshutdown => false
wizard.default Cshutdown => true
+wizard.default System => true
wizard.default Client => false
wizard.default Lowports => true
wizard.default Portforward => true
@@ -421,6 +423,7 @@ wizard.label.opt Portforward => Port Forwarding
wizard.label.opt Startup => Run At Startup
wizard.label.opt Rshutdown => Shutdown With Arm
wizard.label.opt Cshutdown => Shutdown With Arm
+wizard.label.opt System => Use System Instance
wizard.label.opt Notice => Disclaimer Notice
wizard.label.opt Policy => Exit Policy
wizard.label.opt Websites => Web Browsing
@@ -452,6 +455,7 @@ wizard.description.opt Portforward => If needed, attempts NAT traversal using UP
wizard.description.opt Startup => Runs Tor in the background when the system starts.
wizard.description.opt Rshutdown => When you quit arm the Tor process is stopped thirty seconds later. This delay is so people using you can gracefully switch their circuits.
wizard.description.opt Cshutdown => Stops the Tor process when you quit arm.
+wizard.description.opt System => Use the system wide tor instance rather than making one of our own.
wizard.description.opt Notice => Provides a disclaimer that this is an exit on port 80 (http://www.atagar.com/exitNotice).
wizard.description.opt Policy => Ports allowed to exit from your relay. The default policy allows for common services while limiting the chance of getting a DMCA takedown for torrent traffic (http://www.atagar.com/exitPolicy).
wizard.description.opt Websites => General Internet browsing including HTTP (80), HTTPS (443), common alternatives (81, 8008), and proxies (3128, 8080)
More information about the tor-commits
mailing list