From: Thomas Jarosch Date: Mon, 7 Apr 2008 16:49:34 +0000 (+0000) Subject: libi2ncommon: (tomj) implemented drop_root_priviledges using new User/Group classes X-Git-Tag: v2.6~182 X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=90246b4a7e51d5baeeb5fbbc8ffb4f5e5b3af9af;p=libi2ncommon libi2ncommon: (tomj) implemented drop_root_priviledges using new User/Group classes --- diff --git a/src/Makefile.am b/src/Makefile.am index 6c8882a..ced5609 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,9 +4,9 @@ INCLUDES = -I$(top_srcdir)/src @LIBGETTEXT_CFLAGS@ @LIBICONV_CFLAGS@ $(all_inclu # the library search path. lib_LTLIBRARIES = libi2ncommon.la -include_HEADERS = containerfunc.hpp daemonfunc.hxx filefunc.hxx \ +include_HEADERS = containerfunc.hpp daemonfunc.hpp filefunc.hxx \ insocketstream.hxx ip_type.hxx ipfunc.hxx logread.hxx oftmpstream.hxx pidfile.hpp \ - pipestream.hxx stringfunc.hxx timefunc.hxx userfunc.hxx + pipestream.hxx stringfunc.hxx timefunc.hxx userfunc.hpp libi2ncommon_la_SOURCES = containerfunc.cpp daemonfunc.cpp filefunc.cpp \ ipfunc.cpp logread.cpp oftmpstream.cpp pidfile.cpp stringfunc.cpp timefunc.cpp \ userfunc.cpp diff --git a/src/daemonfunc.cpp b/src/daemonfunc.cpp index 979920e..680ef96 100644 --- a/src/daemonfunc.cpp +++ b/src/daemonfunc.cpp @@ -27,41 +27,55 @@ using namespace std; */ void daemonize() { - int pid=fork(); - - if (pid < 0) - { - throw runtime_error("fork() failed"); - } - if (pid > 0) - { - // parent process - exit (0); - } - // pid==0 -> child process: continue + int pid=fork(); + + if (pid < 0) + { + throw runtime_error("fork() failed"); + } + if (pid > 0) + { + // parent process + exit (0); + } + // pid==0 -> child process: continue } /** * Drop root privileges * @param username User to become. Don't change user if empty * @param group Group to become. Don't change group if empty + * @param get_group_from_user Get group GID from user information if group is empty. + * @return true if all is fine, false otherwise */ -void drop_root_privileges(const std::string &username, - const std::string &group) +bool drop_root_privileges(const std::string &username, + const std::string &group, bool get_group_from_user) { -/* - if (!group.empty()) { - if (setgid(daemon::lookup_gid(group))) { - throw runtime_error("Can't change to group " + group); - } - } - - if (!username.empty()) { - if (setuid(daemon::lookup_uid(username))) { - throw runtime_error("Can't change to user " + username); - } - } -*/ + if (!group.empty()) + { + Group my_group(group); + if (!my_group.is_valid()) + return false; + + if (setgid((my_group.Gid))) + return false; + } + + if (!username.empty()) + { + User my_user(username); + if (!my_user.is_valid()) + return false; + + if (get_group_from_user && group.empty()) + { + if (setgid((my_user.Gid))) + return false; + } + + if (setuid(my_user.Uid)) + return false; + } } /** @@ -79,48 +93,48 @@ void drop_root_privileges(const std::string &username, */ bool pid_of(const std::string& name, std::vector< pid_t >& result) { - std::vector< std::string > entries; - std::vector< pid_t > fuzz1_result; - std::vector< pid_t > fuzz2_result; - result.clear(); - if (!get_dir("/proc", entries)) return false; - for(std::vector< std::string >::const_iterator it= entries.begin(); - it != entries.end(); - ++it) - { - pid_t pid; - if (! string_to(*it, pid)) continue; - std::string base_path= std::string("/proc/") + *it; - std::string exe_path= base_path + "/exe"; - I2n::Stat stat(exe_path, false); - if (not stat or not stat.is_link()) continue; - std::string real_exe= read_link(exe_path); - if (real_exe == name) - { - result.push_back( pid ); - continue; - } - - std::string proc_stat= read_file( base_path + "/stat"); - if (proc_stat.empty()) continue; // process vanished - - //TODO some more fuzz tests here?! (cmdline, stat(us)) - - if (basename(real_exe) == name) - { - fuzz2_result.push_back(pid); - continue; - } - } - if (result.empty()) - { - result.swap(fuzz1_result); - } - if (result.empty()) - { - result.swap(fuzz2_result); - } - return true; + std::vector< std::string > entries; + std::vector< pid_t > fuzz1_result; + std::vector< pid_t > fuzz2_result; + result.clear(); + if (!get_dir("/proc", entries)) return false; + for (std::vector< std::string >::const_iterator it= entries.begin(); + it != entries.end(); + ++it) + { + pid_t pid; + if (! string_to(*it, pid)) continue; + std::string base_path= std::string("/proc/") + *it; + std::string exe_path= base_path + "/exe"; + I2n::Stat stat(exe_path, false); + if (not stat or not stat.is_link()) continue; + std::string real_exe= read_link(exe_path); + if (real_exe == name) + { + result.push_back( pid ); + continue; + } + + std::string proc_stat= read_file( base_path + "/stat"); + if (proc_stat.empty()) continue; // process vanished + + //TODO some more fuzz tests here?! (cmdline, stat(us)) + + if (basename(real_exe) == name) + { + fuzz2_result.push_back(pid); + continue; + } + } + if (result.empty()) + { + result.swap(fuzz1_result); + } + if (result.empty()) + { + result.swap(fuzz2_result); + } + return true; } // eo pidOf(const std::string&,std::vector< pid_t >&) } diff --git a/src/daemonfunc.hxx b/src/daemonfunc.hpp similarity index 71% rename from src/daemonfunc.hxx rename to src/daemonfunc.hpp index 14deeb1..e8698b7 100644 --- a/src/daemonfunc.hxx +++ b/src/daemonfunc.hpp @@ -15,12 +15,12 @@ namespace I2n { namespace daemon { - void daemonize(); +void daemonize(); - void drop_root_privileges(const std::string &username, - const std::string &group); +bool drop_root_privileges(const std::string &username, + const std::string &group, bool get_group_from_user=false); - bool pid_of(const std::string& name, std::vector< pid_t >& result); +bool pid_of(const std::string& name, std::vector< pid_t >& result); } } diff --git a/src/filefunc.hxx b/src/filefunc.hxx index b2216af..9de7873 100644 --- a/src/filefunc.hxx +++ b/src/filefunc.hxx @@ -7,7 +7,7 @@ #ifndef __FILEFUNC_HXX #define __FILEFUNC_HXX -#include "userfunc.hxx" +#include "userfunc.hpp" namespace I2n { diff --git a/src/userfunc.cpp b/src/userfunc.cpp index 2930ecd..c11ec20 100644 --- a/src/userfunc.cpp +++ b/src/userfunc.cpp @@ -11,7 +11,7 @@ * */ -#include "userfunc.hxx" +#include "userfunc.hpp" #include #include diff --git a/src/userfunc.hxx b/src/userfunc.hpp similarity index 100% rename from src/userfunc.hxx rename to src/userfunc.hpp diff --git a/test/test_filefunc.cpp b/test/test_filefunc.cpp index e315df3..e011060 100644 --- a/test/test_filefunc.cpp +++ b/test/test_filefunc.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #ifdef NOISEDEBUG #define DOUT(msg) std::cout << msg << std::endl diff --git a/test/test_pidfile.cpp b/test/test_pidfile.cpp index 477072d..815ae85 100644 --- a/test/test_pidfile.cpp +++ b/test/test_pidfile.cpp @@ -52,7 +52,7 @@ public: PidFile pidfile(Filename); bool rtn_write = pidfile.write(); - CPPUNIT_ASSERT_EQUAL(rtn_write, true); + CPPUNIT_ASSERT_EQUAL(true, rtn_write); } void AutoRemoval() @@ -64,8 +64,8 @@ public: } bool exists = I2n::file_exists(Filename); - CPPUNIT_ASSERT_EQUAL(rtn_write, true); - CPPUNIT_ASSERT_EQUAL(exists, false); + CPPUNIT_ASSERT_EQUAL(true, rtn_write); + CPPUNIT_ASSERT_EQUAL(false, exists); } void NoAutoRemoval() @@ -78,8 +78,8 @@ public: bool exists = I2n::file_exists(Filename); I2n::unlink(Filename); - CPPUNIT_ASSERT_EQUAL(rtn_write, true); - CPPUNIT_ASSERT_EQUAL(exists, true); + CPPUNIT_ASSERT_EQUAL(true, rtn_write); + CPPUNIT_ASSERT_EQUAL(true, exists); } void NotRunning() @@ -87,7 +87,7 @@ public: PidFile pidfile(Filename); bool rtn_check = pidfile.check_already_running(); - CPPUNIT_ASSERT_EQUAL(rtn_check, false); + CPPUNIT_ASSERT_EQUAL(false, rtn_check); } void IsAlreadyRunning() @@ -96,13 +96,15 @@ public: bool rtn_file1_check = pidfile1.check_already_running(); bool rtn_file1_write = pidfile1.write(); - CPPUNIT_ASSERT_EQUAL(rtn_file1_check, false); - CPPUNIT_ASSERT_EQUAL(rtn_file1_write, true); + CPPUNIT_ASSERT_EQUAL(false, rtn_file1_check); + CPPUNIT_ASSERT_EQUAL(true, rtn_file1_write); PidFile pidfile2(Filename); - bool rtn_file2_check = pidfile2.check_already_running(); + pid_t my_pid = 0; + bool rtn_file2_check = pidfile2.check_already_running(&my_pid); - CPPUNIT_ASSERT_EQUAL(rtn_file2_check, true); + CPPUNIT_ASSERT_EQUAL(true, rtn_file2_check); + CPPUNIT_ASSERT_EQUAL(getpid(), my_pid); } private: