#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; // This program runs a script as a different user. // It sets the ruid and rgid ("real" uid and gid) // to be equal to the euid and egid ("effective" // uid and gid). It checks that the owner/group // of the script is the same as this binary first // and that the script is executable. // This is needed since Linux does not honor the suid // settings for scripts as a security measure. void Usage(string binowner="", string bingroup="") { cout << endl; cout << "Usage:" << endl; cout << " hdrun_script script [arg1 arg2 ...]" << endl; cout << endl; cout << " Run a script as the owner of that script." << endl; cout << "The owner of the script must match the" << endl; cout << "owner of this binary and have the suid" << endl; cout << "bit set. This partially re-enables a " << endl; cout << "functionality Linux removed of using suid" << endl; cout << "with scripts." << endl; cout << endl; cout << "This binary can run scripts owned by:" << endl; cout << endl; cout << " " << binowner << ":" << bingroup << endl; cout << endl; exit(-1); } int main(int narg, char *argv[]) { // Get owner and group of this binary struct passwd *pwd = getpwuid(geteuid()); struct group *grp = getgrgid(getegid()); string binowner = pwd->pw_name; string bingroup = grp->gr_name; // Get args for script command vector args; bool is_script_command = false; // set when we start copying script and arguments for(int i=1; ipw_name; string scriptgroup = grp->gr_name; // Make sure script has setuid and setgid bits set if( !(info.st_mode&S_ISUID) ){ cerr << endl << "ERROR: The setuid bit is not set on " << script << "!" << endl << endl; exit(-5); } if( !(info.st_mode&S_ISGID) ){ cerr << endl << "ERROR: The setgid bit is not set on " << script << "!" << endl << endl; exit(-5); } // Make sure owner and group of script we are running // matches euid of this binary. if( binowner!=scriptowner ){ cerr << endl << "ERROR: Owner of this binary and script must match! (" << binowner <<" != " << scriptowner << ")" << endl << endl; exit(-3); } if( bingroup!=scriptgroup ){ cerr << endl << "ERROR: Group ID of this binary and script must match! (" << bingroup <<" != " << scriptgroup << ")" << endl << endl; exit(-4); } // Set real id and group setreuid(geteuid(), -1); setregid(getegid(), -1); // Make single command string cmd; for(auto s : args) cmd += s + " "; //cout << "script command: " << cmd << endl; return system(cmd.c_str()); }