Как найти исходного пользователя с помощью нескольких команд sudo и su? - PullRequest
77 голосов
/ 04 января 2011

При запуске скрипта через sudo или su я хочу получить оригинального пользователя.Это должно происходить независимо от нескольких sudo или su прогонов внутри друг друга и, в частности, sudo su -.

Ответы [ 8 ]

123 голосов
/ 04 января 2011

Результаты:

Используйте who am i | awk '{print $1}' ИЛИ logname, так как другие методы не гарантированы.

Вы вошли как пользователь:

evan> echo $USER
evan
evan> echo $SUDO_USER

evan> echo $LOGNAME
evan
evan> whoami
evan
evan> who am i | awk '{print $1}'
evan
evan> logname
evan
evan>

Обычный sudo:

evan> sudo -s
root> echo $USER
root
root> echo $SUDO_USER
evan
root> echo $LOGNAME
root
root> whoami
root
root> who am i | awk '{print $1}'
evan
root> logname
evan
root>

sudo su -:

evan> sudo su -
[root ]# echo $USER
root
[root ]# echo $SUDO_USER

[root ]# echo $LOGNAME
root
[root ]# whoami
root
[root ]# who am i | awk '{print $1}'
evan
[root ]# logname
evan
[root ]#

sudo su -; су том:

evan> sudo su -
[root ]# su tom
tom$ echo $USER
tom
tom$ echo $SUDO_USER

tom$ echo $LOGNAME
tom
tom$ whoami
tom
tom$ who am i | awk '{print $1}'
evan
tom$ logname
evan
tom$
13 голосов
/ 04 июля 2011

Нет идеального ответа.При изменении идентификаторов пользователей первоначальный идентификатор пользователя обычно не сохраняется, поэтому информация теряется.Некоторые программы, такие как logname и who -m, осуществляют взлом, где они проверяют, какой терминал подключен к stdin, а затем проверяют, какой пользователь вошел в систему на этом терминале.

Это решение часто работает, но не является надежным и, конечно, не должно считаться безопасным.Например, представьте, если who выдает следующее:

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 использовал su для доступа к root и запускает вашу программу.Если STDIN не перенаправлен, то такая программа, как logname, выдаст tom.Если он перенаправлен (например, из файла) следующим образом:

logname < /some/file

, то результатом будет "no login name", поскольку вход не является терминалом.Тем не менее, еще интереснее то, что пользователь может выдавать себя за другого зарегистрированного пользователя.Так как Джо вошел в систему на pts / 1, Том мог притвориться им, выполнив

logname < /dev/pts1

Теперь он говорит joe, хотя Том и выполнил команду.Другими словами, если вы используете этот механизм в любой роли безопасности, вы с ума сошли.

8 голосов
/ 20 октября 2012

Это функция ksh, которую я написал в HP-UX. Я не знаю, как это будет работать с Bash в Linux. Идея состоит в том, что процесс sudo выполняется как исходный пользователь, а дочерние процессы являются целевым пользователем. Возвращаясь к родительским процессам, мы можем найти пользователя исходного процесса.

#
# 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
}

Я знаю, что первоначальный вопрос был задуман давно, но люди (такие как я) все еще спрашивают, и это выглядело как хорошее место для решения.

5 голосов
/ 05 января 2011

Как насчет использования логина (1) для получения логина пользователя?

3 голосов
/ 09 августа 2018
THIS_USER=`pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1 | sed 's/[()]//g'`

Это единственное, что сработало для меня.

2 голосов
/ 14 апреля 2017

цикл назад и выдача списка пользователей

на основе ответа пользователя 1683793

Исключая процессы, не относящиеся к TTY, я пропускаю root в качестве инициатора входа в систему.Я не уверен, может ли это в некоторых случаях излишне излишне

#!/bin/ksh
function findUserList
{
    typeset userList prevUser thisPID thisUser myPPid myPid myTTY myComm
    thisPID=$$                 # starting with this process-ID
    while [ "$thisPID" != 1 ]  # and cycling back to the origin
    do
        (  ps -p$thisPID -ouser,ppid,pid,tty,comm ) | grep $thisPID | read thisUser myPPid myPid myTTY myComm
        thisPID=$myPPid
        [[ $myComm =~ ^su ]] && continue        # su is always run by root -> skip it
        [[ $myTTY == '?' ]] && continue         # skip what is running somewhere in the background (without a terminal)
        if [[ $prevUser != $thisUser ]]; then   # we only want the change of user
                prevUser="$thisUser"            # keep the user for comparing
                userList="${userList:+$userList }$thisUser"  # and add the new user to the list
        fi
        #print "$thisPID=$thisUser: $userList -> $thisUser -> $myComm " >&2
    done
    print "$userList"
    return 0
}

logname или who am i не дать мне желаемого ответа, особенно в более длинных списках su user1, su user2, su user3, ...

Я знаю, что первоначальный вопрос был задуман давно, но люди (такие как я) все еще спрашивают, и это выглядело как хорошее место для решения проблемы.

2 голосов
/ 11 декабря 2013
Функция

user1683793 findUser () портирована на bash и расширена, поэтому она возвращает имена пользователей, хранящиеся также в библиотеках NSS.

#!/bin/bash

function findUser() {
    thisPID=$$
    origUser=$(whoami)
    thisUser=$origUser

    while [ "$thisUser" = "$origUser" ]
    do
        ARR=($(ps h -p$thisPID -ouser,ppid;))
        thisUser="${ARR[0]}"
        myPPid="${ARR[1]}"
        thisPID=$myPPid
    done

    getent passwd "$thisUser" | cut -d: -f1
}

user=$(findUser)
echo "logged in: $user"
1 голос
/ 23 января 2018

Альтернатива вызову ps несколько раз: сделать один вызов pstree

pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1

вывод (при входе в систему как четный): (evan)

аргументы pstree:

  • -l: длинные строки (не укороченные)
  • -u: показать, когда пользователь изменяется как (userName)
  • -s $$: показать родителям этого процесса

Получить первое изменение пользователя (то есть логин) с помощью grep -o и head.

ограничение: команда не может содержать фигурные скобки () (обычно это не так)

...