use Exporter qw(import);
-our @EXPORT_OK = qw(Init CheckAction Update);
+our @EXPORT_OK = qw(Init CheckAction GenerateIgnoreList Update);
# Hash which stores all supported commands from the queue.
my %commands = (
# when the block for this address can be released.
my %blockhash = ();
+# Hash to store user-defined IP addresses and/or subnets which should be
+# ignored in case any events should be repored for them.
+my %ignorehash = ();
+
# This object will contain the reference to the logger object after calling Init.
my $logger;
my $module_name = "Guardian::" . $self->{FirewallEngine};
eval "use $module_name; 1" or die "Could not load a module for firewall engine: $self->{FirewallEngine}!";
+ # Check if an IgnoreFile has been configured.
+ if (exists($self->{IgnoreFile})) {
+ # Call function to handle the ignore mechanism.
+ &GenerateIgnoreList($self->{IgnoreFile});
+ }
+
# Return the class object.
return $self;
}
return;
}
- # XXX
- # Check if the given address is valid.
+ # Convert and validate the given address.
+ my $bin_address = &Guardian::Base::IPOrNet2Int($address);
+
+ # Abort if the given address could not be converted because it is not valid.
+ unless ($bin_address) {
+ $logger->Log("err", "Invalid IP address: $address");
+ return;
+ }
+
+ # Check if address should be ignored.
+ if(&_IsOnIgnoreList($bin_address)) {
+ # Log message.
+ $logger->Log("info", "Ignoring event for $address, because it is part of the ignore list.");
+ return;
+ }
# Call required handler.
my $error = $commands{$command}->($self, $address, $module, $message);
# not been blocked yet, call the responisible
# function to do this now.
unless (exists($blockhash{$address})) {
- # XXX
- # Add posibility to use a configure-able action.
- my $action;
+ # Obtain the configured FirewallAction.
+ my $action = $self->{FirewallAction};
# Block the given address.
my $error = &DoBlock($address, $action);
# If we got back an error message something went wrong.
if ($error) {
- # Exit function and return the error message.
- return $error;
+ # Exit function and return the used FirewallEngine and the error message.
+ return "$self->{FirewallEngine} - $error";
} else {
# Address has been successfully blocked, print a log message.
$logger->Log("debug", "Address $address successfully has been blocked...");
return undef;
}
+#
+## GenerateIgnoreList function.
+#
+## This function is responsible for generating/updating the
+## IgnoreHash which contains all ignored IP addresses and
+## networks.
+#
+sub GenerateIgnoreList($) {
+ my $file = shift;
+
+ # Check if the given IgnoreFile could be opened.
+ unless(-e $file) {
+ $logger->Log("err", "The configured IgnoreFile \($file\) could not be opened. Skipped!");
+ return;
+ }
+
+ # Open the given IgnoreFile.
+ open (IGNORE, $file);
+
+ # Read-in the file line by line.
+ while (<IGNORE>) {
+ # Skip comments.
+ next if (/\#/);
+
+ # Skip blank lines.
+ next if (/^\s*$/);
+
+ # Remove any newlines.
+ chomp;
+
+ # Check if the line contains a valid single address or network and
+ # convert it into binary format. Store the result/start and
+ # end values in a temporary array.
+ my @values = &Guardian::Base::IPOrNet2Int($_);
+
+ # If the function returned any values, the line contained a valid
+ # single address or network which successfully has been converted into
+ # binary format.
+ if (@values) {
+ # Assign the array as value to the ignorehash.
+ $ignorehash{$_} = [@values];
+ } else {
+ # Log invalid entry.
+ $logger->Log("err", "IgnoreFile contains an invalid address/network: $_");
+
+ # Skip line.
+ next;
+ }
+ }
+
+ # Close filehandle for the IgnoreFile.
+ close (IGNORE);
+}
+
+#
+## Private function to check if an address is part of the Ignore Hash.
+#
+## This function checks if a passed IP address in binary format (!),
+## directly or as part of an ignored network is stored in the ignore hash.
+#
+sub _IsOnIgnoreList ($) {
+ my $bin_address = shift;
+
+ # Loop through the ignore hash and grab the stored values.
+ foreach my $key ( keys %ignorehash ) {
+ # Dereference values array.
+ my @values = @{$ignorehash{$key}};
+
+ # Obtain amount of items for the current value array.
+ my $items = scalar @values;
+
+ # Whether the amount equals one, the given binary address just
+ # needs to be compared against a single address.
+ if ($items eq "1") {
+ my ($ignored_address) = @values;
+
+ # Simple check if the stored and the given binary address
+ # are the same.
+ if ($bin_address eq $ignored_address) {
+ # The given address is part of the ignore list.
+ $logger->Log("debug", "Address $key found on the ignore list.");
+
+ # Return "1" (True).
+ return 1;
+ }
+ }
+
+ # If the amount equals two, for passed binary address needs to
+ # be checked if it is part of the ignored network range.
+ elsif ($items eq "2") {
+ my ($first_address, $last_address) = @values;
+
+ # Check if the passed binary address is bigger than
+ # the first address and smaler than the last address
+ # (between) the stored network range.
+ if (($bin_address >= $first_address) && ($bin_address <= $last_address)) {
+ # The address is part of an ignored network.
+ $logger->Log("debug", "Address is found inside the ignored network $key.");
+
+ # Return "1" (True).
+ return 1;
+ }
+
+ # If the amount is not eighter one or two, the current entry of the ignorehash seems
+ # to be corrupted. Skip and log it.
+ } else {
+ # Write log message about this corruped item in the ignore hash.
+ $logger->Log("err", "Invalid item in the Ignore Hash: $key - @values");
+
+ # Skip this element of the ignore hash.
+ next;
+ }
+ }
+
+ # If we got here, the given address is not part of the ignore hash.
+ # Return nothing (False).
+ return;
+}
+
1;