#!/usr/bin/perl5
#
# +---------------------------------------------------------------------+
# | Digital-Phalanx                                                     |
# | Written By   : Trans-Euro I.T Ltd                                   |
# | Written On   : May 2nd 1998                                         |
# |                                                                     |
# | Purpose        Close in System Defense Software                     |
# |                Ensures that  no un-authorised telnet sessions       |
# |                can remain in the machine for very long.. and        |
# |                that recognised sessions are only accepted from      |
# |                predefined domain patterns and IP's                  |
# |                This daemon is basically the last line of defense    |
# |                working on the premise that:-                        |
# |                a 'cracker' has broken password security.            |
# |                And has either telneted into the machine from an     |
# |                un-authorised domain, or has added a user to your    |
# |                server and is attempting to exploit that trap door.  |
# |                                                                     |
# |                Digital Phalanx will Detect, Identify and if         |
# |                required DESTROY them.                               |                
# +---------------------------------------------------------------------+
# | (c) 1998 This script is the intellectual property of                |
# | Trans-Euro I.T Ltd                                                  |
# +---------------------------------------------------------------------+

use Config;
use AnyDBM_File;

my $PROGRAM="Digital-Phalanx";
my $VERSION="1.10";

$ENV{"LOGNAME"}="$PROGRAM";
$ENV{"USER"}="$PROGRAM";   

my $hup     =0;
my $config  ="/usr/local/phalanx/phalanx.conf";
my $dbdir   ="/usr/local/phalanx/database/";
my $contact ="";
my $report  ="";
my $pidfile ="";
my $pmessage="";
my $database="";
my $klevel  ="";
my $w       ="";
my $kill    ="";
my $sendmail="";
my $ps      ="";
my $psflags ="";
my $sleep   ="";
my $license ="";
my $date    =get_date();
my $time    =get_time();
my $node    =`uname -n`;
my $user    ="";
my $domain  ="";
my $tty     ="";
my $tty_pre ="";
my $action  ="";

@telnets    ="";
@message    ="";

format ID =
Target Ident   @<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<< @<<<<<
               $time                     $user        $domain         $tty
.

format DO =
Target @<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<< @<<<<<
       $action $time                     $user        $domain         $tty
.

format HP =
@<<<<<<<<<<<<<<<<<< : HUP re-reading @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$time                                $tab
.


unless ( -s "$config") { die "$config is either missing or empty !!\n";}
                 
read_config();

unless ( -f "/usr/local/phalanx/$license") { 
         die "Your License file is missing!!\n";}

lic();
        
unless (fork) {
 unless (fork) {
   sleep1 until getppid == 1;

# +---------------------------------------------------------------------+
# | Main Daemon control loop                                            |
# +---------------------------------------------------------------------+

   $0="$PROGRAM $VERSION";

   write_pid();
   write_report_header();
       
   while ( ! $daemon_control) {

         # +---------------------+
         # | Catch signals here! |
         # +---------------------+

         $SIG{HUP} = \&hup;
         if ($hup) { read_config();$hup=0;}

         # +---------------------+
         # | main process loop   |
         # +---------------------+

         $SIG{HUP} = \&hup;

         $date=get_date();
         $time=get_time();
         telnet_aquire();
         telnet_ident();
         
         sleep $sleep;
                              }
            
 exit 0;
               }
exit 0;
              }

# +---------------------------------------------------------------------+
# | Sub programs                                                        |
# +---------------------------------------------------------------------+

sub hup {
  $hup=1;
 }

# +---------------------------------------------------------------------+

sub read_config {
    my $line;
    if ($hup eq "1") { log_hup();}

    open(CONFIG,"$config") || die "Cannot open configuration $config!\n";
     while($line=<CONFIG>) { 
       $line=~s/\012//g;
       $line=~s/\ {1,}//g;
         SWITCH: {
          if ($line =~ /^CONTACT=/)   {(undef,$contact)=split(/=/,$line)};
          if ($line =~ /^REPORTFILE=/){(undef,$report)=split(/=/,$line)};
          if ($line =~ /^PIDFILE=/)   {(undef,$pidfile)=split(/=/,$line)};
          if ($line =~ /^PMESSAGE=/)  {(undef,$pmessage)=split(/=/,$line)};
          if ($line =~ /^DATABASE=/)  {(undef,$database)=split(/=/,$line)};
          if ($line =~ /^KLEVEL=/)    {(undef,$klevel)=split(/=/,$line)};
          if ($line =~ /^W=/)         {(undef,$w)=split(/=/,$line)};
          if ($line =~ /^PS=/)        {(undef,$ps)=split(/=/,$line)};
          if ($line =~ /^TTY_PREFIX=/){(undef,$tty_pre)=split(/=/,$line)};    
          if ($line =~ /^PSFLAGS=/)   {(undef,$psflags)=split(/=/,$line)};
          if ($line =~ /^SLEEP=/)     {(undef,$sleep)=split(/=/,$line)};
          if ($line =~ /^KILL=/)      {(undef,$kill)=split(/=/,$line)};
          if ($line =~ /^SENDMAIL=/)  {(undef,$sendmail)=split(/=/,$line)};
          if ($line =~ /^LICENSE=/)   {(undef,$license)=split(/=/,$line)};}}
    close(CONFIG);

    open(P,"$pmessage");
        @message=<P>;
    close(P); 
}

# +---------------------------------------------------------------------+

sub write_pid {
open(PID,">$pidfile") || die "Cannot open $pidfile!!\n";
print PID $$;
close(PID);
}

# +---------------------------------------------------------------------+

sub get_date {
my $date=`date`;
$_=$date;
s/\012//g;
$date=$_;
return $date;
}

# +---------------------------------------------------------------------+

sub write_report_header {
open(REP,">$report")|| die "Cannot open $report!!\n";
print REP "--------------------------------------------------------\n";
print REP "$PROGRAM : $VERSION starts at $date\n";
print REP "Trans-Euro I.T (c) 1998.\n";
print REP "Written by Stephen Martin\n";
print REP "--------------------------------------------------------\n";
close(REP);
} 

# +---------------------------------------------------------------------+

sub get_time {
my $time=`date +"%D : %T"`;
$_=$time;
s/\012//g;
$time=$_;
return $time;
}

# +---------------------------------------------------------------------+

sub log_hup {
    open(HP,">>$report")|| die "Cannot log HUP call to $result!\n";
    write HP;
    close(HP);
}

# +---------------------------------------------------------------------+

sub mail_support {

     my ($d_name) = @_;

     open (MAIL, "| $sendmail $contact") || die "Can't open $sendmail!\n";
     print MAIL "To: $contact\n";
     print MAIL "From:$PROGRAM\n";
     print MAIL "Subject:$PROGRAM : Intruder Detected on $node\n";
     print MAIL "------------------------------------------------------\n\n";
     print MAIL "$PROGRAM has detected and $action $d_name\n";
     print MAIL "Logging in from $domain on terminal $tty\n";
     close (MAIL);
}

# +---------------------------------------------------------------------+

sub telnet_aquire {
    
    my $undef;
   
    open(W,"$w|")||die "Cannot exec $w\n";
         $undef=<W>;
         $undef=<W>;
         @telnets=<W>;
    close(W);

}

sub telnet_ident {
    my $telnet="";
    my $db_rec="";
    my $dbmfile="$dbdir$database";
    my $dbe   =";";
    my @hosts ="";

    foreach $telnet (@telnets) {
    ($user,$tty,$domain)=split(/\ {1,}/,$telnet);

    dbmopen(%DB,"$dbmfile",undef)||die "Cannot open $dbmfile\n";
            $db_rec=$DB{"$user"};
            if ( $db_rec eq "" ) { telnet_do($user,$tty,$domain);}
    
    reset @hosts;
    
    @hosts=split(/$dbe/,$db_rec);

    if ( ! grep /$domain/, @hosts ) {telnet_do($user,$tty,$domain);}    
    
    dbmclose(%DB);
    reset %DB;
    

                               }

}

# +---------------------------------------------------------------------+   

sub telnet_do {
    my ($intr)=@_;
        shift;
    my ($term)=@_;
        shift;
    my ($site)=@_;
    my $proc="";

    my @process_list="";

    open(PS,"$ps $psflags|grep $intr|grep $term|") ||
      die "Cannot exec ps command to search for processes!\n";
      @process_list=<PS>;
    close(PS);

    foreach $proc (@process_list) {
            (undef,$proc)=split(/\ {1,}/,$proc);
            SWITCH: { if ($klevel == 1 ) { message($user,$tty);
                                           $action="Messaged";
                                           last SWITCH;}

                      if ($klevel == 2 ) { message($user,$tty);
                                           kill9($proc);
                                           $action="Messaged and killed";
                                           last SWITCH;}

                      if ($klevel == 3 ) { kill9($proc);
                                           $action="Killed"; 
                                           last SWITCH;}}}

    open(ID,">>$report")|| die "Cannot open $report!!\n";         
         write ID;
    close(ID);

    open(DO,">>$report")|| die "Cannot open $report!!\n";         
         write DO;
    close(DO);

    mail_support($user);
}


# +---------------------------------------------------------------------+   

sub message {
    my ($user)=@_;
    shift;
    my ($tty)=@_;
        $tty="$tty_pre$tty";

    open(TTY,">$tty");
         print TTY @message;
         print "\n$PROGRAM $VERSION\n";
    close(TTY);
}

# +---------------------------------------------------------------------+   

sub kill9 {
    my ($proc)=@_;
    open(KILL,"|$kill -9 $proc 2> /dev/null");
    close(KILL);
}

# +---------------------------------------------------------------------+   

sub lic {
    open(LIC,"|nohup /usr/local/phalanx/$license > /dev/null 2>&1 &") ||
     die "Cannot invoke $license program??\n";
    close(LIC); 
}

# +---------------------------------------------------------------------+   

