Merge branch 'next' of ssh://git.ipfire.org/pub/git/ipfire-2.x into next-suricata
authorStefan Schantl <stefan.schantl@ipfire.org>
Mon, 21 Jan 2019 12:04:13 +0000 (13:04 +0100)
committerStefan Schantl <stefan.schantl@ipfire.org>
Mon, 21 Jan 2019 12:04:13 +0000 (13:04 +0100)
14 files changed:
1  2 
config/backup/include
config/cfgroot/general-functions.pl
config/rootfiles/common/aarch64/initscripts
config/rootfiles/common/armv5tel/initscripts
config/rootfiles/common/configroot
config/rootfiles/common/i586/initscripts
config/rootfiles/common/x86_64/initscripts
html/cgi-bin/ids.cgi
html/cgi-bin/logs.cgi/log.dat
langs/de/cgi-bin/de.pl
langs/en/cgi-bin/en.pl
lfs/configroot
lfs/initscripts
make.sh

Simple merge
Simple merge
@@@ -103,7 -104,8 +104,8 @@@ etc/rc.d/rc0.d/K45rando
  etc/rc.d/rc0.d/K47setclock
  etc/rc.d/rc0.d/K49cyrus-sasl
  etc/rc.d/rc0.d/K51vnstat
 -etc/rc.d/rc0.d/K78snort
+ etc/rc.d/rc0.d/K77conntrackd
 +etc/rc.d/rc0.d/K78suricata
  etc/rc.d/rc0.d/K79leds
  etc/rc.d/rc0.d/K79unbound
  etc/rc.d/rc0.d/K80network
@@@ -154,7 -157,8 +157,8 @@@ etc/rc.d/rc6.d/K45rando
  etc/rc.d/rc6.d/K47setclock
  etc/rc.d/rc6.d/K49cyrus-sasl
  etc/rc.d/rc6.d/K51vnstat
 -etc/rc.d/rc6.d/K78snort
+ etc/rc.d/rc6.d/K77conntrackd
 +etc/rc.d/rc6.d/K78suricata
  etc/rc.d/rc6.d/K79leds
  etc/rc.d/rc6.d/K79unbound
  etc/rc.d/rc6.d/K80network
@@@ -103,7 -104,8 +104,8 @@@ etc/rc.d/rc0.d/K45rando
  etc/rc.d/rc0.d/K47setclock
  etc/rc.d/rc0.d/K49cyrus-sasl
  etc/rc.d/rc0.d/K51vnstat
 -etc/rc.d/rc0.d/K78snort
+ etc/rc.d/rc0.d/K77conntrackd
 +etc/rc.d/rc0.d/K78suricata
  etc/rc.d/rc0.d/K79leds
  etc/rc.d/rc0.d/K79unbound
  etc/rc.d/rc0.d/K80network
@@@ -154,7 -157,8 +157,8 @@@ etc/rc.d/rc6.d/K45rando
  etc/rc.d/rc6.d/K47setclock
  etc/rc.d/rc6.d/K49cyrus-sasl
  etc/rc.d/rc6.d/K51vnstat
 -etc/rc.d/rc6.d/K78snort
+ etc/rc.d/rc6.d/K77conntrackd
 +etc/rc.d/rc6.d/K78suricata
  etc/rc.d/rc6.d/K79leds
  etc/rc.d/rc6.d/K79unbound
  etc/rc.d/rc6.d/K80network
Simple merge
@@@ -102,7 -103,8 +103,8 @@@ etc/rc.d/rc0.d/K45rando
  etc/rc.d/rc0.d/K47setclock
  etc/rc.d/rc0.d/K49cyrus-sasl
  etc/rc.d/rc0.d/K51vnstat
 -etc/rc.d/rc0.d/K78snort
+ etc/rc.d/rc0.d/K77conntrackd
 +etc/rc.d/rc0.d/K78suricata
  etc/rc.d/rc0.d/K79leds
  etc/rc.d/rc0.d/K79unbound
  etc/rc.d/rc0.d/K80network
@@@ -153,7 -156,8 +156,8 @@@ etc/rc.d/rc6.d/K45rando
  etc/rc.d/rc6.d/K47setclock
  etc/rc.d/rc6.d/K49cyrus-sasl
  etc/rc.d/rc6.d/K51vnstat
 -etc/rc.d/rc6.d/K78snort
+ etc/rc.d/rc6.d/K77conntrackd
 +etc/rc.d/rc6.d/K78suricata
  etc/rc.d/rc6.d/K79leds
  etc/rc.d/rc6.d/K79unbound
  etc/rc.d/rc6.d/K80network
@@@ -102,7 -103,8 +103,8 @@@ etc/rc.d/rc0.d/K45rando
  etc/rc.d/rc0.d/K47setclock
  etc/rc.d/rc0.d/K49cyrus-sasl
  etc/rc.d/rc0.d/K51vnstat
 -etc/rc.d/rc0.d/K78snort
+ etc/rc.d/rc0.d/K77conntrackd
 +etc/rc.d/rc0.d/K78suricata
  etc/rc.d/rc0.d/K79leds
  etc/rc.d/rc0.d/K79unbound
  etc/rc.d/rc0.d/K80network
@@@ -153,7 -156,8 +156,8 @@@ etc/rc.d/rc6.d/K45rando
  etc/rc.d/rc6.d/K47setclock
  etc/rc.d/rc6.d/K49cyrus-sasl
  etc/rc.d/rc6.d/K51vnstat
 -etc/rc.d/rc6.d/K78snort
+ etc/rc.d/rc6.d/K77conntrackd
 +etc/rc.d/rc6.d/K78suricata
  etc/rc.d/rc6.d/K79leds
  etc/rc.d/rc6.d/K79unbound
  etc/rc.d/rc6.d/K80network
@@@ -210,371 -251,98 +210,370 @@@ if (($cgiparams{'WHITELIST'} eq $Lang::
        }
  }
  
 -#######################  End added for snort rules control  #################################
 +# Check if any error has been stored.
 +if (-e $IDS::storederrorfile) {
 +        # Open file to read in the stored error message.
 +        open(FILE, "<$IDS::storederrorfile") or die "Could not open $IDS::storederrorfile. $!\n";
 +
 +        # Read the stored error message.
 +        $errormessage = <FILE>;
  
 -if ($snortsettings{'OINKCODE'} ne "") {
 -      $errormessage = $Lang::tr{'invalid input for oink code'} unless ($snortsettings{'OINKCODE'} =~ /^[a-z0-9]+$/);
 +        # Close file.
 +        close (FILE);
 +
 +        # Delete the file, which is now not longer required.
 +        unlink($IDS::storederrorfile);
  }
  
 -if (!$errormessage) {
 -      if ($snortsettings{'RULES'} eq 'subscripted') {
 -              $url=" https://www.snort.org/rules/snortrules-snapshot-29120.tar.gz?oinkcode=$snortsettings{'OINKCODE'}";
 -      } elsif ($snortsettings{'RULES'} eq 'registered') {
 -              $url=" https://www.snort.org/rules/snortrules-snapshot-29120.tar.gz?oinkcode=$snortsettings{'OINKCODE'}";
 -      } elsif ($snortsettings{'RULES'} eq 'community') {
 -              $url=" https://www.snort.org/rules/community";
 -      } else {
 -              $url="https://rules.emergingthreats.net/open/snort-2.9.0/emerging.rules.tar.gz";
 +## Grab all available snort rules and store them in the idsrules hash.
 +#
 +# Open snort rules directory and do a directory listing.
 +opendir(DIR, $IDS::rulespath) or die $!;
 +      # Loop through the direcory.
 +      while (my $file = readdir(DIR)) {
 +
 +              # We only want files.
 +              next unless (-f "$IDS::rulespath/$file");
 +
 +              # Ignore empty files.
 +              next if (-z "$IDS::rulespath/$file");
 +
 +              # Use a regular expression to find files ending in .rules
 +              next unless ($file =~ m/\.rules$/);
 +
 +              # Ignore files which are not read-able.
 +              next unless (-R "$IDS::rulespath/$file");
 +
 +              # Skip whitelist rules file.
 +              next if( $file eq "whitelist.rules");
 +
 +              # Call subfunction to read-in rulefile and add rules to
 +              # the idsrules hash.
 +              &readrulesfile("$file");
        }
  
 -      if ($snortsettings{'ACTION'} eq $Lang::tr{'save'} && $snortsettings{'ACTION2'} eq "snort" ) {
 -              &General::writehash("${General::swroot}/snort/settings", \%snortsettings);
 -              if ($snortsettings{'ENABLE_SNORT'} eq 'on')
 -              {
 -                      system ('/usr/bin/touch', "${General::swroot}/snort/enable");
 -              } else {
 -                      unlink "${General::swroot}/snort/enable";
 +closedir(DIR);
 +
 +# Gather used rulefiles.
 +#
 +# Check if the file for activated rulefiles is not empty.
 +if(-f $IDS::used_rulefiles_file) {
 +      # Open the file for used rulefile and read-in content.
 +      open(FILE, $IDS::used_rulefiles_file) or die "Could not open $IDS::used_rulefiles_file. $!\n";
 +
 +      # Read-in content.
 +      my @lines = <FILE>;
 +
 +      # Close file.
 +      close(FILE);
 +
 +      # Loop through the array.
 +      foreach my $line (@lines) {
 +              # Remove newlines.
 +              chomp($line);
 +
 +              # Skip comments.
 +              next if ($line =~ /\#/);
 +
 +              # Skip blank  lines.
 +              next if ($line =~ /^\s*$/);
 +
 +              # Gather rule sid and message from the ruleline.
 +              if ($line =~ /.*- (.*)/) {
 +                      my $rulefile = $1;
 +
 +                      # 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";
 +                      }
                }
 -              if ($snortsettings{'ENABLE_SNORT_GREEN'} eq 'on')
 -              {
 -                      system ('/usr/bin/touch', "${General::swroot}/snort/enable_green");
 -              } else {
 -                      unlink "${General::swroot}/snort/enable_green";
 +      }
 +}
 +
 +# Save ruleset configuration.
 +if ($cgiparams{'RULESET'} eq $Lang::tr{'save'}) {
 +      my %oldsettings;
 +
 +      # Read-in current (old) IDS settings.
 +      &General::readhash("$IDS::rules_settings_file", \%oldsettings);
 +
 +      # Prevent form name from been stored in conf file.
 +      delete $cgiparams{'RULESET'};
 +
 +      # Check if an oinkcode has been provided.
 +      if ($cgiparams{'OINKCODE'}) {
 +              # Check if the oinkcode contains unallowed chars.
 +              unless ($cgiparams{'OINKCODE'} =~ /^[a-z0-9]+$/) {
 +                      $errormessage = $Lang::tr{'invalid input for oink code'};
                }
 -              if ($snortsettings{'ENABLE_SNORT_BLUE'} eq 'on')
 -              {
 -                      system ('/usr/bin/touch', "${General::swroot}/snort/enable_blue");
 -              } else {
 -                      unlink "${General::swroot}/snort/enable_blue";
 +      }
 +
 +      # Go on if there are no error messages.
 +      if (!$errormessage) {
 +              # Store settings into settings file.
 +              &General::writehash("$IDS::rules_settings_file", \%cgiparams);
 +      }
 +
 +      # Check if the the automatic rule update hass been touched.
 +      if($cgiparams{'AUTOUPDATE_INTERVAL'} ne $oldsettings{'AUTOUPDATE_INTERVAL'}) {
 +              # Call suricatactrl to set the new interval.
 +              &IDS::call_suricatactrl("cron", $cgiparams{'AUTOUPDATE_INTERVAL'});
 +      }
 +
 +# Save ruleset.
 +} elsif ($cgiparams{'RULESET'} eq $Lang::tr{'update'}) {
 +      # Arrays to store which rulefiles have been enabled and will be used.
 +      my @enabled_rulefiles;
 +
 +      # Hash to store the user-enabled and disabled sids.
 +      my %enabled_disabled_sids;
 +
 +      # Loop through the hash of idsrules.
 +      foreach my $rulefile(keys %idsrules) {
 +              # Check if the rulefile is enabled.
 +              if ($cgiparams{$rulefile} eq "on") {
 +                      # Add rulefile to the array of enabled rulefiles.
 +                      push(@enabled_rulefiles, $rulefile);
 +
 +                      # Drop item from cgiparams hash.
 +                      delete $cgiparams{$rulefile};
                }
 -              if ($snortsettings{'ENABLE_SNORT_ORANGE'} eq 'on')
 -              {
 -                      system ('/usr/bin/touch', "${General::swroot}/snort/enable_orange");
 -              } else {
 -                      unlink "${General::swroot}/snort/enable_orange";
 +      }
 +
 +      # Read-in the files for enabled/disabled sids.
 +      # This will be done by calling the read_enabled_disabled_sids_file function two times
 +      # and merge the returned hashes together into the enabled_disabled_sids hash.
 +      %enabled_disabled_sids = (
 +              &read_enabled_disabled_sids_file($IDS::disabled_sids_file),
 +              &read_enabled_disabled_sids_file($IDS::enabled_sids_file));
 +
 +      # Loop through the hash of idsrules.
 +      foreach my $rulefile (keys %idsrules) {
 +              # Loop through the single rules of the rulefile.
 +              foreach my $sid (keys %{$idsrules{$rulefile}}) {
 +                      # Skip the current sid if it is not numeric.
 +                      next unless ($sid =~ /\d+/ );
 +
 +                      # Check if there exists a key in the cgiparams hash for this sid.
 +                      if (exists($cgiparams{$sid})) {
 +                              # Look if the rule is disabled.
 +                              if ($idsrules{$rulefile}{$sid}{'State'} eq "off") {
 +                                      # Check if the state has been set to 'on'.
 +                                      if ($cgiparams{$sid} eq "on") {
 +                                              # Add/Modify the sid to/in the enabled_disabled_sids hash.
 +                                              $enabled_disabled_sids{$sid} = "enabled";
 +
 +                                              # Drop item from cgiparams hash.
 +                                              delete $cgiparams{$rulefile}{$sid};
 +                                      }
 +                              }
 +                      } else {
 +                              # Look if the rule is enabled.
 +                              if ($idsrules{$rulefile}{$sid}{'State'} eq "on") {
 +                                      # Check if the state is 'on' and should be disabled.
 +                                      # In this case there is no entry
 +                                      # for the sid in the cgiparams hash.
 +                                      # Add/Modify it to/in the enabled_disabled_sids hash.
 +                                      $enabled_disabled_sids{$sid} = "disabled";
 +
 +                                      # Drop item from cgiparams hash.
 +                                      delete $cgiparams{$rulefile}{$sid};
 +                              }
 +                      }
                }
 -              if ($snortsettings{'ENABLE_PREPROCESSOR_HTTP_INSPECT'} eq 'on')
 -              {
 -                      system ('/usr/bin/touch', "${General::swroot}/snort/enable_preprocessor_http_inspect");
 -              } else {
 -                      unlink "${General::swroot}/snort/enable_preprocessor_http_inspect";
 +      }
 +
 +      # Open enabled sid's file for writing.
 +      open(ENABLED_FILE, ">$IDS::enabled_sids_file") or die "Could not write to $IDS::enabled_sids_file. $!\n";
 +
 +      # Open disabled sid's file for writing.
 +      open(DISABLED_FILE, ">$IDS::disabled_sids_file") or die "Could not write to $IDS::disabled_sids_file. $!\n";
 +
 +      # Write header to the files.
 +      print ENABLED_FILE "#Autogenerated file. Any custom changes will be overwritten!\n";
 +      print DISABLED_FILE "#Autogenerated file. Any custom changes will be overwritten!\n";
 +
 +      # Check if the hash for enabled/disabled files contains any entries.
 +      if (%enabled_disabled_sids) {
 +              # Loop through the hash.
 +              foreach my $sid (keys %enabled_disabled_sids) {
 +                      # Check if the sid is enabled.
 +                      if ($enabled_disabled_sids{$sid} eq "enabled") {
 +                              # Print the sid to the enabled_sids file.
 +                              print ENABLED_FILE "enablesid $sid\n";
 +                      # Check if the sid is disabled.
 +                      } elsif ($enabled_disabled_sids{$sid} eq "disabled") {
 +                              # Print the sid to the disabled_sids file.
 +                              print DISABLED_FILE "disablesid $sid\n";
 +                      # Something strange happende - skip the current sid.
 +                      } else {
 +                              next;
 +                      }
                }
 +      }
 +
 +      # Close file for enabled_sids after writing.
 +      close(ENABLED_FILE);
 +
 +      # Close file for disabled_sids after writing.
 +      close(DISABLED_FILE);
 +
 +      # Call function to generate and write the used rulefiles file.
 +      &IDS::write_used_rulefiles_file(@enabled_rulefiles);
 +
 +      # Lock the webpage and print message.
 +      &working_notice("$Lang::tr{'snort working'}");
  
 -              system('/usr/local/bin/snortctrl restart >/dev/null');
 +      # Call oinkmaster to alter the ruleset.
 +      &IDS::oinkmaster();
 +
 +      # Check if the IDS is running.
 +      if(&IDS::ids_is_running()) {
 +              # Call suricatactrl to perform a reload.
 +              &IDS::call_suricatactrl("reload");
        }
  
 -      # INSTALLMD5 is not in the form, so not retrieved by getcgihash
 -      &General::readhash("${General::swroot}/snort/settings", \%snortsettings);
 +      # Reload page.
 +      &reload();
  
 -      if ($snortsettings{'ACTION'} eq $Lang::tr{'download new ruleset'} || $snortsettings{'ACTION'} eq $Lang::tr{'upload new ruleset'}) {
 -              my @df = `/bin/df -B M /var`;
 -              foreach my $line (@df) {
 -                      next if $line =~ m/^Filesystem/;
 -                      my $return;
 +# Download new ruleset.
 +} elsif ($cgiparams{'RULESET'} eq $Lang::tr{'download new ruleset'}) {
 +      # Check if the red device is active.
 +      unless (-e "${General::swroot}/red/active") {
 +              $errormessage = $Lang::tr{'could not download latest updates'};
 +      }
  
 -                      if ($line =~ m/dev/ ) {
 -                              $line =~ m/^.* (\d+)M.*$/;
 -                              my @temp = split(/ +/,$line);
 -                              if ($1<300) {
 -                                      $errormessage = "$Lang::tr{'not enough disk space'} < 300MB, /var $1MB";
 -                              } else {
 -                                      if ( $snortsettings{'ACTION'} eq $Lang::tr{'download new ruleset'}) {
 -                                              &downloadrulesfile();
 -                                              sleep(3);
 -                                              $return = `cat /var/tmp/log 2>/dev/null`;
 -
 -                                      } elsif ( $snortsettings{'ACTION'} eq $Lang::tr{'upload new ruleset'}) {
 -                                              my $upload = $a->param("UPLOAD");
 -                                              open UPLOADFILE, ">/var/tmp/snortrules.tar.gz";
 -                                              binmode $upload;
 -                                              while ( <$upload> ) {
 -                                                      print UPLOADFILE;
 -                                              }
 -                                              close UPLOADFILE;
 -                                      }
 +      # Check if enought free disk space is availabe.
 +      if(&IDS::checkdiskspace()) {
 +              $errormessage = "$Lang::tr{'not enough disk space'}";
 +      }
  
 -                                      if ($return =~ "ERROR") {
 -                                              $errormessage = "<br /><pre>".$return."</pre>";
 -                                      } else {
 -                                              system("/usr/local/bin/oinkmaster.pl -v -s -u file:///var/tmp/snortrules.tar.gz -C /var/ipfire/snort/oinkmaster.conf -o /etc/snort/rules >>/var/tmp/log 2>&1 &");
 -                                              sleep(2);
 -                                      }
 -                              }
 +      # Check if any errors happend.
 +      unless ($errormessage) {
 +              # Lock the webpage and print notice about downloading
 +              # a new ruleset.
 +              &working_notice("$Lang::tr{'snort working'}");
 +
 +              # Call subfunction to download the ruleset.
 +              if(&IDS::downloadruleset()) {
 +                      $errormessage = $Lang::tr{'could not download latest updates'};
 +
 +                      # Call function to store the errormessage.
 +                      &IDS::_store_error_message($errormessage);
 +
 +                      # Preform a reload of the page.
 +                      &reload();
 +              } else {
 +                      # Call subfunction to launch oinkmaster.
 +                      &IDS::oinkmaster();
 +
 +                      # Check if the IDS is running.
 +                      if(&IDS::ids_is_running()) {
 +                              # Call suricatactrl to perform a reload.
 +                              &IDS::call_suricatactrl("reload");
 +                      }
 +
 +                      # Perform a reload of the page.
 +                      &reload();
 +              }
 +      }
 +# Save snort settings.
 +} elsif ($cgiparams{'IDS'} eq $Lang::tr{'save'}) {
 +      my %oldidssettings;
 +      my $reload_page;
 +      my $monitored_zones = 0;
 +
 +      # Read-in current (old) IDS settings.
 +      &General::readhash("$IDS::ids_settings_file", \%oldidssettings);
 +
 +      # Prevent form name from been stored in conf file.
 +      delete $cgiparams{'IDS'};
 +
 +      # Check if the IDS should be enabled.
 +      if ($cgiparams{'ENABLE_IDS'} eq "on") {
 +              # Check if any ruleset is available. Otherwise abort and display an error.
 +              unless(%idsrules) {
 +                      $errormessage = $Lang::tr{'ids no ruleset available'};
 +              }
 +
 +              # Loop through the array of available interfaces.
 +              foreach my $zone (@network_zones) {
 +                      # Convert interface name into upper case.
 +                      my $zone_upper = uc($zone);
 +
 +                      # Check if the IDS is enabled for this interaces.
 +                      if ($cgiparams{"ENABLE_IDS_$zone_upper"}) {
 +                              # Increase count.
 +                              $monitored_zones++;
                        }
                }
 +
 +              # Check if at least one zone should be monitored, or show an error.
 +              unless ($monitored_zones >= 1) {
 +                      $errormessage = $Lang::tr{'ids no network zone'};
 +              }
 +      }
 +
 +      # Go on if there are no error messages.
 +      if (!$errormessage) {
 +              # Store settings into settings file.
 +              &General::writehash("$IDS::ids_settings_file", \%cgiparams);
 +      }
 +
 +      # Generate file to store the home net.
 +      &IDS::generate_home_net_file();
 +
 +      # Temporary variable to set the ruleaction.
 +      # Default is "drop" to use suricata as IPS.
 +      my $ruleaction="drop";
 +
 +      # Check if the traffic only should be monitored.
 +      if($cgiparams{'MONITOR_TRAFFIC_ONLY'} eq 'on') {
 +              # Switch the ruleaction to "alert".
 +              # Suricata acts as an IDS only.
 +              $ruleaction="alert";
 +      }
 +
 +      # Write the modify sid's file and pass the taken ruleaction.
 +      &IDS::write_modify_sids_file($ruleaction);
 +
 +      # Check if "MONITOR_TRAFFIC_ONLY" has been changed.
 +      if($cgiparams{'MONITOR_TRAFFIC_ONLY'} ne $oldidssettings{'MONITOR_TRAFFIC_ONLY'}) {
 +              # Check if a ruleset exists.
 +              if (%idsrules) {
 +                      # Lock the webpage and print message.
 +                      &working_notice("$Lang::tr{'snort working'}");
 +
 +                      # Call oinkmaster to alter the ruleset.
 +                      &IDS::oinkmaster();
 +
 +                      # Set reload_page to "True".
 +                      $reload_page="True";
 +              }
 +      }
 +
 +      # Check if the IDS currently is running.
 +      if(&IDS::ids_is_running()) {
 +              # Check if ENABLE_IDS is set to on.
 +              if($cgiparams{'ENABLE_IDS'} eq "on") {
 +                      # Call suricatactrl to perform a reload of suricata.
 +                      &IDS::call_suricatactrl("reload");
 +              } else {
 +                      # Call suricatactrl to stop suricata.
 +                      &IDS::call_suricatactrl("stop");
 +              }
 +      } else {
 +              # Call suricatactrl to start suricata.
 +              &IDS::call_suricatactrl("start");
 +      }
 +
 +      # Check if the page should be reloaded.
 +      if ($reload_page) {
 +              # Perform a reload of the page.
 +              &reload();
        }
  }
  
Simple merge
Simple merge
Simple merge
diff --cc lfs/configroot
Simple merge
diff --cc lfs/initscripts
Simple merge
diff --cc make.sh
Simple merge