Pourquoi la saisie du mot de passe fonctionne-t-elle dans une commande piped sudo?

25

Si je fais:

sudo cat /etc/resolv.conf | less

Il me demandera le mot de passe, même si moins (probablement) prend stdin. Sur quels fd s'affiche l'invite de mot de passe et comment récupère-t-elle l'entrée?

Karlo
la source

Réponses:

48

En fait, une invocation typique de sudone lit pas du tout le mot de passe stdin. Au lieu de cela, sudoaccédera directement au terminal de contrôle (a ttyou pty, via le /dev/ttyfichier spécial) et sortira l'invite et lira directement les caractères. Cela peut être vu dans le tgetpass.cfichier dans la sudosource.

Il existe quelques autres scénarios:

  • Si un askpassprogramme est spécifié, par exemple dans le -Aparam, ce programme sera invoqué.
  • Sinon, si vous demandez spécifiquement sudoà lire stdin, par exemple avec le -Sdrapeau - et il écrira également l'invite à stderr. C'est le cas où la réponse de MadHatter s'applique.
  • Dans le cas contraire, s'il n'y a pas ttydisponible
    • Si l'écho du mot de passe est désactivé (il est par défaut contrôlé par le visiblepwdrapeau sudoers), sudosignalera une erreur:no tty present and no askpass program specified
    • Sinon, sudoreviendra à utiliser stdinet stderrmême si cela n'a pas été spécifiquement demandé. La réponse de MadHatter s'appliquera également ici.
Bob
la source
10

Le tuyau connecte sudo catstdout à lessstdin, donc sudo catstdin n'est pas affecté et peut recevoir le mot de passe.

Quant à l'invite, elle s'éteint sur sudo catstderr; en bash, essayez de rediriger cela avec stdout, en utilisant

sudo cat /etc/resolv.conf |& less

et voyez à quel point la réponse est différente.

MadHatter soutient Monica
la source
16
Bien que cette réponse soit correcte dans la mesure où sudostdin est toujours connecté au terminal avec l'exemple de commande, cela n'est pas directement pertinent pour la façon dont il obtient son mot de passe: par défaut, sudoil ne demandera pas de mots de passe via stdin et il ne montrera pas l'invite via stderr- vous peut essayer 2>/dev/nullde le confirmer. Au lieu de cela, sudoaccède directement au tty.
Bob