commit cab3641638540834a0867f26eb5b432fd793fd5e
Author: Robert Ransom <rransom.8774(a)gmail.com>
Date: Sat Aug 6 13:42:32 2011 -0700
Fix handling of ISO_STREAM
Now we track *which* stream with ISO_STREAM set is associated to a
particular circuit, so that we won't think that stream is incompatible
with its circuit and launch another one a second later, and we use that
same field to mark circuits which have had an ISO_STREAM stream attached
to them, so that …
[View More]we won't ever put a second stream on that circuit.
Fixes bug 3695.
---
src/or/connection_edge.c | 9 ++++++---
src/or/or.h | 3 +++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 971cee2..37a695c 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -3432,9 +3432,9 @@ connection_edge_compatible_with_circuit(const edge_connection_t *conn,
tor_strdup(conn->socks_request->address);
}
- /* If isolation_values_set, then the circuit is not compatible with
- * any new ISO_STREAM stream. */
- if (iso & ISO_STREAM)
+ if ((iso & ISO_STREAM) &&
+ (circ->associated_isolated_stream_global_id !=
+ TO_CONN(conn)->global_identifier))
return 0;
if ((iso & ISO_DESTPORT) && conn->socks_request->port != circ->dest_port)
@@ -3487,6 +3487,8 @@ connection_edge_update_circuit_isolation(const edge_connection_t *conn,
if (!circ->isolation_values_set) {
if (dry_run)
return -1;
+ circ->associated_isolated_stream_global_id =
+ TO_CONN(conn)->global_identifier;
circ->dest_port = conn->socks_request->port;
circ->dest_address = tor_strdup(conn->original_dest_address);
circ->client_proto_type = conn->socks_request->listener_type;
@@ -3562,6 +3564,7 @@ circuit_clear_isolation(origin_circuit_t *circ)
circ->isolation_values_set = 0;
circ->isolation_flags_mixed = 0;
+ circ->associated_isolated_stream_global_id = 0;
circ->client_proto_type = 0;
circ->client_proto_socksver = 0;
circ->dest_port = 0;
diff --git a/src/or/or.h b/src/or/or.h
index eb271b5..9c5d354 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2530,6 +2530,9 @@ typedef struct origin_circuit_t {
socks_username_len and socks_password_len for their lengths. */
char *socks_username;
char *socks_password;
+ /** Global identifier for the first stream attached here; used by
+ * ISO_STREAM. */
+ uint64_t associated_isolated_stream_global_id;
/**@}*/
} origin_circuit_t;
[View Less]
commit b05003e808913ec89a206ae9abec7031392e902b
Author: Damian Johnson <atagar(a)torproject.org>
Date: Tue Jul 26 19:26:51 2011 -0700
fix: renaming torrc-override to torrcOverride
Everything else uses camel case so changing to match.
---
src/resources/torrc-override/override.c | 50 ------
src/resources/torrc-override/override.h | 1 -
src/resources/torrc-override/override.py | 265 ------------------------------
src/resources/torrcOverride/override.c | 50 ++++…
[View More]++
src/resources/torrcOverride/override.h | 1 +
src/resources/torrcOverride/override.py | 265 ++++++++++++++++++++++++++++++
6 files changed, 316 insertions(+), 316 deletions(-)
diff --git a/src/resources/torrc-override/override.c b/src/resources/torrc-override/override.c
deleted file mode 100644
index b989584..0000000
--- a/src/resources/torrc-override/override.c
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// This is a very small C wrapper that invokes
-// $(DESTDIR)/usr/bin/tor-arm-replace-torrc.py to work around setuid scripting
-// issues on the Gnu/Linux operating system.
-//
-// We assume you have installed it as such for GROUP
-// "debian-arm" - This should ensure that only members of the GROUP group will
-// be allowed to run this program. When run this program will execute the
-// $(DESTDIR)/usr/bin/tor-arm-replace-torrc.py program and will run with the
-// uid and group as marked by the OS.
-//
-// Compile it like so:
-//
-// make
-//
-// Or by hand like so:
-//
-// gcc -o tor-arm-replace-torrc tor-arm-replace-torrc.c
-//
-// Make it useful like so:
-//
-// chown root:debian-arm tor-arm-replace-torrc
-// chmod 04750 tor-arm-replace-torrc
-//
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-//
-// If you place a user inside of the $GROUP - they are now able to reconfigure
-// Tor. This may lead them to do nasty things on your system. If you start Tor
-// as root, you should consider that adding a user to $GROUP is similar to
-// giving those users root directly.
-//
-// This program was written simply to help a users who run arm locally and is
-// not required if arm is communicating with a remote Tor process.
-//
-// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-//
-//
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include "tor-arm-replace-torrc.h"
-
-int main()
-{
- return execve(TOR_ARM_REPLACE_TORRC, NULL, NULL);
-}
diff --git a/src/resources/torrc-override/override.h b/src/resources/torrc-override/override.h
deleted file mode 100644
index 65adc9d..0000000
--- a/src/resources/torrc-override/override.h
+++ /dev/null
@@ -1 +0,0 @@
-#define TOR_ARM_REPLACE_TORRC HELPER_NAME
diff --git a/src/resources/torrc-override/override.py b/src/resources/torrc-override/override.py
deleted file mode 100755
index 6cfdbc6..0000000
--- a/src/resources/torrc-override/override.py
+++ /dev/null
@@ -1,265 +0,0 @@
-#!/usr/bin/python
-
-"""
-This overwrites the system wide torrc, located at /etc/tor/torrc, with the
-contents of the ARM_CONFIG_FILE. The system wide torrc is owned by root so
-this will effectively need root permissions and for us to be in GROUP.
-
-This file is completely unusable until we make a tor-arm user and perform
-other prep by running with the '--init' argument.
-
-After that's done this is meant to either be used by arm automatically after
-writing a torrc to ARM_CONFIG_FILE or by users manually. For arm to use this
-automatically you'll either need to...
-
-- compile torrc-override.c, setuid on the binary, and move it to your path
- cd /usr/share/arm/resources/torrc-override
- make
- chown root:tor-arm override
- chmod 04750 override
- mv override /usr/bin/torrc-override
-
-- allow passwordless sudo for this script
- edit /etc/sudoers and add a line with:
- <arm user> ALL= NOPASSWD: /usr/share/arm/resources/torrc-override/override.py
-
-To perform this manually run:
-/usr/share/arm/resources/torrc-override/override.py
-pkill -sighup tor
-"""
-
-import os
-import sys
-import grp
-import pwd
-import time
-import shutil
-import tempfile
-import signal
-
-USER = "tor-arm"
-GROUP = "tor-arm"
-TOR_CONFIG_FILE = "/etc/tor/torrc"
-ARM_CONFIG_FILE = "/var/lib/tor-arm/torrc"
-
-HELP_MSG = """Usage %s [OPTION]
- Backup the system wide torrc (%s) and replace it with the
- contents of %s.
-
- --init creates the necessary user and paths
- --remove reverts changes made with --init
-""" % (os.path.basename(sys.argv[0]), TOR_CONFIG_FILE, ARM_CONFIG_FILE)
-
-def init():
- """
- Performs system preparation needed for this script to run, adding the tor-arm
- user and setting up paths/permissions.
- """
-
- # the following is just here if we have a custom destination directory (which
- # arm doesn't currently account for)
- if not os.path.exists("/bin/"):
- print "making '/bin'..."
- os.mkdir("/bin")
-
- if not os.path.exists("/var/lib/tor-arm/"):
- print "making '/var/lib/tor-arm'..."
- os.makedirs("/var/lib/tor-arm")
-
- if not os.path.exists("/var/lib/tor-arm/torrc"):
- print "making '/var/lib/tor-arm/torrc'..."
- open("/var/lib/tor-arm/torrc", 'w').close()
-
- try: gid = grp.getgrnam(GROUP).gr_gid
- except KeyError:
- print "adding %s group..." % GROUP
- os.system("addgroup --quiet --system %s" % GROUP)
- gid = grp.getgrnam(GROUP).gr_gid
- print " done, gid: %s" % gid
-
- try: pwd.getpwnam(USER).pw_uid
- except KeyError:
- print "adding %s user..." % USER
- os.system("adduser --quiet --ingroup %s --no-create-home --home /var/lib/tor-arm/ --shell /bin/sh --system %s" % (GROUP, USER))
- uid = pwd.getpwnam(USER).pw_uid
- print " done, uid: %s" % uid
-
- os.chown("/bin", 0, 0)
- os.chown("/var/lib/tor-arm", 0, gid)
- os.chmod("/var/lib/tor-arm", 0750)
- os.chown("/var/lib/tor-arm/torrc", 0, gid)
- os.chmod("/var/lib/tor-arm/torrc", 0760)
-
-def remove():
- """
- Reverts the changes made by init, and also removes the optional
- /bin/torrc-override binary if it exists.
- """
-
- print "removing %s user..." % USER
- os.system("deluser --quiet %s" % USER)
-
- print "removing %s group..." % GROUP
- os.system("delgroup --quiet %s" % GROUP)
-
- # might not exist since this is compiled and placed separately
- try:
- print "removing '/bin/torrc-override'..."
- os.remove("/bin/torrc-override")
- except OSError:
- print " no such path"
-
- try:
- print "removing '/var/lib/tor-arm'..."
- shutil.rmtree("/var/lib/tor-arm/")
- except Exception, exc:
- print " unsuccessful: %s" % exc
-
-def replaceTorrc():
- orig_uid = os.getuid()
- orig_euid = os.geteuid()
-
- # the USER and GROUP must exist on this system
- try:
- dropped_uid = pwd.getpwnam(USER).pw_uid
- dropped_gid = grp.getgrnam(GROUP).gr_gid
- dropped_euid, dropped_egid = dropped_uid, dropped_gid
- except KeyError:
- print "tor-arm user and group was not found, have you run this script with '--init'?"
- exit(1)
-
- # if we're actually root, we skip this group check
- # root can get away with all of this
- if orig_uid != 0:
- # check that the user is in GROUP
- if not dropped_gid in os.getgroups():
- print "Your user needs to be a member of the %s group for this to work" % GROUP
- sys.exit(1)
-
- # drop to the unprivileged group, and lose the rest of the groups
- os.setgid(dropped_gid)
- os.setegid(dropped_egid)
- os.setresgid(dropped_gid, dropped_egid, dropped_gid)
- os.setgroups([dropped_gid])
-
- # make a tempfile and write out the contents
- try:
- tf = tempfile.NamedTemporaryFile(delete=False) # uses mkstemp internally
-
- # allows our child process to write to tf.name (not only if their uid matches, not their gid)
- os.chown(tf.name, dropped_uid, orig_euid)
- except:
- print "We were unable to make a temporary file"
- sys.exit(1)
-
- fork_pid = os.fork()
-
- # open the suspect config after we drop privs
- # we assume the dropped privs are still enough to write to the tf
- if (fork_pid == 0):
- signal.signal(signal.SIGCHLD, signal.SIG_IGN)
-
- # Drop privs forever in the child process
- # I believe this drops os.setfsuid os.setfsgid stuff
- # Clear all other supplemental groups for dropped_uid
- os.setgroups([dropped_gid])
- os.setresgid(dropped_gid, dropped_egid, dropped_gid)
- os.setresuid(dropped_uid, dropped_euid, dropped_uid)
- os.setgid(dropped_gid)
- os.setegid(dropped_egid)
- os.setuid(dropped_uid)
- os.seteuid(dropped_euid)
-
- try:
- af = open(ARM_CONFIG_FILE) # this is totally unpriv'ed
-
- # ensure that the fd we opened has the properties we requrie
- configStat = os.fstat(af.fileno()) # this happens on the unpriv'ed FD
- if configStat.st_gid != dropped_gid:
- print "Arm's configuration file (%s) must be owned by the group %s" % (ARM_CONFIG_FILE, GROUP)
- sys.exit(1)
-
- # if everything checks out, we're as safe as we're going to get
- armConfig = af.read(1024 * 1024) # limited read but not too limited
- af.close()
- tf.file.write(armConfig)
- tf.flush()
- except:
- print "Unable to open the arm config as unpriv'ed user"
- sys.exit(1)
- finally:
- tf.close()
- sys.exit(0)
- else:
- # If we're here, we're in the parent waiting for the child's death
- # man, unix is really weird...
- _, status = os.waitpid(fork_pid, 0)
-
- if status != 0:
- print "The child seems to have failed; exiting!"
- tf.close()
- sys.exit(1)
-
- # attempt to verify that the config is OK
- if os.path.exists(tf.name):
- # construct our SU string
- SUSTRING = "su -c 'tor --verify-config -f " + str(tf.name) + "' " + USER
- # We raise privs to drop them with 'su'
- os.setuid(0)
- os.seteuid(0)
- os.setgid(0)
- os.setegid(0)
- # We drop privs here and exec tor to verify it as the dropped_uid
- print "Using Tor to verify that arm will not break Tor's config:"
- success = os.system(SUSTRING)
- if success != 0:
- print "Tor says the new configuration file is invalid: %s (%s)" % (ARM_CONFIG_FILE, tf.name)
- sys.exit(1)
-
- # backup the previous tor config
- if os.path.exists(TOR_CONFIG_FILE):
- try:
- backupFilename = "%s_backup_%i" % (TOR_CONFIG_FILE, int(time.time()))
- shutil.copy(TOR_CONFIG_FILE, backupFilename)
- except IOError, exc:
- print "Unable to backup %s (%s)" % (TOR_CONFIG_FILE, exc)
- sys.exit(1)
-
- # overwrites TOR_CONFIG_FILE with ARM_CONFIG_FILE as loaded into tf.name
- try:
- shutil.copy(tf.name, TOR_CONFIG_FILE)
- print "Successfully reconfigured Tor"
- except IOError, exc:
- print "Unable to copy %s to %s (%s)" % (tf.name, TOR_CONFIG_FILE, exc)
- sys.exit(1)
-
- # unlink our temp file
- try:
- os.remove(tf.name)
- except:
- print "Unable to close temp file %s" % tf.name
- sys.exit(1)
-
- sys.exit(0)
-
-if __name__ == "__main__":
- # sanity check that we're on linux
- if os.name != "posix":
- print "This is a script specifically for configuring Linux"
- sys.exit(1)
-
- # check that we're running effectively as root
- if os.geteuid() != 0:
- print "This script needs to be run as root"
- sys.exit(1)
-
- if len(sys.argv) < 2:
- replaceTorrc()
- elif len(sys.argv) == 2 and sys.argv[1] == "--init":
- init()
- elif len(sys.argv) == 2 and sys.argv[1] == "--remove":
- remove()
- else:
- print HELP_MSG
- sys.exit(1)
-
diff --git a/src/resources/torrcOverride/override.c b/src/resources/torrcOverride/override.c
new file mode 100644
index 0000000..b989584
--- /dev/null
+++ b/src/resources/torrcOverride/override.c
@@ -0,0 +1,50 @@
+//
+// This is a very small C wrapper that invokes
+// $(DESTDIR)/usr/bin/tor-arm-replace-torrc.py to work around setuid scripting
+// issues on the Gnu/Linux operating system.
+//
+// We assume you have installed it as such for GROUP
+// "debian-arm" - This should ensure that only members of the GROUP group will
+// be allowed to run this program. When run this program will execute the
+// $(DESTDIR)/usr/bin/tor-arm-replace-torrc.py program and will run with the
+// uid and group as marked by the OS.
+//
+// Compile it like so:
+//
+// make
+//
+// Or by hand like so:
+//
+// gcc -o tor-arm-replace-torrc tor-arm-replace-torrc.c
+//
+// Make it useful like so:
+//
+// chown root:debian-arm tor-arm-replace-torrc
+// chmod 04750 tor-arm-replace-torrc
+//
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+//
+// If you place a user inside of the $GROUP - they are now able to reconfigure
+// Tor. This may lead them to do nasty things on your system. If you start Tor
+// as root, you should consider that adding a user to $GROUP is similar to
+// giving those users root directly.
+//
+// This program was written simply to help a users who run arm locally and is
+// not required if arm is communicating with a remote Tor process.
+//
+// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+//
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "tor-arm-replace-torrc.h"
+
+int main()
+{
+ return execve(TOR_ARM_REPLACE_TORRC, NULL, NULL);
+}
diff --git a/src/resources/torrcOverride/override.h b/src/resources/torrcOverride/override.h
new file mode 100644
index 0000000..65adc9d
--- /dev/null
+++ b/src/resources/torrcOverride/override.h
@@ -0,0 +1 @@
+#define TOR_ARM_REPLACE_TORRC HELPER_NAME
diff --git a/src/resources/torrcOverride/override.py b/src/resources/torrcOverride/override.py
new file mode 100755
index 0000000..3e42892
--- /dev/null
+++ b/src/resources/torrcOverride/override.py
@@ -0,0 +1,265 @@
+#!/usr/bin/python
+
+"""
+This overwrites the system wide torrc, located at /etc/tor/torrc, with the
+contents of the ARM_CONFIG_FILE. The system wide torrc is owned by root so
+this will effectively need root permissions and for us to be in GROUP.
+
+This file is completely unusable until we make a tor-arm user and perform
+other prep by running with the '--init' argument.
+
+After that's done this is meant to either be used by arm automatically after
+writing a torrc to ARM_CONFIG_FILE or by users manually. For arm to use this
+automatically you'll either need to...
+
+- compile override.c, setuid on the binary, and move it to your path
+ cd /usr/share/arm/resources/torrcOverride
+ make
+ chown root:tor-arm override
+ chmod 04750 override
+ mv override /usr/bin/torrc-override
+
+- allow passwordless sudo for this script
+ edit /etc/sudoers and add a line with:
+ <arm user> ALL= NOPASSWD: /usr/share/arm/resources/torrcOverride/override.py
+
+To perform this manually run:
+/usr/share/arm/resources/torrcOverride/override.py
+pkill -sighup tor
+"""
+
+import os
+import sys
+import grp
+import pwd
+import time
+import shutil
+import tempfile
+import signal
+
+USER = "tor-arm"
+GROUP = "tor-arm"
+TOR_CONFIG_FILE = "/etc/tor/torrc"
+ARM_CONFIG_FILE = "/var/lib/tor-arm/torrc"
+
+HELP_MSG = """Usage %s [OPTION]
+ Backup the system wide torrc (%s) and replace it with the
+ contents of %s.
+
+ --init creates the necessary user and paths
+ --remove reverts changes made with --init
+""" % (os.path.basename(sys.argv[0]), TOR_CONFIG_FILE, ARM_CONFIG_FILE)
+
+def init():
+ """
+ Performs system preparation needed for this script to run, adding the tor-arm
+ user and setting up paths/permissions.
+ """
+
+ # the following is just here if we have a custom destination directory (which
+ # arm doesn't currently account for)
+ if not os.path.exists("/bin/"):
+ print "making '/bin'..."
+ os.mkdir("/bin")
+
+ if not os.path.exists("/var/lib/tor-arm/"):
+ print "making '/var/lib/tor-arm'..."
+ os.makedirs("/var/lib/tor-arm")
+
+ if not os.path.exists("/var/lib/tor-arm/torrc"):
+ print "making '/var/lib/tor-arm/torrc'..."
+ open("/var/lib/tor-arm/torrc", 'w').close()
+
+ try: gid = grp.getgrnam(GROUP).gr_gid
+ except KeyError:
+ print "adding %s group..." % GROUP
+ os.system("addgroup --quiet --system %s" % GROUP)
+ gid = grp.getgrnam(GROUP).gr_gid
+ print " done, gid: %s" % gid
+
+ try: pwd.getpwnam(USER).pw_uid
+ except KeyError:
+ print "adding %s user..." % USER
+ os.system("adduser --quiet --ingroup %s --no-create-home --home /var/lib/tor-arm/ --shell /bin/sh --system %s" % (GROUP, USER))
+ uid = pwd.getpwnam(USER).pw_uid
+ print " done, uid: %s" % uid
+
+ os.chown("/bin", 0, 0)
+ os.chown("/var/lib/tor-arm", 0, gid)
+ os.chmod("/var/lib/tor-arm", 0750)
+ os.chown("/var/lib/tor-arm/torrc", 0, gid)
+ os.chmod("/var/lib/tor-arm/torrc", 0760)
+
+def remove():
+ """
+ Reverts the changes made by init, and also removes the optional
+ /bin/torrc-override binary if it exists.
+ """
+
+ print "removing %s user..." % USER
+ os.system("deluser --quiet %s" % USER)
+
+ print "removing %s group..." % GROUP
+ os.system("delgroup --quiet %s" % GROUP)
+
+ # might not exist since this is compiled and placed separately
+ try:
+ print "removing '/bin/torrc-override'..."
+ os.remove("/bin/torrc-override")
+ except OSError:
+ print " no such path"
+
+ try:
+ print "removing '/var/lib/tor-arm'..."
+ shutil.rmtree("/var/lib/tor-arm/")
+ except Exception, exc:
+ print " unsuccessful: %s" % exc
+
+def replaceTorrc():
+ orig_uid = os.getuid()
+ orig_euid = os.geteuid()
+
+ # the USER and GROUP must exist on this system
+ try:
+ dropped_uid = pwd.getpwnam(USER).pw_uid
+ dropped_gid = grp.getgrnam(GROUP).gr_gid
+ dropped_euid, dropped_egid = dropped_uid, dropped_gid
+ except KeyError:
+ print "tor-arm user and group was not found, have you run this script with '--init'?"
+ exit(1)
+
+ # if we're actually root, we skip this group check
+ # root can get away with all of this
+ if orig_uid != 0:
+ # check that the user is in GROUP
+ if not dropped_gid in os.getgroups():
+ print "Your user needs to be a member of the %s group for this to work" % GROUP
+ sys.exit(1)
+
+ # drop to the unprivileged group, and lose the rest of the groups
+ os.setgid(dropped_gid)
+ os.setegid(dropped_egid)
+ os.setresgid(dropped_gid, dropped_egid, dropped_gid)
+ os.setgroups([dropped_gid])
+
+ # make a tempfile and write out the contents
+ try:
+ tf = tempfile.NamedTemporaryFile(delete=False) # uses mkstemp internally
+
+ # allows our child process to write to tf.name (not only if their uid matches, not their gid)
+ os.chown(tf.name, dropped_uid, orig_euid)
+ except:
+ print "We were unable to make a temporary file"
+ sys.exit(1)
+
+ fork_pid = os.fork()
+
+ # open the suspect config after we drop privs
+ # we assume the dropped privs are still enough to write to the tf
+ if (fork_pid == 0):
+ signal.signal(signal.SIGCHLD, signal.SIG_IGN)
+
+ # Drop privs forever in the child process
+ # I believe this drops os.setfsuid os.setfsgid stuff
+ # Clear all other supplemental groups for dropped_uid
+ os.setgroups([dropped_gid])
+ os.setresgid(dropped_gid, dropped_egid, dropped_gid)
+ os.setresuid(dropped_uid, dropped_euid, dropped_uid)
+ os.setgid(dropped_gid)
+ os.setegid(dropped_egid)
+ os.setuid(dropped_uid)
+ os.seteuid(dropped_euid)
+
+ try:
+ af = open(ARM_CONFIG_FILE) # this is totally unpriv'ed
+
+ # ensure that the fd we opened has the properties we requrie
+ configStat = os.fstat(af.fileno()) # this happens on the unpriv'ed FD
+ if configStat.st_gid != dropped_gid:
+ print "Arm's configuration file (%s) must be owned by the group %s" % (ARM_CONFIG_FILE, GROUP)
+ sys.exit(1)
+
+ # if everything checks out, we're as safe as we're going to get
+ armConfig = af.read(1024 * 1024) # limited read but not too limited
+ af.close()
+ tf.file.write(armConfig)
+ tf.flush()
+ except:
+ print "Unable to open the arm config as unpriv'ed user"
+ sys.exit(1)
+ finally:
+ tf.close()
+ sys.exit(0)
+ else:
+ # If we're here, we're in the parent waiting for the child's death
+ # man, unix is really weird...
+ _, status = os.waitpid(fork_pid, 0)
+
+ if status != 0:
+ print "The child seems to have failed; exiting!"
+ tf.close()
+ sys.exit(1)
+
+ # attempt to verify that the config is OK
+ if os.path.exists(tf.name):
+ # construct our SU string
+ SUSTRING = "su -c 'tor --verify-config -f " + str(tf.name) + "' " + USER
+ # We raise privs to drop them with 'su'
+ os.setuid(0)
+ os.seteuid(0)
+ os.setgid(0)
+ os.setegid(0)
+ # We drop privs here and exec tor to verify it as the dropped_uid
+ print "Using Tor to verify that arm will not break Tor's config:"
+ success = os.system(SUSTRING)
+ if success != 0:
+ print "Tor says the new configuration file is invalid: %s (%s)" % (ARM_CONFIG_FILE, tf.name)
+ sys.exit(1)
+
+ # backup the previous tor config
+ if os.path.exists(TOR_CONFIG_FILE):
+ try:
+ backupFilename = "%s_backup_%i" % (TOR_CONFIG_FILE, int(time.time()))
+ shutil.copy(TOR_CONFIG_FILE, backupFilename)
+ except IOError, exc:
+ print "Unable to backup %s (%s)" % (TOR_CONFIG_FILE, exc)
+ sys.exit(1)
+
+ # overwrites TOR_CONFIG_FILE with ARM_CONFIG_FILE as loaded into tf.name
+ try:
+ shutil.copy(tf.name, TOR_CONFIG_FILE)
+ print "Successfully reconfigured Tor"
+ except IOError, exc:
+ print "Unable to copy %s to %s (%s)" % (tf.name, TOR_CONFIG_FILE, exc)
+ sys.exit(1)
+
+ # unlink our temp file
+ try:
+ os.remove(tf.name)
+ except:
+ print "Unable to close temp file %s" % tf.name
+ sys.exit(1)
+
+ sys.exit(0)
+
+if __name__ == "__main__":
+ # sanity check that we're on linux
+ if os.name != "posix":
+ print "This is a script specifically for configuring Linux"
+ sys.exit(1)
+
+ # check that we're running effectively as root
+ if os.geteuid() != 0:
+ print "This script needs to be run as root"
+ sys.exit(1)
+
+ if len(sys.argv) < 2:
+ replaceTorrc()
+ elif len(sys.argv) == 2 and sys.argv[1] == "--init":
+ init()
+ elif len(sys.argv) == 2 and sys.argv[1] == "--remove":
+ remove()
+ else:
+ print HELP_MSG
+ sys.exit(1)
+
[View Less]
commit 4f88292730be74ede753b2bdc9c1fdcbb9437106
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sat Aug 6 16:14:07 2011 -0700
fix: detecting for /var/lib/tor-arm
The '/var/lib/tor-arm' directory lack read permissions for the user we're
running as, so checking for '/var/lib/tor-arm/torrc' always fails. This is
just meant to determine if we're run the 'override.py --init' prep so detecting
for the directory is fine.
---
src/cli/wizard.py | 2 +-
1 …
[View More]files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/cli/wizard.py b/src/cli/wizard.py
index 6d9d488..ff4e5cf 100644
--- a/src/cli/wizard.py
+++ b/src/cli/wizard.py
@@ -320,7 +320,7 @@ def showWizard():
# 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):
+ if not os.path.exists(os.path.dirname(SYSTEM_DROP_PATH)) or not os.path.exists(OVERRIDE_SCRIPT):
disabledOpt.append(Options.SYSTEM)
while True:
[View Less]
commit 4a1604958c6da5862c344f4d7ba6f0e0560daa23
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sat Aug 6 15:35:00 2011 -0700
fix: avoiding setresuid/gid if unavailable
The os.setresuid and os.setresgid functions are only available in Python 2.7
and later. Arm aims for 2.5 compatability so using os.setreuid/gid if running
a prior version. This, unfortunately, means that the saved uid is not reduced
which might be a vulnerability - hopefully Jake will …
[View More]know of an alternative if
this is a concern.
---
src/resources/torrcOverride/override.py | 26 +++++++++++++++++++++++---
1 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/src/resources/torrcOverride/override.py b/src/resources/torrcOverride/override.py
index b99ae95..8261eab 100755
--- a/src/resources/torrcOverride/override.py
+++ b/src/resources/torrcOverride/override.py
@@ -145,6 +145,13 @@ def remove():
print " unsuccessful: %s" % exc
def replaceTorrc():
+ # TODO: The setresgid and setresuid functions are only available in
+ # python 2.7 (arm aims for 2.5 compatability). I'm not spotting a method
+ # for setting the saved user id without it, though. :/
+
+ majorVersion, minorVersion = sys.version_info[:2]
+ canSetSavedUid = majorVersion >= 3 or (majorVersion == 2 and minorVersion >= 7)
+
orig_uid = os.getuid()
orig_euid = os.geteuid()
@@ -168,7 +175,13 @@ def replaceTorrc():
# drop to the unprivileged group, and lose the rest of the groups
os.setgid(dropped_gid)
os.setegid(dropped_egid)
- os.setresgid(dropped_gid, dropped_egid, dropped_gid)
+
+ if canSetSavedUid:
+ # only usable in python 2.7 or later
+ os.setresgid(dropped_gid, dropped_egid, dropped_gid)
+ else:
+ os.setregid(dropped_gid, dropped_egid)
+
os.setgroups([dropped_gid])
# make a tempfile and write out the contents
@@ -192,8 +205,15 @@ def replaceTorrc():
# I believe this drops os.setfsuid os.setfsgid stuff
# Clear all other supplemental groups for dropped_uid
os.setgroups([dropped_gid])
- os.setresgid(dropped_gid, dropped_egid, dropped_gid)
- os.setresuid(dropped_uid, dropped_euid, dropped_uid)
+
+ if canSetSavedUid:
+ # only usable in python 2.7 or later
+ os.setresgid(dropped_gid, dropped_egid, dropped_gid)
+ os.setresuid(dropped_uid, dropped_euid, dropped_uid)
+ else:
+ os.setregid(dropped_gid, dropped_egid)
+ os.setreuid(dropped_uid, dropped_euid)
+
os.setgid(dropped_gid)
os.setegid(dropped_egid)
os.setuid(dropped_uid)
[View Less]
commit ec49c74ba52d9410d6f108a4e76dfad063d40500
Author: Damian Johnson <atagar(a)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(…
[View More]-)
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)
[View Less]