web-dev-qa-db-fra.com

Comment trouvez-vous l'utilisateur d'origine via plusieurs commandes Sudo et su?

Lors de l'exécution d'un script via Sudo ou su, je souhaite obtenir l'utilisateur d'origine. Cela devrait se produire quelles que soient les exécutions Sudo ou su et notamment Sudo su -.

75
evan

Résultats:

Utilisez who am i | awk '{print $1}' OR logname car aucune autre méthode n'est garantie.

Connecté en tant que soi:

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 normal:

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 -; su tom:

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$
119
evan

Il n'y a pas de réponse parfaite. Lorsque vous modifiez les ID utilisateur, l'ID utilisateur d'origine n'est généralement pas conservé. Les informations sont donc perdues. Certains programmes, tels que logname et who -m implémentent un hack où ils vérifient quel terminal est connecté à stdin, puis déterminent quel utilisateur est connecté à ce terminal. 

Cette solution souvent fonctionne, mais n’est pas infaillible et ne devrait certainement pas être considérée comme sécurisée. Par exemple, imaginez si who génère les éléments suivants:

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 a utilisé su pour aller à la racine et exécute votre programme. Si STDIN n'est pas redirigé, un programme comme logname affichera tom. Si IS est redirigé (par exemple à partir d'un fichier) comme suit: 

logname < /some/file

Alors, le résultat est "no login name", puisque l'entrée n'est pas le terminal. Ce qui est encore plus intéressant, c’est que l’utilisateur puisse se faire passer pour un autre utilisateur connecté. Depuis que Joe est connecté sur pts/1, Tom pourrait se faire passer pour lui en courant 

logname < /dev/pts1

Maintenant, il est écrit joe même si tom est celui qui a exécuté la commande. En d’autres termes, si vous utilisez ce mécanisme dans n’importe quel rôle de sécurité, vous êtes fou.

11
tylerl

C’est une fonction ksh que j’ai écrite sur HP-UX. Je ne sais pas comment cela fonctionnera avec Bash sous Linux. L'idée est que le processus Sudo est exécuté en tant qu'utilisateur d'origine et que les processus enfants sont l'utilisateur cible. En revenant en arrière dans les processus parents, nous pouvons trouver l'utilisateur du processus d'origine.

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

Je sais que la question initiale remontait à il y a longtemps, mais les gens (comme moi) le demandent toujours et cela semblait être un bon endroit pour mettre la solution en place.

8
user1683793

Pourquoi ne pas utiliser logname (1) pour obtenir le nom de connexion de l'utilisateur?

5
sam

la fonction findUser () de user1683793 a été portée à bash et étendue afin de renvoyer les noms d'utilisateur stockés dans les bibliothèques 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"
2
asdfghjkl

revenir et donner une liste des utilisateurs

basé sur la réponse de user1683793

En excluant les processus non-TTY, je saute root en tant qu'initiateur de la connexion. Je ne sais pas si cela peut en excéder dans certains cas

#!/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 ou who am i ne m'a pas donné la réponse souhaitée, surtout pas dans les listes plus longues de su user1, su user2, su user3, ... 

Je sais que la question initiale remontait à il y a longtemps, mais les gens (comme moi) le demandent toujours et cela semblait être un bon endroit pour mettre la solution en place.

2
ULick
THIS_USER=`pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1 | sed 's/[()]//g'`

C'est la seule chose qui a fonctionné pour moi.

1
Grey Christoforo

Alternative à appeler ps plusieurs fois: faire un appel pstree

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

sortie (lorsque connecté en tant que pair): (evan)

pstree arguments:

  • -l: longues lignes (ne pas raccourcir)
  • -u: afficher quand l'utilisateur change comme (userName)
  • -s $$: affiche les parents de ce processus

Obtenez le premier changement d'utilisateur (qui est login) avec grep -o et head.

limitation: la commande ne doit contenir aucune accolade () (normalement pas)

0
simohe