I want to run process as a different user in Linux with its personal rights. In server program I ask user to enter login and password to get an access to the system. Next I have to run client program as another user to separate workspaces and provide the authentication. Then client program is supposed to send and receive messages from server via Linux IPC sockets. I have found some ways to run a program as another user:
int pid = fork();
if(pid == 0) // child
{
int ret = system("sudo -u username ./client.out");
}
else if(pid > 0) // server
{
// communicate with client via socket
}
else {
exit(EXIT_FAILURE);
}
But it does not use password. My question is how to run a program as another user and pass a password? Also using system
command is not a good solution. sudo
is a command line program, but I have to call it from C. How to run another program properly in C?
I don't have privileges to comment, so I'll write this as an answer. One way to do it would be to prompt for a password and validate it yourself, then fork and set the new user for that process. You can check Given a linux username and a password how can I test if it is a valid account? to see how to validate a password, basically it's generating a hash for the password you have, reading the hash for the user inside /etc/shadow, and comparing both of them. For switching the user, you need to call setuid and setgid(which sets the groupid). Check this answer: Linux C programming execute as user
You can get the uid and gid for a user from /etc/password. A sample entry in that file would be:
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
The third field is the userid, the fourth field is the groupid, in this case 39 and 39. After calling setuid, your process will be running under the new user's identity. Then you can start whatever process you want. For this to work, your program must have the setuid bit on.
Edit:
You don't need to set the setuid bit in the executable if you run it as root.
Since you're using fork() already, you may want to call any variant of exec() instead of system(), as system() will create an additional process. See Difference between "system" and "exec" in Linux?
You can use getpwdnam() to read /etc/passwd as it will parse the fields for you. See How to get linux user id by user name?