From ecd7d470831c61bc78e33cdbc786937eed0fa2d1 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Fri, 11 Apr 2008 19:07:41 +0000 Subject: anytun-controld: bind to option ctr: daemonize, chroot drop privs --- anymuxOptions.cpp | 126 +++++++++++++++++++++++++++++++++++++++++++++++----- anymuxOptions.h | 27 ++++++++--- anytun-controld.cpp | 84 +++++++++++++++++++++++++++++++++-- anytun.cpp | 2 +- 4 files changed, 218 insertions(+), 21 deletions(-) diff --git a/anymuxOptions.cpp b/anymuxOptions.cpp index 92726e7..418eebd 100644 --- a/anymuxOptions.cpp +++ b/anymuxOptions.cpp @@ -52,9 +52,15 @@ Options& Options::instance() Options::Options() { - progname_ = "anymux"; - local_port_ = 1234; + progname_ = "anytun-controld"; file_name_ = ""; + daemonize_ = true; + chroot_ = false; + username_ = "nobody"; + chroot_dir_ = "/var/run/anytun-controld"; + pid_file_ = ""; + bind_to_addr_ = "127.0.0.1"; + bind_to_port_ = 4445; } Options::~Options() @@ -128,6 +134,7 @@ bool Options::parse(int argc, char* argv[]) progname_ = argv[0]; argc--; + std::string control_host(""); for(int i=1; argc > 0; ++i) { std::string str(argv[i]); @@ -135,28 +142,50 @@ bool Options::parse(int argc, char* argv[]) if(str == "-h" || str == "--help") return false; - PARSE_SCALAR_PARAM("-p","--port", local_port_) PARSE_SCALAR_PARAM("-f","--file", file_name_) + 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("-P","--write-pid", pid_file_) + PARSE_SCALAR_PARAM("-X","--control-host", control_host) else return false; } + if(control_host != "") { + std::stringstream tmp_stream(control_host); + getline(tmp_stream,bind_to_addr_,':'); + if(!tmp_stream.good()) + return false; + tmp_stream >> bind_to_port_; + } + return true; } void Options::printUsage() { std::cout << "USAGE:" << std::endl; - std::cout << "anymux [-h|--help] prints this..." << std::endl; - std::cout << " [-p|--port] local port to bind to" << std::endl; - std::cout << " [-f|--file] path to file" << std::endl; + std::cout << "anytun-controld [-h|--help] prints this..." << std::endl; + 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 << " [-P|--write-pid] write pid to this file" << std::endl; + std::cout << " [-f|--file] path to file" << std::endl; + } void Options::printOptions() { Lock lock(mutex); std::cout << "Options:" << std::endl; - std::cout << "local_port='" << local_port_ << "'" << std::endl; + std::cout << "daemonize=" << daemonize_ << std::endl; + std::cout << "chroot=" << chroot_ << std::endl; + std::cout << "username='" << username_ << "'" << std::endl; + std::cout << "chroot_dir='" << chroot_dir_ << "'" << std::endl; + std::cout << "pid_file='" << pid_file_ << "'" << std::endl; } std::string Options::getProgname() @@ -173,13 +202,73 @@ Options& Options::setProgname(std::string p) return *this; } +bool Options::getDaemonize() +{ + return daemonize_; +} + +Options& Options::setDaemonize(bool d) +{ + daemonize_ = d; + return *this; +} + +bool Options::getChroot() +{ + return chroot_; +} + +Options& Options::setChroot(bool c) +{ + chroot_ = c; + return *this; +} + +std::string Options::getUsername() +{ + Lock lock(mutex); + return username_; +} + +Options& Options::setUsername(std::string u) +{ + Lock lock(mutex); + username_ = u; + return *this; +} + +std::string Options::getChrootDir() +{ + Lock lock(mutex); + return chroot_dir_; +} + +Options& Options::setChrootDir(std::string c) +{ + Lock lock(mutex); + chroot_dir_ = c; + return *this; +} + +std::string Options::getPidFile() +{ + Lock lock(mutex); + return pid_file_; +} + +Options& Options::setPidFile(std::string p) +{ + Lock lock(mutex); + pid_file_ = p; + return *this; +} + std::string Options::getFileName() { Lock lock(mutex); return file_name_; } - Options& Options::setFileName(std::string f) { Lock lock(mutex); @@ -187,13 +276,26 @@ Options& Options::setFileName(std::string f) return *this; } -u_int16_t Options::getLocalPort() +std::string Options::getBindToAddr() +{ + Lock lock(mutex); + return bind_to_addr_; +} + +Options& Options::setBindToAddr(std::string b) +{ + Lock lock(mutex); + bind_to_addr_ = b; + return *this; +} + +uint16_t Options::getBindToPort() { - return local_port_; + return bind_to_port_; } -Options& Options::setLocalPort(u_int16_t l) +Options& Options::setBindToPort(uint16_t b) { - local_port_ = l; + bind_to_port_ = b; return *this; } diff --git a/anymuxOptions.h b/anymuxOptions.h index 45e6a93..dfbc213 100644 --- a/anymuxOptions.h +++ b/anymuxOptions.h @@ -36,8 +36,6 @@ #include "threadUtils.hpp" #include - - class Options { public: @@ -47,12 +45,25 @@ public: void printUsage(); void printOptions(); - u_int16_t getLocalPort(); - Options& setLocalPort(u_int16_t l); std::string getProgname(); 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 getChrootDir(); + Options& setChrootDir(std::string c); + std::string getPidFile(); + Options& setPidFile(std::string p); std::string getFileName(); Options& setFileName(std::string f); + std::string getBindToAddr(); + Options& setBindToAddr(std::string b); + uint16_t getBindToPort(); + Options& setBindToPort(uint16_t b); + private: Options(); @@ -72,8 +83,14 @@ private: Mutex mutex; + std::string bind_to_addr_; + uint16_t bind_to_port_; std::string progname_; - u_int16_t local_port_; + bool daemonize_; + bool chroot_; + std::string username_; + std::string chroot_dir_; + std::string pid_file_; std::string file_name_; }; diff --git a/anytun-controld.cpp b/anytun-controld.cpp index ff5db52..204694e 100644 --- a/anytun-controld.cpp +++ b/anytun-controld.cpp @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include #include "datatypes.h" @@ -46,7 +49,8 @@ class ThreadParam { public: - ThreadParam() : port(0) {}; + ThreadParam() : addr(""), port(0) {}; + std::string addr; u_int16_t port; }; @@ -57,7 +61,7 @@ void* syncListener(void* p ) SOCKETS_NAMESPACE::SocketHandler h; SOCKETS_NAMESPACE::ListenSocket l(h,true); - if( l.Bind(param->port) ) + if( l.Bind(param->addr, param->port) ) pthread_exit(NULL); Utility::ResolveLocal(); // resolve local hostname @@ -67,6 +71,60 @@ void* syncListener(void* p ) h.Select(1,0); } } + +void chrootAndDrop(std::string const& chrootdir, std::string const& username) +{ + if (getuid() != 0) + { + std::cerr << "this programm has to be run as root in order to run in a chroot" << std::endl; + exit(-1); + } + + 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); + } + cLog.msg(Log::PRIO_NOTICE) << "we are in chroot jail (" << chrootdir << ") now" << std::endl; + chdir("/"); + 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); + } + 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); + } +} + +void daemonize() +{ + pid_t pid; + + pid = fork(); + if(pid) exit(0); + setsid(); + pid = fork(); + if(pid) exit(0); + +// std::cout << "running in background now..." << std::endl; + + int fd; +// for (fd=getdtablesize();fd>=0;--fd) // close all file descriptors + for (fd=0;fd<=2;fd++) // close all file descriptors + close(fd); + fd=open("/dev/null",O_RDWR); // stdin + dup(fd); // stdout + dup(fd); // stderr + umask(027); +} + int main(int argc, char* argv[]) { if(!gOpt.parse(argc, argv)) @@ -84,11 +142,31 @@ int main(int argc, char* argv[]) exit(-1); } + std::ofstream pidFile; + if(gOpt.getPidFile() != "") { + pidFile.open(gOpt.getPidFile().c_str()); + if(!pidFile.is_open()) { + std::cout << "can't open pid file" << std::endl; + } + } + + if(gOpt.getChroot()) + chrootAndDrop(gOpt.getChrootDir(), gOpt.getUsername()); + if(gOpt.getDaemonize()) + daemonize(); + + if(pidFile.is_open()) { + pid_t pid = getpid(); + pidFile << pid; + pidFile.close(); + } + SignalController sig; sig.init(); ThreadParam p; - p.port = gOpt.getLocalPort(); + p.addr = gOpt.getBindToAddr(); + p.port = gOpt.getBindToPort(); pthread_t syncListenerThread; pthread_create(&syncListenerThread, NULL, syncListener, &p); diff --git a/anytun.cpp b/anytun.cpp index a309f67..5100ab8 100644 --- a/anytun.cpp +++ b/anytun.cpp @@ -342,7 +342,7 @@ bool initLibGCrypt() return true; } -void chrootAndDrop(string const& chrootdir, string const& username) +void chrootAndDrop(std::string const& chrootdir, std::string const& username) { if (getuid() != 0) { -- cgit v1.2.3