diff --git a/pandora_agents/unix/Linux/pandora_agent.conf b/pandora_agents/unix/Linux/pandora_agent.conf index a0e473063e..62e785b74e 100644 --- a/pandora_agents/unix/Linux/pandora_agent.conf +++ b/pandora_agents/unix/Linux/pandora_agent.conf @@ -165,9 +165,15 @@ remote_config 0 # should consider changing the temporal directory, since /tmp is world writable. xml_buffer 1 -# Minimum available bytes in the temporal directory to enable the XML buffer +# Minimum available megabytes in the temporal directory to enable the XML buffer temporal_min_size 1024 +# Maximum size (in megabytes) allowed for the XML buffer. +temporal_max_size 1024 + +# Maximum number of files allowed for the XML buffer. +temporal_max_files 1024 + # Agent mode: Learn (default), No-learn, Autodisable # agent_mode autodisable diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index de1ad955e0..091dcf93c3 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -1145,7 +1145,9 @@ my %DefaultConf = ( 'secondary_server_opts' => '', 'secondary_temporal' => '/var/spool/pandora', 'autotime' => 0, - 'temporal_min_size' => 1, + 'temporal_min_size' => 1024, + 'temporal_max_files' => 1024, + 'temporal_max_size' => 1024, 'timezone_offset' => 0, 'pandora_exec' => 'pandora_agent_exec', 'agent_threads' => 1, @@ -2110,13 +2112,13 @@ sub send_xml_file ($) { swap_servers(); # Secondary buffer. - if ($rc_sec != 0 && $Conf{'xml_buffer'} == 1 && temporal_freedisk () > $Conf{'temporal_min_size'}) { + if ($rc_sec != 0 && write_to_buffer($Conf{'secondary_temporal'}) == 1) { copy($file, $Conf{'secondary_temporal'}) || die("Error copying file $file to " . $Conf{'secondary_temporal'} . ": $!"); } } # Primary buffer. - if ($rc == 0 || $Conf{'xml_buffer'} == 0 || temporal_freedisk () <= $Conf{'temporal_min_size'}) { + if ($rc == 0 || write_to_buffer($Conf{'temporal'}) == 0) { if ($Conf{'debug'} eq '1') { rename($file, $file . "sent"); } else { @@ -3761,20 +3763,45 @@ sub kill_signal_handler (){ } ################################################################################ -# Get the free disk space in the temporal directory (in bytes). +# Get the free disk space in the temporal directory (in megabytes). ################################################################################ -sub temporal_freedisk () { +sub temporal_freedisk { + my ($temporal) = @_; # Call df return 0 unless defined (DF_CMDS->{$OS}); - my $cmd = DF_CMDS->{$OS} . ' ' . $Conf{'temporal'} . ' | awk \'NR > 1 {print $4}\''; + my $cmd = DF_CMDS->{$OS} . ' ' . $temporal . ' | awk \'NR > 1 {print $4}\''; my $temporal_freedisk = `$cmd`; # Check for errors return 0 unless ($? eq 0); - # Convert to bytes - return 1024 * int ($temporal_freedisk); + # Convert from KB to MB. + return $temporal_freedisk / 1024; +} + +################################################################################ +# Return the number of data files in the temporal directory and their total +# size (in megabytes). +################################################################################ +sub temporal_stats { + my ($temporal) = @_; + + my $file_count = 0; + my $file_size = 0; + opendir(my $dir, $temporal) or die($!); + while (my $f = readdir($dir)) { + if ($f =~ m/.data$/ || $f =~ m/.datasent$/) { + $file_count += 1; + $file_size += (stat $temporal . '/' . $f)[7]; + } + } + closedir($dir); + + # Convert from B to MB. + $file_size /= 1048576; + + return ($file_count, $file_size); } ################################################################################ @@ -3960,6 +3987,27 @@ sub get_ehkey { return ''; } +################################################################################ +# Return 1 if XML files should be written to the buffer. 0 otherwise. +################################################################################ +sub write_to_buffer { + my ($temporal) = @_; + + # The XML buffer is disabled. + return 0 if ($Conf{'xml_buffer'} == 0); + + # Check available disk space. + return 0 if ($Conf{'temporal_min_size'} != 0 && temporal_freedisk($temporal) < $Conf{'temporal_min_size'}); + + # Check buffer file count and size limits. + my ($file_count, $file_size) = temporal_stats($temporal); + return 0 if ($Conf{'temporal_max_files'} != 0 && $file_count > $Conf{'temporal_max_files'}); + return 0 if ($Conf{'temporal_max_size'} != 0 && $file_size > $Conf{'temporal_max_size'}); + + # It's OK to write to the buffer. + return 1; +} + ################################################################################ # Main. ################################################################################ diff --git a/pandora_agents/win32/bin/pandora_agent.conf b/pandora_agents/win32/bin/pandora_agent.conf index 549b0e7ac9..200a31d57d 100644 --- a/pandora_agents/win32/bin/pandora_agent.conf +++ b/pandora_agents/win32/bin/pandora_agent.conf @@ -55,9 +55,15 @@ address auto # or setting a fixed IP address, like for example: #address 192.168.36.73 -# This limits operation if temporal dir has not enough free disk. +# This limits operation if temporal dir has not enough free disk (in megabytes). #temporal_min_size 1024 +# Maximum size (in megabytes) allowed for the XML buffer. +temporal_max_size 1024 + +# Maximum number of files allowed for the XML buffer. +temporal_max_files 1024 + # Delay start execution X second before start to monitoring nothing #startup_delay 30 diff --git a/pandora_agents/win32/pandora_windows_service.cc b/pandora_agents/win32/pandora_windows_service.cc index f047eb17ff..f369935aac 100644 --- a/pandora_agents/win32/pandora_windows_service.cc +++ b/pandora_agents/win32/pandora_windows_service.cc @@ -1696,7 +1696,7 @@ Pandora_Windows_Service::checkConfig (string file) { int Pandora_Windows_Service::sendXml (Pandora_Module_List *modules, string extra /* = ""*/) { - int rc = 0, rc_sec = 0, xml_buffer; + int rc = 0, rc_sec = 0, xml_buffer; string data_xml; string xml_filename, random_integer; string tmp_filename, tmp_filepath; @@ -1705,12 +1705,10 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules, string extra /* string ehorus_conf, eh_key; static HANDLE mutex = 0; ULARGE_INTEGER free_bytes; - double min_free_bytes = 0; Pandora_Agent_Conf *conf = NULL; FILE *conf_fh = NULL; conf = this->getConf (); - min_free_bytes = 1024 * atoi (conf->getValue ("temporal_min_size").c_str ()); xml_buffer = atoi (conf->getValue ("xml_buffer").c_str ()); if (mutex == 0) { @@ -1814,14 +1812,14 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules, string extra /* rc_sec = this->copyToSecondary (tmp_filename, false); /* Secondary buffer. */ - if (rc_sec != 0 && xml_buffer == 1 && (GetDiskFreeSpaceEx (conf->getValue ("secondary_temporal").c_str (), &free_bytes, NULL, NULL) != 0 && free_bytes.QuadPart >= min_free_bytes)) { + if (rc_sec != 0 && this->writeToBuffer(conf->getValue ("secondary_temporal").c_str ())) { secondary_filepath = conf->getValue ("secondary_temporal") + "\\" + tmp_filename; CopyFile (tmp_filepath.c_str(), secondary_filepath.c_str(), false); } } /* Primary buffer. Delete the file if successfully copied, buffer disabled or not enough space available. */ - if (rc == 0 || xml_buffer == 0 || (GetDiskFreeSpaceEx (tmp_filepath.c_str (), &free_bytes, NULL, NULL) != 0 && free_bytes.QuadPart < min_free_bytes)) { + if (rc == 0 || !writeToBuffer(conf->getValue ("temporal").c_str ())) { /* Rename the file if debug mode is enabled*/ if (getPandoraDebug ()) { string tmp_filepath_sent = tmp_filepath; @@ -2218,3 +2216,60 @@ Pandora_Windows_Service::generateAgentName () { sha256(data.str().c_str(), digest); return std::string(digest); } + +bool +Pandora_Windows_Service::writeToBuffer (string temporal) { + int xml_buffer; + long int temporal_max_files; + double temporal_min_size, temporal_max_size; + string dir, file_name; + ULARGE_INTEGER free_bytes; + Pandora_Agent_Conf *conf = NULL; + + conf = this->getConf (); + + dir = temporal; + if (dir[dir.length () - 1] != '\\') { + dir += "\\"; + } + file_name = dir + "*.data"; + + // Is the XML buffer disabled? + xml_buffer = atoi (conf->getValue ("xml_buffer").c_str ()); + if (xml_buffer == 0) { + return false; + } + + // Check available disk space. + temporal_min_size = atoi (conf->getValue ("temporal_min_size").c_str ()); + if (GetDiskFreeSpaceEx (dir.c_str (), &free_bytes, NULL, NULL) && (free_bytes.QuadPart / 1048576) < temporal_min_size) { // Convert free_bytes.QuadPart from B to MB. + pandoraLog ("[writeToBuffer] Disk full."); + return false; + } + + // Check buffer file count and size limits. + temporal_max_size = atoi (conf->getValue ("temporal_max_size").c_str ()); + temporal_max_files = atol (conf->getValue ("temporal_max_files").c_str ()); + if (temporal_max_size != 0 || temporal_max_files != 0) { + long int file_count = 0; + ULONGLONG file_size = 0; + HANDLE hFind; + WIN32_FIND_DATA FindFileData; + if ((hFind = FindFirstFile(file_name.c_str(), &FindFileData)) != INVALID_HANDLE_VALUE) { + do { + file_count += 1; + file_size += (FindFileData.nFileSizeHigh * (MAXDWORD + 1)) + FindFileData.nFileSizeLow; + } while (FindNextFile(hFind, &FindFileData)); + FindClose(hFind); + } + + file_size /= 1048576; // Convert from B to MB. + if ((temporal_max_size != 0 && file_size > temporal_max_size) || + (temporal_max_files != 0 && file_count > temporal_max_files)) { + pandoraLog ("[writeToBuffer] Too many files or buffer full."); + return false; + } + } + + return true; +} diff --git a/pandora_agents/win32/pandora_windows_service.h b/pandora_agents/win32/pandora_windows_service.h index 39ad2e8e44..f863ae2c27 100644 --- a/pandora_agents/win32/pandora_windows_service.h +++ b/pandora_agents/win32/pandora_windows_service.h @@ -124,6 +124,7 @@ namespace Pandora { long getInterval (); long getIntensiveInterval (); string generateAgentName (); + bool writeToBuffer (string temporal); }; }