aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Hazel <sah@freehaven.net>2003-10-22 06:03:11 +0000
committerSteven Hazel <sah@freehaven.net>2003-10-22 06:03:11 +0000
commitb1eca56b77ba1316eb23587341319fbbe2bc6560 (patch)
tree1c38a5d88f170dd0aca2c221d9f2c8343258b304
parent524d63ecc62cc6e1dcaafd0ec2ad507328415c19 (diff)
downloadtor-b1eca56b77ba1316eb23587341319fbbe2bc6560.tar
tor-b1eca56b77ba1316eb23587341319fbbe2bc6560.tar.gz
added User and Group options -- if you set them, tor will try to
setuid and setgid respectively, and die if it can't. (If the User option is set, tor will setgid to the user's gid as well.) This happens after the pidfile is created, so that in cases where tor needs to be root to work with the pidfile, it will at least be able to create it, although it won't be able to delete it. That sucks, but it's somewhat better than not being able to create the pidfile in the first place. svn:r652
-rw-r--r--configure.in2
-rw-r--r--src/or/config.c2
-rw-r--r--src/or/main.c68
-rw-r--r--src/or/or.h8
4 files changed, 75 insertions, 5 deletions
diff --git a/configure.in b/configure.in
index 33d948416..7933cf767 100644
--- a/configure.in
+++ b/configure.in
@@ -130,7 +130,7 @@ LIBS="$saved_LIBS -lcrypto -lssl"
dnl The warning message here is no longer strictly accurate.
-AC_CHECK_HEADERS(unistd.h string.h signal.h netdb.h ctype.h poll.h sys/stat.h sys/poll.h sys/types.h sys/fcntl.h sys/ioctl.h sys/socket.h sys/time.h netinet/in.h arpa/inet.h errno.h assert.h time.h, , AC_MSG_WARN(some headers were not found, compilation may fail))
+AC_CHECK_HEADERS(unistd.h string.h signal.h netdb.h ctype.h poll.h sys/stat.h sys/poll.h sys/types.h sys/fcntl.h sys/ioctl.h sys/socket.h sys/time.h netinet/in.h arpa/inet.h errno.h assert.h time.h pwd.h grp.h, , AC_MSG_WARN(some headers were not found, compilation may fail))
dnl These headers are not essential
diff --git a/src/or/config.c b/src/or/config.c
index 8bc0e17ff..c049b681f 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -162,6 +162,8 @@ static void config_assign(or_options_t *options, struct config_line *list) {
config_compare(list, "ExitPolicy", CONFIG_TYPE_STRING, &options->ExitPolicy) ||
config_compare(list, "SocksBindAddress",CONFIG_TYPE_STRING,&options->SocksBindAddress) ||
config_compare(list, "ORBindAddress", CONFIG_TYPE_STRING, &options->ORBindAddress) ||
+ config_compare(list, "User", CONFIG_TYPE_STRING, &options->User) ||
+ config_compare(list, "Group", CONFIG_TYPE_STRING, &options->Group) ||
/* int options */
config_compare(list, "MaxConn", CONFIG_TYPE_INT, &options->MaxConn) ||
diff --git a/src/or/main.c b/src/or/main.c
index a7bd83adf..1d6511f52 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -599,7 +599,7 @@ static int do_main_loop(void) {
(uint16_t) options.DirPort);
for(;;) {
-#ifndef MS_WIN32 /* do signal stuff only on unix */
+#ifndef MS_WINDOWS /* do signal stuff only on unix */
if(please_dumpstats) {
/* prefer to log it at INFO, but make sure we always see it */
dumpstats(options.loglevel>LOG_INFO ? options.loglevel : LOG_INFO);
@@ -670,14 +670,14 @@ static int do_main_loop(void) {
static void catch(int the_signal) {
-#ifndef MS_WIN32 /* do signal stuff only on unix */
+#ifndef MS_WINDOWS /* do signal stuff only on unix */
switch(the_signal) {
// case SIGABRT:
case SIGTERM:
case SIGINT:
log(LOG_ERR,"Catching signal %d, exiting cleanly.", the_signal);
- /* we don't care if there was an error when we unlink,
- nothing we could do about it anyways */
+ /* we don't care if there was an error when we unlink, nothing
+ we could do about it anyways */
unlink(options.PidFile);
exit(0);
case SIGHUP:
@@ -767,6 +767,7 @@ void daemonize(void) {
}
void write_pidfile(char *filename) {
+#ifndef MS_WINDOWS
FILE *pidfile;
if ((pidfile = fopen(filename, "w")) == NULL) {
@@ -776,6 +777,52 @@ void write_pidfile(char *filename) {
fprintf(pidfile, "%d", getpid());
fclose(pidfile);
}
+#endif
+}
+
+int switch_user(char *user) {
+#ifndef MS_WINDOWS
+ int status;
+ struct passwd *pw = NULL;
+
+ pw = getpwnam(user);
+ if(pw == NULL) {
+ log_fn(LOG_ERR,"User '%s' not found.", user);
+ return -1;
+ }
+ status = setuid(pw->pw_uid);
+ if (status != 0) {
+ log_fn(LOG_ERR,"Error setting UID: %s", strerror(errno));
+ return -1;
+ }
+ status = setgid(pw->pw_gid);
+ if (status != 0) {
+ log_fn(LOG_ERR,"Error setting GID: %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+#endif
+}
+
+int switch_group(char *group) {
+#ifndef MS_WINDOWS
+ int status;
+ struct group *gr = NULL;
+
+ gr = getgrnam(group);
+ if(gr == NULL) {
+ log_fn(LOG_ERR,"Group '%s' not found.", group);
+ return -1;
+ }
+ status = setgid(gr->gr_gid);
+ if (status != 0) {
+ log_fn(LOG_ERR,"Error setting GID: %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+#endif
}
int tor_main(int argc, char *argv[]) {
@@ -802,6 +849,19 @@ int tor_main(int argc, char *argv[]) {
/* write our pid to the pid file */
write_pidfile(options.PidFile);
+ /* now that we've written the pid file, we can switch the user and group */
+ if(options.User) {
+ if(switch_user(options.User) != 0) {
+ return -1;
+ }
+ }
+
+ if(options.Group) {
+ if(switch_group(options.Group) != 0) {
+ return -1;
+ }
+ }
+
if(options.RunAsDaemon)
daemonize();
diff --git a/src/or/or.h b/src/or/or.h
index 85ce9092b..bc96e0869 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -72,6 +72,12 @@
#ifdef HAVE_TIME_H
#include <time.h>
#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
#ifdef HAVE_WINSOCK_H
#include <winsock.h>
#endif
@@ -428,6 +434,8 @@ typedef struct {
char *ExitPolicy;
char *SocksBindAddress;
char *ORBindAddress;
+ char *User;
+ char *Group;
double CoinWeight;
int ORPort;
int SocksPort;