How do you find the original user through multiple sudo and su commands?
Results:
Use who am i | awk '{print $1}'
OR logname
as no other methods are guaranteed.
Logged in as self:
evan> echo $USERevanevan> echo $SUDO_USERevan> echo $LOGNAMEevanevan> whoamievanevan> who am i | awk '{print $1}'evanevan> lognameevanevan>
Normal sudo:
evan> sudo -sroot> echo $USERrootroot> echo $SUDO_USERevanroot> echo $LOGNAMErootroot> whoamirootroot> who am i | awk '{print $1}'evanroot> lognameevanroot>
sudo su - :
evan> sudo su -[root ]# echo $USERroot[root ]# echo $SUDO_USER[root ]# echo $LOGNAMEroot[root ]# whoamiroot[root ]# who am i | awk '{print $1}'evan[root ]# lognameevan[root ]#
sudo su -; su tom :
evan> sudo su -[root ]# su tomtom$ echo $USERtomtom$ echo $SUDO_USERtom$ echo $LOGNAMEtomtom$ whoamitomtom$ who am i | awk '{print $1}'evantom$ lognameevantom$
There's no perfect answer. When you change user IDs, the original user ID is not usually preserved, so the information is lost. Some programs, such as logname
and who -m
implement a hack where they check to see which terminal is connected to stdin
, and then check to see what user is logged in on that terminal.
This solution often works, but isn't foolproof, and certainly shouldn't be considered secure. For example, imagine if who
outputs the following:
tom pts/0 2011-07-03 19:18 (1.2.3.4)joe pts/1 2011-07-03 19:10 (5.6.7.8)
tom
used su
to get to root, and runs your program. If STDIN
is not redirected, then a program like logname
will output tom
. If it IS redirected (e.g. from a file) as so:
logname < /some/file
Then the result is "no login name
", since the input isn't the terminal. More interestingly still, though, is the fact that the user could pose as a different logged in user. Since Joe is logged in on pts/1, Tom could pretend to be him by running
logname < /dev/pts1
Now, it says joe
even though tom is the one who ran the command. In other words, if you use this mechanism in any sort of security role, you're crazy.
This is a ksh
function I wrote on HP-UX. I don't know how it will work with Bash
in Linux. The idea is that the sudo
process is running as the original user and the child processes are the target user. By cycling back through parent processes, we can find the user of the original process.
## The options of ps require UNIX_STD=2003. I am setting it# in a subshell to avoid having it pollute the parent's namespace.#function findUser{ thisPID=$$ origUser=$(whoami) thisUser=$origUser while [ "$thisUser" = "$origUser" ] do ( export UNIX_STD=2003; ps -p$thisPID -ouser,ppid,pid,comm ) | grep $thisPID | read thisUser myPPid myPid myComm thisPID=$myPPid done if [ "$thisUser" = "root" ] then thisUser=$origUser fi if [ "$#" -gt "0" ] then echo $origUser--$thisUser--$myComm else echo $thisUser fi return 0}
I know the original question was from a long time ago but people (such as me) are still asking and this looked like a good place to put the solution.