views:

1453

answers:

2

I have an expect script that connects to a few routers through ssh. All these routers have the same password (I know, it's wrong), and the script needs to know that password in order to be able to connect to the routers. Currently, the password is passed to my script as an argument on the command line, but this means that there's a trace of that password in my .bash_history file as well as in the running processes. So instead I would like the user to be prompted for a password, if possible silently.

Do you know whether or not it's possible to prompt the user for a password with expect?

Thank you.

Edit: if I was connecting to servers instead of routers, I would probably use ssh keys instead of passwords. But the routers I'm using just support passwords.

+3  A: 

Use expect's stty command like this:

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

Note that it's important to call stty -echo before calling send_user -- I'm not sure exactly why: I think it's a timing issue.

expect programmers should all read the book: Exploring Expect by Don Libes

glenn jackman
Cool thanks! It's amazing how intolerant this language is: I wrote "set pass $expect_out(1, string)", with a space before the word "string", and it bombs. I can't find much documentation either. I wish there was some other solution than expect. Anyway, thanks a lot.
MiniQuark
"can't find much documentation" ?!? There's a whole book, which is generally considered so well written that it has not needed a second edition. Seriously, check that book out.
glenn jackman
Re: a space between "1," and "string" -- Tcl (and hence expect) does not have multidimensional arrays. The array key is just a string, and "1,string" and "1, string" are different.
glenn jackman
A: 

thanks , I have spent long hours to incoperate this code to mine but no luck so far, I am new please could you help me where I should add or /replace this recomended line on my code. apperciated your time.

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

# ############## Get two arguments - (1) Device (2) Command to be executed
set device  [lindex $argv 0] 
set command [lindex $argv 1]
spawn /usr/local/bin/ssh -l $userid $device
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 "$password\r"}
     -re "Warning:" {send "$password\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 device 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"