diff --git a/config/cfgroot/ids-functions.pl b/config/cfgroot/ids-functions.pl index ed9bb203b..245a267bf 100644 --- a/config/cfgroot/ids-functions.pl +++ b/config/cfgroot/ids-functions.pl @@ -27,12 +27,15 @@ package IDS; require '/var/ipfire/general-functions.pl'; require "${General::swroot}/network-functions.pl"; -require "${General::swroot}/suricata/ruleset-sources"; +require "${General::swroot}/suricata/ruleset-sources-new"; # Location where all config and settings files are stored. our $settingsdir = "${General::swroot}/suricata"; -# File where the used rulefiles are stored. +# File where the main file for providers ruleset inclusion exists. +our $suricata_used_providers_file = "$settingsdir/suricata-used-providers.yaml"; + +# DEPRECATED - File where the used rulefiles are stored. our $used_rulefiles_file = "$settingsdir/suricata-used-rulefiles.yaml"; # File where the addresses of the homenet are stored. @@ -138,7 +141,7 @@ sub check_and_create_filelayout() { unless (-f "$enabled_sids_file") { &create_empty_file($enabled_sids_file); } unless (-f "$disabled_sids_file") { &create_empty_file($disabled_sids_file); } unless (-f "$modify_sids_file") { &create_empty_file($modify_sids_file); } - unless (-f "$used_rulefiles_file") { &create_empty_file($used_rulefiles_file); } + unless (-f "$suricata_used_providers_file") { &create_empty_file($suricata_used_providers_file); } unless (-f "$ids_settings_file") { &create_empty_file($ids_settings_file); } unless (-f "$providers_settings_file") { &create_empty_file($providers_settings_file); } unless (-f "$ignored_file") { &create_empty_file($ignored_file); } @@ -1226,13 +1229,18 @@ sub generate_http_ports_file() { } # -## Function to generate and write the file for used rulefiles. +## Function to generate and write the file for used rulefiles file for a given provider. +## +## The function requires as first argument a provider handle, and as second an array with files. # -sub write_used_rulefiles_file(@) { - my @files = @_; +sub write_used_provider_rulefiles_file($@) { + my ($provider, @files) = @_; + + # Get the path and file for the provider specific used rulefiles file. + my $used_provider_rulesfile_file = &get_used_provider_rulesfile_file($provider); # Open file for used rulefiles. - open (FILE, ">$used_rulefiles_file") or die "Could not write to $used_rulefiles_file. $!\n"; + open (FILE, ">$used_provider_rulesfile_file") or die "Could not write to $used_provider_rulesfile_file. $!\n"; # Write yaml header to the file. print FILE "%YAML 1.1\n"; @@ -1241,9 +1249,6 @@ sub write_used_rulefiles_file(@) { # Write header to file. print FILE "#Autogenerated file. Any custom changes will be overwritten!\n"; - # Allways use the whitelist. - print FILE " - whitelist.rules\n"; - # Loop through the array of given files. foreach my $file (@files) { # Check if the given filename exists and write it to the file of used rulefiles. @@ -1256,6 +1261,53 @@ sub write_used_rulefiles_file(@) { close(FILE); } +# +## Function to write the main file for provider rulesfiles inclusions. +## +## This function requires an array of provider handles. +# +sub write_main_used_rulefiles_file (@) { + my (@providers) = @_; + + # Open file for used rulefils inclusion. + open (FILE, ">", "$suricata_used_providers_file") or die "Could not write to $suricata_used_providers_file. $!\n"; + + # Write yaml header to the file. + print FILE "%YAML 1.1\n"; + print FILE "---\n\n"; + + # Write header to file. + print FILE "#Autogenerated file. Any custom changes will be overwritten!\n"; + + # Loop through the list of given providers. + foreach my $provider (@providers) { + # Call function to get the providers used rulefiles file. + my $filename = &get_used_provider_rulesfile_file($provider); + + # Print the provider to the file. + print FILE "include\: $filename\n"; + } + + # XXX - whitelist.rules is not allowed directly, needs to be in a yaml file which has to be included. + # Always use the whitelist file. + #print FILE "\n - whitelist.rules\n"; + + # Close the filehandle after writing. + close(FILE); +} + +# +## Tiny function to generate the full path and name for the used_provider_rulesfile file of a given provider. +# +sub get_used_provider_rulesfile_file ($) { + my ($provider) = @_; + + my $filename = "$settingsdir/suricata\-$provider\-used\-rulefiles.yaml"; + + # Return the gernerated file. + return $filename; +} + # ## Function to generate and write the file for modify the ruleset. # @@ -1509,16 +1561,21 @@ sub get_red_address() { } # -## Function to get all used rulesfiles files. +## Function to get the used rules files of a given provider. # -sub get_used_rulesfiles() { +sub read_used_provider_rulesfiles($) { + my ($provider) = @_; + # Array to store the used rulefiles. my @used_rulesfiles = (); + # Get the used rulesefile file for the provider. + my $rulesfile_file = &get_used_provider_rulesfile_file($provider); + # Check if the used rulesfile is empty. - unless (-z $used_rulefiles_file) { + unless (-z $rulesfile_file) { # Open the file or used rulefiles and read-in content. - open(FILE, $used_rulefiles_file) or die "Could not open $used_rulefiles_file. $!\n"; + open(FILE, $rulesfile_file) or die "Could not open $rulesfile_file. $!\n"; while () { # Assign the current line to a nice variable. diff --git a/config/suricata/suricata.yaml b/config/suricata/suricata.yaml index b4a188d40..84f50f54e 100644 --- a/config/suricata/suricata.yaml +++ b/config/suricata/suricata.yaml @@ -46,8 +46,8 @@ vars: ## default-rule-path: /var/lib/suricata rule-files: - # Include enabled ruleset files from external file - include: /var/ipfire/suricata/suricata-used-rulefiles.yaml + # Include enabled ruleset files from external file. + include: /var/ipfire/suricata/suricata-used-providers.yaml # Include default rules. include: /var/ipfire/suricata/suricata-default-rules.yaml diff --git a/html/cgi-bin/ids.cgi b/html/cgi-bin/ids.cgi index a1be76b79..908ad9c28 100644 --- a/html/cgi-bin/ids.cgi +++ b/html/cgi-bin/ids.cgi @@ -254,6 +254,10 @@ if (-e $IDS::storederrorfile) { if ($cgiparams{'RULESET'}) { ## Grab all available rules and store them in the idsrules hash. # + + # Get enabled providers. + my @enabled_providers = &IDS::get_enabled_providers(); + # Open rules directory and do a directory listing. opendir(DIR, $IDS::rulespath) or die $!; # Loop through the direcory. @@ -274,6 +278,15 @@ if ($cgiparams{'RULESET'}) { # Skip whitelist rules file. next if( $file eq "whitelist.rules"); + # Splitt vendor from filename. + my @filename_parts = split(/-/, $file); + + # Assign vendor name for easy processing. + my $vendor = @filename_parts[0]; + + # Skip rulefile if the provider is disabled. + next unless ($vendor ~~ @enabled_providers); + # Call subfunction to read-in rulefile and add rules to # the idsrules hash. &readrulesfile("$file"); @@ -281,17 +294,20 @@ if ($cgiparams{'RULESET'}) { closedir(DIR); - # Gather used rulefiles. - my @used_rulesfiles = &IDS::get_used_rulesfiles(); + # Loop through the array of used providers. + foreach my $provider (@enabled_providers) { + # Gather used rulefiles. + my @used_rulesfiles = &IDS::read_used_provider_rulesfiles($provider); - # Loop through the array of used rulesfiles. - foreach my $rulesfile (@used_rulesfiles) { - # Check if the current rulefile exists in the %idsrules hash. - # If not, the file probably does not exist anymore or contains - # no rules. - if($idsrules{$rulefile}) { - # Add the rulefile state to the %idsrules hash. - $idsrules{$rulefile}{'Rulefile'}{'State'} = "on"; + # Loop through the array of used rulesfiles. + foreach my $rulefile (@used_rulesfiles) { + # Check if the current rulefile exists in the %idsrules hash. + # If not, the file probably does not exist anymore or contains + # no rules. + if($idsrules{$rulefile}) { + # Add the rulefile state to the %idsrules hash. + $idsrules{$rulefile}{'Rulefile'}{'State'} = "on"; + } } } } @@ -479,8 +495,40 @@ if ($cgiparams{'RULESET'} eq $Lang::tr{'save'}) { # Close file for disabled_sids after writing. close(DISABLED_FILE); + # Handle enabled / disabled rulefiles. + # + # Get enabled providers. + my @enabled_providers = &IDS::get_enabled_providers(); + + # Loop through the array of enabled providers. + foreach my $provider(@enabled_providers) { + # Array to store the rulefiles which belong to the current processed provider. + my @provider_rulefiles = (); + + # Loop through the array of enabled rulefiles. + foreach my $rulesfile (@enabled_rulefiles) { + # Split the rulefile name. + my @filename_parts = split(/-/, "$rulesfile"); + + # Assign vendor name for easy processings. + my $vendor = @filename_parts[0]; + + # Check if the rulesvendor is our current processed enabled provider. + if ("$vendor" eq "$provider") { + # Add the rulesfile to the array of provider rulesfiles. + push(@provider_rulefiles, $rulesfile); + } + + # Check if any rulesfiles have been found for this provider. + if (@provider_rulefiles) { + # Call function and write the providers used rulesfile file. + &IDS::write_used_provider_rulefiles_file($provider, @provider_rulefiles); + } + } + } + # Call function to generate and write the used rulefiles file. - &IDS::write_used_rulefiles_file(@enabled_rulefiles); + &IDS::write_main_used_rulefiles_file(@enabled_providers); # Lock the webpage and print message. &working_notice("$Lang::tr{'ids apply ruleset changes'}"); @@ -779,6 +827,10 @@ if ($cgiparams{'RULESET'} eq $Lang::tr{'save'}) { # Cleanup temporary directory. &IDS::cleanup_tmp_directory(); + # Create new empty file for used rulefiles + # for this provider. + &IDS::write_used_provider_rulefiles_file($provider); + # Perform a reload of the page. &reload(); }