summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd-option-letters10
-rw-r--r--src/anytun-controld.cpp15
-rw-r--r--src/anytun.cpp12
-rw-r--r--src/daemon.hpp89
-rw-r--r--src/options.cpp36
-rw-r--r--src/options.h6
6 files changed, 106 insertions, 62 deletions
diff --git a/cmd-option-letters b/cmd-option-letters
index e9ad440..841a06d 100644
--- a/cmd-option-letters
+++ b/cmd-option-letters
@@ -4,7 +4,7 @@ c: cipher
d: device name
e:
f: input file
-g:
+g: unix group
h: print help text
i: local interface
j:
@@ -18,7 +18,7 @@ q:
r: remote host
s: sender id
t: device type
-u: username when chroot
+u: unix username
v:
w: window size
x: post up script
@@ -27,18 +27,18 @@ z:
A: master salt
B:
-C: run in chroot
+C: chroot directory
D: do not daemonize
E: passphrase
F:
G:
-H: chroot direcotry
+H:
I: local sync interface
J:
K: master key
L:
M: remote sync hosts
-N:
+N:
O:
P: write pid file
Q:
diff --git a/src/anytun-controld.cpp b/src/anytun-controld.cpp
index c73abbd..cff0932 100644
--- a/src/anytun-controld.cpp
+++ b/src/anytun-controld.cpp
@@ -120,12 +120,13 @@ int main(int argc, char* argv[])
std::ifstream file( gOpt.getFileName().c_str() );
if( file.is_open() )
file.close();
- else
- {
+ else {
std::cout << "ERROR: unable to open file!" << std::endl;
exit(-1);
}
+ PrivInfo privs(gOpt.getUsername(), gOpt.getGroupname());
+
std::ofstream pidFile;
if(gOpt.getPidFile() != "") {
pidFile.open(gOpt.getPidFile().c_str());
@@ -134,10 +135,12 @@ int main(int argc, char* argv[])
}
}
- if(gOpt.getChroot())
- chrootAndDrop(gOpt.getChrootDir(), gOpt.getUsername());
- if(gOpt.getDaemonize())
- {
+ if(gOpt.getChrootDir() != "")
+ do_chroot(gOpt.getChrootDir());
+
+ privs.drop();
+
+ if(gOpt.getDaemonize()) {
daemonize();
daemonized = true;
}
diff --git a/src/anytun.cpp b/src/anytun.cpp
index 19c4587..8f6a0c9 100644
--- a/src/anytun.cpp
+++ b/src/anytun.cpp
@@ -346,6 +346,8 @@ int main(int argc, char* argv[])
}
#ifndef NO_DAEMON
+ PrivInfo privs(gOpt.getUsername(), gOpt.getGroupname());
+
std::ofstream pidFile;
if(gOpt.getPidFile() != "") {
pidFile.open(gOpt.getPidFile().c_str());
@@ -412,10 +414,12 @@ int main(int argc, char* argv[])
}
#endif
#ifndef NO_DAEMON
- if(gOpt.getChroot())
- chrootAndDrop(gOpt.getChrootDir(), gOpt.getUsername());
- if(gOpt.getDaemonize())
- {
+ if(gOpt.getChrootDir() != "")
+ do_chroot(gOpt.getChrootDir());
+
+ privs.drop();
+
+ if(gOpt.getDaemonize()) {
daemonize();
daemonized = true;
}
diff --git a/src/daemon.hpp b/src/daemon.hpp
index 0bcd7f3..cc95337 100644
--- a/src/daemon.hpp
+++ b/src/daemon.hpp
@@ -33,6 +33,8 @@
#define _DAEMON_HPP
#ifndef NO_DAEMON
+#include <sstream>
+
#include <poll.h>
#include <fcntl.h>
#include <pwd.h>
@@ -41,39 +43,76 @@
#include <sys/stat.h>
#include <unistd.h>
-void chrootAndDrop(std::string const& chrootdir, std::string const& username)
+#include "log.h"
+
+class PrivInfo
{
- if (getuid() != 0)
+public:
+ PrivInfo(std::string const& username, std::string const& groupname)
{
- std::cerr << "this programm has to be run as root in order to run in a chroot" << std::endl;
- exit(-1);
+ pw_ = NULL;
+ gr_ = NULL;
+
+ if(username == "")
+ return;
+
+ pw_ = getpwnam(username.c_str());
+ if(!pw_)
+ throw std::runtime_error("unkown user " + username);
+
+ if(groupname != "")
+ gr_ = getgrnam(groupname.c_str());
+ else
+ gr_ = getgrgid(pw_->pw_gid);
+
+ if(!gr_)
+ throw std::runtime_error("unkown group " + groupname);
}
- struct passwd *pw = getpwnam(username.c_str());
- if(pw) {
- if(chroot(chrootdir.c_str()))
- {
- std::cerr << "can't chroot to " << chrootdir << std::endl;
- exit(-1);
+ void drop()
+ {
+ if(!pw_ || !gr_)
+ return;
+
+ if(setgid(gr_->gr_gid)) {
+ std::stringstream msg;
+ msg << "setgid('" << gr_->gr_name << "') failed: " << LogErrno(errno);
+ throw std::runtime_error(msg.str());
}
- cLog.msg(Log::PRIO_NOTICE) << "we are in chroot jail (" << chrootdir << ") now" << std::endl;
- if(chdir("/"))
- {
- std::cerr << "can't change to /" << std::endl;
- exit(-1);
+
+ gid_t gr_list[1];
+ gr_list[0] = gr_->gr_gid;
+ if(setgroups (1, gr_list)) {
+ std::stringstream msg;
+ msg << "setgroups(['" << gr_->gr_name << "']) failed: " << LogErrno(errno);
+ throw std::runtime_error(msg.str());
}
- if (initgroups(pw->pw_name, pw->pw_gid) || setgid(pw->pw_gid) || setuid(pw->pw_uid))
- {
- std::cerr << "can't drop to user " << username << " " << pw->pw_uid << ":" << pw->pw_gid << std::endl;
- exit(-1);
+
+ if(setuid(pw_->pw_uid)) {
+ std::stringstream msg;
+ msg << "setuid('" << pw_->pw_name << "') failed: " << LogErrno(errno);
+ throw std::runtime_error(msg.str());
}
- cLog.msg(Log::PRIO_NOTICE) << "dropped user to " << username << " " << pw->pw_uid << ":" << pw->pw_gid << std::endl;
- }
- else
- {
- std::cerr << "unknown user " << username << std::endl;
- exit(-1);
+
+ cLog.msg(Log::PRIO_NOTICE) << "dropped privileges to " << pw_->pw_name << ":" << gr_->gr_name;
}
+
+private:
+ struct passwd* pw_;
+ struct group* gr_;
+};
+
+void do_chroot(std::string const& chrootdir)
+{
+ if (getuid() != 0)
+ throw std::runtime_error("this programm has to be run as root in order to run in a chroot");
+
+ if(chroot(chrootdir.c_str()))
+ throw std::runtime_error("can't chroot to " + chrootdir);
+
+ cLog.msg(Log::PRIO_NOTICE) << "we are in chroot jail (" << chrootdir << ") now" << std::endl;
+ if(chdir("/"))
+ throw std::runtime_error("can't change to /");
}
void daemonize()
diff --git a/src/options.cpp b/src/options.cpp
index ba49711..690630b 100644
--- a/src/options.cpp
+++ b/src/options.cpp
@@ -142,18 +142,16 @@ Options::Options() : key_(u_int32_t(0)), salt_(u_int32_t(0))
{
#if defined(ANYCTR_OPTIONS)
progname_ = "anytun-controld";
- chroot_dir_ = "/var/run/anytun-controld";
#elif defined(ANYCONF_OPTIONS)
progname_ = "anytun-config";
- chroot_dir_ = "/var/run/anytun-config";
#else
progname_ = "anytun";
- chroot_dir_ = "/var/run/anytun";
#endif
daemonize_ = true;
- chroot_ = false;
- username_ = "nobody";
+ username_ = "";
+ groupname_ = "";
+ chroot_dir_ = "";
pid_file_ = "";
file_name_ = "";
@@ -324,9 +322,9 @@ bool Options::parse(int argc, char* argv[])
#ifndef NO_DAEMON
PARSE_INVERSE_BOOL_PARAM("-D","--nodaemonize", daemonize_)
- PARSE_BOOL_PARAM("-C","--chroot", chroot_)
PARSE_SCALAR_PARAM("-u","--username", username_)
- PARSE_SCALAR_PARAM("-H","--chroot-dir", chroot_dir_)
+ PARSE_SCALAR_PARAM("-g","--groupname", groupname_)
+ PARSE_SCALAR_PARAM("-C","--chroot-dir", chroot_dir_)
PARSE_SCALAR_PARAM("-P","--write-pid", pid_file_)
#endif
@@ -427,9 +425,9 @@ void Options::printUsage()
#ifndef NO_DAEMON
std::cout << " [-D|--nodaemonize] don't run in background" << std::endl;
- std::cout << " [-C|--chroot] chroot and drop privileges" << std::endl;
- std::cout << " [-u|--username] <username> if chroot change to this user" << std::endl;
- std::cout << " [-H|--chroot-dir] <path> chroot to this directory" << std::endl;
+ std::cout << " [-u|--username] <username> change to this user" << std::endl;
+ std::cout << " [-g|--groupname] <groupname> change to this group" << std::endl;
+ std::cout << " [-C|--chroot-dir] <path> chroot to this directory" << std::endl;
std::cout << " [-P|--write-pid] <path> write pid to this file" << std::endl;
#endif
@@ -509,8 +507,8 @@ void Options::printOptions()
std::cout << "Options:" << std::endl;
std::cout << std::endl;
std::cout << "daemonize = " << daemonize_ << std::endl;
- std::cout << "chroot = " << chroot_ << std::endl;
std::cout << "username = '" << username_ << "'" << std::endl;
+ std::cout << "groupname = '" << groupname_ << "'" << std::endl;
std::cout << "chroot_dir = '" << chroot_dir_ << "'" << std::endl;
std::cout << "pid_file = '" << pid_file_ << "'" << std::endl;
std::cout << std::endl;
@@ -580,29 +578,29 @@ Options& Options::setDaemonize(bool d)
return *this;
}
-bool Options::getChroot()
+std::string Options::getUsername()
{
ReadersLock lock(mutex);
- return chroot_;
+ return username_;
}
-Options& Options::setChroot(bool c)
+Options& Options::setUsername(std::string u)
{
WritersLock lock(mutex);
- chroot_ = c;
+ username_ = u;
return *this;
}
-std::string Options::getUsername()
+std::string Options::getGroupname()
{
ReadersLock lock(mutex);
- return username_;
+ return groupname_;
}
-Options& Options::setUsername(std::string u)
+Options& Options::setGroupname(std::string g)
{
WritersLock lock(mutex);
- username_ = u;
+ groupname_ = g;
return *this;
}
diff --git a/src/options.h b/src/options.h
index 694526e..e24655f 100644
--- a/src/options.h
+++ b/src/options.h
@@ -88,10 +88,10 @@ public:
Options& setProgname(std::string p);
bool getDaemonize();
Options& setDaemonize(bool d);
- bool getChroot();
- Options& setChroot(bool b);
std::string getUsername();
Options& setUsername(std::string u);
+ std::string getGroupname();
+ Options& setGroupname(std::string g);
std::string getChrootDir();
Options& setChrootDir(std::string c);
std::string getPidFile();
@@ -174,8 +174,8 @@ private:
std::string progname_;
bool daemonize_;
- bool chroot_;
std::string username_;
+ std::string groupname_;
std::string chroot_dir_;
std::string pid_file_;