From e8174227dec7cb107600a227647fa1abedcb5e63 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Fri, 30 Jan 2009 18:26:31 +0000 Subject: droping privileges is now possible without chroot added groupname command line option --- cmd-option-letters | 10 +++--- src/anytun-controld.cpp | 15 +++++---- src/anytun.cpp | 12 ++++--- src/daemon.hpp | 89 +++++++++++++++++++++++++++++++++++-------------- src/options.cpp | 36 ++++++++++---------- src/options.h | 6 ++-- 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 + #include #include #include @@ -41,39 +43,76 @@ #include #include -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] if chroot change to this user" << std::endl; - std::cout << " [-H|--chroot-dir] chroot to this directory" << std::endl; + std::cout << " [-u|--username] change to this user" << std::endl; + std::cout << " [-g|--groupname] change to this group" << std::endl; + std::cout << " [-C|--chroot-dir] chroot to this directory" << std::endl; std::cout << " [-P|--write-pid] 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_; -- cgit v1.2.3