我正在尝试让一个 C 程序始终以 root 身份运行,无论谁调用它。基本上,我希望它调用“mkdir /test”作为示例。因此我创建了如下 C 程序:
#include <stdio.h>
int main()
{
system("mkdir /test");
printf("bye...\n");
return 0;
}
现在,我刚刚编译了它:gcc test.c -o test
现在我尝试设置权限:
chmod +s test
但是以普通用户身份运行它时,我收到权限被拒绝的错误。因此,它执行该文件但不具有 root 权限。我还尝试将权限设置为:
chmod a+s test
chmod o+s test
但我总是遇到同样的问题。
有人能帮我吗?顺便说一下,文件 test.c 是由 root 创建的,并且也是以 root 身份编译的。
bash-3.2# ls -al | grep test
-rwxr-xr-x 1 root staff 8796 5 Ago 19:07 test
bash-3.2# chmod +s test
bash-3.2# ls -al | grep test
-rwsr-sr-x 1 root staff 8796 5 Ago 19:07 test
bash-3.2# whoami
root
bash-3.2#
提前致谢!干杯!
答案1
这里有两件事需要了解:
这
setuid
标志,允许程序以其所有者权限运行。OS X 中似乎有一个限制,但显然没有记录,即可执行文件上的 setuid 位只有在可执行文件位于 root 拥有的目录中(并且不向其他人开放写入)时才有效,直到 root 目录。否则,出于安全原因,它将被忽略。
无论如何,你可以修改 sudoers 文件,这样它就不需要密码来执行某个命令了。记住,你有用来visudo
编辑它。如果你在编辑文件时语法错误,你将无法再运行sudo
。
sudo visudo
然后按I,并在底部插入:
username ALL= NOPASSWD: /path/to/command
在这里,您显然需要将username
运行命令而无需输入密码的用户更改为。此外,更改可执行文件的路径。请注意,此时,可执行文件也可以由 拥有,root
并且仅对 具有执行权限root
。
按Esc,然后 写入:wq
,然后Enter。
现在,用户username
可以运行该命令,sudo /path/to/command
而不需要输入密码。
答案2
我在 Linux 下工作,但由于 OSX 只是 BSD,我认为它遵循与任何其他 Unix 相同的(一般)规则。
在您的程序中,您需要调用 setuid (UID),成功时返回 0,以使其以该 UID 运行,并且您希望以 root 身份运行。Root 的 UID 是大概0,但如果您特别偏执,请使用 getpwnam (const char *szUserName) 来获取 UID。
因此,是这样的:
#include <stdio.h> // needed for printf
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>
void change_to_user (const char *szUserName)
{
struct passwd *pw;
pw = getpwnam(szUserName);
if (pw != NULL)
{
uid_t uid = pw->pw_uid; // we now have the UID of the username
printf ("UID of user %s is %d\n", szUserName, (int)uid);
if (setuid (uid) != 0)
{
perror ("setuid");
}
else
{
// this will fail if you try to change to root without the SUID
// bit set. This executive needs to be owned by root (probably
// group owned by root as well), and set the SUID bit with:
// suid a+s {executable}
printf ("UID is now %d\n", (int)uid);
}
}
else
{
perror ("getpwnam");
}
}
int main (int argc, char **argv)
{
int iIter;
if (argc == 1)
{
printf ("Give me a user name\n");
return 1;
}
for (iIter = 1 ; iIter < argc ; iIter++)
{
change_to_user (argv[iIter]);
}
return 0;
}
您可以将 UID 设置为任何用户名,因此也许您正在运行 cgi 脚本,并且想要在自己的帐户上以用户名运行,而不是“www-data”或其他任何名称 - 您可以在那里使用它。我就是这样做的,这就是我可以详细回答您的问题的原因。