Making a program always run as root in OS X
Solution 1:
There are two things to know here:
The sticky bit, which could be used on files and directories, but won't do what you want. From
sticky(8)
: The sticky bit has no effect on executable files.The
setuid
flag, which would allow a program to be run with its owners permissions. What seems to be a restriction in OS X, and apparently is not documented, is that the setuid bit on an executable has an effect only if the executable is in a directory that is owned by root (and not open for writing by others), etc, up to the root directory. Otherwise it is ignored for security reasons though.
Anyway, you can modify the sudoers file in such a way that it won't require a password for one command. Remember that you have to use visudo
to edit it. If you manage to get the syntax wrong while editing the file, you won't be able to run sudo
at all anymore.
sudo visudo
Then, press I, and at the bottom insert:
username ALL= NOPASSWD: /path/to/command
Here, you obviously need to change the username
for the user who is supposed to run the command without having to type a password. Also, change the path to your executable. Note that at this point, the executable can be owned by root
and have execute permissions only for root
as well.
Press Esc, then write :wq
, then Enter.
Now, the user username
can run the command with sudo /path/to/command
and doesn't need to enter a password to do that.
Solution 2:
I'm working under Linux, but since OSX is just BSD I assume it follows the same (general) rules as any other Unix.
Within your program, you need to call setuid (UID), which returns 0 on success, to make it run as that UID and you want to run as root. Root's UID is probably 0, but if you're especially paranoid, use getpwnam (const char *szUserName) to get the UID.
So, something like this:
#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;
}
You can setuid to ANY username, so maybe you're running a cgi script, and you want to run as your username on your own account instead of "www-data" or whatever - you can use it there. I do this, which is why I can answer your question in detail.