Advertisement
Guest User

Untitled

a guest
Jun 25th, 2017
530
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 27.46 KB | None | 0 0
  1. #! /usr/local/bin/expect --
  2. ##
  3. ## Copyright (C) 1997-2004 by Terrapin Communications, Inc.
  4. ## All rights reserved.
  5. ##
  6. ## This software may be freely copied, modified and redistributed
  7. ## without fee for non-commerical purposes provided that this license
  8. ## remains intact and unmodified with any RANCID distribution.
  9. ##
  10. ## There is no warranty or other guarantee of fitness of this software.
  11. ## It is provided solely "as is".  The author(s) disclaim(s) all
  12. ## responsibility and liability with respect to this software's usage
  13. ## or its effect upon hardware, computer systems, other software, or
  14. ## anything else.
  15. ##
  16. ## Except where noted otherwise, rancid was written by and is maintained by
  17. ## Henry Kilmer, John Heasley, Andrew Partan, Pete Whiting, and Austin Schutz.
  18. ##
  19. #
  20. # The login expect scripts were based on Erik Sherk's gwtn, by permission.
  21. #
  22. # Dell mods by: Jeremy Singletary
  23. # dlogin - Dell login
  24. #
  25.  
  26. #exp_internal 1
  27. # Usage line
  28. set usage "Usage: $argv0 \[-autoenable\] \[-noenable\] \[-c command\] \
  29. \[-Evar=x\] \[-e enable-password\] \[-f cloginrc-file\] \[-p user-password\] \
  30. \[-s script-file\] \[-t timeout\] \[-u username\] \
  31. \[-v vty-password\] \[-w enable-username\] \[-x command-file\] \
  32. \[-y ssh_cypher_type\] router \[router...\]\n"
  33.  
  34. # env(CLOGIN) may contain:
  35. #        x == do not set xterm banner or name
  36.  
  37. # Password file
  38. set password_file $env(HOME)/.cloginrc
  39. # Default is to login to the router
  40. set do_command 0
  41. set do_script 0
  42. # The default is to automatically enable
  43. set avenable 1
  44. # The default is that you login non-enabled (tacacs can have you login already
  45. # enabled)
  46. set avautoenable 0
  47. # The default is to look in the password file to find the passwords.  This
  48. # tracks if we receive them on the command line.
  49. set do_passwd 1
  50. set do_enapasswd 1
  51. # attempt at platform switching.
  52. set platform ""
  53.  
  54. # Find the user in the ENV, or use the unix userid.
  55. if {[ info exists env(CISCO_USER) ]} {
  56.     set default_user $env(CISCO_USER)
  57. } elseif {[ info exists env(USER) ]} {
  58.     set default_user $env(USER)
  59. } elseif {[ info exists env(LOGNAME) ]} {
  60.     set default_user $env(LOGNAME)
  61. } else {
  62.     # This uses "id" which I think is portable.  At least it has existed
  63.     # (without options) on all machines/OSes I've been on recently -
  64.     # unlike whoami or id -nu.
  65.     if [ catch {exec id} reason ] {
  66.         send_error "\nError: could not exec id: $reason\n"
  67.         exit 1
  68.     }
  69.     regexp {\(([^)]*)} "$reason" junk default_user
  70. }
  71.  
  72. set send_human {.1 .3 1 .05 2}
  73. # Sometimes routers take awhile to answer (the default is 10 sec)
  74. set timeout 45
  75.  
  76. # Process the command line
  77. for {set i 0} {$i < $argc} {incr i} {
  78.     set arg [lindex $argv $i]
  79.  
  80.     switch  -glob -- $arg {
  81.         # Username
  82.         -u* -
  83.         -U* {
  84.             if {! [  regexp .\[uU\](.+) $arg ignore user]} {
  85.                 incr i
  86.                 set username [ lindex $argv $i ]
  87.             }
  88.         # VTY Password
  89.         } -p* -
  90.         -P* {
  91.             if {! [  regexp .\[pP\](.+) $arg ignore userpasswd]} {
  92.                 incr i
  93.                 set userpasswd [ lindex $argv $i ]
  94.             }
  95.             set do_passwd 0
  96.         # VTY Password
  97.         } -v* -
  98.         -v* {
  99.             if {! [  regexp .\[vV\](.+) $arg ignore passwd]} {
  100.                 incr i
  101.                 set passwd [ lindex $argv $i ]
  102.             }
  103.             set do_passwd 0
  104.         # Enable Username
  105.         } -w* -
  106.         -W* {
  107.             if {! [  regexp .\[wW\](.+) $arg ignore enauser]} {
  108.                 incr i
  109.                 set enausername [ lindex $argv $i ]
  110.             }
  111.         # Environment variable to pass to -s scripts
  112.         } -E*
  113.         {
  114.             if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} {
  115.                 set E$varname $varvalue
  116.             } else {
  117.                 send_user "\nError: invalid format for -E in $arg\n"
  118.                 exit 1
  119.             }
  120.         # Enable Password
  121.         } -e*
  122.         {
  123.             if {! [  regexp .\[e\](.+) $arg ignore enapasswd]} {
  124.                 incr i
  125.                 set enapasswd [ lindex $argv $i ]
  126.             }
  127.             set do_enapasswd 0
  128.         # Command to run.
  129.         } -c* -
  130.         -C* {
  131.             if {! [  regexp .\[cC\](.+) $arg ignore command]} {
  132.                 incr i
  133.                 set command [ lindex $argv $i ]
  134.             }
  135.             set do_command 1
  136.         # Expect script to run.
  137.         } -s* -
  138.         -S* {
  139.             if {! [  regexp .\[sS\](.+) $arg ignore sfile]} {
  140.                 incr i
  141.                 set sfile [ lindex $argv $i ]
  142.             }
  143.             if { ! [ file readable $sfile ] } {
  144.                 send_user "\nError: Can't read $sfile\n"
  145.                 exit 1
  146.             }
  147.             set do_script 1
  148.         # 'ssh -c' cypher type
  149.         } -y* -
  150.         -Y* {
  151.             if {! [  regexp .\[eE\](.+) $arg ignore cypher]} {
  152.                 incr i
  153.                 set cypher [ lindex $argv $i ]
  154.             }
  155.         # alternate cloginrc file
  156.         } -f* -
  157.         -F* {
  158.             if {! [ regexp .\[fF\](.+) $arg ignore password_file]} {
  159.                 incr i
  160.                 set password_file [ lindex $argv $i ]
  161.             }
  162.         # Timeout
  163.         } -t* -
  164.         -T* {
  165.             if {! [ regexp .\[tT\](.+) $arg ignore timeout]} {
  166.                 incr i
  167.                 set timeout [ lindex $argv $i ]
  168.             }
  169.         # Command file
  170.         } -x* -
  171.         -X {
  172.             if {! [  regexp .\[xX\](.+) $arg ignore cmd_file]} {
  173.                 incr i
  174.                 set cmd_file [ lindex $argv $i ]
  175.             }
  176.             if [ catch {set cmd_fd [open $cmd_file r]} reason ] {
  177.                 send_user "\nError: $reason\n"
  178.                 exit 1
  179.             }
  180.             set cmd_text [read $cmd_fd]
  181.             close $cmd_fd
  182.             set command [join [split $cmd_text \n] \;]
  183.             set do_command 1
  184.         # Do we enable?
  185.         } -noenable {
  186.             set avenable 0
  187.         # Does tacacs automatically enable us?
  188.         } -autoenable {
  189.             set avautoenable 1
  190.             set avenable 0
  191.         } -* {
  192.             send_user "\nError: Unknown argument! $arg\n"
  193.             send_user $usage
  194.             exit 1
  195.         } default {
  196.             break
  197.         }
  198.     }
  199. }
  200. # Process routers...no routers listed is an error.
  201. if { $i == $argc } {
  202.     send_user "\nError: $usage"
  203. }
  204.  
  205. # Only be quiet if we are running a script (it can log its output
  206. # on its own)
  207. if { $do_script } {
  208.     log_user 0
  209. } else {
  210.     log_user 1
  211. }
  212.  
  213. #
  214. # Done configuration/variable setting.  Now run with it...
  215. #
  216.  
  217. # custom send for Dell switches, they need to pause briefly before sending
  218. proc dsend {send_this} {
  219.     # sleep works as quick as .02, setting a bit higher for tolerance
  220.     sleep .05
  221.     send $send_this
  222. }
  223.  
  224. # Sets Xterm title if interactive...if its an xterm and the user cares
  225. proc label { host } {
  226.     global env
  227.     # if CLOGIN has an 'x' in it, don't set the xterm name/banner
  228.     if [info exists env(CLOGIN)] {
  229.         if {[string first "x" $env(CLOGIN)] != -1} { return }
  230.     }
  231.     # take host from ENV(TERM)
  232.     if [info exists env(TERM)] {
  233.         if [regexp \^(xterm|vs) $env(TERM) ignore ] {
  234.             send_user "\033]1;[lindex [split $host "."] 0]\a"
  235.             send_user "\033]2;$host\a"
  236.         }
  237.     }
  238. }
  239.  
  240. # This is a helper function to make the password file easier to
  241. # maintain.  Using this the password file has the form:
  242. # add password sl*        pete cow
  243. # add password at*        steve
  244. # add password *        hanky-pie
  245. proc add {var args} { global int_$var ; lappend int_$var $args}
  246. proc include {args} {
  247.     global env
  248.     regsub -all "(^{|}$)" $args {} args
  249.     if { [ regexp "^/" $args ignore ] == 0 } {
  250.         set args $env(HOME)/$args
  251.     }
  252.     source_password_file $args
  253. }
  254.  
  255. proc find {var router} {
  256.     upvar int_$var list
  257.     if { [info exists list] } {
  258.         foreach line $list {
  259.             if { [string match [lindex $line 0] $router ] } {
  260.                 return [lrange $line 1 end]
  261.             }
  262.         }
  263.     }
  264.     return {}
  265. }
  266.  
  267. # Loads the password file.  Note that as this file is tcl, and that
  268. # it is sourced, the user better know what to put in there, as it
  269. # could install more than just password info...  I will assume however,
  270. # that a "bad guy" could just as easy put such code in the clogin
  271. # script, so I will leave .cloginrc as just an extention of that script
  272. proc source_password_file { password_file } {
  273.     global env
  274.     if { ! [file exists $password_file] } {
  275.         send_user "\nError: password file ($password_file) does not exist\n"
  276.         exit 1
  277.     }
  278.     file stat $password_file fileinfo
  279.     if { [expr ($fileinfo(mode) & 007)] != 0000 } {
  280.         send_user "\nError: $password_file must not be world readable/writable\n"
  281.         exit 1
  282.     }
  283.     if [ catch {source $password_file} reason ] {
  284.         send_user "\nError: $reason\n"
  285.         exit 1
  286.     }
  287. }
  288.  
  289. # Log into the router.
  290. # returns: 0 on success, 1 on failure, -1 if rsh was used successfully
  291. proc login { router user userpswd passwd enapasswd cmethod cyphertype } {
  292.     global spawn_id in_proc do_command do_script platform
  293.     global prompt u_prompt p_prompt e_prompt sshcmd
  294.     set in_proc 1
  295.     set uprompt_seen 0
  296.  
  297.     # try each of the connection methods in $cmethod until one is successful
  298.     set progs [llength $cmethod]
  299.     foreach prog [lrange $cmethod 0 end] {
  300.         incr progs -1
  301.         if [string match "telnet*" $prog] {
  302.             regexp {telnet(:([^[:space:]]+))*} $prog command suffix port
  303.             if {"$port" == ""} {
  304.                 set retval [ catch {spawn telnet $router} reason ]
  305.             } else {
  306.                 set retval [ catch {spawn telnet $router $port} reason ]
  307.             }
  308.             if { $retval } {
  309.                 send_user "\nError: telnet failed: $reason\n"
  310.                 return 1
  311.             }
  312.         } elseif [string match "ssh*" $prog] {
  313.             regexp {ssh(:([^[:space:]]+))*} $prog command suffix port
  314.             if {"$port" == ""} {
  315.                 set retval [ catch {spawn $sshcmd -c $cyphertype -x -l $user $router} reason ]
  316.  
  317.             } else {
  318.                 set retval [ catch {spawn $sshcmd -c $cyphertype -x -l $user -p $port $router} reason ]
  319.             }
  320.             if { $retval } {
  321.                 send_user "\nError: $sshcmd failed: $reason\n"
  322.                 return 1
  323.             }
  324.         } elseif ![string compare $prog "rsh"] {
  325.             global command
  326.  
  327.             if { ! $do_command } {
  328.                 if { [llength $cmethod] == 1 } {
  329.                     send_user "\nError: rsh is an invalid method for -x and "
  330.                     send_user "interactive logins\n"
  331.                 }
  332.                 if { $progs == 0 } {
  333.                     return 1
  334.                 }
  335.                 continue;
  336.             }
  337.  
  338.             set commands [split $command \;]
  339.             set num_commands [llength $commands]
  340.             set rshfail 0
  341.             for {set i 0} {$i < $num_commands && !$rshfail} { incr i} {
  342.                 log_user 0
  343.                 set retval [ catch {spawn rsh $user@$router [lindex $commands $i] } reason ]
  344.                 if { $retval } {
  345.                     send_user "\nError: rsh failed: $reason\n"
  346.                     log_user 1; return 1
  347.                 }
  348.                 send_user "$router# [lindex $commands $i]\n"
  349.  
  350.                 # rcmd does not get a pager and no prompts, so we just have to
  351.                 # look for failures & lines.
  352.                 expect {
  353.                     "Connection refused" {
  354.                         catch {close}; wait;
  355.                         send_user "\nError: Connection\
  356.                        Refused ($prog): $router\n"
  357.                         set rshfail 1
  358.                     }
  359.                     -re "(Connection closed by|Connection to \[^\n\r]+ closed)" {
  360.                         catch {close}; wait;
  361.                         send_user "\nError: Connection\
  362.                        closed ($prog): $router\n"
  363.                         set rshfail 1
  364.                     }
  365.                     "Host is unreachable" {
  366.                         catch {close}; wait;
  367.                         send_user "\nError: Host Unreachable:\
  368.                        $router\n"
  369.                         set rshfail 1
  370.                     }
  371.                     "No address associated with" {
  372.                         catch {close}; wait;
  373.                         send_user "\nError: Unknown host\
  374.                        $router\n"
  375.                         set rshfail 1
  376.                     }
  377.                     -re "\b+" { exp_continue }
  378.                     -re "\[\n\r]+" { send_user -- "$expect_out(buffer)"; exp_continue }
  379.                     timeout {
  380.                         catch {close}; wait
  381.                         send_user "\nError: TIMEOUT reached\n"
  382.                         set rshfail 1
  383.                     }
  384.                     eof { catch {close}; wait }
  385.                 }
  386.                 log_user 1
  387.             }
  388.             if { $rshfail } {
  389.                 if { !$progs } {
  390.                     return 1
  391.                 } else {
  392.                     continue
  393.                 }
  394.             }
  395.             # fake the end of the session for rancid.
  396.             send_user "$router# exit\n"
  397.             # return rsh "success"
  398.             return -1
  399.         } else {
  400.             send_user "\nError: unknown connection method: $prog\n"
  401.             return 1
  402.         }
  403.         sleep 0.3
  404.  
  405.         # This helps cleanup each expect clause.
  406.         expect_after {
  407.             timeout {
  408.                 send_user "\nError: TIMEOUT reached\n"
  409.                 catch {close}; wait
  410.                 if { $in_proc} {
  411.                     return 1
  412.                 } else {
  413.                     continue
  414.                 }
  415.             } eof {
  416.                 send_user "\nError: EOF received\n"
  417.                 catch {close}; wait
  418.                 if { $in_proc} {
  419.                     return 1
  420.                 } else {
  421.                     continue
  422.                 }
  423.             }
  424.         }
  425.  
  426.         # Here we get a little tricky.  There are several possibilities:
  427.         # the router can ask for a username and passwd and then
  428.         # talk to the TACACS server to authenticate you, or if the
  429.         # TACACS server is not working, then it will use the enable
  430.         # passwd.  Or, the router might not have TACACS turned on,
  431.         # then it will just send the passwd.
  432.         # if telnet fails with connection refused, try ssh
  433.         expect {
  434.             -re "(Connection refused|Secure connection \[^\n\r]+ refused)" {
  435.                 catch {close}; wait
  436.                 if !$progs {
  437.                     send_user "\nError: Connection Refused ($prog): $router\n"
  438.                     return 1
  439.                 }
  440.             }
  441.             -re "(Connection closed by|Connection to \[^\n\r]+ closed)" {
  442.                 catch {close}; wait
  443.                 if !$progs {
  444.                     send_user "\nError: Connection closed ($prog): $router\n"
  445.                     return 1
  446.                 }
  447.             }
  448.             eof {
  449.                 send_user "\nError: Couldn't login: $router\n"
  450.                 wait; return 1
  451.             }
  452.             -nocase "unknown host\r" {
  453.                 catch {close};
  454.                 send_user "\nError: Unknown host $router\n"
  455.                 wait; return 1
  456.             }
  457.             "Host is unreachable" {
  458.                 catch {close};
  459.                 send_user "\nError: Host Unreachable: $router\n"
  460.                 wait; return 1
  461.             }
  462.             "No address associated with name" {
  463.                 catch {close};
  464.                 send_user "\nError: Unknown host $router\n"
  465.                 wait; return 1
  466.             }
  467.             -re "(Host key not found |The authenticity of host .* be established).*\(yes\/no\)\?" {
  468.                 dsend "yes\r"
  469.                 send_user "\nHost $router added to the list of known hosts.\n"
  470.                 exp_continue
  471.             }
  472.             -re "HOST IDENTIFICATION HAS CHANGED.* \(yes\/no\)\?" {
  473.                 dsend "no\r"
  474.                 send_user "\nError: The host key for $router has changed.  Update the SSH known_hosts file accordingly.\n"
  475.                 return 1
  476.             }
  477.             -re "Offending key for .* \(yes\/no\)\?" {
  478.                 dsend "no\r"
  479.                 send_user "\nError: host key mismatch for $router.  Update the SSH known_hosts file accordingly.\n"
  480.                 return 1
  481.             }
  482.             -re "(denied|Sorry)" {
  483.                 send_user "\nError: Check your passwd for $router\n"
  484.                 catch {close}; wait; return 1
  485.             }
  486.             "Login failed" {
  487.                 send_user "\nError: Check your passwd for $router\n"
  488.                 return 1
  489.             }
  490.             -re "% (Bad passwords|Authentication failed)" {
  491.                 send_user "\nError: Check your passwd for $router\n"
  492.                 return 1
  493.             }
  494.             "Press any key to continue." {
  495.                 # send_user "Pressing the ANY key\n"
  496.                 dsend "\r"
  497.                 exp_continue
  498.             }
  499.             -re "Enter Selection: " {
  500.                 # Catalyst 1900s have some lame menu.  Enter
  501.                 # K to reach a command-line.
  502.                 dsend "K\r"
  503.                 exp_continue;
  504.             }
  505.             -re "@\[^\r\n]+ $p_prompt" {
  506.                 # ssh pwd prompt
  507.                 sleep 1
  508.                 dsend "$userpswd\r"
  509.                 exp_continue
  510.             }
  511.             -re "$u_prompt" {
  512.                 dsend "$user\r"
  513.                 set uprompt_seen 1
  514.                 exp_continue
  515.             }
  516.             -re "$p_prompt" {
  517.                 sleep 1
  518.                 if {$uprompt_seen == 1} {
  519.                     dsend "$userpswd\r"
  520.                 } else {
  521.                     dsend "$passwd\r"
  522.                 }
  523.                 exp_continue
  524.             }
  525.             -re "$prompt" { break; }
  526.             "Login invalid" {
  527.                 send_user "\nError: Invalid login: $router\n";
  528.                 catch {close}; wait; return 1
  529.             }
  530.         }
  531.     }
  532.  
  533.     set in_proc 0
  534.     return 0
  535. }
  536.  
  537. # Enable
  538. proc do_enable { enauser enapasswd } {
  539.     global prompt in_proc
  540.     global u_prompt e_prompt
  541.     set in_proc 1
  542.  
  543.     dsend "enable\r"
  544.     expect {
  545.         -re "$u_prompt" { dsend "$enauser\r"; exp_continue }
  546.         -re "$e_prompt" { dsend "$enapasswd\r"; exp_continue }
  547.         "#"             { set prompt "#" }
  548.         "(enable)"      { set prompt "> (enable) " }
  549.         -re "(denied|Sorry|Incorrect)" {
  550.             # % Access denied - from local auth and poss. others
  551.             send_user "\nError: Check your Enable passwd\n";
  552.             return 1
  553.         }
  554.         "% Error in authentication" {
  555.             send_user "\nError: Check your Enable passwd\n"
  556.             return 1
  557.         }
  558.         "% Bad passwords" {
  559.             send_user "\nError: Check your Enable passwd\n"
  560.             return 1
  561.         }
  562.     }
  563.     # We set the prompt variable (above) so script files don't need
  564.     # to know what it is.
  565.     set in_proc 0
  566.     return 0
  567. }
  568.  
  569. proc processCommandOutput {prompt reprompt} {
  570.     global in_proc
  571.     expect {
  572.         -re "\b+"                       { exp_continue }
  573.         -re "^\[^\n\r *]*$reprompt"     { send_user -- "$expect_out(buffer)" }
  574.         -re "^\[^\n\r *]*$prompt"       { send_user -- "$expect_out(buffer)" }
  575.         -re "^\[^\n\r]*$reprompt."      { send_user -- "$expect_out(buffer)"; exp_continue }
  576.         -re "\[\n\r]+"                  { send_user -- "$expect_out(buffer)"; exp_continue }
  577.         # I don't know what this is, but it started showing up with the More prompt
  578.         # in newer Dells.  It's invisible when looking normally in a terminal.
  579.         -re "\u001b\\\[0m"              { exp_continue }
  580.         # The pager can not be turned off on earlier Dells, so we have to look
  581.         # for the "More" prompt.
  582.         -re "--More-- or \\(q\\)uit" {
  583.             send_user -- "$expect_out(buffer)"
  584.             dsend " "
  585.             exp_continue
  586.         }
  587.         -re "^More: <space>\[^\n\r]*"   {
  588.             send_user -- "$expect_out(buffer)"
  589.             dsend " "
  590.             exp_continue
  591.         }
  592.     }
  593. }
  594.  
  595. # Run commands given on the command line.
  596. proc run_commands { prompt command } {
  597.     global in_proc platform
  598.     set in_proc 1
  599.  
  600.     # escape any parens in the prompt, such as "(enable)"
  601.     regsub -all {[)(]} $prompt {\\&} reprompt
  602.     # match cisco config mode prompts too, such as router(config-if)#
  603.     regsub -all {^(.{1,14}).*([#>])$} $reprompt {\1([^#>\r\n]+)?[#>](\\([^)\\r\\n]+\\))?} reprompt
  604.  
  605.     # this is the only way i see to get rid of more prompts in o/p..grrrrr
  606.     log_user 0
  607.     # Is this a multi-command?
  608.     if [ string match "*\;*" "$command" ] {
  609.         set commands [split $command \;]
  610.         set num_commands [llength $commands]
  611.         for {set i 0} {$i < $num_commands} { incr i} {
  612.             dsend "[subst -nocommands [lindex $commands $i]]\r"
  613.             processCommandOutput $prompt $reprompt
  614.         }
  615.     } else {
  616.         dsend "[subst -nocommands $command]\r"
  617.         processCommandOutput $prompt $reprompt
  618.     }
  619.     log_user 1
  620.  
  621.     # drancid was failing because the switch is closing the connection before
  622.     # it has finished echoing the exit command.
  623.     set logout "exit"
  624.     set send_slow {1 .05}
  625.     send -s "$logout\r"
  626.     expect {
  627.         # 6248 wants quit to logout instead of exit
  628.         -re "\\% Invalid input detected at '\\^' marker." {
  629.             set logout "quit"
  630.             exp_continue;
  631.         }
  632.         # 6248 drops to unprivileged user on exit
  633.         -re ">" {
  634.             dsend "$logout\r"
  635.             exp_continue;
  636.         }
  637.         -re "^\[^\n\r *]*$reprompt" {
  638.             # the Cisco CE and Jnx ERX
  639.             # return to non-enabled mode
  640.             # on exit in enabled mode.
  641.             dsend "exit\r"
  642.             exp_continue;
  643.         }
  644.         "Do you wish to save your configuration changes" {
  645.             dsend "n\r"
  646.             exp_continue
  647.         }
  648.         -re "\[\n\r]+" { exp_continue }
  649.         timeout        { return 0 }
  650.         eof            { return 0 }
  651.     }
  652.     set in_proc 0
  653. }
  654.  
  655. #
  656. # For each router... (this is main loop)
  657. #
  658. source_password_file $password_file
  659. set in_proc 0
  660. foreach router [lrange $argv $i end] {
  661.     set router [string tolower $router]
  662.     send_user "$router\n"
  663.  
  664.     # Figure out the prompt.
  665.     # autoenable is off by default.  If we have it defined, it was done
  666.     # on the command line.  If it is not specifically set on the command
  667.     # line, check the password file.
  668.     if $avautoenable {
  669.         set autoenable 1
  670.         set enable 0
  671.         set prompt "(#| \\(enable\\))"
  672.     } else {
  673.         set ae [find autoenable $router]
  674.         if { "$ae" == "1" } {
  675.             set autoenable 1
  676.             set enable 0
  677.             set prompt "(#| \\(enable\\))"
  678.         } else {
  679.             set autoenable 0
  680.             set enable $avenable
  681.             set prompt ">"
  682.         }
  683.     }
  684.  
  685.     # look for noenable option in .cloginrc
  686.     if { [find noenable $router] != "" } {
  687.         set enable 0
  688.     }
  689.  
  690.     # Figure out passwords
  691.     if { $do_passwd || $do_enapasswd } {
  692.       set pswd [find password $router]
  693.       if { [llength $pswd] == 0 } {
  694.         send_user "\nError: no password for $router in $password_file.\n"
  695.         continue
  696.       }
  697.       if { $enable && $do_enapasswd && $autoenable == 0 && [llength $pswd] < 2 } {
  698.         send_user "\nError: no enable password for $router in $password_file.\n"
  699.         continue
  700.       }
  701.       set passwd [join [lindex $pswd 0] ""]
  702.       set enapasswd [join [lindex $pswd 1] ""]
  703.     }
  704.  
  705.     # Figure out username
  706.     if {[info exists username]} {
  707.       # command line username
  708.       set ruser $username
  709.     } else {
  710.       set ruser [join [find user $router] ""]
  711.       if { "$ruser" == "" } { set ruser $default_user }
  712.     }
  713.  
  714.     # Figure out username's password (if different from the vty password)
  715.     if {[info exists userpasswd]} {
  716.       # command line username
  717.       set userpswd $userpasswd
  718.     } else {
  719.       set userpswd [join [find userpassword $router] ""]
  720.       if { "$userpswd" == "" } { set userpswd $passwd }
  721.     }
  722.  
  723.     # Figure out enable username
  724.     if {[info exists enausername]} {
  725.       # command line enausername
  726.       set enauser $enausername
  727.     } else {
  728.       set enauser [join [find enauser $router] ""]
  729.       if { "$enauser" == "" } { set enauser $ruser }
  730.     }
  731.     # Figure out prompts
  732.     set u_prompt [find userprompt $router]
  733.     if { "$u_prompt" == "" } {
  734.         set u_prompt "(\[Ll]ogin|\[Uu]ser( *\[Nn]ame)?):"
  735.     } else {
  736.         set u_prompt [join [lindex $u_prompt 0] ""]
  737.     }
  738.     set p_prompt [find passprompt $router]
  739.     if { "$p_prompt" == "" } {
  740.         set p_prompt "(\[Pp]asswo*r*d):"
  741.     } else {
  742.         set p_prompt [join [lindex $p_prompt 0] ""]
  743.     }
  744.     set e_prompt [find enableprompt $router]
  745.     if { "$e_prompt" == "" } {
  746.         set e_prompt "\[Pp]assword:"
  747.     } else {
  748.         set e_prompt [join [lindex $e_prompt 0] ""]
  749.     }
  750.  
  751.     # Figure out cypher type
  752.     if {[info exists cypher]} {
  753.         # command line cypher type
  754.         set cyphertype $cypher
  755.     } else {
  756.         set cyphertype [find cyphertype $router]
  757.         if { "$cyphertype" == "" } { set cyphertype "3des" }
  758.     }
  759.  
  760.     # Figure out connection method
  761.     set cmethod [find method $router]
  762.     if { "$cmethod" == "" } { set cmethod {{telnet} {ssh}} }
  763.  
  764.     # Figure out the SSH executable name
  765.     set sshcmd [find sshcmd $router]
  766.     if { "$sshcmd" == "" } { set sshcmd {ssh} }
  767.  
  768.     # Login to the router
  769.     if {[login $router $ruser $userpswd $passwd $enapasswd $cmethod $cyphertype]} {
  770.         # if login failed or rsh was successful, move on to the next device
  771.         continue
  772.     }
  773.     if { $enable } {
  774.         if {[do_enable $enauser $enapasswd]} {
  775.             if { $do_command || $do_script } {
  776.                 close; wait
  777.                 continue
  778.             }
  779.         }
  780.     }
  781.     # we are logged in, now figure out the full prompt
  782.     dsend "\r"
  783.     expect {
  784.         -re "\[\r\n]+"                { exp_continue; }
  785.         # don't reset $prompt for dells, still expect this stuff, but do nothing
  786.         -re "^.+$prompt"        { set junk $expect_out(0,string);
  787.                                   #regsub -all "\[\]\[]" $junk {\\&} prompt;
  788.                                 }
  789.         # don't reset $prompt for dells, still expect this stuff, but do nothing
  790.         -re "^.+> \\\(enable\\\)"        {
  791.                                   set junk $expect_out(0,string);
  792.                                   #regsub -all "\[\]\[]" $junk {\\&} prompt;
  793.                                 }
  794.     }
  795.  
  796.     if { $do_command } {
  797.         if {[run_commands $prompt $command]} {
  798.             continue
  799.         }
  800.     } elseif { $do_script } {
  801.         # If the prompt is (enable), then we are on a switch and the
  802.         # command is "set length 0"; otherwise its "term length 0".
  803.         #if [ regexp -- ".*> .*enable" "$prompt" ] {
  804.         #    dsend "set length 0\r"
  805.         #    dsend "set logging session disable\r"
  806.         #} else {
  807.         #    dsend "term length 0\r"
  808.         #}
  809.         expect -re $prompt        {}
  810.         source $sfile
  811.         close
  812.     } else {
  813.         label $router
  814.         log_user 1
  815.         interact
  816.     }
  817.  
  818.     # End of for each router
  819.     wait
  820.     sleep 0.3
  821. }
  822. exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement