Come eseguire comandi con privilegi di uno specifico utente in C and Python su Linux

Se avete accesso da root ma avete bisogno di eseguire alcuni applicazioni o script con credenziali di altri utenti potete semplicemente farlo direttamente dalla shell con:

su - username -c "command to execute"

Ma se invece avete bisogno di eseguire tale programma dalla vostra applicazione C/C++ avete bisogno di seguire questa procedura:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>

int main(int argc, char* argv[])
{
        if(argc != 3)
        {
                printf("Usage: %s [USERNAME] [COMMAND]\n",argv[0]);
                return 1;
        }
        char *env[16];
        char envc[16][64];
        struct passwd *pw = getpwnam(argv[1]);
        if(pw==NULL)
        {
                printf("User %s does not exists!\n",argv[1]);
                return 1;
        }

        sprintf(env[0]=envc[0],"TERM=xterm");
        sprintf(env[1]=envc[1],"USER=%s",pw->pw_name);
        sprintf(env[2]=envc[2],"HOME=%s",pw->pw_dir);
        sprintf(env[3]=envc[3],"SHELL=%s",pw->pw_shell);
        sprintf(env[4]=envc[4],"LOGNAME=%s",pw->pw_name);
        sprintf(env[5]=envc[5],"PATH=/usr/bin:/bin:/opt/bin");
        env[6]=0;

        initgroups(argv[1],pw->pw_gid);
        setgid(pw->pw_gid);
        setuid(pw->pw_uid);
        execve(argv[2],NULL,env);

        return 0;
}

Potete compilare ed eseguire il codice in questo modo:

[root@barracuda ~]# gcc mysu.c -o mysu
[root@barracuda ~]# id
uid=0(root) gid=0(root) gruppi=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),19(log)
[root@barracuda ~]# ./mysu matteo /bin/bash
[matteo@barracuda /root]$ id
uid=1000(matteo) gid=100(users) groups=100(users),3(sys),10(wheel),14(uucp),91(video),92(audio),93(optical),95(storage),96(scanner),97(camera),98(power),108(vboxusers)

Lo stesso risultato si puo’ ottenere anche in Python con pochissimo sforzo:

#!/usr/bin/env python

import sys,pwd,os

pw = pwd.getpwnam(sys.argv[1])
os.initgroups(sys.argv[1],pw.pw_gid)
env={"TERM":"xterm","USER":pw.pw_name,"HOME":pw.pw_dir,"SHELL":pw.pw_shell,"LOGNAME":pw.pw_name,"PATH":"/usr/bin:/bin:/opt/bin"};
os.setgid(pw.pw_gid);
os.setuid(pw.pw_uid);
os.execve(sys.argv[2],[],env);