void droproot()

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;
    }
}