in src/controller/controller.cpp [166:238]
void droproot(const std::string& dropuser)
{
gid_t re_gid = getgid();
gid_t ef_gid = getegid();
uid_t re_uid = getuid();
uid_t ef_uid = geteuid();
gid_t new_gid;
uid_t new_uid;
if(re_gid != ef_gid || re_uid != ef_uid) // suid bit is being set
{
new_gid = re_gid;
new_uid = re_uid;
if(!dropuser.empty())
{
if(utils::Out message{})
{
message << "Note: Ignoring -Z option since SUID bit is set.";
}
}
}
else if(!dropuser.empty())
{
struct passwd* pw = getpwnam(dropuser.c_str()); //get user uid & gid
if(!pw)
{
throw ControllerError{std::string{"The user is not found: "} + dropuser};
}
new_gid = pw->pw_gid;
new_uid = pw->pw_uid;
}
else
{
if(utils::Out message{})
{
message << "Note: It's potentially unsafe to run this program as root "
<< "without dropping root privileges.\n"
<< "Note: Use -Z username option for dropping root privileges "
<< "when you run this program as user with root privileges.";
}
return;
}
try
{
if(setgroups(1, &new_gid) == -1 ||
setgid(new_gid) == -1 ||
setuid(new_uid) == -1)
{
throw ControllerError{std::string{"Error dropping root: "} +
std::string{strerror(errno)}};
}
//check if we've really dropped privileges
if(setuid(0) != -1)
{
throw ControllerError{"Managed to regain root privileges"};
}
}
catch(const ControllerError& e)
{
if(utils::Out message{})
{
message << "Error dropping superuser privileges: " << e.what();
}
throw;
}
}