#! /usr/bin/perl -w
#
# Philip Markwalder <pm@unix.ch>
# Roland Gafner <roland.gafner@gmx.net>
#
use strict;
use POSIX;
use Net::SSH::Perl;                        # SSH implementation in pure Perl
use Net::SSH::Perl::Constants qw( :msg );
use Getopt::Long qw(GetOptions);           # command line parsing
###################################################################################
#
# Please configure these values!
#
my $PIX_LG="pix";		# username on pix ( default = pix )
my $PIX_PW="PASSWORD";		# ssh login password 
my $PIX_PW_ENA="ENABLEPASSORD"; # enable password
my $PIX_HOST="PIXFIREWALL"; 	# Pix firewall ipadress or hostname
my $PIX_DEBUG=0; 		# 1 for debugging informations, 0 for none
###################################################################################


my $PIX_CMD="" ; 		# command will be executed on pix ( will be defined later)	
my $PIX_HELP=0;
my $PIX_BLOCK=0;
my $PIX_UNBLOCK=0;
my $stdout_buff = '';
use constant STATE_NONE        =>   0;
use constant STATE_ENABLE      =>  10;
use constant STATE_ENABLEPW    =>  20;
use constant STATE_CONFMODE    =>  30;
use constant STATE_SETPAGER    =>  40;
use constant STATE_GETCLOCK    =>  44;
use constant STATE_SETCLOCK    =>  47;
use constant STATE_GETCONFIG   =>  50;
use constant STATE_GETCERT     =>  60;
use constant STATE_GETPUBKEY   =>  70;
use constant STATE_GETVERSION  =>  80;
use constant STATE_CMD    =>  90;
use constant STATE_EXIT        => 100;
use constant STATE_FINISH => 200;

my $state = STATE_NONE;

######################################################################
# Commandline parsing
######################################################################

{
    my %CmdOptions = ("help!"        => \$PIX_HELP,
                      "block:s"     => \$PIX_BLOCK,
                      "unblock:s"       => \$PIX_UNBLOCK,
                      );
    
	GetOptions(%CmdOptions)
}
if ( $PIX_BLOCK )
{
	print "Block Connection \n";
	$PIX_CMD="shun $PIX_BLOCK ";
};
if ( $PIX_UNBLOCK )
{
	$PIX_CMD="no shun $PIX_UNBLOCK";
};
if ( length($PIX_CMD)==0 || $PIX_HELP || ( $PIX_BLOCK && $PIX_UNBLOCK ) )
{
	print "Usage $0 [--block|--unblock] SOURCE_IP \n";
	exit 0;
};


my $ssh = Net::SSH::Perl->new($PIX_HOST,
				  debug =>$PIX_DEBUG,
                                  cipher => 'DES',
                                  );
$ssh->login($PIX_LG, $PIX_PW);
$ssh->{config}->set('use_pty', 1);
$ssh->_setup_connection;
my $packet = $ssh->packet_start(SSH_CMSG_EXEC_SHELL);
$packet->send;
my $s = IO::Select->new;
$s->add($ssh->{session}{sock});
my $str = $packet->get_str;
CLOOP:
while(1)
{
	my @ready = $s->can_read;
	for my $a (@ready) {
		if ($a == $ssh->{session}{sock}) {                                    # Got an SSH packet?
                	my $buf;
                	sysread $a, $buf, 8192;                                           # read it and...
                	($buf) = $buf =~ /(.*)/s;                                         # Untaint data. Anything allowed.
                	$ssh->incoming_data->append($buf);
		};		
	};
	while (my $packet = Net::SSH::Perl::Packet->read_poll($ssh)) {            # Get the next SSH packet (we recieved above)
            if ($packet->type == SSH_SMSG_STDOUT_DATA) {                          # normal output from STDOUT on the remote side?
                my $str = $packet->get_str;                                       # get the output
		if ("1") {
                    foreach (split (/[\n\r]/, $str)) {
                        printf STDERR "OUT: %s\n", $_  if ( $PIX_DEBUG );
                    }
                }
		$str =~ s/\r//g;
		$stdout_buff .= $str; 
		if ($state == STATE_NONE) {                                       # Just after connecting
                    if ($stdout_buff =~ m|Type help or.*> $|s) {                  # Banner after logging in and User-Prompt?
                        send_string ($ssh, "enable \n");                           # SEND: enable<LF> to enable super-user mode
                        $state = STATE_ENABLE;
                    }
                } elsif ($state == STATE_ENABLE) {                                # Waiting for the enable password prompt
                    if ($stdout_buff =~ m|Password:|) {                           # Got the password prompt?
                        send_string ($ssh, $PIX_PW_ENA . "\n");                       # SEND: <enable pw><LF>
                        $state = STATE_ENABLEPW;
                    }
		}elsif ($state == STATE_ENABLEPW) {                              # Waiting for success or un-success of enable
                    if ($stdout_buff =~ m|\# $|s) {                               # Got the Super-User-Prompt? ('# ')
                        print STDERR "* systemname: enabled, entering configuration mode\n"  if ( $PIX_DEBUG ); 
                        send_string ($ssh, "config terminal\n");                  # SEND: config terminal<LF> to enter configuration mode
                        $state = STATE_CONFMODE;
                    } elsif ($stdout_buff =~ m|Invalid password|) {               # Passwort was wrong? Bad!
                        print STDERR "* systemname: wrong enable password\n" ;
                        $state = STATE_CMD;
                        last CLOOP;                                               # just leave!
                    }
                } elsif ($state == STATE_CONFMODE) {                              # Wait to get into configuration mode
                    if ($stdout_buff =~ m|\(config\)\#|) {                        # got the config-mode-prompt?
                        print STDERR "* systemname: entered configuration mode\n" if ( $PIX_DEBUG );
			print STDERR "* systemname: setting pager to 0\n" if ( $PIX_DEBUG );
                            send_string ($ssh, "pager 0\n");                      # SEND: pager 0<LF> to disable paging
                            $state = STATE_SETPAGER;
                    }
		
		} elsif ( $state == STATE_SETPAGER) {
			if ($stdout_buff =~ m|\(config\)\#|) {
				 send_string ($ssh, $PIX_CMD . "\n");
				$state = STATE_CMD;
			};
		} elsif ( $state == STATE_CMD) {
			send_string ($ssh, "exit\n");
			send_string ($ssh, "exit\n");
			$state = STATE_FINISH ;

		} elsif ( $state == STATE_FINISH) {
			if ($stdout_buff =~ m|\*\*|) {	
				last CLOOP;	
			};
		};
		
	     } elsif  ($packet->type == SSH_SMSG_EXITSTATUS) {
			print $stdout_buff;
			last CLOOP;                                                       # That's it

	#	};
	   }
	}						
};
$packet = $ssh->packet_start(SSH_CMSG_EXIT_CONFIRMATION);                     # Confirm the SSH session closing
$packet->send;
$ssh->_disconnect;

sub send_string
{
    my ($ssh, $string) = @_;
    
    print STDERR "* Send String ", $string  if ( $PIX_DEBUG );
    $stdout_buff = '';
    my $packet = $ssh->packet_start(SSH_CMSG_STDIN_DATA);
    $packet->put_str($string);
    $packet->send;
} # send_string


