0

I have a program that runs as the root user (getuid() returns 0).

I need to execute a command line tool as the user that's currently logged in (which I can determine by getting the HOME env var). (See below for an elaboration)

How do I do that, ideally by using NSTask?

I know how to execute the tool using NSTask as the current (root) user, so all I need is to know what I need to change about that.

Alternatively, is there a way to run a section of my program's code under a different user's ID?

Elaboration

In particular, said program is launched by AuthorizationExecuteWithPrivileges. Interestingly, this gives the program a slightly different environment as when launching the program with sudo:

With sudo, the actual and effective user (from getuid() and geteuid()) are both "root".

However, with AuthorizationExecuteWithPrivileges, the effective user remains the user that called that function. This has some weird effects, e.g. then the program uses NSUserDefaults, as they end up in different domains, my testing shows.

Thomas Tempelmann
  • 11,045
  • 8
  • 74
  • 149
  • Consider to refactor your design to run the current user temporarily as root (which is the usual way) rather than the root as current user. And consider also that running an app permanently as root can cause security issues. – vadian Apr 13 '19 at 17:05
  • I know. But that's currently not an option for me. Also, even though I wrote "app", this question can apply to any background process running as root - it may need to execute tools and for security reasons it should be able to run them with lowered permissions. – Thomas Tempelmann Apr 13 '19 at 17:20
  • What is the user currently logged in? There is likely more than one user currently logged in!? – Amin Negm-Awad Apr 13 '19 at 22:54

1 Answers1

0

Someone else suggested to use the fork function and then call setuid in the forked process, before using NSTask or system() to run the external command.

Here's how this would be done:

int userID = 501; // or whatever user you need to be
assert (geteuid() == 0); // are we root?
pid_t pid;
if ((pid = fork()) == 0) {
    setuid(userID);
    int res = system("...");
    exit (res);
} else {
    // wait for the forked process to finish
    pid_t endid;
    do {
        int status;
        endid = waitpid (pid, &status, WNOHANG|WUNTRACED);
    } while (endid == 0);
}
Thomas Tempelmann
  • 11,045
  • 8
  • 74
  • 149