Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
#!/usr/bin/perl -w # setpassCat.pl # pod at tail use strict; use Net::Telnet::Cisco; # simplify telnet to Cisco devices use Term::ReadKey; # disable screen echo during password ent +ry use Tie::IxHash; # insertion-order hash of passwords+promp +ts use Time::localtime; # timestamp of each target device use vars qw( $target $input $newpass $newenablepass $ntc @cmd_output ); my %file = ( in => 'spC.in', sessionlog => 'spC.log', sessionsummary => 'spC.summ', NTClog => 'spC.input_log', ); my %parm = ( pwtimeout => 120, # seconds to wait for password from keybo +ard NTCtimeout => 5, # seconds to wait for response from devic +e NTCerrmode => 'return', # Net::Telnet::Cisco not die on problem d +evice targetcount => 0, # start with device count at zero ); ###################################################################### +##### umask oct 177; # $input_log file accessible to only this + user PrintBar(); print " Change passwords for multiple Cisco CatOS LAN switches\n"; PrintBar(); ###################################################################### +##### if (-e $file{sessionlog} and -f _) { unlink ($file{sessionlog}) or die " Error unlinking $file{sessionlog}: $!" } open (LOG, "> $file{sessionlog}") or die " Error opening $file{sessionlog}: $!"; ###################################################################### +##### unless (@ARGV) { unless (-r $file{in} && -T_) { Usage(); } @ARGV = "$file{in}" or die " Error opening $file{in}: $!"; chomp (@ARGV = <>); } ###################################################################### +##### print " Validating target list.\n"; foreach $target (@ARGV) { chomp $target; print (" $target\n"); unless ($target =~ (/^(\w|-|\.)+$/)) { print( "\n Error reading $file{in}:\n", " \"$target\" is an improperly formatted device name.\n", " Only alphanumeric, underscore, dash and dot allowed.\n\ +n", " Edit $file{in} to remove puctuation,", " blank lines and/or blank spaces.\n", ); WrapItUp(); exit; } } print ("\n"); ###################################################################### +##### print " Prompting for existing passwords\n", " (keystrokes *not* echoed to screen or written to disk)\n"; tie my %prompts, "Tie::IxHash"; %prompts = ( 'Enter existing password:' => 'oldpass', 'Enter existing enable password:' => 'olden', ); tie my %passwds, "Tie::IxHash"; foreach my $prompt (keys %prompts) { print " $prompt "; ReadMode('noecho'); # don't echo password to s +creen &WaitForPassword(); $passwds{$prompts{$prompt}} = $input; ReadMode('restore'); # re-activate screen + echo print "\n"; } print "\n"; my $oldpass = ($passwds{"oldpass"}); my $oldenablepass = ($passwds{"olden"}); ###################################################################### +##### print " Prompting for new passwords\n", " (keystrokes *not* echoed to screen or written to disk)\n"; tie my %newprompts, "Tie::IxHash"; %newprompts = ( 'Enter new password:' => 'newpass', ' Retype to confirm:' => 'confpass', 'Enter new enable password:' => 'newen', ' Retype to confirm: ' => 'confen', ); tie my %newpasswds, "Tie::IxHash"; foreach my $newprompt(keys %newprompts) { print " $newprompt "; ReadMode('noecho'); # don't echo password to scre +en &WaitForPassword(); $newpasswds{$newprompts{$newprompt}} = $input; ReadMode(0); # re-activate screen ec +ho print "\n"; } print "\n"; $newpass = ($newpasswds{"newpass"}); my $confirmpass = ($newpasswds{"confpass"}); $newenablepass = ($newpasswds{"newen"}); my $confirmenablepass = ($newpasswds{"confen"}); unless ( ("$newpass" eq "$confirmpass") and ("$newenablepass" eq "$confirmenablepass")) { PasswordsMismatch(); } ###################################################################### +##### PrintLogConsole (" Passwords will be updated on these devices:\n"); for(@ARGV) { PrintLogConsole (" $_\n"); } PrintLogConsole ("\n"); Pause (); PrintBar(); ###################################################################### +##### foreach $target (@ARGV) { ShowPcTime(); ++$parm{targetcount}; if ($ntc = Net::Telnet::Cisco->new ( host => $target, errmode => $parm{NTCerrmode}, timeout => $parm{NTCtimeout}, input_log => $file{NTClog}, )) { $ntc -> login('',$oldpass); PrintLastPrompt(4); if ($ntc -> enable($oldenablepass)) { PrintLastPrompt(2); ChangePass(); } else { PrintLogConsole ("Error accessing $target\n"); PrintLastPrompt(2); } $ntc -> cmd('disa'); print (@cmd_output); PrintLastPrompt(2); $ntc -> disable; PrintLastPrompt(4); $ntc -> close; } else { PrintLogConsole ("Error connecting to $target\n"); } } ShowPcTime(); WrapItUp(); ParseLog2Summary(); ###################################################################### +##### # print most recent telnet session prompt to log and console # param is number of spaces to precede device prompt sub PrintLastPrompt { PrintLogConsole (' 'x $_[0], $ntc -> last_prompt, "\n"); } ###################################################################### +##### # Summarize results sub ParseLog2Summary { my $loglines = 0; my $pwschanged = 0; my $errors = 0; open (LOG, "< $file{sessionlog}") or die " Error opening $file{sessionlog}: $!"; open (SUMMARY, "> $file{sessionsummary}") or die " Error opening $file{sessionsummary}: $!"; for (<LOG>) { ++$loglines; ++$errors if /^Error /; ++$pwschanged if /^\s+Password changed/; } printf " $^O %d:%d:%d %d-%d-%d\n", localtime -> hour(), localtime -> min(), localtime -> sec(), localtime -> mon()+1, localtime -> mday(), localtime -> year()+1900, ; printf SUMMARY " $^O %d:%d:%d %d-%d-%d\n", localtime -> hour(), localtime -> min(), localtime -> sec(), localtime -> mon()+1, localtime -> mday(), localtime -> year()+1900, ; PrintSummConsole (" Parsed $loglines line logfile\n\n"); PrintSummConsole (" $parm{targetcount} device(s)\n"); PrintSummConsole (" $pwschanged passwords changed\n"); PrintSummConsole (" $errors error(s)\n\n"); PrintSummConsole (" Review $file{sessionlog} for details.\n"); PrintSummConsole (" Search for \"Error\" if any errors indicated. +\n"); PrintBar(); close LOG or die " Error closing $file{sessionlog}: $!"; close SUMMARY or die " Error closing $file{sessionsummary}: $!"; } ###################################################################### +##### # print() instead of cmd() because 'set password' does not return std +prompt sub ChangePass { my $old; my $new; my @commands = ( 'set password', 'set enablepass' ); foreach my $command (@commands) { if ($ntc -> print("$command")) { PrintLogConsole (" $command\n"); } else { return ("Error sending '$command' command to $target.\n +"); } # "$ntc -> getline" must be here to populate @getlines properl +y # I don't understand it, but is what made it work |^( my $getline = $ntc -> getline; # print "\$getline = $getl +ine\n"; my @getlines = $ntc -> getlines; # print ("\$getlines = $ge +tlines\n"); foreach my $getlines (@getlines) { if ($getlines =~ /% Invalid input/) { PrintLogConsole ("Error running '$command' command at +$target.\n"); PrintLastPrompt(2); return(); # skip to next target if c +ommand fails } } if ($command =~ $commands[0]) { $old = "$oldpass"; $new + = "$newpass"; } if ($command =~ $commands[1]) { $old = "$oldenablepass"; $new + = "$newenablepass"; } # Additional error checking still needed here. if ($ntc -> waitfor('/Enter old password:/')) { PrintLastPrompt(2); $ntc -> print($old); print (@cmd_output); } else { return PrintLogConsole ("Error getting 'Enter old password' pr +ompt.\n"); } if ($ntc ->waitfor('/Enter new password:/')) { PrintLastPrompt(2); $ntc -> print($new); print (@cmd_output); } else { return PrintLogConsole ("Error getting 'Enter new password +' prompt.\n"); } if ($ntc ->waitfor('/Retype new password:/')) { PrintLastPrompt(2); $ntc -> print($new); print (@cmd_output); } else { return PrintLogConsole ("Error getting 'Retype new passwor +d' prompt.\n"); } if ($ntc ->waitfor('/Password changed./')) { PrintLastPrompt(2); } else { return PrintLogConsole ("Error getting 'Password changed' +prompt.\n"); } } } ###################################################################### +##### # Subroutines start here ###################################################################### +##### sub WaitForPassword { eval { local $SIG{ALRM} = sub { die "ALARUM" }; alarm("$parm{pwtimeout}"); chomp($input = <STDIN>); alarm(0); }; if ($@ =~ /ALARUM/) { print "\n\n"; print " Sorry - You waited too long before entering a passwor +d.\n"; print " Try again, if you want.\n\n"; ReadMode(0); # re-activate screen ec +ho exit; # "exit" instead of "die" so no error to conso +le } } ###################################################################### +##### sub PasswordsMismatch { print( " D'oh! Password confirmation(s) didn't match!\n", " Run this program again if you want, ", "and try not to fatfinger it next time!\n\n" ); exit; # "exit" instead of "die" so no error to cons +ole } ###################################################################### +##### sub WrapItUp { close LOG or die " Error closing $file{sessionlog}: $!"; PrintBar(); } ###################################################################### +##### sub Pause { print " Ctrl+c to abort or <enter> to continue."; (<STDIN>); } ###################################################################### +##### sub ShowPcTime { printf " $^O %d:%d:%d %d-%d-%d\n", localtime -> hour(), localtime -> min(), localtime -> sec(), localtime -> mon()+1, localtime -> mday(), localtime -> year()+1900, ; printf LOG " $^O %d:%d:%d %d-%d-%d\n", localtime -> hour(), localtime -> min(), localtime -> sec(), localtime -> mon()+1, localtime -> mday(), localtime -> year()+1900, ; } ###################################################################### +##### # print to console *and* logfile # param is text string to be printed sub PrintLogConsole { print @_; print(LOG @_) or die " Error printing to $file{sessionlog}: $!"; } ###################################################################### +##### # print to console *and* logfile # param is text string to be printed sub PrintSummConsole { print @_; print(SUMMARY @_) or die " Error printing to $file{sessionsummary}: $!"; } ###################################################################### +##### sub PrintBar { # Visual divider for ou +tput print "\n ", '=' x 54, "\n\n"; } ###################################################################### +##### sub Usage { print <<EOF Oops - you forgot to specify *what* CatOS switches to reset password +s on! Usage : setpassCat.pl device1 device2...<enter> or : setpassCat.pl<enter> where $file{in} = textfile list of devices address/name, one per line. "perldoc setpassCat.pl" for a bit more info. EOF ; #my @modules = ( # "Term::ReadKey", # "Tie::IxHash", # "Time::localtime", # "Net::Telnet", # "Net::Telnet::Cisco", # ); #foreach my $module (@modules) { # print ("$module $module::VERSION\n"); # } print( " Net::Telnet::Cisco $Net::Telnet::Cisco::VERSION\n", " Net::Telnet $Net::Telnet::VERSION\n", " Term::ReadKey $Term::ReadKey::VERSION\n", " Tie::IxHash $Tie::IxHash::VERSION\n", " Time::localtime $Time::localtime::VERSION\n", " Perl $]\n", " OS $^O\n", " Program $0\n\n", ); exit; } ###################################################################### +##### =head1 Title setpassCat.pl =head1 Description Automate password resets for multiple Cisco CatOS LAN switches Runtime is a couple seconds for each CatOS device CatOS = 2948g plus 4000, 5000 and 6000 family chassis IOS = 2916, 2924, 3548, and routers ??? = 1900 =head1 Usage Usage : setpassCat.pl device1 device2...<enter> or : setpassCat.pl<enter> where $file{in} = textfile list of devices address/name, one per line. =head1 Tested with: pass - Debian 2.2r2 "Espy" Perl 5.00503 Term::ReadKey 2.14 Tie::IxHash 1.21 Time::localtime 1.01 Net::Telnet 3.02 Net::Telnet::Cisco 1.03 fail - Windows 2000pro SiePerl 5.00503 install fails for Term::ReadKey Net::Telnet::Cisco against: CatOS 4.5(4) on Cisco Catalyst 2948g 5.5(1) 4006 4.5(2) 5500 5.3(5a)CSX 6009 5.5(1) 6509 =head1 Updated 2001-04-30 16:15 Hashamafy file and ntc param scalar variables. Un-subify to eliminate unecessary global variables. Mixed-case subroutine names, without ampersan. Format for 75 chars/line (well, mostly). 2001-04-10 15:00 Insignificant tweaks 2001-03-29 Changed doublequote to singlequote around "=" in PrintBar() 2001-03-28 Removed unecessary quotes around "$_ [0]" in PrintLastPrompt() Commented function parameters 2001-03-27 Commented reason for extra "$ntc -> getline" in ChangePass() Removed surrounding quotes from variable definitions Eliminated unecessary "my $continue" from Pause() Reduced copy+paste redundancy by adding PrintLastPrompt() Removed surrounding single quotes from numeric variables Fixed inconsistant indentation Tweaked console messages 2001-03-12 Added ParseLog2Summary to count (Password changed|Error)s and PrintSummConsole for output of above Simplified output syntax with 'print "=" x 54' 2001-03-09 Simplified ChangePass() with $command =~ $commands[0] Closed $file{sessionlog} in WrapItUp() 2001-03-08 Added check for 'Invalid input detected' Moved password timeout to function Improved error handling if device unreachable Tweaked console messages Replaced die"\n" with exit 2001-03-05 Added working timeout for passwords entry 2001-03-04 Initial post to Perl Monks 2001-02-26 Start rewrite of CiscoPassMass using waitfor() =head1 Comments The regex to sanity-check infile is very limited. But it should suffice for most $file{in} problems. =head1 Todos Figure out array for installed modules::VERSIONS. Improve (DNS name|IP address) check for infile sanity-checking. Net::IPv4Addr - ipv4_checkip Untaint infile instead of just sanity check. User.pm to save (log|summary) files to home dir. =head1 Author ybiC =head1 Credits Thanks to: Petruchio for mondo suggestions and help chromatic for $command =~ $commands[0] suggestion on a different post ar0n for timeout example at [id://30092] tilly for tips on functions strredwolf, jcwren, boo_radley, danger, crazyinsomniac, OeufMayo, azatoth and deprecated for suggestions in CB Oh yeah, and some guy named vroom {grin} =cut

In reply to (code)) Cisco Pass Mass - CatOS (deprecated by node 123464) by ybiC

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2024-03-29 12:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found