summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@anytun.org>2009-01-28 23:46:40 +0000
committerChristian Pointner <equinox@anytun.org>2009-01-28 23:46:40 +0000
commit88f0cd597773fe896f9a144088c717f05b19b90f (patch)
treee88180fdebaa0de694e62755682001a83668e3c1
parentreadded phony targets to makefile (diff)
droping privileges without chroot is now possible
-rw-r--r--doc/uanytun.8.txt30
-rw-r--r--src/daemon.h101
-rw-r--r--src/options.c20
-rw-r--r--src/options.h2
-rw-r--r--src/uanytun.c14
5 files changed, 113 insertions, 54 deletions
diff --git a/doc/uanytun.8.txt b/doc/uanytun.8.txt
index 3364294..319a206 100644
--- a/doc/uanytun.8.txt
+++ b/doc/uanytun.8.txt
@@ -11,9 +11,9 @@ SYNOPSIS
*uanytun*
[ *-h|--help* ]
[ *-D|--nodaemonize* ]
-[ *-C|--chroot* ]
[ *-u|--username* <username> ]
-[ *-H|--chroot-dir* <directory> ]
+[ *-g|--groupname* <groupname> ]
+[ *-C|--chroot* <path> ]
[ *-P|--write-pid* <filename> ]
[ *-i|--interface* <ip-address> ]
[ *-p|--port* <port> ]
@@ -56,30 +56,32 @@ passed to the daemon:
-D|--nodaemonize
~~~~~~~~~~~~~~~~
-This option instructs *uAnytun* to run in the foreground
+This option instructs *uAnytun* to run in foreground
instead of becoming a daemon which is the default.
--C|--chroot
-~~~~~~~~~~~
-
-Instruct *uAnytun* to run in a chroot chail and drop privileges. The
-default is not to run in chroot.
-
-u|--username <username>
~~~~~~~~~~~~~~~~~~~~~~~~
-if chroot change to this user. default: nobody
+run as this user. If no group is specified (*-g*) the default group of
+the user is used. The default is to not drop privileges.
--H|--chroot-dir <directory>
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-g|--groupname <groupname>
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+run as this group. If no username is specified (*-u*) this gets ignored.
+The default is to not drop privileges.
+
+-C|--chroot <path>
+~~~~~~~~~~~~~~~~~~
-chroot to this directory. default: /var/run/uanytun
+Instruct *uAnytun* to run in a chroot jail. The default is
+to not run in chroot.
-P|--write-pid <filename>
~~~~~~~~~~~~~~~~~~~~~~~~~
Instruct *uAnytun* to write it's pid to this file. The default is
-not to create a pid file.
+to not create a pid file.
-i|--interface <ip address>
~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/src/daemon.h b/src/daemon.h
index 085f563..4ebc8cd 100644
--- a/src/daemon.h
+++ b/src/daemon.h
@@ -43,38 +43,83 @@
#include <sys/stat.h>
#include <unistd.h>
-void chrootAndDrop(const char* chrootdir, const char* username)
+struct priv_info_struct {
+ struct passwd* pw_;
+ struct group* gr_;
+};
+typedef struct priv_info_struct priv_info_t;
+
+int priv_init(priv_info_t* priv, const char* username, const char* groupname)
{
- if (getuid() != 0)
- {
- fprintf(stderr, "this programm has to be run as root in order to run in a chroot\n");
- exit(-1);
- }
+ if(!priv)
+ return -1;
- struct passwd *pw = getpwnam(username);
- if(pw) {
- if(chroot(chrootdir))
- {
- fprintf(stderr, "can't chroot to %s\n", chrootdir);
- exit(-1);
- }
- log_printf(NOTICE, "we are in chroot jail (%s) now\n", chrootdir);
- if(chdir("/"))
- {
- fprintf(stderr, "can't change to /\n");
- exit(-1);
- }
- if (initgroups(pw->pw_name, pw->pw_gid) || setgid(pw->pw_gid) || setuid(pw->pw_uid))
- {
- fprintf(stderr, "can't drop to user %s %d:%d\n", username, pw->pw_uid, pw->pw_gid);
- exit(-1);
- }
- log_printf(NOTICE, "dropped user to %s %d:%d\n", username, pw->pw_uid, pw->pw_gid);
+ priv->pw_ = NULL;
+ priv->gr_ = NULL;
+
+ priv->pw_ = getpwnam(username);
+ if(!priv->pw_) {
+ log_printf(ERR, "unkown user %s", username);
+ return -1;
}
+
+ if(groupname)
+ priv->gr_ = getgrnam(groupname);
else
- {
- fprintf(stderr, "unknown user %s\n", username);
- exit(-1);
+ priv->gr_ = getgrgid(priv->pw_->pw_gid);
+
+ if(!priv->gr_) {
+ log_printf(ERR, "unkown group %s", groupname);
+ return -1;
+ }
+
+ return 0;
+}
+
+int priv_drop(priv_info_t* priv)
+{
+ if(!priv || !priv->pw_ || !priv->gr_) {
+ log_printf(ERR, "privileges not initialized properly");
+ return -1;
+ }
+
+ if(setgid(priv->gr_->gr_gid)) {
+ log_printf(ERR, "setgid('%s') failed: %m", priv->gr_->gr_name);
+ return -1;
+ }
+
+ gid_t gr_list[1];
+ gr_list[0] = priv->gr_->gr_gid;
+ if(setgroups (1, gr_list)) {
+ log_printf(ERR, "setgroups(['%s']) failed: %m", priv->gr_->gr_name);
+ return -1;
+ }
+
+ if(setuid(priv->pw_->pw_uid)) {
+ log_printf(ERR, "setuid('%s') failed: %m", priv->pw_->pw_name);
+ return -1;
+ }
+
+ log_printf(NOTICE, "dropped privileges to %s:%s", priv->pw_->pw_name, priv->gr_->gr_name);
+ return 0;
+}
+
+
+int do_chroot(const char* chrootdir)
+{
+ if(getuid() != 0) {
+ log_printf(ERR, "this programm has to be run as root in order to run in a chroot");
+ return -1;
+ }
+
+ if(chroot(chrootdir)) {
+ log_printf(ERR, "can't chroot to %s: %m", chrootdir);
+ return -1;
+ }
+ log_printf(NOTICE, "we are in chroot jail (%s) now", chrootdir);
+ if(chdir("/")) {
+ log_printf(ERR, "can't change to /: %m");
+ return -1;
}
}
diff --git a/src/options.c b/src/options.c
index 9931c51..843cd4a 100644
--- a/src/options.c
+++ b/src/options.c
@@ -180,9 +180,9 @@ int options_parse(options_t* opt, int argc, char* argv[])
if(!strcmp(str,"-h") || !strcmp(str,"--help"))
return -1;
PARSE_INVERSE_BOOL_PARAM("-D","--nodaemonize", opt->daemonize_)
- PARSE_BOOL_PARAM("-C","--chroot", opt->chroot_)
PARSE_STRING_PARAM("-u","--username", opt->username_)
- PARSE_STRING_PARAM("-H","--chroot-dir", opt->chroot_dir_)
+ PARSE_STRING_PARAM("-g","--groupname", opt->groupname_)
+ PARSE_STRING_PARAM("-C","--chroot", opt->chroot_dir_)
PARSE_STRING_PARAM("-P","--write-pid", opt->pid_file_)
PARSE_STRING_PARAM("-i","--interface", opt->local_addr_)
PARSE_STRING_PARAM("-p","--port", opt->local_port_)
@@ -236,9 +236,9 @@ void options_default(options_t* opt)
opt->progname_ = strdup("uanytun");
opt->daemonize_ = 1;
- opt->chroot_ = 0;
- opt->username_ = strdup("nobody");
- opt->chroot_dir_ = strdup("/var/run/uanytun");
+ opt->username_ = NULL;
+ opt->groupname_ = NULL;
+ opt->chroot_dir_ = NULL;
opt->pid_file_ = NULL;
opt->local_addr_ = NULL;
opt->local_port_ = strdup("4444");
@@ -276,6 +276,8 @@ void options_clear(options_t* opt)
free(opt->progname_);
if(opt->username_)
free(opt->username_);
+ if(opt->groupname_)
+ free(opt->groupname_);
if(opt->chroot_dir_)
free(opt->chroot_dir_);
if(opt->pid_file_)
@@ -319,9 +321,9 @@ void options_print_usage()
printf("USAGE:\n");
printf("uanytun [-h|--help] prints this...\n");
printf(" [-D|--nodaemonize] don't run in background\n");
- printf(" [-C|--chroot] chroot and drop privileges\n");
- printf(" [-u|--username] <username> if chroot change to this user\n");
- printf(" [-H|--chroot-dir] <path> chroot to this directory\n");
+ printf(" [-u|--username] <username> change to this user\n");
+ printf(" [-g|--groupname] <groupname> change to this group\n");
+ printf(" [-C|--chroot] <path> chroot to this directory\n");
printf(" [-P|--write-pid] <path> write pid to this file\n");
printf(" [-i|--interface] <ip-address> local ip address to bind to\n");
printf(" [-p|--port] <port> local port to bind to\n");
@@ -352,8 +354,8 @@ void options_print(options_t* opt)
{
printf("progname: '%s'\n", opt->progname_);
printf("daemonize: %d\n", opt->daemonize_);
- printf("chroot: %d\n", opt->chroot_);
printf("username: '%s'\n", opt->username_);
+ printf("groupname: '%s'\n", opt->groupname_);
printf("chroot_dir: '%s'\n", opt->chroot_dir_);
printf("pid_file: '%s'\n", opt->pid_file_);
printf("local_addr: '%s'\n", opt->local_addr_);
diff --git a/src/options.h b/src/options.h
index b1695a8..4186055 100644
--- a/src/options.h
+++ b/src/options.h
@@ -38,8 +38,8 @@
struct options_struct {
char* progname_;
int daemonize_;
- int chroot_;
char* username_;
+ char* groupname_;
char* chroot_dir_;
char* pid_file_;
char* local_addr_;
diff --git a/src/uanytun.c b/src/uanytun.c
index d1919d6..48cc020 100644
--- a/src/uanytun.c
+++ b/src/uanytun.c
@@ -341,6 +341,11 @@ int main(int argc, char* argv[])
exit(ret);
}
+ priv_info_t priv;
+ if(opt.username_)
+ if(priv_init(&priv, opt.username_, opt.groupname_))
+ exit(-1);
+
#ifndef NO_CRYPT
#ifndef USE_SSL_CRYPTO
ret = init_libgcrypt();
@@ -395,8 +400,13 @@ int main(int argc, char* argv[])
}
}
- if(opt.chroot_)
- chrootAndDrop("/var/run/", "nobody");
+ if(opt.chroot_dir_)
+ if(do_chroot(opt.chroot_dir_))
+ exit(-1);
+ if(opt.username_)
+ if(priv_drop(&priv))
+ exit(-1);
+
if(opt.daemonize_) {
pid_t oldpid = getpid();
daemonize();