以 Linux 中的另一个用户身份执行进程

Execute process as another user in Linux

我想 运行 作为 Linux 中的不同用户处理,并具有其个人权利。在服务器程序中,我要求用户输入登录名和密码以访问系统。接下来我必须 运行 客户端程序作为另一个用户来分隔工作区并提供身份验证。然后客户端程序应该通过 Linux IPC 套接字从服务器发送和接收消息。我找到了一些方法 运行 作为另一个用户的程序:

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

但它不使用密码。我的问题是如何运行一个程序作为另一个用户并传递密码?同样使用 system 命令也不是一个好的解决方案。 sudo 是一个命令行程序,但我必须从 C 调用它。如何在 C 中正确地 运行 另一个程序?

我没有评论的权限,所以我会写这个作为答案。 一种方法是提示输入密码并自行验证,然后为该过程分叉并设置新用户。 您可以检查 Given a linux username and a password how can I test if it is a valid account? 以查看如何验证密码,基本上它是为您拥有的密码生成哈希,读取 /etc/shadow 中用户的哈希,然后比较两者。 切换用户需要调用setuid和setgid(设置groupid)。检查这个答案:Linux C programming execute as user

您可以从 /etc/password 获取用户的 uid 和 gid。该文件中的示例条目为:

irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin

第三个字段是userid,第四个字段是groupid,在本例中是39和39。 调用 setuid 后,您的进程将 运行ning 在新用户的身份下。然后你可以开始任何你想要的过程。 为此,您的程序必须打开 setuid 位。

编辑:

如果您 运行 以 root 身份执行,则无需在可执行文件中设置 setuid 位。

由于您已经在使用 fork(),您可能希望调用 exec() 的任何变体而不是 system(),因为 system() 将创建一个额外的进程。参见 Difference between "system" and "exec" in Linux?

您可以使用 getpwdnam() 读取 /etc/passwd,因为它会为您解析字段。参见 How to get linux user id by user name?