summaryrefslogtreecommitdiffstats
path: root/bin/rivlogin.in
diff options
context:
space:
mode:
Diffstat (limited to 'bin/rivlogin.in')
-rw-r--r--bin/rivlogin.in433
1 files changed, 222 insertions, 211 deletions
diff --git a/bin/rivlogin.in b/bin/rivlogin.in
index 12554d5..2d80217 100644
--- a/bin/rivlogin.in
+++ b/bin/rivlogin.in
@@ -1,8 +1,9 @@
#! @EXPECT_PATH@ --
##
-## $Id: rivlogin.in,v 1.15 2004/01/11 05:39:15 heas Exp $
+## $Id: rivlogin.in,v 1.26 2006/12/08 21:28:26 heas Exp $
##
-## Copyright (C) 1997-2004 by Terrapin Communications, Inc.
+## @PACKAGE@ @VERSION@
+## Copyright (C) 1997-2006 by Terrapin Communications, Inc.
## All rights reserved.
##
## This software may be freely copied, modified and redistributed
@@ -24,24 +25,28 @@
# rivlogin - Riverstone (and Enterasys SSR) login
#
# Based upon rscmd (see nmops.org)
-# rscmd - Riverstone Networks Automated login
-# by Mike MacFaden, Kiran Addepalli
+# rscmd - Riverstone Networks Automated login
+# by Mike MacFaden, Kiran Addepalli
# Riverstone Networks, 2000
#
# Returned to the RANCID crowd by andrew fort
-# Global vars section
+# Usage line
+set usage "Error: Usage: $argv0 \[-noenable\] \
+\[-f cloginrc-file\] \[-c command\] \[-Evar=x\] \[-s script-file\] \
+\[-x command-file\] \[-t timeout\] \[-o output-file\] \
+router \[router...\]\n"
# program diagnostics
set verbose 0
set success 1
set config 0
-
+
# in seconds to wait for data back from device
set timeout 10
set tempfile "/tmp/rivlogin.[exec date]"
-# cli command prompt
+# cli command prompt
set my_prompt ">"
set enable_prompt "\#"
@@ -60,18 +65,35 @@ set do_script 0
set log_user 0
# The default CLI mode to login to is "enable" mode
-set enable 1
+set avenable 1
# The default is to look in the password file to find the passwords. This
# tracks if we receive them on the command line.
set do_passwd 1
set do_enapasswd 1
-
-# cmd usage
-set usage "Error: Usage: $argv0 \[-noenable\] \
-\[-f cloginrc-file\] \[-c command\] \[-Evar=x\] \[-s script-file\] \
-\[-x command-file\] \[-t timeout\] \[-o output-file\] \
-router \[router...\]\n"
+#
+set send_human {.4 .4 .7 .3 5}
+
+# Find the user in the ENV, or use the unix userid.
+if {[ info exists env(CISCO_USER) ]} {
+ set default_user $env(CISCO_USER)
+} elseif {[ info exists env(USER) ]} {
+ set default_user $env(USER)
+} elseif {[ info exists env(LOGNAME) ]} {
+ set default_user $env(LOGNAME)
+} 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.
+ if [ catch {exec id} reason ] {
+ send_error "\nError: could not exec id: $reason\n"
+ exit 1
+ }
+ regexp {\(([^)]*)} "$reason" junk default_user
+}
+if {[ info exists env(CLOGINRC) ]} {
+ set password_file $env(CLOGINRC)
+}
# Procedures Section
@@ -79,7 +101,6 @@ router \[router...\]\n"
#
# Sets Xterm title if interactive...if its an xterm and the user cares
#
-
proc label { host } {
global env
@@ -97,35 +118,32 @@ proc label { host } {
}
}
-
# 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
-
-proc add { var args } {
+proc add { var args } {
global $var
lappend $var $args
-}
+}
# Loads the password file. Note that as this file is tcl, and that
# it is sourced, the user better know what to put in there, as it
# could install more than just password info... I will assume however,
# 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
-
+# 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] } {
+ if { [info exists read_password_file] } {
return 1
}
- if { [info exists password_file] == 0 } {
+ if { [info exists password_file] == 0 } {
set password_file $env(HOME)/.cloginrc
}
@@ -142,15 +160,14 @@ proc source_password_file { } {
# pre: var is x, router is y
# post: return routerr entry from database else null string
-
proc find { var router } {
if {[ source_password_file ] == 0 } {
return {}
}
- upvar $var list
- if { [info exists list] } {
+ upvar $var list
+ if { [info exists list] } {
foreach line $list {
if { [string match [lindex $line 0] $router ] } {
return [lrange $line 1 end]
@@ -160,13 +177,11 @@ proc find { var router } {
return {}
}
-
# pre: login completed ok
# post: terminate login session by closing tcp connection
-
proc auto_exit { } {
- global telnet_id
+ global telnet_id
if { $verbose == 1 } {
puts "DEBUG: auto_exit closing connection to pid $telnet_id\n"
@@ -179,8 +194,7 @@ proc auto_exit { } {
# post: return 0 on successful login, else 1
#
# NOTE: a number of globals are setup: my_prompt, telnet_id are key
-# and paging of cli output is disabled
-
+# and paging of cli output is disabled
proc login { router user userpswd passwd enapasswd } {
global login_array
@@ -212,7 +226,7 @@ proc login { router user userpswd passwd enapasswd } {
expect "*"
send "\r"
- # If password fails 3 times then expect again
+ # If password fails 3 times then expect again
set pass_attempt 0
expect {
@@ -220,7 +234,7 @@ proc login { router user userpswd passwd enapasswd } {
-re ".*> " { }
"Password:" {
- incr pass_attempt
+ incr pass_attempt
send "$passwd\r"
exp_continue
}
@@ -232,13 +246,13 @@ proc login { router user userpswd passwd enapasswd } {
send "$user\r"
expect {
- "Password: " {
+ "Password: " {
incr pattempt
if {$pattempt == 1} {
- send "$userpswd\r";
- } else {
- send "$enapasswd\r";
+ send "$userpswd\r";
+ } else {
+ send "$enapasswd\r";
}
exp_continue
}
@@ -246,8 +260,8 @@ proc login { router user userpswd passwd enapasswd } {
-re ".*> " { exp_continue;}
}
}
-
- "%TELNETD-W-BADPASSWD" {
+
+ "%TELNETD-W-BADPASSWD" {
puts "ERROR: bad userid or password to telnet."
return 1
}
@@ -266,7 +280,7 @@ proc login { router user userpswd passwd enapasswd } {
return 1
}
- "Connection closed *" {
+ "Connection closed *" {
if {$pass_attempt == 3} {
puts "ERROR: Maximum attempts for password reached. Check password. Exiting.";
puts $expect_out(0,string);
@@ -279,7 +293,7 @@ proc login { router user userpswd passwd enapasswd } {
return 1
}
- eof {
+ eof {
puts "ERROR: device closed telnet connection during login"
return 1
}
@@ -298,7 +312,6 @@ proc login { router user userpswd passwd enapasswd } {
# pre: login completed ok
# post: turn off paging of commands
-
proc disable_cli_paging { } {
global my_prompt
@@ -313,7 +326,6 @@ 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 { } {
global my_prompt
@@ -322,9 +334,9 @@ proc disable_cmd_autocomplete { } {
$my_prompt { }
- timeout {
+ timeout {
puts "ERROR:disable_cmd_autocomplete(TIMEOUT)";
- return 0;
+ return 0;
}
}
@@ -333,8 +345,7 @@ proc disable_cmd_autocomplete { } {
}
# pre: login returned 0, do_enable returned 0, cli is in enable or config mode
-# post: issues logout cli to device, returns 0
-
+# post: issues logout cli to device, returns 0
proc logout { prompt } {
global config_mode enable_prompt
@@ -342,7 +353,7 @@ proc logout { prompt } {
# verify top level prompt state, move to it if necessary
if { $config_mode == 1 } {
-
+
send "exit\r"
expect {
@@ -370,7 +381,6 @@ proc logout { prompt } {
# pre: current mode allows transition to enable mode
# post: enable mode entered, my_prompt updated, return 0 else 1
-
proc do_enable { enauser enapasswd userpswd } {
global expect_out verbose
global my_prompt enable_prompt
@@ -380,19 +390,32 @@ proc do_enable { enauser enapasswd userpswd } {
if { $verbose == 1 } {
puts "DEBUG: do_enable: my_prompt = $my_prompt ena_prompt = $enable_prompt"
}
-
+
+ set uses_username 0;
+
send "enable\r"
expect {
- Username: { send "$enauser\r"; exp_continue }
- Password: { send "$userpswd\r"; exp_continue }
+ Username: {
+ set uses_username 1;
+ send "$enauser\r";
+ exp_continue
+ }
+ Password: {
+ if {$uses_username == 1} {
+ send "$userpswd\r";
+ } else {
+ send "$enapasswd\r";
+ }
+ exp_continue
+ }
"$my_prompt" {
puts "ERROR: do_enable failed to gain enable mode."
return 1
}
- "CONS-W-AUTH_PASSWD" { send "$enapasswd\r"; }
+ "CONS-W-AUTH_PASSWD" { send "$enapasswd\r"; }
"$enable_prompt " { }
"%SYS-W-NOPASSWD*" { }
@@ -402,14 +425,13 @@ proc do_enable { enauser enapasswd userpswd } {
return 1
}
}
-
+
set my_prompt $enable_prompt
return 0
}
# pre: current mode allows transition to enable mode
# post: enable mode entered, my_prompt updated, return 0 else 1
-
proc do_configure { } {
global expect_out verbose config_mode
global my_prompt
@@ -419,7 +441,7 @@ proc do_configure { } {
if { $verbose == 1 } {
puts "DEBUG: do_config: my_prompt = $my_prompt cfg_prompt = $config_prompt"
}
-
+
send "configure\r"
expect {
"$config_prompt " { }
@@ -438,15 +460,14 @@ proc do_configure { } {
# track sent/received from device to output_file
# pre: outut_file is valid filename w/write access
# post: logfile open, global var logging == 1, return 0 , else 1
-
proc start_logfile { output_file } {
- global logging
+ global logging
if { [ string length $output_file ] != 0 } {
- set rc [ catch {
+ set rc [ catch {
log_file -noappend $output_file
} errMsg ]
-
+
if { $rc != 0 } {
puts "ERROR: open file $output_file for write access failed. $errMsg\n"
return 1
@@ -458,7 +479,7 @@ proc start_logfile { output_file } {
}
proc run_commands { prompt cmdstring } {
- global sendstring
+ global sendstring
set commands [split $cmdstring \;]
set num_commands [llength $cmdstring]
@@ -474,13 +495,11 @@ proc run_commands { prompt cmdstring } {
return 0
}
-
# Run commands given on the command line
# pre: prompt is current system cli prompt, cmdstring is command to execute
# post: return 0 on success else 1
# NOTE: output from router ends up in output_file if specified
# expect internal input buffer is reset to "" after each command
-
proc run_single_command { prompt cmdstring } {
global verbose
set rc 0
@@ -498,7 +517,7 @@ proc run_single_command { prompt cmdstring } {
set need_ays 1
set delay 1
if {$verbose == 1} {
- puts "DEBUG: save startup cmd seen, set need_ays = 1"
+ puts "DEBUG: save startup cmd seen, set need_ays = 1"
}
}
@@ -511,7 +530,7 @@ proc run_single_command { prompt cmdstring } {
if { $delay == 1} {
sleep 1
- }
+ }
expect {
@@ -542,7 +561,7 @@ proc run_single_command { prompt cmdstring } {
"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
}
@@ -551,7 +570,7 @@ proc run_single_command { prompt cmdstring } {
"%CONFIG-E-DUPLICATE,*" {
}
- "$prompt" {
+ "$prompt" {
if { $seen_prompt == 0 } {
set seen_prompt 1
}
@@ -571,7 +590,7 @@ proc run_single_command { prompt cmdstring } {
}
- timeout {
+ timeout {
if {$verbose == 1} {
puts "DEBUG: timeout occured for the $seen_time time\n"
}
@@ -586,8 +605,8 @@ proc run_single_command { prompt cmdstring } {
set rc 1
}
- eof {
- puts "ERROR:run_commands(connection closed by device)\n"
+ eof {
+ puts "ERROR:run_commands(connection closed by device)\n"
set rc 1
}
@@ -602,15 +621,14 @@ proc run_single_command { prompt cmdstring } {
# pre: RSTONE_USER env var is set
# post: update global "default_user" to this string
-
proc init_userid { } {
global default_user
if {[ info exists 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 -
+ # 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
}
@@ -631,14 +649,13 @@ proc source_script_file { filename } {
# 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 rc [ catch {
set ifile [ open $filename r]
} errMsg ]
@@ -650,16 +667,16 @@ proc process_script_file { filename } {
set line_cnt 0
while { [eof $ifile] != 1 } {
-
+
set bytes [ gets $ifile cmd ]
incr line_cnt
- if { $bytes < 0 } {
- break
+ if { $bytes < 0 } {
+ break
} elseif { $bytes == 0 } {
continue
}
-
+
if { $verbose == 1 } {
puts "DEBUG: line:$line_cnt cmd = $cmd\n"
}
@@ -693,12 +710,11 @@ proc process_script_file { filename } {
# 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 } {
global tempfile
- set rc [ catch {
+ set rc [ catch {
set ifile [ open $filename r]
} errMsg ]
@@ -706,7 +722,7 @@ proc strip_log { filename router } {
puts "ERROR: strip_log: open script file $filename for read access failed. $errMsg\n"
return 1
}
- set rc [ catch {
+ set rc [ catch {
set ofile [ open $tempfile w]
} errMsg ]
@@ -718,12 +734,11 @@ proc strip_log { filename router } {
set nl 0
puts $ofile "rscmd: $router : [exec date]"
-
+
while { [eof $ifile] != 1 } {
-
set bytes [ gets $ifile cmd ]
- if { $bytes <= 0 } {
- break
+ if { $bytes <= 0 } {
+ break
}
incr nl
if { $nl <= 2 } {
@@ -801,6 +816,10 @@ for {set idx 0} {$idx < $argc} {incr idx} {
}
set do_script 1
+ # Version string
+ } -V* {
+ send_user "@PACKAGE@ @VERSION@\n"
+ exit 0
# Command file
} -x* -
-X {
@@ -832,22 +851,21 @@ for {set idx 0} {$idx < $argc} {incr idx} {
puts "DEBUG: output file: $output_file"
}
}
-
- } -t* -
- -T* {
- incr idx
- set timeout [ lindex $argv $idx ]
-
- } -noenable {
- set enable 0
- } -* {
- puts "ERROR:unkown argument passed: $arg\n"
- puts $usage
+ # Timeout
+ } -t* -
+ -T* {
+ incr idx
+ set timeout [ lindex $argv $idx ]
+ # Do we enable?
+ } -noenable {
+ set avenable 0
+ } -* {
+ send_user "Error: Unkown argument! $arg\n"
+ send_user $usage
exit 1
-
- } default {
+ } default {
break
- }
+ }
}
}
@@ -859,146 +877,139 @@ if { $idx == $argc } {
}
# main loop
-
foreach router [lrange $argv $idx end] {
set router [string tolower $router]
-# Figure out passwords
-if {$verbose == 1} {
- puts "DEBUG: do_passwd = $do_passwd\n"
- puts "DEBUG: do_enablepasswd = $do_enapasswd\n"
-}
-
-if { $do_passwd || $do_enapasswd } {
- set pswd [find password $router]
- if { [llength $pswd] == 0 } {
- puts "ERROR: - no password for $router in $password_file.\n"
- exit 1
- }
- if { $do_enapasswd && [llength $pswd] < 2 } {
- puts "ERROR: no enable password found for $router in $password_file."
- exit 1
- }
-
- set passwd [join [lindex $pswd 0] ""]
- set enapasswd [join [lindex $pswd 1] ""]
-}
-
-
-# Figure out user to login with if necessary
-
-if {[info exists username]} {
- # command line username
- set user $username
-} else {
- set user [join [find user $router] ""]
- if { "$user" == "" } { set user $default_user }
-}
-
-# Figure out username's password
-
-if {[info exists userpasswd]} {
- # command line username
- set userpswd $userpasswd
-} else {
- set userpswd [join [find userpassword $router] ""]
- if { "$userpswd" == "" } { set userpswd $passwd }
-}
+ # Figure out passwords
+ if {$verbose == 1} {
+ puts "DEBUG: do_passwd = $do_passwd\n"
+ puts "DEBUG: do_enablepasswd = $do_enapasswd\n"
+ }
-# Figure out enable username
+ # look for noenable option in .cloginrc
+ if { [find noenable $router] != "" } {
+ set enable 0
+ } else {
+ set enable $avenable
+ }
-if {[info exists enausername]} {
- # command line enausername
- set enauser $enausername
-} else {
- set enauser [join [find enauser $router] ""]
- if { "$enauser" == "" } { set enauser $user }
-}
+ if { $do_passwd || $do_enapasswd } {
+ set pswd [find password $router]
+ if { [llength $pswd] == 0 } {
+ puts "ERROR: - no password for $router in $password_file.\n"
+ exit 1
+ }
+ if { $do_enapasswd && [llength $pswd] < 2 } {
+ puts "ERROR: no enable password found for $router in $password_file."
+ exit 1
+ }
-# Login to the router, set my_prompt to router's cmd prompt
+ set passwd [join [lindex $pswd 0] ""]
+ set enapasswd [join [lindex $pswd 1] ""]
+ } else {
+ set passwd $userpasswd
+ set enapasswd $enapasswd
+ }
-if {[login $router $user $userpswd $passwd $enapasswd ]} {
- if { $verbose == 1 } {
- puts "DEBUG: login to $router failed\n"
+ # Figure out user to login with if necessary
+ if {[info exists username]} {
+ # command line username
+ set user $username
+ } else {
+ set user [join [find user $router] ""]
+ if { "$user" == "" } { set user $default_user }
}
- exit 1
-}
-if {$verbose == 1 } {
- puts "DEBUG: login completed ok\n"
-}
+ # Figure out username's password
+ if {[info exists userpasswd]} {
+ # command line username
+ set userpswd $userpasswd
+ } else {
+ set userpswd [join [find userpassword $router] ""]
+ if { "$userpswd" == "" } { set userpswd $passwd }
+ }
-if { $enable == 1 } {
+ # Figure out enable username
+ if {[info exists enausername]} {
+ # command line enausername
+ set enauser $enausername
+ } else {
+ set enauser [join [find enauser $router] ""]
+ if { "$enauser" == "" } { set enauser $user }
+ }
- if { [do_enable $enauser $enapasswd $userpswd] == 1} {
+ # Login to the router, set my_prompt to router's cmd prompt
+ if {[login $router $user $userpswd $passwd $enapasswd ]} {
if { $verbose == 1 } {
- puts "DEBUG: switch to enable mode on $router failed\n"
+ puts "DEBUG: login to $router failed\n"
}
exit 1
}
-}
-
-# run in one of three modes
-
-if { $do_command } {
- disable_cmd_autocomplete
- disable_cli_paging
-
- if {[ start_logfile $output_file] != 0 } {
- exit 1
+ if {$verbose == 1 } {
+ puts "DEBUG: login completed ok\n"
}
- if {[ run_commands $my_prompt $command ]} {
-
- log_file
- exit 1
+ if { $enable == 1 } {
+ if { [do_enable $enauser $enapasswd $userpswd] == 1} {
+ if { $verbose == 1 } {
+ puts "DEBUG: switch to enable mode on $router failed\n"
+ }
+ exit 1
+ }
+ }
- } else {
+ # run in one of three modes
+ if { $do_command } {
+ disable_cmd_autocomplete
+ disable_cli_paging
- logout $my_prompt
+ if { [start_logfile $output_file] != 0 } {
+ exit 1
+ }
- }
-
-} elseif { $do_script } {
-
- disable_cmd_autocomplete
- disable_cli_paging
-
- if {[ start_logfile $output_file] != 0 } {
- exit 1
- }
+ if {[ run_commands $my_prompt $command ]} {
+ log_file
+ exit 1
+ } else {
+ logout $my_prompt
+ }
+ } elseif { $do_script } {
+ disable_cmd_autocomplete
+ disable_cli_paging
- #if { [process_script_file $sfile] == 1} {
-# puts "DEBUG: logfile $output_file closed on error\n"
-# logout $my_prompt
-# exit 1
-# }
+ if {[ start_logfile $output_file] != 0 } {
+ exit 1
+ }
- source_script_file $sfile
+# if { [process_script_file $sfile] == 1} {
+# puts "DEBUG: logfile $output_file closed on error\n"
+# logout $my_prompt
+# exit 1
+# }
- logout $my_prompt
+ source_script_file $sfile
-} else {
-
- label $router
- log_user 1
+ logout $my_prompt
+ } else {
+ label $router
+ log_user 1
- if {[ start_logfile $output_file] != 0 } {
- exit 1
+ if {[ start_logfile $output_file] != 0 } {
+ exit 1
+ }
+ interact
+ log_file
}
- interact
- log_file
-}
-if { $verbose == 1 } {
- puts "DEBUG: exiting normally.\n"
-}
+ if { $verbose == 1 } {
+ puts "DEBUG: exiting normally.\n"
+ }
-if { $logging == 1} {
- log_file
- strip_log $output_file $router
-}
+ if { $logging == 1} {
+ log_file
+ strip_log $output_file $router
+ }
}
# puts "\n"