diff options
Diffstat (limited to 'src/posix/posixDaemon.cpp')
-rw-r--r-- | src/posix/posixDaemon.cpp | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/posix/posixDaemon.cpp b/src/posix/posixDaemon.cpp new file mode 100644 index 0000000..4b4f63b --- /dev/null +++ b/src/posix/posixDaemon.cpp @@ -0,0 +1,160 @@ +/* + * anytun + * + * The secure anycast tunneling protocol (satp) defines a protocol used + * for communication between any combination of unicast and anycast + * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel + * mode and allows tunneling of every ETHER TYPE protocol (e.g. + * ethernet, ip, arp ...). satp directly includes cryptography and + * message authentication based on the methodes used by SRTP. It is + * intended to deliver a generic, scaleable and secure solution for + * tunneling and relaying of packets of any protocol. + * + * + * Copyright (C) 2007-2009 Othmar Gsenger, Erwin Nindl, + * Christian Pointner <satp@wirdorange.org> + * + * This file is part of Anytun. + * + * Anytun is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * Anytun is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with anytun. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <poll.h> +#include <fcntl.h> +#include <pwd.h> +#include <grp.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "daemonService.h" +#include "log.h" +#include "options.h" +#include "anytunError.h" + +DaemonService::DaemonService() : pw_(NULL), gr_(NULL), daemonized_(false) +{ +} + +void DaemonService::initPrivs(std::string const& username, std::string const& groupname) +{ + if(username == "") + return; + + pw_ = getpwnam(username.c_str()); + if(!pw_) + AnytunError::throwErr() << "unknown user " << username; + + if(groupname != "") + gr_ = getgrnam(groupname.c_str()); + else + gr_ = getgrgid(pw_->pw_gid); + + if(!gr_) + AnytunError::throwErr() << "unknown group " << groupname; +} + +void DaemonService::dropPrivs() +{ + if(!pw_ || !gr_) + return; + + if(setgid(gr_->gr_gid)) + AnytunError::throwErr() << "setgid('" << gr_->gr_name << "') failed: " << AnytunErrno(errno); + + gid_t gr_list[1]; + gr_list[0] = gr_->gr_gid; + if(setgroups (1, gr_list)) + AnytunError::throwErr() << "setgroups(['" << gr_->gr_name << "']) failed: " << AnytunErrno(errno); + + if(setuid(pw_->pw_uid)) + AnytunError::throwErr() << "setuid('" << pw_->pw_name << "') failed: " << AnytunErrno(errno); + + cLog.msg(Log::PRIO_NOTICE) << "dropped privileges to " << pw_->pw_name << ":" << gr_->gr_name; +} + +void DaemonService::chroot(std::string const& chrootdir) +{ + if (getuid() != 0) + AnytunError::throwErr() << "this program has to be run as root in order to run in a chroot"; + + if(::chroot(chrootdir.c_str())) + AnytunError::throwErr() << "can't chroot to " << chrootdir; + + cLog.msg(Log::PRIO_NOTICE) << "we are in chroot jail (" << chrootdir << ") now" << std::endl; + if(chdir("/")) + AnytunError::throwErr() << "can't change to /"; +} + +void DaemonService::daemonize() +{ + std::ofstream pidFile; + if(gOpt.getPidFile() != "") { + pidFile.open(gOpt.getPidFile().c_str()); + if(!pidFile.is_open()) + AnytunError::throwErr() << "can't open pid file (" << gOpt.getPidFile() << "): " << AnytunErrno(errno); + } + + pid_t pid; + + pid = fork(); + if(pid < 0) + AnytunError::throwErr() << "daemonizing failed at fork(): " << AnytunErrno(errno) << ", exitting"; + + if(pid) exit(0); + + umask(0); + + if(setsid() < 0) + AnytunError::throwErr() << "daemonizing failed at setsid(): " << AnytunErrno(errno) << ", exitting"; + + pid = fork(); + if(pid < 0) + AnytunError::throwErr() << "daemonizing failed at fork(): " << AnytunErrno(errno) << ", exitting"; + + if(pid) exit(0); + + if ((chdir("/")) < 0) + AnytunError::throwErr() << "daemonizing failed at chdir(): " << AnytunErrno(errno) << ", exitting"; + +// 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 + if(fd == -1) + cLog.msg(Log::PRIO_WARNING) << "can't open /dev/null as stdin"; + else { + if(dup(fd) == -1) // stdout + cLog.msg(Log::PRIO_WARNING) << "can't open /dev/null as stdout"; + if(dup(fd) == -1) // stderr + cLog.msg(Log::PRIO_WARNING) << "can't open /dev/null as stderr"; + } + + if(pidFile.is_open()) { + pid_t pid = getpid(); + pidFile << pid; + pidFile.close(); + } + + setpgid(0, 0); + daemonized_ = true; +} + +bool DaemonService::isDaemonized() +{ + return daemonized_; +} |