commit b05003e808913ec89a206ae9abec7031392e902b Author: Damian Johnson atagar@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 ++++++ 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) +
tor-commits@lists.torproject.org