diff options
Diffstat (limited to 'bin/rivlogin.in')
-rw-r--r-- | bin/rivlogin.in | 441 |
1 files changed, 191 insertions, 250 deletions
diff --git a/bin/rivlogin.in b/bin/rivlogin.in index b9ca2bc..df8bc21 100644 --- a/bin/rivlogin.in +++ b/bin/rivlogin.in @@ -3,7 +3,7 @@ ## $Id$ ## ## @PACKAGE@ @VERSION@ -## Copyright (c) 1997-2008 by Terrapin Communications, Inc. +## Copyright (c) 1997-2009 by Terrapin Communications, Inc. ## All rights reserved. ## ## This code is derived from software contributed to and maintained by @@ -75,6 +75,8 @@ set output_file "" set conf_prompt "*\(config\)# " set logging 0 set config_mode 0 +# Save config, if prompted +set do_saveconfig 0 # Password file for routers to access set password_file $env(HOME)/.cloginrc @@ -122,28 +124,27 @@ if {[ info exists env(CLOGINRC) ]} { # Sets Xterm title if interactive...if its an xterm and the user cares # proc label { host } { - global env # if CLOGIN has an 'x' in it, don't set the xterm name/banner if [info exists env(CLOGIN)] { - if {[string first "x" $env(CLOGIN)] != -1} { return } + if {[string first "x" $env(CLOGIN)] != -1} { return } } if [info exists env(TERM)] { - if [regexp \^(xterm|vs) $env(TERM) ignore ] { - send_user "\033]1;[lindex [split $host "."] 0]\a" - send_user "\033]2;$host\a" - } + if [regexp \^(xterm|vs) $env(TERM) ignore ] { + send_user "\033]1;[lindex [split $host "."] 0]\a" + send_user "\033]2;$host\a" + } } } # This is a helper function to make the password file easier to # maintain. # NOTES: Using this the password file has the form: -# add password sl* pete cow -# add password at* steve -# add password * hanky-pie +# add password sl* pete cow +# add password at* steve +# add password * hanky-pie proc add { var args } { global $var @@ -156,23 +157,22 @@ proc add { var args } { # that a "bad guy" could just as easy put such code in the clogin # script, so I will leave .cloginrc as just an extention of that script proc source_password_file { } { - global env password_file read_password_file if { [info exists read_password_file] } { - return 1 + return 1 } if { [info exists password_file] == 0 } { - set password_file $env(HOME)/.cloginrc + set password_file $env(HOME)/.cloginrc } set read_password_file 1 file stat $password_file fileinfo if { [expr ($fileinfo(mode) & 007)] != 0000 } { - puts "ERROR: $password_file must not be group or world readable and writable\n" - return 1 + puts "ERROR: $password_file must not be group or world readable and writable\n" + return 1 } source $password_file @@ -183,23 +183,23 @@ proc source_password_file { } { proc find { var router } { if {[ source_password_file ] == 0 } { - return {} + return {} } upvar $var list if { [info exists list] } { - foreach line $list { - if { [string match [lindex $line 0] $router ] } { - return [lrange $line 1 end] - } - } + foreach line $list { + if { [string match [lindex $line 0] $router ] } { + return [lrange $line 1 end] + } + } } return {} } # pre: login completed ok # post: terminate login session by closing tcp connection -proc auto_exit { } { +proc auto_exit { } { global telnet_id @@ -225,19 +225,19 @@ proc login { router user userpswd passwd enapasswd } { global config verbose my_prompt if { $verbose == 1 } { - puts "DEBUG: login router = $router" - puts "DEBUG: login username = $user" - puts "DEBUG: login userpasswd = $userpswd" + puts "DEBUG: login router = $router" + puts "DEBUG: login username = $user" + puts "DEBUG: login userpasswd = $userpswd" puts "DEBUG: login passwd = $passwd" - puts "DEBUG: login enapasswd = $enapasswd" + puts "DEBUG: login enapasswd = $enapasswd" } spawn -noecho telnet $router set telnet_id $spawn_id if { $telnet_id == 0 } { - puts "ERROR: login: spawn telnet session failed.\n" - return 1 + puts "ERROR: login: spawn telnet session failed.\n" + return 1 } # wait for initial 'Press RETURN to...' response @@ -249,70 +249,56 @@ proc login { router user userpswd passwd enapasswd } { # If password fails 3 times then expect again set pass_attempt 0 - expect { - - -re ".*> " { } - - "Password:" { - incr pass_attempt - send -- "$passwd\r" - exp_continue - } - - "Username: " { - - set pattempt 0 - - send -- "$user\r" - expect { - - "Password: " { - - incr pattempt - if {$pattempt == 1} { - send -- "$userpswd\r"; - } else { - send -- "$enapasswd\r"; - } - exp_continue - } - - -re ".*> " { exp_continue;} - } - } - + expect { + -re ".*> " { } + "Password:" { + incr pass_attempt + send -- "$passwd\r" + exp_continue + } + "Username: " { + set pattempt 0 + + send -- "$user\r" + expect { + "Password: " { + incr pattempt + if {$pattempt == 1} { + send -- "$userpswd\r"; + } else { + send -- "$enapasswd\r"; + } + exp_continue + } + -re ".*> " { exp_continue;} + } + } "%TELNETD-W-BADPASSWD" { puts "ERROR: bad userid or password to telnet." return 1 } "%CONS-W-AUTH_PASSWD" { exp_continue - } - + } "% Authentication failed." { puts "ERROR: bad userid or password to telnet." return 1 } - - "Authentication Failed:" { puts "ERROR: bad userid or password to radius/tacacs+" return 1 } - - "Connection closed *" { - if {$pass_attempt == 3} { - puts "ERROR: Maximum attempts for password reached. Check password. Exiting."; - puts $expect_out(0,string); + "Connection closed *" { + if {$pass_attempt == 3} { + puts "ERROR: Maximum attempts for password reached. Check password. Exiting."; + puts $expect_out(0,string); return 1 - } - } - - timeout { - puts "ERROR: Timeout on login. Exiting."; - return 1 - } - + } + } + timeout { + puts "ERROR: Timeout on login. Exiting."; + return 1 + } eof { puts "ERROR: device closed telnet connection during login" return 1 @@ -324,7 +310,7 @@ proc login { router user userpswd passwd enapasswd } { expect -re ".*> " set abc "$expect_out(buffer)" set my_prompt "[lindex $abc 0]" - regexp {(.*[^>])} $my_prompt my + regexp {(.*[^>])} $my_prompt my return 0; } @@ -338,7 +324,7 @@ proc disable_cli_paging { } { send "cli set terminal rows 0\r" expect { - "$my_prompt" {return 0 } + "$my_prompt" {return 0 } } return 1 } @@ -346,19 +332,17 @@ proc disable_cli_paging { } { # pre: login returned 0, prompt at top level # post: turn off command completion return 0 # on error, return 1 -proc disable_cmd_autocomplete { } { +proc disable_cmd_autocomplete { } { global my_prompt send "cli set command completion off\r" expect { + $my_prompt { } - $my_prompt { } - - timeout { - puts "ERROR:disable_cmd_autocomplete(TIMEOUT)"; - return 0; - } - + timeout { + puts "ERROR:disable_cmd_autocomplete(TIMEOUT)"; + return 0; + } } return 0 @@ -371,18 +355,14 @@ proc logout { prompt } { # in case of not being at root cmd... # verify top level prompt state, move to it if necessary - if { $config_mode == 1 } { - send "exit\r" expect { "Do you want*" { send "no\r" } - "$enable_prompt" { } - timeout { puts "ERROR: logout: timeout from config mode\n" } eof { puts "ERROR: device dropped connection\n" } } @@ -391,8 +371,7 @@ proc logout { prompt } { send "logout\r" expect { - - "Are you sure*" { + "Are you sure*" { send "yes\r" return 0 } @@ -406,22 +385,21 @@ proc do_enable { enauser enapasswd userpswd } { global my_prompt enable_prompt set enable_prompt [ string trimright $my_prompt ">" ] set enable_prompt $enable_prompt\# + set uses_username 0; if { $verbose == 1 } { puts "DEBUG: do_enable: my_prompt = $my_prompt ena_prompt = $enable_prompt" } - set uses_username 0; - send "enable\r" expect { - Username: { + Username: { set uses_username 1; send -- "$enauser\r"; exp_continue } - Password: { + Password: { if {$uses_username == 1} { send -- "$userpswd\r"; } else { @@ -429,18 +407,14 @@ proc do_enable { enauser enapasswd userpswd } { } exp_continue } - - "$my_prompt" { + "$my_prompt" { puts "ERROR: do_enable failed to gain enable mode." return 1 } - "CONS-W-AUTH_PASSWD" { send -- "$enapasswd\r"; } - - "$enable_prompt " { } - "%SYS-W-NOPASSWD*" { } - - "Authentication Failed: Access Denied" { + "$enable_prompt " { } + "%SYS-W-NOPASSWD*" { } + "Authentication Failed: Access Denied" { puts "ERROR: Bad user or password for enable mode." return 1 } @@ -464,10 +438,8 @@ proc do_configure { } { send "configure\r" expect { - "$config_prompt " { } - "$my_prompt" { - } - + "$config_prompt " { } + "$my_prompt" { } eof { return 1} timeout { return 1} } @@ -484,9 +456,7 @@ proc start_logfile { output_file } { global logging if { [ string length $output_file ] != 0 } { - set rc [ catch { - log_file -noappend $output_file - } errMsg ] + set rc [ catch { log_file -noappend $output_file } errMsg ] if { $rc != 0 } { puts "ERROR: open file $output_file for write access failed. $errMsg\n" @@ -505,12 +475,12 @@ proc run_commands { prompt cmdstring } { set num_commands [llength $cmdstring] for {set i 0} {$i < $num_commands} { incr i} { - regsub -- {[ ]*([^\.]*)} [subst -nocommands [lindex $commands $i]] {\1} sendstring + regsub -- {[ ]*([^\.]*)} [subst -nocommands [lindex $commands $i]] {\1} sendstring - if {[ run_single_command $prompt $sendstring ] == 1} { - puts "ERROR: command '$sendstring' not processed by device. Check previous error messages." - return 1 - } + if {[ run_single_command $prompt $sendstring ] == 1} { + puts "ERROR: command '$sendstring' not processed by device. Check previous error messages." + return 1 + } } return 0 } @@ -529,16 +499,16 @@ proc run_single_command { prompt cmdstring } { set delay 0 if {$verbose == 1} { - puts "DEBUG: run_commands: prompt=$prompt \"$cmdstring\" " + puts "DEBUG: run_commands: prompt=$prompt \"$cmdstring\" " } # ays == "are you sure" - must send back yes if { [string compare $cmdstring "save startup" ] == 0 } { set need_ays 1 - set delay 1 - if {$verbose == 1} { - puts "DEBUG: save startup cmd seen, set need_ays = 1" - } + set delay 1 + if {$verbose == 1} { + puts "DEBUG: save startup cmd seen, set need_ays = 1" + } } # TODO: add case for copy command to startup, also prompts for ok @@ -549,48 +519,39 @@ proc run_single_command { prompt cmdstring } { send "$cmdstring\r" if { $delay == 1} { - sleep 1 + sleep 1 } expect { - - "%CLI-E-IVCMD*" { - puts "ERROR: run_commands(command rejected by device)\n" - set rc 1 - } - + "%CLI-E-IVCMD*" { + puts "ERROR: run_commands(command rejected by device)\n" + set rc 1 + } "%CLI-E-FACUNKNWN*" { - puts "ERROR: run_commands(command rejected by device)\n" - set rc 1 + puts "ERROR: run_commands(command rejected by device)\n" + set rc 1 } - "%SYS-I-ADDFAILED*" { - puts "ERROR: run_commands(command rejected by device)\n" - set rc 1 + puts "ERROR: run_commands(command rejected by device)\n" + set rc 1 } "%TFTP-E-REMOTE,*" { - puts "ERROR: run_commands(command rejected by device)\n" - set rc 1 + puts "ERROR: run_commands(command rejected by device)\n" + set rc 1 } - "%SYS-E-PRIMARY_NO_SUCH_IMAGE*" { - puts "ERROR: run_commands(command rejected by device)\n" - set rc 1 + puts "ERROR: run_commands(command rejected by device)\n" + set rc 1 } - "want to overwrite " { send "yes\r" if {$verbose == 1} { - puts "DEBUG: got overwrite question, set need_ays to 0" - } + puts "DEBUG: got overwrite question, set need_ays to 0" + } set need_ays 0 } - - - "%CONFIG-E-DUPLICATE,*" { - } - - "$prompt" { + "%CONFIG-E-DUPLICATE,*" { } + "$prompt" { if { $seen_prompt == 0 } { set seen_prompt 1 } @@ -603,14 +564,11 @@ proc run_single_command { prompt cmdstring } { exp_continue } } - - -re ".* More: m,<space> --- Quit: q --- One line: <return> ---" { - send "q" - exp_continue - } - - - timeout { + -re ".* More: m,<space> --- Quit: q --- One line: <return> ---" { + send "q" + exp_continue + } + timeout { if {$verbose == 1} { puts "DEBUG: timeout occured for the $seen_time time\n" } @@ -621,16 +579,14 @@ proc run_single_command { prompt cmdstring } { exp_continue } - puts "ERROR:run_commands(TIMEOUT)" - set rc 1 - } - - eof { + puts "ERROR:run_commands(TIMEOUT)" + set rc 1 + } + eof { puts "ERROR:run_commands(connection closed by device)\n" set rc 1 - } - - "\n" { exp_continue } + } + "\n" { exp_continue } } # clear input buffer of any remaining data @@ -645,39 +601,34 @@ proc init_userid { } { global default_user if {[ info exists env(RSTONE_USER) ] } { - set default_user $env(RSTONE_USER) + set default_user $env(RSTONE_USER) } else { - # This uses "id" which I think is portable. At least it has existed - # (without options) on all machines/OSes I've been on recently - - # unlike whoami or id -nu. - regexp {\(([^)]*)} [exec id] junk default_user + # This uses "id" which I think is portable. At least it has existed + # (without options) on all machines/OSes I've been on recently - + # unlike whoami or id -nu. + regexp {\(([^)]*)} [exec id] junk default_user } } proc source_script_file { filename } { - global my_prompt - - expect -re "$my_prompt" {} + global my_prompt - source $filename + expect -re "$my_prompt" {} + source $filename } - # pre: login completed ok, filename contains set of cli commands one per line # post: each command is extracted from filename and sent to device # return 0 on success, return 1 on error # NOTE: for scripts that begin with "configure", change the mode to configure # before executing the following commands proc process_script_file { filename } { - global my_prompt verbose set rc 0 set ifile "" - set rc [ catch { - set ifile [ open $filename r] - } errMsg ] + set rc [ catch { set ifile [ open $filename r] } errMsg ] if { $rc != 0 } { puts "ERROR: process_script_file: open script file $filename for read access failed. $errMsg\n" @@ -724,27 +675,20 @@ proc process_script_file { filename } { return $rc } - - # pre: filename is valid file # post: remove extended ascii sequences and other cruft # and prepend a header: rscmd: ip-addr : date # TODO: should watch all file commands more closely -proc strip_log { filename router } { - +proc strip_log { filename router } { global tempfile - set rc [ catch { - set ifile [ open $filename r] - } errMsg ] + set rc [ catch { set ifile [ open $filename r] } errMsg ] if { $rc != 0 } { puts "ERROR: strip_log: open script file $filename for read access failed. $errMsg\n" return 1 } - set rc [ catch { - set ofile [ open $tempfile w] - } errMsg ] + set rc [ catch { set ofile [ open $tempfile w] } errMsg ] if { $rc != 0 } { puts "ERROR: strip_log: open temp file $tempfile for write access failed. $errMsg\n" @@ -780,8 +724,6 @@ proc strip_log { filename router } { # # main section # - - if { $verbose == 1 } { puts "\n\nrscmd: Version 1.1 started on [exec date]" puts "[exec uname -a]" @@ -795,84 +737,83 @@ set send_human {.1 .3 1 .05 2} init_userid # Parse Command Line - for {set idx 0} {$idx < $argc} {incr idx} { - set arg [lindex $argv $idx] switch -glob -- $arg { - -c* - - -C* { - if {! [ regexp .\[cC\](.+) $arg ignore command]} { - incr idx - set command [ lindex $argv $idx ] - } - set do_command 1 + -c* - + -C* { + if {! [ regexp .\[cC\](.+) $arg ignore command]} { + incr idx + set command [ lindex $argv $idx ] + } + set do_command 1 # Expect debug mode } -d* { exp_internal 1 - # Environment variable to pass to -s scripts - } -E* - { - if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} { - set E$varname $varvalue - } else { - send_user "Error: invalid format for -E in $arg\n" - exit 1 - } + # Environment variable to pass to -s scripts + } -E* + { + if {[ regexp .\[E\](.+)=(.+) $arg ignore varname varvalue]} { + set E$varname $varvalue + } else { + send_user "Error: invalid format for -E in $arg\n" + exit 1 + } # Expect script to run - } -s* - - -S* { - if {! [ regexp .\[sS\](.+) $arg ignore sfile]} { - incr idx - set sfile [ lindex $argv $idx ] - } - - if { ! [ file exists $sfile ] } { - puts "ERROR: invalid argument script file \"$sfile\" does not exist.\n" + } -s* { + if {! [ regexp .\[sS\](.+) $arg ignore sfile]} { + incr idx + set sfile [ lindex $argv $idx ] + } + + if { ! [ file exists $sfile ] } { + puts "ERROR: invalid argument script file \"$sfile\" does not exist.\n" exit 1 } - if { ! [ file readable $sfile ] } { - puts "ERROR: invalid argument script file \"$sfile\" permissions disallow read access.\n" + if { ! [ file readable $sfile ] } { + puts "ERROR: invalid argument script file \"$sfile\" permissions disallow read access.\n" exit 1 - } + } - set do_script 1 + set do_script 1 + # save config on exit + } -S* { + set do_saveconfig 1 # Version string } -V* { send_user "@PACKAGE@ @VERSION@\n" exit 0 - # Command file - } -x* - - -X { - if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} { - incr idx - set cmd_file [ lindex $argv $idx ] - } - if [ catch {set cmd_fd [open $cmd_file r]} reason ] { - send_user "\nError: $reason\n" - exit 1 - } - set cmd_text [read $cmd_fd] - close $cmd_fd - set command [join [split $cmd_text \n] \;] - set do_command 1 - } -f* - - -F* { - if {! [ regexp .\[fF\](.+) $arg ignore password_file]} { - incr idx - set password_file [ lindex $argv $idx ] - } - - } -o* - - -O* { - if {! [ regexp .\[fF\](.+) $arg ignore password_file]} { - incr idx - set output_file [ lindex $argv $idx ] + # Command file + } -x* - + -X { + if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} { + incr idx + set cmd_file [ lindex $argv $idx ] + } + if [ catch {set cmd_fd [open $cmd_file r]} reason ] { + send_user "\nError: $reason\n" + exit 1 + } + set cmd_text [read $cmd_fd] + close $cmd_fd + set command [join [split $cmd_text \n] \;] + set do_command 1 + } -f* - + -F* { + if {! [ regexp .\[fF\](.+) $arg ignore password_file]} { + incr idx + set password_file [ lindex $argv $idx ] + } + } -o* - + -O* { + if {! [ regexp .\[fF\](.+) $arg ignore password_file]} { + incr idx + set output_file [ lindex $argv $idx ] if { $verbose == 1 } { puts "DEBUG: output file: $output_file" } - } + } # Timeout } -t* - -T* { @@ -1009,7 +950,7 @@ foreach router [lrange $argv $idx end] { exit 1 } -# if { [process_script_file $sfile] == 1} { +# if { [process_script_file $sfile] == 1}{ # puts "DEBUG: logfile $output_file closed on error\n" # logout $my_prompt # exit 1 |