#!/usr/local/bin/perl
#
# $Id$
# $Source$
# Paul Traina (Feburary 1994)
#
# configure multiple cisco boxes at the same time
#

require 'chat2.pl';
require 'getopts.pl';

@router_firewalls = ( "harpo", "groucho", "chico"" );
$router_acls      = "walls/rtr-acl";

@exterior_routers = ( "turfnet-gw", "pornonet-gw");
$exterior_acls	  = "walls/ext-rtr-vtys";

@ts_card_firewalls     = ( "checkpoint-charlie" );
$ts_card_acls	  = "walls/ts-card-vtys";

@ts_firewalls     = ( "chump" );
$ts_acls	  = "walls/ts-vtys";

@cio_firewalls	  = ( "hurtme-gw" );
$cio_acls	  = "walls/cio-acl";

@ecs_console_servers = ( "console-server",
			 "console-server-2" );
$cs_users	  = "walls/utmp";

$user             = $ENV{'USER'};
$tftp_server      = "splat";

#-----------------------------------------------------------------------

&Getopts("c:CdEf:Ms:Stu:");

if ($opt_t) {
    @servers = @ts_firewalls;
    $config  = $ts_acls;
} elsif ($opt_C) {
    @servers = @cio_firewalls;
    $config  = $cio_acls;
} elsif ($opt_S) {
    @servers = @ecs_console_servers;
    $config  = $cs_users;
} elsif ($opt_E) {
    @servers = @exterior_routers;
    $config  = $exterior_acls;
} elsif ($opt_f) {
    open(ROUTERS, "$opt_f") || die "Can't access file $opt_f";
    while (<ROUTERS>) {
	chop;
	push(@servers,$_);
    }
    close(ROUTERS);
} else {
    @servers = @router_firewalls;
    $config  = $router_acls;
}

if (defined(@ARGV)) {  # single command mode...
    $single_command = @ARGV[0];
}
	

$debug       = $opt_d if $opt_d;
$user	     = $opt_u if $opt_u;
$config      = $opt_c if $opt_c;
$tftp_server = $opt_s if $opt_s;

print "Configuring:";
for $rtr (@servers) {
    print " $rtr";
}
print "\n";

$user 		 = &askdefault("Username", $user);
$password	 = &askdefault_noecho("Password", "");
if (defined($opt_M)) {
	print "Multiple enable password mode:\n";
	while ($response = &askdefault_noecho("Enable password [return for last]", -1)) {
		push(@enable_passwords, $response);
	}
} else {
	$enable_password = &askdefault_noecho("Enable password", "");
}

if ($opt_S) {
	$new_con_password = &askdefault_noecho("New Console Password", "");
	$new_enable_password = &askdefault_noecho("New Enable Password", "");
	&make_utmp($new_con_password, $new_enable_password);
}	
if (!defined($single_command)) {
	$config		 = &askdefault("Configuration file", $config);
	$tftp_server	 = &askdefault("TFTP server", $tftp_server);
	print "Transferring files to tftp server...";
	@elements = split(/\./, $tftp_server);
	$tftp_s_addr = pack("C4", @elements[0], @elements[1], @elements[2], @elements[3]);
	$tftphost = (gethostbyaddr($tftp_s_addr, 2))[0];
	system("/usr/ucb/rcp /usr/$config $tftphost:/tftpboot/$config"); 
	print "...[DONE]\n";
}

#-----------------------------------------------------------------------

$sec = 1000;

foreach $server (@servers) {
    print "Connecting to $server...\n";

    &chat'open_port($server, 23);

    $ret = &expect(20 * $sec,
			"Username: ", 1);

    &send($user);

    $ret = &expect(20 * $sec,
			"Password: ", 1);

    &blind_send($password);
    if (defined($opt_M)) {
        $ret = &expect(20 * $sec,
			"$server.*>", 1,
			"Access denied", 2,
			"Password:", 2,
			"enable password", 3);
	if ($ret == 3) {
        	foreach $enable_password (@enable_passwords) {
        		&blind_send($enable_password);
			$ret = &expect(20 * $sec,
				"$server.*>", 1,
				"Password:", 2);
			if ($ret == 1) { last; }
		}
		goto quit;
	}
	if ($ret != 1) { goto quit; }
	&send("enable");
			$ret = &expect(20 * $sec,
				"$server.*#", 1,
				"Password:", 2);
	if ($ret == 1) { goto noenable; }
	foreach $enable_password (@enable_passwords) {
		&blind_send($enable_password);
		$ret = &expect(20 * $sec,
				"$server.*#", 1,
				"Password:", 2,
				"Bad passwords", 3);
		if ($ret != 2) { last; }	
	}
	if ($ret != 1) { goto quit; }
noenable:		
    } else {

    	$ret = &expect(20 * $sec,
			"$server.*>", 1,
			"Access denied", 2,
			"Password:", 2,
			"enable password", 3);

	    if ($ret == 3) {
		&blind_send($enable_password);
		&expect(60 * $sec,
			"$server.*>", 1,
			"Password:", 2,
			"Access denied", 2);
    		}

    	if ($ret != 1) { goto quit; }

    	&send("enable");
    	$ret = &expect(5 * $sec,
				"Password:", 1);
    	if ($ret != 1) { goto quit; }

	    &blind_send($enable_password);
    	$ret = &expect(5 * $sec,
			"$server.*#", 1,
			"Password: ", 2,
			"Bad passwords", 3);
    	if ($ret != 1) { goto quit; }
    }

    if (defined($single_command)) {
	&send("$single_command");
	$ret = &expect(5 * $sec,
			"$server.*", 1,
			"error", 2);
	if ($ret != 1) { goto quit; }
    	goto quit_ok;
    } else {
    	&send("configure network");
    	$ret = &expect(5 * $sec,
				"\[host\]\? ", 1);
    	if ($ret != 1) { goto quit; }

    	&send("net");
    	$ret = &expect(5 * $sec,
				"of remote host .*\\? ", 1);
    	if ($ret != 1) { goto quit; }

    	&send($tftp_server);
    	$ret = &expect(5 * $sec,
			"Name of configuration file .*\\? ", 1);
    	if ($ret != 1) { goto quit; }

    	&send($config);
   	 $ret = &expect(5 * $sec,
			"\[confirm\]", 1);
    	if ($ret != 1) { goto quit; }

    	&send("");
    	$ret = &expect(30 * $sec,
			"OK", 1,
			"timed out", 2);
    	if ($ret != 1) { goto quit; }

    	print STDERR "\n";

    	$ret = &expect(5 * $sec,
 			"$server.*#", 1);
    	if ($ret != 1) { goto quit; };

    	&send("write memory");
    	$ret = &expect(20 * $sec,
			"$server.*#", 1,
			"error", 2);

    	$record{$server} = "successful";
    	goto quit_ok;
     }

  quit:
    $record{$server} = "failed";
  quit_ok:
    &send("quit");
    &chat'close();
}

foreach $s (keys(%record)) {
    print "Configured of $s $record{$s}\n";
}

if ($opt_S) {
	unlink("/tftpboot/walls/utmp");
}

system("rsh $tftphost /bin/rm /tftpboot/$config");

sub send {
    local ($arg) = @_[0];
    print STDERR " $arg\n";
    &chat'print($arg . "\r");
}

sub blind_send {
    local ($arg) = @_[0];
    local ($print_arg) = $debug ? $arg : "[output suppressed]";
    print STDERR " $print_arg\n";
    &chat'print($arg . "\r");
}

sub expect {
    local(@expect_args);
    local($time_out);
    local($ret);

    @expect_args = ();
    $time_out = shift(@_);

    while(@_) {
	local($match) = shift(@_);
	local($result) = shift(@_);
	push(@expect_args, $match);
	push(@expect_args,
	     "print STDERR \"$server: $match\"; $result");
    }

    push(@expect_args, 'TIMEOUT');
    push(@expect_args, "print STDERR \"$server: TIMEOUT\n\"; exit");
    push(@expect_args, 'EOF');
    push(@expect_args, "print STDERR \"$server: EOF\n\"; exit");

    $ret = &chat'expect($time_out, @expect_args);
    return $ret;
}

sub askdefault {
    local ($prompt, $default) = @_;
    local ($answer);

    if ($default == -1) {
      print "$prompt? ";
      $answer = <STDIN>;
      chop $answer;
    } elsif ($default ne "") {
	print "$prompt [$default]? ";
	$answer = <STDIN>;
	chop $answer;
	$answer = $default if ($answer eq "");
    } else {
	$answer = "";
	while ($answer eq "") {
	    print "$prompt? ";
	    $answer = <STDIN>;
	    chop $answer;
	    print "-- response required\n" if ($answer eq "");
        }
    }
    return $answer;
}

sub askdefault_noecho
{   
    local ($prompt, $default) = @_;
    local ($answer);

    system "stty", "-echo";
    if ($default == -1) {
      print "$prompt? ";
      $answer = <STDIN>;
      print "\n";
      chop $answer;
    } elsif ($default ne "") {
        print "$prompt [$default]? ";
        $answer = <STDIN>;
        print "\n";
        chop $answer;
        $answer = $default if ($answer eq "");
    } else {
        $answer = "";
        while ($answer eq "") {
            print "$prompt? ";
            $answer = <STDIN>;
            print "\n";
            chop $answer;
            print "-- response required\n" if ($answer eq "");
        }
    }
    system "stty", "echo";
    return $answer;
}

sub make_utmp {

local($con, $ena) = @_;
open(GROUP,"/etc/group");
while(<GROUP>) {
	chop;
	@entries = split(/:/);
	if (@entries[0] eq "consoles") {
		@users = split(/,/, @entries[3]);
		next;
	}
}
close(GROUP);

open(UTMP, ">/tftpboot/walls/utmp");
print UTMP "service password-encryption\n";
foreach $user (@users) {
	print UTMP "username $user password $con\n";
} 
print UTMP "enable-password $ena\n";

close(UTMP);
}

#-------------------------------------------------------------------
# $Log$
#
#-------------------------------------------------------------------
