Introduce message parser for snort alerts.
[people/stevee/guardian.git] / modules / Parser.pm
index 86e7aa1..db54cf3 100644 (file)
@@ -4,12 +4,12 @@ use warnings;
 
 use Exporter qw(import);
 
-our @EXPORT_OK = qw(Parser);
+our @EXPORT_OK = qw(IsSupportedParser Parser);
 
-# This hash contains all supported logfiles and which function
-# has to be called to parse them in the right way.
+# This hash contains all supported parsers and which function
+# has to be called to parse messages in the right way.
 my %logfile_parsers = (
-       "/var/log/snort/alert" => \&message_parser_snort,
+       "snort" => \&message_parser_snort,
 );
 
 #
@@ -20,18 +20,49 @@ my %logfile_parsers = (
 ## any action should be performed.
 #
 sub Parser ($$) {
-        my ($file, @message) = @_;
+        my ($parser, @message) = @_;
 
        # If no responsible message parser could be found, just return nothing.
-       unless (exists($logfile_parsers{$file})) {
+       unless (exists($logfile_parsers{$parser})) {
                return;
        }
 
-       # Call responsible logfile parser.
-       my $action = $logfile_parsers{$file}->(@message);
+       # Call responsible message parser.
+       my $action = $logfile_parsers{$parser}->(@message);
 
-       # Return which action should be performed.
-       return $action;
+       # If the parser successfully parsed the message, an action
+       # has been returned.
+       if ($action) {
+               # Return which action should be performed.
+               return "count $action";
+       }
+
+       # If the parser was not able to parse the the given message
+       # in the right way, return Nothing.
+       return;
+}
+
+#
+## IsSupportedParser function.
+#
+## This very tiny function checks if a given parser name is available and
+## therefore a supported parser.
+#
+## To perform these check, the function is going to lookup if a key in the
+## hash of supported parsers is available
+#
+sub IsSupportedParser ($) {
+       my $parser = $_[0];
+
+       # Check if a key for the given parser exists in the hash of logfile_parsers.
+       if(exists($logfile_parsers{$parser})) {
+               # Found a valid parser, so return nothing.
+               return 1;
+       }
+
+       # Return "False" if we got here, and therefore no parser
+       # is available.
+       return;
 }
 
 #
@@ -40,12 +71,58 @@ sub Parser ($$) {
 ## This subfunction is responsible for parsing sort alerts and determine if
 ## an action should be performed.
 #
-sub message_parser_snort($) {
+## XXX Currently the parser only supports IPv4. Add support for IPv6 at a
+## later time.
+#
+sub message_parser_snort(@) {
        my @message = @_;
 
-       # XXX
-       # Currently this parser just returns a simple message.
-       return "snort_parser_return\n";
+       # The name of the parser module.
+       my $name = "SNORT";
+
+       # Variable to store the grabbed IP-address.
+       my $address;
+
+       # Default returned message in case no one could be grabbed
+       # from the snort alert.
+       my $message = "An active snort rule has matched and gained an alert.";
+
+       # A snort alert contains multiple lines, loop through all lines
+       # to parse the complete alert.
+       foreach my $line (@message) {
+               # Check Priority Level and skip the alert if it is to low.
+               #if ($line =~ /.*\[Priority: (\d+)\].*/) {
+               #       return unless($1 < $priority);
+               #}
+
+               # Search for a line like xxx.xxx.xxx.xxx -> xxx.xxx.xxx.xxx
+               if ($line =~ /(\d+\.\d+\.\d+\.\d+)+ -\> (\d+\.\d+\.\d+\.\d+)+/) {
+                       # Store the grabbed IP-address.
+                       $address = $1;
+               }
+
+               # Search for a line like xxx.xxx.xxx.xxx:xxx -> xxx.xxx.xxx.xxx:xxx
+               elsif ($line =~ /(\d+\.\d+\.\d+\.\d+):\d+ -\> (\d+\.\d+\.\d+\.\d+):\d+/) {
+                       # Store the obtained IP-address.
+                       $address = $1;
+               }
+
+               # Obtain the reported reason.
+               if ($line =~ /.*msg:\"(.*)\".*/) {
+                       # Store the extracted message.
+                       $message = $1;
+               }
+       }
+
+       # Check if at least the IP-address information are obtained from the
+       # provided alert.
+       if ($address) {
+               # Return the extracted values.
+               return "$address $name $message";
+       }
+
+       # If we got here, the alert could not be parsed correctly, return nothing.
+       return;
 }
 
 1;