1#! @EXPECT_PATH@ -- 2## 3## @PACKAGE@ @VERSION@ 4@copyright@ 5# 6# alogin - Alteon WebOS switch login 7# 8# afort@choqolat.org is responsible for this particular mess 9# (andrew fort) 10# 11 12# default timeout 13set timeoutdflt 45 14# Some CLIs having problems if we write too fast (Extreme, PIX, Cat) 15set send_human {.2 .1 .4 .2 1} 16 17@login_top@ 18 19# Log into the router. 20# returns: 0 on success, 1 on failure 21proc login { router user userpswd passwd prompt cmethod cyphertype } { 22 global spawn_id in_proc do_command do_script 23 global u_prompt p_prompt sshcmd telnetcmd 24 set in_proc 1 25 set uprompt_seen 0 26 27 # try each of the connection methods in $cmethod until one is successful 28 set progs [llength $cmethod] 29 foreach prog [lrange $cmethod 0 end] { 30 incr progs -1 31 if [string match "telnet*" $prog] { 32 regexp {telnet(:([^[:space:]]+))*} $prog command suffix port 33 if {"$port" == ""} { 34 set retval [ catch {eval spawn [split "$telnetcmd $router"]} reason ] 35 } else { 36 set retval [ catch {eval spawn [split "$telnetcmd $router $port"]} reason ] 37 } 38 if { $retval } { 39 send_user "\nError: telnet failed: $reason\n" 40 return 1 41 } 42 } elseif ![string compare $prog "ssh"] { 43 regexp {ssh(:([^[:space:]]+))*} $prog methcmd suffix port 44 set cmd $sshcmd 45 if {"$port" != ""} { 46 set cmd "$cmd -p $port" 47 } 48 if {"$cyphertype" != ""} { 49 set cmd "$cmd -c $cyphertype" 50 } 51 set retval [ catch {eval spawn [split "$cmd -x -l $user $router" { }]} reason ] 52 if { $retval } { 53 send_user "\nError: $cmd failed: $reason\n" 54 return 1 55 } 56 } elseif ![string compare $prog "rsh"] { 57 send_error "\nError: unsupported method: rsh\n" 58 if { $progs == 0 } { 59 return 1 60 } 61 continue; 62 } else { 63 send_user "\nError: unknown connection method: $prog\n" 64 return 1 65 } 66 sleep 0.3 67 68 # This helps cleanup each expect clause. 69 expect_after { 70 timeout { 71 global in_proc 72 send_user "\nError: TIMEOUT reached\n" 73 catch {close}; catch {wait}; 74 if {$in_proc} { 75 return 1 76 } else { 77 continue 78 } 79 } eof { 80 global in_proc 81 send_user "\nError: EOF received\n" 82 catch {close}; catch {wait}; 83 if {$in_proc} { 84 return 1 85 } else { 86 continue 87 } 88 } 89 } 90 91 expect { 92 "Connection refused" { 93 catch {close}; catch {wait}; 94 sleep 0.3 95 catch {expect eof} 96 send_user "\nError: Connection Refused\n"; 97 catch {wait}; 98 return 1 99 } 100 eof { 101 send_user "\nError: Couldn't login\n"; 102 catch {wait}; 103 return 1 104 } 105 "Unknown host\r\n" { 106 catch {expect eof} 107 send_user "\nError: Unknown host\n"; 108 catch {wait}; 109 return 1 110 } 111 "Host is unreachable" { 112 expect eof 113 send_user "\nError: Host Unreachable!\n"; 114 catch {wait}; 115 return 1 116 } 117 "No address associated with name" { 118 expect eof 119 send_user "\nError: Unknown host\n"; 120 catch {wait}; 121 return 1 122 } 123 -re "(Host key not found |The authenticity of host .* be established)" { 124 expect { 125 -re "\\(yes\/no\[^\\)]*\\)\\?" { 126 send "yes\r"; 127 send_user "\nHost $router added to the list of known hosts.\n" 128 } 129 -re "\[^\r\n]*\[\r\n]+" { exp_continue; } 130 } 131 exp_continue 132 } 133 -re "HOST IDENTIFICATION HAS CHANGED" { 134 send_user "\nError: The host key for $router has changed. Update the SSH known_hosts file accordingly.\n" 135 expect { 136 -re "\\(yes\/no\\)\\?" { send "no\r" } 137 -re " strict checking\.\[\r\n]+" { } 138 -re "\[^\r\n]*\[\r\n]+" { exp_continue; } 139 } 140 catch {close}; catch {wait}; 141 return 1 142 } 143 -re "Offending key for " { 144 send_user "\nError: host key mismatch for $router. Update the SSH known_hosts file accordingly.\n" 145 expect { 146 -re "\\(yes\/no\\)\\?" { send "no\r" } 147 -re "\[^\r\n]*\[\r\n]+" { exp_continue; } 148 } 149 catch {close}; catch {wait}; 150 return 1 151 } 152 -nocase -re "^warning: remote host denied authentication agent forwarding." { 153 exp_continue; 154 } 155 -re "NOTICE:\[^\n\r]* - display now \[^\n\r]*:" { 156 send "no\r" 157 exp_continue 158 } 159 -re "$u_prompt" { 160 send -- "$user\r" 161 set uprompt_seen 1 162 exp_continue 163 } 164 -re "$p_prompt" { 165 sleep 1 166 if {$uprompt_seen == 1} { 167 send -- "$userpswd\r" 168 } else { 169 send -- "$passwd\r" 170 } 171 exp_continue 172 } 173 -re "^Confirm seeing above note" { 174 send "y\r" 175 exp_continue 176 } 177 -re "^Select Command Line Interface mode\[^:]*:" { 178 send "ibmnos-cli\r" 179 exp_continue 180 } 181 "Password incorrect" { send_user "\nError: Check your password for $router\n"; 182 catch {close}; catch {wait}; return 1 } 183 -re "$prompt" { break; } 184 -re "Warning: Remote host denied" { 185 exp_continue 186 } 187 denied { send_user "\nError: Check your passwd for $router\n" 188 catch {close}; catch {wait}; return 1 189 } 190 -re "\[^\r\n]*\[\r\n]+" { exp_continue; } 191 } 192 } 193 set in_proc 0 194 return 0 195} 196 197# Run commands given on the command line. 198proc run_commands { prompt command } { 199 global do_interact do_saveconfig in_proc cmethod 200 set in_proc 1 201 202 send "lines 0\r" 203 expect -re $prompt {} 204 205 regsub -all "\[)(]" $prompt {\\&} reprompt 206 207 # handle escaped ;s in commands, and ;; and ^; 208 regsub -all {([^\\]);} $command "\\1\u0002;" esccommand 209 regsub -all {([^\\]);;} $esccommand "\\1;\u0002;" command 210 regsub {^;} $command "\u0002;" esccommand 211 regsub -all {[\\];} $esccommand ";" command 212 regsub -all {\u0002;} $command "\u0002" esccommand 213 set sep "\u0002" 214 set commands [split $esccommand $sep] 215 set num_commands [llength $commands] 216 for {set i 0} {$i < $num_commands} { incr i} { 217 send -- "[subst -nocommands [lindex $commands $i]]\r" 218 expect { 219 -re "^\[^\n\r]*$reprompt" {} 220 -re "^\[^\n\r ]*>>.*$reprompt" { exp_continue } 221 -re "\[\n\r]+" { exp_continue } 222 -re "Display private keys" { 223 if { "$cmethod" == "ssh" } { 224 send "y\r" 225 } else { 226 send "n\r" 227 } 228 exp_continue 229 } 230 } 231 } 232 233 if { $do_interact == 1 } { 234 interact 235 return 0 236 } 237 238 send "exit\r" 239 expect { 240 -re "^WARNING: There are unsaved configuration changes." { 241 if {$do_saveconfig} { 242 catch {send "y\r"} 243 } else { 244 catch {send "n\r"} 245 } 246 exp_continue 247 } 248 -re "^Confirm Sync to Peer \[^:]*: " { 249 if {$do_saveconfig} { 250 catch {send "y\r"} 251 } else { 252 catch {send "n\r"} 253 } 254 exp_continue 255 } 256 "\n" { exp_continue } 257 "\[^\n\r *]*Session terminated" { return 0 } 258 timeout { catch {close}; catch {wait}; 259 return 0 260 } 261 eof { return 0 } 262 } 263 set in_proc 0 264} 265 266# 267# For each router... (this is main loop) 268# 269source_password_file $password_file 270set in_proc 0 271set exitval 0 272foreach router [lrange $argv $i end] { 273 set router [string tolower $router] 274 send_user "$router\n" 275 276 # device timeout 277 set timeout [find timeout $router] 278 if { [llength $timeout] == 0 } { 279 set timeout $timeoutdflt 280 } 281 282 # Figure out prompt. 283 set prompt ">> \[^\r\n]*\[#|>] " 284 # alteon only "enables" based on the password used at login time 285 set autoenable 1 286 set enable 0 287 288 # Figure out passwords 289 if { $do_passwd } { 290 set pswd [find password $router] 291 if { [llength $pswd] == 0 } { 292 send_user -- "\nError: no password for $router in $password_file.\n" 293 continue 294 } 295 set passwd [join [lindex $pswd 0] ""] 296 } 297 298 # Figure out username 299 if {[info exists username]} { 300 # command line username 301 set ruser $username 302 } else { 303 set ruser [join [find user $router] ""] 304 if { "$ruser" == "" } { set ruser $default_user } 305 } 306 307 # Figure out username's password (if different from the vty password) 308 if {[info exists userpasswd]} { 309 # command line username 310 set userpswd $userpasswd 311 } else { 312 set userpswd [join [find userpassword $router] ""] 313 if { "$userpswd" == "" } { set userpswd $passwd } 314 } 315 316 # Figure out prompts 317 set u_prompt [find userprompt $router] 318 if { "$u_prompt" == "" } { 319 set u_prompt "(Username|login| Login):" 320 } else { 321 set u_prompt [join [lindex $u_prompt 0] ""] 322 } 323 set p_prompt [find passprompt $router] 324 if { "$p_prompt" == "" } { 325 set p_prompt "\[Pp]assword:" 326 } else { 327 set p_prompt [join [lindex $p_prompt 0] ""] 328 } 329 330 # Figure out cypher type 331 if {[info exists cypher]} { 332 # command line cypher type 333 set cyphertype $cypher 334 } else { 335 set cyphertype [find cyphertype $router] 336 } 337 338 # Figure out connection method 339 set cmethod [find method $router] 340 if { "$cmethod" == "" } { set cmethod {{telnet} {ssh}} } 341 342 # Figure out the SSH executable name 343 set sshcmd [join [lindex [find sshcmd $router] 0] ""] 344 if { "$sshcmd" == "" } { set sshcmd {ssh} } 345 346 # Figure out the telnet executable name 347 set telnetcmd [join [lindex [find telnetcmd $router] 0] ""] 348 if { "$telnetcmd" == "" } { set telnetcmd "@TELNET_CMD@" } 349 350 # if [-mM], skip do not login 351 if { $do_cloginrcdbg > 0 } { continue; } 352 353 # Login to the router 354 if {[login $router $ruser $userpswd $passwd $prompt $cmethod $cyphertype]} { 355 incr exitval 356 continue 357 } 358 359 if { $do_command } { 360 if {[run_commands $prompt $command]} { 361 incr exitval 362 continue 363 } 364 } elseif { $do_script } { 365 send "lines 0\r" 366 expect -re $prompt {} 367 source $sfile 368 catch {close}; 369 } else { 370 label $router 371 log_user 1 372 interact 373 } 374 375 # End of for each router 376 catch {wait}; 377 sleep 0.3 378} 379exit $exitval 380