24

The program I am running needs root privledges and therefore is run with sudo, but it also needs to know what user is running it. getuid and geteuid both return root. How do I get the actual users username (or uid)?

Thanks!

chacham15
  • 13,719
  • 26
  • 104
  • 207

4 Answers4

31

sudo provides some environment variables to help you with exactly this case:

   SUDO_UID        Set to the user ID of the user who invoked
                   sudo

   SUDO_USER       Set to the login of the user who invoked sudo

steveayre has pointed out in the comments that the user can set these environment variables in some cases; the sudo(8) manpage includes in part:

The sudoers policy subjects variables
passed on the command line to the same restrictions as normal
environment variables with one important exception.  If the
setenv option is set in sudoers, the command to be run has the
SETENV tag set or the command matched is ALL, the user may set
variables that would otherwise be forbidden.  See sudoers(5)
for more information.

So be sure that you don't grant ALL commands to users when you need to rely upon this feature.

sarnold
  • 102,305
  • 22
  • 181
  • 238
  • 1
    i really hate using environment variables, is there another way? (the main reason i hate using them is because they arent reliable: from a security POV or a compatability POV) – chacham15 Apr 22 '12 at 22:48
  • 2
    The environment variables should be safe to trust -- you must completely trust `sudo` in order to use it in this fashion. Any attack against `sudo` that allows marginally-trusted users to execute programs with modified environment variables is going to bring focus from dozens of security teams around the world to fix the flaw (or remove the feature if it cannot be fixed). As for compatibility, this is more portable than the other option I just thought of -- answered separately for its own comments. And this is probably safer than writing your own setuid-root program. – sarnold Apr 22 '12 at 23:02
  • The security problem that I am referring to comes from either other programs running on the system or plugin-code which can both modify environment variables. But seeing as how the other solution doesnt work, I'll probably end up going with this and caching the variable myself on program startup (so hopefully noone will modify it before then). – chacham15 Apr 22 '12 at 23:12
  • 2
    Only processes with `CAP_SYS_PTRACE` capability will be able to attach to the executing program -- user processes won't have that capability -- and modify the environment variable. Processes with `CAP_SYS_PTRACE` are already able to do vast amounts of damage regardless of this environment variable. :) – sarnold Apr 22 '12 at 23:19
  • 1
    The user can still override the SUDO_USER environment variable: `$ sudo SUDO_USER=fake env | grep ^SUDO_USER` gives `SUDO_USER=fake` – steveayre Feb 07 '17 at 16:25
  • @steveayre -- well this is frustrating. Thanks. – sarnold Feb 09 '17 at 18:57
3

A Linux-specific audit_getloginuid() function provided by the auditing system may be able to help; since pam_loginuid(8) is only going to be installed for the "main" daemons (sshd, login, gdm, etc.) the audit uid will remain unchanged when sudo(8) executes.

This will require a little configuration; add:

session    required     pam_loginuid.so

to the /etc/pam.d/sshd file -- and whichever other services you allow your users to use.

Ensure pam_loginuid.so isn't loaded in the /etc/pam.d/sudo configuration file.

sarnold
  • 102,305
  • 22
  • 181
  • 238
  • great idea, but it doesnt work: `audit_getloginuid()` returns -1. – chacham15 Apr 22 '12 at 23:06
  • Ah, silly me, assuming it was already configured; my Ubuntu 11.04 doesn't have `pam_loginuid` loaded by default. I edited my post to include a line to load the `pam_loginuid` module for `sshd` -- if you want it to work for GUI, console, or elsewhere, you'll have to load the PAM module in the corresponding services. – sarnold Apr 22 '12 at 23:17
2

You have two good choices...

  1. Trust sudo and just use its environment
  2. Make your program setuid-on-execution and then geteuid, et al, will work just fine

Update:

The setuid bit is an access right flag in the file mode that causes a program to run with the capabilities of the executable file's owner. This is how sudo(1) is able to run things as root ... the sudo program itself has this mode.

$ ls -l /usr/bin/sudo
-r-s--x--x  1 root  wheel  272384 Jun 22  2009 /usr/bin/sudo*

To make a program setuid root one might:

$ chown root a.out
$ chmod +s a.out

Needless to say, setuid root programs should be written carefully. You can setuid to a less privileged user if all you need is access to a protected directory or file.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
1

The easier way would be using Who am i

who am i | awk '{print $1}'

or

who am i | cut -f1 -d" "
iknow
  • 8,358
  • 12
  • 41
  • 68