#!/usr/bin/perl
#
# Script permettant de scruter les messages venant du Firewall et d'envoyer
# un message à root pour le prévenir d'une tentative d'intrusion.
#

my $touser   = "root";
my $tube     = "/dev/xconsole";
my $mesg     = "/tmp/firelog-message";
my $syslog   = "/var/log/messages";
my $mysyslog = "/var/log/firelog";

my $services   = "/etc/services";
my $protocoles = "/etc/protocols";

my $nolog = -1;
my $logmail = 0;
my $logfile = 1;
my $logboth = 2;

my $log = $logmail;


# Variables contenant les données traitées...
my $newdata = 0;
my $version = "0.2.0";

$debug = 0;
$next  = 0;
foreach $arg (@ARGV) {
  if ($next == 0) {
    $next = -1;
    if ($arg eq "-debug") {$debug = 1; $next = 0;}
    if ($arg eq "-to")    {$next  = 1;}
    if ($arg eq "-f")     {$next  = 2;}
    if ($arg eq "-x")     {$next  = 3;}
    if ($arg eq "-l")     {$log = $logfile; $next  = 0;}
    if ($arg eq "-lm")    {$log = $logboth; $next  = 0;}
    if ($arg eq "-h") {
      print "firelog v$version\n\n";
      print "Usage : firelog [-u user] [-f file] [-debug] ";
      print " [-x excl] [-l] [-h]\n";
      print " -h      : this help\n";
      print " -debug  : debug mode\n";
      print " -u user : notify user of connexions ($touser)\n";
      print " -f file : use file as fifo ($tube)\n";
      print " -x excl : exclude from logging connections to";
      print " a port in the excl list,\n";
      print "           \"--\" terminates the list\n";
      print " -l      : log to $mysyslog -- disable mail logging.\n";
      print " -lm     : log to $mysyslog -- do NOT disable mail logging.\n";
      print "\n";
      exit;
    }
  } elsif ($next == 1) {
    $touser = $arg;
    $next   = 0;
  } elsif ($next == 2) {
    $tube = $arg;
    $next = 0;
  } elsif ($next == 3) {
    if ($arg eq "--") {
      $next = 0;
    } else {
      $excl[$xelt] = $arg;
      $xelt++;
      $next = 3;
    }
  } else {
    print "Argument inconnu : $arg\n";
  };
};

if ( ($log == $logfile) || ($log == $logboth) ) {
  system ("touch $mysyslog");
}

if ($debug == 1) {
  print "Firelog... Exclusion des ports/services :";
  if ($#excl > -1) {
    foreach $elt (@excl) {
      print " $elt";
    }
  } else {
    print " none";
  }
  print ".\n";
}


sub send_data {
  if ($newdata > 0) {
    $datatosend = $newdata;
    # Vérification de la présence de données à transmettre
    for ($i = 0 ; $i < $newdata ; $i++) {
      # Récupération du nom du protocole
      $protoline =
        `grep '\\<$proto[$i]\\>' $protocoles|grep -v '^#'`;
      chop ($protoline);
      ($protocol) = ($protoline =~ /^([^\s]*)\s.*/x);
      # Récupération du nom du service local
       $servline =
        `grep '\\<$dport[$i]\\>' $services|grep -v '^#'|grep $protocol`;
      chop ($servline);
      ($dservice) = ($servline =~ /^([^\s]*)\s.*/x);
      $is_ok = 1;
      if ($#excl > -1) {
        foreach $xport (@excl) {
          print "Vérification pour le port/service : $xport\n";
          if ( ($dservice ne "") && ($xport eq $dservice) ) {
            $is_ok = 0;
            print "$dservice ($dport[$i]) est considéré comme $xport...\n";
          } elsif ($xport eq $dport[$i]) {
            $is_ok = 0;
            print "$dport[$i] ($dservice) est considéré comme $xport...\n";
          }
        }
      }
      if ($is_ok == 0) {$datatosend--;}
      if ( ($log == $logfile) || ($log == $logboth) ) {
        $filemode = ">> $mysyslog";
        open (FILE, $filemode) or die "Impossible d'ouvir $mysyslog : $!";
        if (is_ok == 0) {
          print FILE "DON'T USE => $log[i]\n";
        } else {
          print FILE "USE LOG : $log[i]\n";
        }
        close (FILE);
      }
    }
    if ($debug == 1) {
      print "Données reçues : $newdata --- ";
      print "Données transmises : $datatosend.\n";
    }
    if ( ($log == $logfile) || ($log == $logboth) ) {
      $filemode = ">> $mysyslog";
      open (FILE, $filemode) or die "Impossible d'ouvir $mysyslog : $!";
      print FILE "Données reçues : $newdata --- ";
      print FILE "Données transmises : $datatosend.\n";
      close (FILE);
    }

    # Il y a encore des données à envoyer...
    if ($datatosend > 0) {
      $filemode = "> $mesg";
      open (FILE, $filemode) or die "Impossible d'ouvir $mesg : $!";
      print FILE "LOG DE $datatosend TENTATIVE(S) DE CONNEXION EFFECTUÉ :\n\n";
      for ($i = 0 ; $i < $newdata ; $i++) {
        # Récupération du nom du protocole
        $protoline =
          `grep '\\<$proto[$i]\\>' $protocoles|grep -v '^#'`;
        chop ($protoline);
        ($protocol) = ($protoline =~ /^([^\s]*)\s.*/x);
        # Récupération du nom du service distant
        $servline =
          `grep '\\<$sport[$i]\\>' $services|grep -v '^#'|grep $protocol`;
        chop ($servline);
        ($sservice) = ($servline =~ /^([^\s]*)\s.*/x);
        if ($sservice ne "") {$sservice = " ($sservice)";}
        # Récupération du nom du service local
        $servline =
          `grep '\\<$dport[$i]\\>' $services|grep -v '^#'|grep $protocol`;
        chop ($servline);
        ($dservice) = ($servline =~ /^([^\s]*)\s.*/x);
        $is_ok = 1;
        if ($#excl > -1) {
          foreach $xport (@excl) {
            if ( ($dservice ne "") && ($xport eq $dservice) ) {
              $is_ok = 0;
            } elsif ($xport eq $dport[$i]) {
              $is_ok = 0;
            }
          }
        }
        if ($dservice ne "") {$dservice = " ($dservice)";}
        if ($is_ok == 1) {
          print FILE "> $log[$i]\n";
          print FILE " - Le $jour[$i] $mois[$i] à $heure[$i],";
          print FILE " sur $protocol ($proto[$i])\n";
          print FILE "\tdepuis $sip[$i],\tport $sport[$i]$sservice\n";
          print FILE "\tvers   $dip[$i],\tport $dport[$i]$dservice.\n\n";
          print FILE "\n";
        }
      };
      close (FILE);
      if ( ($log == $logmail) || ($log == $logboth) ) {
        system ("mail $touser -s Firelog < $mesg");
        system ("sendmail -q");
      }
      if ( ($log == $logfile) || ($log == $logboth) ) {
        system ("cat $mesg >> $mysyslog");
      }
      if ($debug == 1) {system ("cat $mesg");}
      unlink ($mesg);
    }
    $newdata = 0;
  }
}


while (TRUE) {
  open (FIFO, $tube) or die "Le tube $tube n'existe pas : $!";
  while (defined ($logline = <FIFO>) ) {
    if ($logline =~ /.*Packet log:.*/) {
      ($jour[$newdata]) = ($logline =~ /^[^\s]*\s*([^\s]*)\s.*/x);
      ($mois[$newdata]) = ($logline =~ /^([^\s]*)\s.*/x);
      ($heure[$newdata]) = ($logline =~ /^[^\s]*\s*[^\s]*\s*([^\s]*)\s.*/x);
      ($iface[$newdata]) =
        ($logline =~ /.*Packet\slog:\s*[^\s]*\s*[^\s]*\s*([^\s]*)\s.*/x);
      ($proto[$newdata]) = ($logline =~ /.*PROTO=([^\s]*)\s.*/x);
      ($sip[$newdata], $sport[$newdata]) =
        ($logline =~ /.*PROTO=[^\s]*\s*([^\s]*):([^\s]*)\s.*/x);
      ($dip[$newdata], $dport[$newdata]) =
        ($logline =~ /.*PROTO=[^\s]*\s*[^\s]*\s*([^\s]*):([^\s]*)\s.*/x);
      $log[$newdata] = $logline;
      chomp($log[$newdata]);
      $newdata++;
    } else {
      &send_data();
    };
  };
  &send_data();
  close (FIFO);
};
