web-dev-qa-db-fra.com

Comment puis-je faire un script d'attente Invite pour un mot de passe?

J'ai un script d'attente qui se connecte à quelques routeurs via ssh. Tous ces routeurs ont le même mot de passe (je sais, c'est faux) et le script doit connaître ce mot de passe pour pouvoir se connecter aux routeurs. Actuellement, le mot de passe est transmis à mon script sous forme d'argument sur la ligne de commande, mais cela signifie qu'il existe une trace de ce mot de passe dans mon fichier .bash_history ainsi que dans les processus en cours d'exécution. Je voudrais donc plutôt que l'utilisateur soit invité à entrer un mot de passe, si possible en silence.

Savez-vous s'il est possible ou non de demander à l'utilisateur un mot de passe avec expect?

Je vous remercie.

Edit : si je me connectais à des serveurs au lieu de routeurs, j'utiliserais probablement des clés ssh au lieu de mots de passe. Mais les routeurs que j'utilise ne supportent que les mots de passe.

20
MiniQuark

Utilisez la commande stty de expect comme ceci:

# grab the password
stty -echo
send_user -- "Password for $user@$Host: "
expect_user -re "(.*)\n"
send_user "\n"
stty echo
set pass $expect_out(1,string)

#... later
send -- "$pass\r"

Notez qu'il est important d'appeler stty -echo avant appeler send_user - Je ne sais pas trop pourquoi: je pense que c'est un problème de synchronisation.

attendez-vous à ce que les programmeurs lisent tous la livre: Exploring Expect de Don Libes

35
glenn jackman

OK, en fusionnant les 2 réponses ci-dessus (ou ci-dessous ou où qu’elles se trouvent maintenant):

#!/usr/bin/expect
log_user 0
set timeout 10
set userid  "XXXXX"
set pass    "XXXXXX"

### Get two arguments - (1) Host (2) Command to be executed
set Host    [lindex $argv 0] 
set command [lindex $argv 1]

# grab the password
stty -echo
send_user -- "Password for $userid@$Host: "
expect_user -re "(.*)\n"
send_user "\n"
stty echo
set pass $expect_out(1,string)

spawn /usr/bin/ssh -l $userid $Host
match_max [expr 32 * 1024]

expect {
    -re "RSA key fingerprint" {send "yes\r"}
    timeout {puts "Host is known"}
}

expect {
     -re "username: " {send "$userid\r"} 
     -re "(P|p)assword: " {send "$pass\r"}
     -re "Warning:" {send "$pass\r"}
     -re "Connection refused" {puts "Host error -> $expect_out(buffer)";exit}
     -re "Connection closed"  {puts "Host error -> $expect_out(buffer)";exit}
     -re "no address.*" {puts "Host error -> $expect_out(buffer)";exit}

     timeout {puts "Timeout error. Is Host down or unreachable?? ssh_expect";exit}
}

expect {
   -re "\[#>]$" {send "term len 0\r"}
   timeout {puts "Error reading Prompt -> $expect_out(buffer)";exit}
}


expect {
   -re "\[#>]$" {send "$command\r"}

   timeout {puts "Error reading Prompt -> $expect_out(buffer)";exit}
}

expect -re "\[#>]$"
set output $expect_out(buffer)
send "exit\r"
puts "$output\r\n"

Notez que j'ai changé la variable $ password en $ pass pour être cohérent avec l'autre réponse.

6
dr-jan

Vous pouvez également laisser ssh collecter le mot de passe via X11 à l'aide de la variable d'environnement SSH_ASKPASS.

De la page de manuel:

> SSH_ASKPASS
>     If ssh needs a passphrase, it will read the passphrase from the
>     current terminal if it was run from a terminal.  If ssh does not
>     have a terminal associated with it but DISPLAY and SSH_ASKPASS
>     are set, it will execute the program specified by SSH_ASKPASS
>     and open an X11 window to read the passphrase.  This is particularly
>     useful when calling ssh from a .xsession or related script.
>     (Note that on some machines it may be necessary to redirect the
>     input from /dev/null to make this work.)
0
qneill