diff --git a/pandora_agents/pc/pandora_agent b/pandora_agents/pc/pandora_agent index 080af0b8fa..b105a8c654 100644 --- a/pandora_agents/pc/pandora_agent +++ b/pandora_agents/pc/pandora_agent @@ -510,8 +510,6 @@ sub parse_conf_modules($) { } } elsif ($line =~ /^\s*module_crontab\s+(((\*|(\d+(-\d+){0,1}))\s*){5}).*$/) { $module->{'cron'} = $1; - } elsif ($line =~ /^\s*module_cron_interval\s+(\d+).*$/) { - $module->{'cron_interval'} = $1; } elsif ($line =~ /^\s*module_end\s*$/) { next unless ($module->{'name'} ne '') and ($module->{'func'} != 0); diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control index e5ecc44071..090ab35d1e 100644 --- a/pandora_agents/unix/DEBIAN/control +++ b/pandora_agents/unix/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-agent-unix -Version: 7.0NG.719-180226 +Version: 7.0NG.719-180228 Architecture: all Priority: optional Section: admin diff --git a/pandora_agents/unix/DEBIAN/make_deb_package.sh b/pandora_agents/unix/DEBIAN/make_deb_package.sh index 837b2398dd..677317a2cf 100644 --- a/pandora_agents/unix/DEBIAN/make_deb_package.sh +++ b/pandora_agents/unix/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.719-180226" +pandora_version="7.0NG.719-180228" echo "Test if you has the tools for to make the packages." whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index 83f81d1d33..d4b862cebf 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -30,6 +30,7 @@ use File::Basename; use File::Copy; use IO::Socket; use Sys::Syslog; +use Time::Local; # Agent XML data my $Xml; @@ -41,7 +42,7 @@ my $Sem = undef; my $ThreadSem = undef; use constant AGENT_VERSION => '7.0NG.719'; -use constant AGENT_BUILD => '180226'; +use constant AGENT_BUILD => '180228'; # Agent log default file size maximum and instances use constant DEFAULT_MAX_LOG_SIZE => 600000; @@ -515,10 +516,11 @@ sub parse_conf_modules($) { } } } elsif ($line =~ /^\s*module_crontab\s+(((\*|(\d+(-\d+){0,1}))\s*){5}).*$/) { - $module->{'cron'} = $1; - chomp ($module->{'cron'}); - } elsif ($line =~ /^\s*module_cron_interval\s+(\d+).*$/) { - $module->{'cron_interval'} = $1; + my $cron_text = $1; + chomp ($cron_text); + if (cron_check_syntax($cron_text)) { + $module->{'cron'} = $cron_text; + } } elsif ($line =~ /^\s*module_end\s*$/) { $module_begin = 0; @@ -1632,8 +1634,8 @@ sub guess_os_version ($) { ################################################################################ # Execute the given module. ################################################################################ -sub exec_module ($) { - my $module = shift; +sub exec_module { + my ($module, $interval) = @_; # Need something to execute if ($module->{'func'} == 0) { @@ -1648,7 +1650,7 @@ sub exec_module ($) { } # Check module cron - if (check_module_cron ($module) != 1) { + if (check_module_cron ($module, $interval) != 1) { $ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); return; } @@ -2044,85 +2046,339 @@ sub evaluate_module_intensive_conditions ($$) { return 1; } +############################################################################### +# Get the number of seconds left to the next execution of the given cron entry. +############################################################################### +sub cron_next_execution { + my ($cron, $interval) = @_; + + # Check cron conf format + if ($cron !~ /^((\*|(\d+(-\d+){0,1}))\s*){5}$/) { + return $interval; + } + + # Get day of the week and month from cron config + my ($mday, $wday) = (split (/\s/, $cron))[2, 4]; + + # Get current time and day of the week + my $cur_time = time(); + my $cur_wday = (localtime ($cur_time))[6]; + + # Any day of the week + if ($wday eq '*') { + my $nex_time = cron_next_execution_date ($cron, $cur_time, $interval); + return $nex_time - time(); + } + # A range? + else { + $wday = cron_get_closest_in_range ($cur_wday, $wday); + } + + # A specific day of the week + my $count = 0; + my $nex_time = $cur_time; + do { + $nex_time = cron_next_execution_date ($cron, $nex_time, $interval); + my $nex_time_wd = $nex_time; + my ($nex_mon, $nex_wday) = (localtime ($nex_time_wd))[4, 6]; + my $nex_mon_wd; + do { + # Check the day of the week + if ($nex_wday == $wday) { + return $nex_time_wd - time(); + } + + # Move to the next day of the month + $nex_time_wd += 86400; + ($nex_mon_wd, $nex_wday) = (localtime ($nex_time_wd))[4, 6]; + } while ($mday eq '*' && $nex_mon_wd == $nex_mon); + $count++; + } while ($count < 60); + + # Something went wrong, default to 5 minutes + return $interval; +} + +############################################################################### +# Get the number of seconds left to the next execution of the given cron entry. +############################################################################### +sub cron_check_syntax ($) { + my ($cron) = @_; + + return 0 if !defined ($cron); + return ($cron =~ m/^(\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+$/); +} + +############################################################################### +# Get the next execution date for the given cron entry in seconds since epoch. +############################################################################### +sub cron_next_execution_date { + my ($cron, $cur_time, $interval) = @_; + + # Get cron configuration + my ($min, $hour, $mday, $mon, $wday) = split (/\s/, $cron); + + # Months start from 0 + if($mon ne '*') { + my ($mon_down, $mon_up) = cron_get_interval ($mon); + if (defined($mon_up)) { + $mon = ($mon_down - 1) . "-" . ($mon_up - 1); + } else { + $mon = $mon_down - 1; + } + } + + # Get current time + if (! defined ($cur_time)) { + $cur_time = time(); + } + # Check if current time + interval is on cron too + my $nex_time = $cur_time + $interval; + my ($cur_min, $cur_hour, $cur_mday, $cur_mon, $cur_year) + = (localtime ($nex_time))[1, 2, 3, 4, 5]; + + my @cron_array = ($min, $hour, $mday, $mon); + my @curr_time_array = ($cur_min, $cur_hour, $cur_mday, $cur_mon); + return ($nex_time) if cron_is_in_cron(\@cron_array, \@curr_time_array) == 1; + + # Get first next date candidate from next cron configuration + # Initialize some vars + my @nex_time_array = @curr_time_array; + + # Update minutes + my ($min_down, undef) = cron_get_interval ($min); + $nex_time_array[0] = ($min_down eq '*') ? 0 : $min_down; + + $nex_time = cron_valid_date(@nex_time_array, $cur_year); + if ($nex_time >= $cur_time) { + return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array); + } + + # Check if next hour is in cron + $nex_time_array[1]++; + $nex_time = cron_valid_date(@nex_time_array, $cur_year); + + if ($nex_time == 0) { + #Update the month day if overflow + $nex_time_array[1] = 0; + $nex_time_array[2]++; + $nex_time = cron_valid_date(@nex_time_array, $cur_year); + if ($nex_time == 0) { + #Update the month if overflow + $nex_time_array[2] = 1; + $nex_time_array[3]++; + $nex_time = cron_valid_date(@nex_time_array, $cur_year); + if ($nex_time == 0) { + #Update the year if overflow + $cur_year++; + $nex_time_array[3] = 0; + $nex_time = cron_valid_date(@nex_time_array, $cur_year); + } + } + } + + #Check the hour + return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array); + + #Update the hour if fails + my ($hour_down, undef) = cron_get_interval ($hour); + $nex_time_array[1] = ($hour_down eq '*') ? 0 : $hour_down; + + # When an overflow is passed check the hour update again + $nex_time = cron_valid_date(@nex_time_array, $cur_year); + if ($nex_time >= $cur_time) { + return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array); + } + + # Check if next day is in cron + $nex_time_array[2]++; + $nex_time = cron_valid_date(@nex_time_array, $cur_year); + if ($nex_time == 0) { + #Update the month if overflow + $nex_time_array[2] = 1; + $nex_time_array[3]++; + $nex_time = cron_valid_date(@nex_time_array, $cur_year); + if ($nex_time == 0) { + #Update the year if overflow + $nex_time_array[3] = 0; + $cur_year++; + $nex_time = cron_valid_date(@nex_time_array, $cur_year); + } + } + + #Check the day + return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array); + + #Update the day if fails + my ($mday_down, undef) = cron_get_interval ($mday); + $nex_time_array[2] = ($mday_down eq '*') ? 1 : $mday_down; + + # When an overflow is passed check the day update in the next execution + $nex_time = cron_valid_date(@nex_time_array, $cur_year); + if ($nex_time >= $cur_time) { + return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array); + } + + # Check if next month is in cron + $nex_time_array[3]++; + $nex_time = cron_valid_date(@nex_time_array, $cur_year); + if ($nex_time == 0) { + #Update the year if overflow + $nex_time_array[3] = 0; + $cur_year++; + $nex_time = cron_valid_date(@nex_time_array, $cur_year); + } + + #Check the month + return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array); + + #Update the month if fails + my ($mon_down, undef) = cron_get_interval ($mon); + $nex_time_array[3] = ($mon_down eq '*') ? 0 : $mon_down; + + # When an overflow is passed check the month update in the next execution + $nex_time = cron_valid_date(@nex_time_array, $cur_year); + if ($nex_time >= $cur_time) { + return $nex_time if cron_is_in_cron(\@cron_array, \@nex_time_array); + } + + #Update the year if fails + $nex_time = cron_valid_date(@nex_time_array, $cur_year + 1); + + return $nex_time; +} + +############################################################################### +# Returns if a date is in a cron. Recursive. +# Needs the cron like an array reference and +# current time in cron format to works properly +############################################################################### +sub cron_is_in_cron { + my ($elems_cron, $elems_curr_time) = @_; + + my @deref_elems_cron = @$elems_cron; + my @deref_elems_curr_time = @$elems_curr_time; + + my $elem_cron = shift(@deref_elems_cron); + my $elem_curr_time = shift (@deref_elems_curr_time); + + #If there is no elements means that is in cron + return 1 unless (defined($elem_cron) || defined($elem_curr_time)); + + # Go to last element if current is a wild card + if ($elem_cron ne '*') { + my ($down, $up) = cron_get_interval($elem_cron); + # Check if there is no a range + return 0 if (!defined($up) && ($down != $elem_curr_time)); + # Check if there is on the range + if (defined($up)) { + if ($down < $up) { + return 0 if ($elem_curr_time < $down || $elem_curr_time > $up); + } else { + return 0 if ($elem_curr_time > $down || $elem_curr_time < $up); + } + } + } + return cron_is_in_cron(\@deref_elems_cron, \@deref_elems_curr_time); +} + +############################################################################### +# Returns the interval of a cron element. If there is not a range, +# returns an array with the first element in the first place of array +# and the second place undefined. +############################################################################### +sub cron_get_interval { + my ($element) = @_; + + # Not a range + if ($element !~ /(\d+)\-(\d+)/) { + return ($element, undef); + } + + return ($1, $2); +} + +############################################################################### +# Returns the closest number to the target inside the given range (including +# the target itself). +############################################################################### +sub cron_get_closest_in_range ($$) { + my ($target, $range) = @_; + + # Not a range + if ($range !~ /(\d+)\-(\d+)/) { + return $range; + } + + # Search the closes number to the target in the given range + my $range_start = $1; + my $range_end = $2; + + # Outside the range + if ($target <= $range_start || $target > $range_end) { + return $range_start; + } + + # Inside the range + return $target; +} + +############################################################################### +# Check if a date is valid to get timelocal +############################################################################### +sub cron_valid_date { + my ($min, $hour, $mday, $month, $year) = @_; + my $utime; + eval { + local $SIG{__DIE__} = sub {}; + $utime = timelocal(0, $min, $hour, $mday, $month, $year); + }; + if ($@) { + return 0; + } + return $utime; +} + ################################################################################ # Checks the module's cron string. Returns 1 if the module should be run, 0 if # not. ################################################################################ -sub check_module_cron ($) { - my $module = shift; +sub check_module_cron { + my ($module, $main_interval) = @_; # No cron string defined return 1 unless ($module->{'cron'} ne ''); + my $now = time(); + # Check if the module was already executed - return 0 unless (time() >= $module->{'cron_utimestamp'}); + return 0 unless ($now >= $module->{'cron_utimestamp'}); - # Get cron configuration - my @cron_params = split (/\s/, $module->{'cron'}); + my $interval = $main_interval * $module->{'interval'}; - # Get current time - my $current_time = time(); - my @time = localtime($current_time); + my $time_to_next_execution = cron_next_execution( + $module->{'cron'}, + $interval + ); - # Minutes, hours, day of the month, month and day of the week - my @time_params = @time[1, 2, 3, 4, 6]; - - # Fix month (localtime retuns 0..11 and we need 1..12) - $time_params[3] += 1; + $module->{'cron_utimestamp'} = $now + $time_to_next_execution; + $module->{'cron_interval'} = $time_to_next_execution; - # Check cron parameters - for (my $i = 0; $i < 5; $i++) { - - # Wildcard - next if ($cron_params[$i] eq '*'); - - # Get interval - my ($bottom, $top) = split (/-/, $cron_params[$i]); - $top = $bottom unless defined ($top); - - # Check if next execution will overflow the cron (only minutes overflow) - # If overflow, execute the module - my $overflow_cron = 0; - if ($i == 0) { - my $start_cron_seconds = $bottom*60; - my $current_exec_seconds = $time_params[$i]*60; - my $next_exec_seconds = $time_params[$i]*60 + $module->{'interval'}*$Conf{'interval'}; - if ($current_exec_seconds > $start_cron_seconds && $current_exec_seconds > $next_exec_seconds) { - $start_cron_seconds += 3600; - } - if (($current_exec_seconds <= $start_cron_seconds) && ($start_cron_seconds <= $next_exec_seconds)) { - $overflow_cron = 1 - } - } - - # Check interval - if ($bottom <= $top) { - return 0 if (($time_params[$i] < $bottom || $time_params[$i] > $top) && !$overflow_cron); - } else { - return 0 if (($time_params[$i] < $bottom && $time_params[$i] > $top) && !$overflow_cron); - } + if ($Conf{'debug'} eq '1') { + log_message ('debug', "Cron for module $module->{'name'} will be executed next time at timestamp: $module->{'cron_utimestamp'}."); } - # Do not check in the next minute, hour, day or month. - my $offset = 0; - if ($module->{'cron_interval'} >= 0) { - $offset = $module->{'cron_interval'}; - } elsif($cron_params[0] ne '*') { - # 1 minute - $offset = 60; - } elsif($cron_params[1] ne '*') { - # 1 hour - $offset = 3600; - } elsif($cron_params[2] ne '*' || $cron_params[4] ne '*') { - # 1 day - $offset = 86400; - } elsif($cron_params[3] ne '*') { - # 31 days - $offset = 2678400; - } + # On first execution checking if cron is valid is required + return 1 unless ($module->{'cron_utimestamp'} == 0); - $module->{'cron_utimestamp'} = $current_time + $offset; - return 1; + # Check if current timestamp is a valid cron date + my $next_execution = cron_next_execution_date( + $module->{'cron'}, + $now - $interval, + $interval + ); + return 1 if ($next_execution == $now); + return 0; } ################################################################################ @@ -2222,8 +2478,9 @@ sub write_module_xml ($@) { # Module Alert template $Xml .= " " . $module->{'alert_template'} . "\n" if (defined ($module->{'alert_template'})); - # Module Alert template + # Module Crontab $Xml .= " " . $module->{'cron'} . "\n" if (defined ($module->{'cron'}) and ($module->{'cron'} ne "")); + $Xml .= " " . $module->{'cron_interval'} . "\n" if (defined ($module->{'cron'}) and (defined ($module->{'cron_interval'}))); # FF threshold configuration $Xml .= " " . $module->{'min_ff_event_normal'} . "\n" if (defined ($module->{'min_ff_event_normal'})); @@ -2461,7 +2718,6 @@ sub init_module ($) { $module->{'conditions'} = []; $module->{'cron'} = ''; $module->{'cron_utimestamp'} = 0; - $module->{'cron_interval'} = -1; $module->{'precondition'} = []; $module->{'is_intensive'} = 0; $module->{'intensive_conditions'} = []; @@ -2770,7 +3026,7 @@ while (1) { # Execute the module in a separate thread if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1) { $ThreadSem->down (); - my $thr = threads->create (\&exec_module, $module); + my $thr = threads->create (\&exec_module, $module, $Conf{'interval'}); if (! defined ($thr)) { $ThreadSem->up (); } else { @@ -2778,7 +3034,7 @@ while (1) { } # Execute the module } else { - exec_module($module); + exec_module($module, $Conf{'interval'}); } } diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec index 684559de55..f24e83b7a8 100644 --- a/pandora_agents/unix/pandora_agent.redhat.spec +++ b/pandora_agents/unix/pandora_agent.redhat.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.719 -%define release 180226 +%define release 180228 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent.spec b/pandora_agents/unix/pandora_agent.spec index ffbf19ef95..2790257e7e 100644 --- a/pandora_agents/unix/pandora_agent.spec +++ b/pandora_agents/unix/pandora_agent.spec @@ -3,7 +3,7 @@ # %define name pandorafms_agent_unix %define version 7.0NG.719 -%define release 180226 +%define release 180228 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent_installer b/pandora_agents/unix/pandora_agent_installer index f6732f6f13..2b75296efa 100755 --- a/pandora_agents/unix/pandora_agent_installer +++ b/pandora_agents/unix/pandora_agent_installer @@ -10,7 +10,7 @@ # ********************************************************************** PI_VERSION="7.0NG.719" -PI_BUILD="180226" +PI_BUILD="180228" OS_NAME=`uname -s` FORCE=0 diff --git a/pandora_agents/win32/Makefile.am b/pandora_agents/win32/Makefile.am index d41c722ced..4641081570 100644 --- a/pandora_agents/win32/Makefile.am +++ b/pandora_agents/win32/Makefile.am @@ -1,9 +1,9 @@ bin_PROGRAMS = PandoraAgent if DEBUG -PandoraAgent_SOURCES = misc/pandora_file.cc modules/pandora_data.cc modules/pandora_module_factory.cc modules/pandora_module.cc modules/pandora_module_list.cc modules/pandora_module_plugin.cc modules/pandora_module_inventory.cc modules/pandora_module_freememory.cc modules/pandora_module_exec.cc modules/pandora_module_perfcounter.cc modules/pandora_module_proc.cc modules/pandora_module_tcpcheck.cc modules/pandora_module_freememory_percent.cc modules/pandora_module_freedisk.cc modules/pandora_module_freedisk_percent.cc modules/pandora_module_logevent.cc modules/pandora_module_service.cc modules/pandora_module_cpuusage.cc modules/pandora_module_wmiquery.cc modules/pandora_module_regexp.cc modules/pandora_module_ping.cc modules/pandora_module_snmpget.cc udp_server/udp_server.cc main.cc pandora_strutils.cc pandora.cc windows_service.cc pandora_agent_conf.cc windows/pandora_windows_info.cc windows/pandora_wmi.cc pandora_windows_service.cc misc/md5.c misc/sha256.cc windows/wmi/disphelper.c ssh/libssh2/channel.c ssh/libssh2/mac.c ssh/libssh2/session.c ssh/libssh2/comp.c ssh/libssh2/misc.c ssh/libssh2/sftp.c ssh/libssh2/crypt.c ssh/libssh2/packet.c ssh/libssh2/userauth.c ssh/libssh2/hostkey.c ssh/libssh2/publickey.c ssh/libssh2/kex.c ssh/libssh2/scp.c ssh/pandora_ssh_client.cc ssh/pandora_ssh_test.cc ftp/pandora_ftp_client.cc ftp/pandora_ftp_test.cc debug_new.cpp +PandoraAgent_SOURCES = misc/cron.cc misc/pandora_file.cc modules/pandora_data.cc modules/pandora_module_factory.cc modules/pandora_module.cc modules/pandora_module_list.cc modules/pandora_module_plugin.cc modules/pandora_module_inventory.cc modules/pandora_module_freememory.cc modules/pandora_module_exec.cc modules/pandora_module_perfcounter.cc modules/pandora_module_proc.cc modules/pandora_module_tcpcheck.cc modules/pandora_module_freememory_percent.cc modules/pandora_module_freedisk.cc modules/pandora_module_freedisk_percent.cc modules/pandora_module_logevent.cc modules/pandora_module_service.cc modules/pandora_module_cpuusage.cc modules/pandora_module_wmiquery.cc modules/pandora_module_regexp.cc modules/pandora_module_ping.cc modules/pandora_module_snmpget.cc udp_server/udp_server.cc main.cc pandora_strutils.cc pandora.cc windows_service.cc pandora_agent_conf.cc windows/pandora_windows_info.cc windows/pandora_wmi.cc pandora_windows_service.cc misc/md5.c misc/sha256.cc windows/wmi/disphelper.c ssh/libssh2/channel.c ssh/libssh2/mac.c ssh/libssh2/session.c ssh/libssh2/comp.c ssh/libssh2/misc.c ssh/libssh2/sftp.c ssh/libssh2/crypt.c ssh/libssh2/packet.c ssh/libssh2/userauth.c ssh/libssh2/hostkey.c ssh/libssh2/publickey.c ssh/libssh2/kex.c ssh/libssh2/scp.c ssh/pandora_ssh_client.cc ssh/pandora_ssh_test.cc ftp/pandora_ftp_client.cc ftp/pandora_ftp_test.cc debug_new.cpp PandoraAgent_CXXFLAGS=-g -O0 else -PandoraAgent_SOURCES = misc/pandora_file.cc modules/pandora_data.cc modules/pandora_module_factory.cc modules/pandora_module.cc modules/pandora_module_list.cc modules/pandora_module_plugin.cc modules/pandora_module_inventory.cc modules/pandora_module_freememory.cc modules/pandora_module_exec.cc modules/pandora_module_perfcounter.cc modules/pandora_module_proc.cc modules/pandora_module_tcpcheck.cc modules/pandora_module_freememory_percent.cc modules/pandora_module_freedisk.cc modules/pandora_module_freedisk_percent.cc modules/pandora_module_logevent.cc modules/pandora_module_logchannel.cc modules/pandora_module_service.cc modules/pandora_module_cpuusage.cc modules/pandora_module_wmiquery.cc modules/pandora_module_regexp.cc modules/pandora_module_ping.cc modules/pandora_module_snmpget.cc udp_server/udp_server.cc main.cc pandora_strutils.cc pandora.cc windows_service.cc pandora_agent_conf.cc windows/pandora_windows_info.cc windows/pandora_wmi.cc pandora_windows_service.cc misc/md5.c misc/sha256.cc windows/wmi/disphelper.c ssh/libssh2/channel.c ssh/libssh2/mac.c ssh/libssh2/session.c ssh/libssh2/comp.c ssh/libssh2/misc.c ssh/libssh2/sftp.c ssh/libssh2/crypt.c ssh/libssh2/packet.c ssh/libssh2/userauth.c ssh/libssh2/hostkey.c ssh/libssh2/publickey.c ssh/libssh2/kex.c ssh/libssh2/scp.c ssh/pandora_ssh_client.cc ssh/pandora_ssh_test.cc ftp/pandora_ftp_client.cc ftp/pandora_ftp_test.cc +PandoraAgent_SOURCES = misc/cron.cc misc/pandora_file.cc modules/pandora_data.cc modules/pandora_module_factory.cc modules/pandora_module.cc modules/pandora_module_list.cc modules/pandora_module_plugin.cc modules/pandora_module_inventory.cc modules/pandora_module_freememory.cc modules/pandora_module_exec.cc modules/pandora_module_perfcounter.cc modules/pandora_module_proc.cc modules/pandora_module_tcpcheck.cc modules/pandora_module_freememory_percent.cc modules/pandora_module_freedisk.cc modules/pandora_module_freedisk_percent.cc modules/pandora_module_logevent.cc modules/pandora_module_logchannel.cc modules/pandora_module_service.cc modules/pandora_module_cpuusage.cc modules/pandora_module_wmiquery.cc modules/pandora_module_regexp.cc modules/pandora_module_ping.cc modules/pandora_module_snmpget.cc udp_server/udp_server.cc main.cc pandora_strutils.cc pandora.cc windows_service.cc pandora_agent_conf.cc windows/pandora_windows_info.cc windows/pandora_wmi.cc pandora_windows_service.cc misc/md5.c misc/sha256.cc windows/wmi/disphelper.c ssh/libssh2/channel.c ssh/libssh2/mac.c ssh/libssh2/session.c ssh/libssh2/comp.c ssh/libssh2/misc.c ssh/libssh2/sftp.c ssh/libssh2/crypt.c ssh/libssh2/packet.c ssh/libssh2/userauth.c ssh/libssh2/hostkey.c ssh/libssh2/publickey.c ssh/libssh2/kex.c ssh/libssh2/scp.c ssh/pandora_ssh_client.cc ssh/pandora_ssh_test.cc ftp/pandora_ftp_client.cc ftp/pandora_ftp_test.cc PandoraAgent_CXXFLAGS=-O2 endif diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi index ebf8fada1f..ca356b1b9c 100644 --- a/pandora_agents/win32/installer/pandora.mpi +++ b/pandora_agents/win32/installer/pandora.mpi @@ -186,7 +186,7 @@ UpgradeApplicationID {} Version -{180226} +{180228} ViewReadme {Yes} diff --git a/pandora_agents/win32/misc/cron.cc b/pandora_agents/win32/misc/cron.cc new file mode 100644 index 0000000000..d712c2685c --- /dev/null +++ b/pandora_agents/win32/misc/cron.cc @@ -0,0 +1,414 @@ +/* Pandora cron manager for Win32. + + Copyright (C) 2018 Artica ST. + Written by Fermin Hernandez. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include +#include +#include +#include "cron.h" +#include "../pandora.h" + +/** + * @brief Constructor of cron class + * + * @param cron_string String with cron format (https://en.wikipedia.org/wiki/Cron) + */ +Cron::Cron (string cron_string) { + char cron_params[5][256], bottom[256], top[256]; + + // Check if cron string is the default or empty + if ( + cron_string.compare(CRON_DEFAULT_STRING) == 0 || + cron_string.compare("") == 0 + ) { + this->isSet = false; + return; + } + + // Parse the cron string + if (sscanf (cron_string.c_str (), "%255s %255s %255s %255s %255s", cron_params[0], cron_params[1], cron_params[2], cron_params[3], cron_params[4]) != 5) { + Pandora::pandoraDebug ("Invalid cron string: %s", cron_string.c_str ()); + this->isSet = false; + this->cronString = CRON_DEFAULT_STRING; + return; + } + + this->cronString = cron_string; + + // Fill the cron structure + this->utimestamp = 0; + this->cronInterval = 0; + this->isSet = true; + // Months in cron are from 1 to 12. For date, are required from 0 to 11. + for (int i = 0; i < 5; i++) { + + // Wildcard + if (cron_params[i][0] == '*') { + this->params[i][CRDOWN] = CR_WILDCARD_VALUE; + this->params[i][1] = CR_WILDCARD_VALUE; + + // Interval + } else if (sscanf (cron_params[i], "%255[^-]-%255s", bottom, top) == 2) { + // Check if there is an interval with two equal values + if (strcmp(bottom, top) == 0) { + this->params[i][CRDOWN] = (i != 3) + ? atoi (cron_params[i]) + : atoi (cron_params[i]) - 1; + this->params[i][CRUP] = CR_WILDCARD_VALUE; + } else { + this->params[i][CRDOWN] = (i != 3) ? atoi (bottom) : atoi (bottom) - 1; + this->params[i][CRUP] = (i != 3) ? atoi (top) : atoi (top) -1; + } + + // Single value + } else { + this->params[i][CRDOWN] = (i != 3) + ? atoi (cron_params[i]) + : atoi (cron_params[i]) - 1; + this->params[i][CRUP] = CR_WILDCARD_VALUE; + } + } +} + +/** + * @brief Getter of isSet property + * + */ +bool Cron::getIsSet () { return this->isSet; } + +/** + * @brief Getter of cronString property + * + */ +string Cron::getCronString() { return this->cronString; } + +/** + * @brief Getter of cronInterval property casting in string + * + */ +string Cron::getCronIntervalStr() { + stringstream ss; + ss << this->cronInterval; + return ss.str(); +} + +/** + * @brief Given a date, return if is inside a cron string or not + * + * @param date Date to check + * @return true If is inside cron + * @return false If is outside cron + */ +bool Cron::isInCron(time_t date) { + struct tm * timeinfo = localtime(&date); + + // Convert the tm struct to an array + int date_array[4] = { + timeinfo->tm_min, + timeinfo->tm_hour, + timeinfo->tm_mday, + timeinfo->tm_mon + }; + + // Check all positions faliures + for (int i = 0; i < 4; i++) { + if (!isBetweenParams(date_array[i], i)) return false; + } + + // If no failures, date is inside cron. + return true; +} + +/** + * @brief Check if a value is in a position of cron + * + * @param value Value to check + * @param position Position in cron to make the check + * @return If position is in cron + */ +bool Cron::isBetweenParams(int value, int position) { + if (!isWildCard(position)) { + if (isSingleValue(position)) { + if (this->params[position][CRDOWN] != value) return false; + } else { + if (isNormalInterval(position)) { + if ( + value < this->params[position][CRDOWN] || + value > this->params[position][CRUP] + ) { + return false; + } + } else { + if ( + value < this->params[position][CRDOWN] && + value > this->params[position][CRUP] + ) { + return false; + } + } + } + } + return true; +} + +/** + * @brief Check if a cron position is a wildcard + * + * @param position Position inside the param array + * @return true if is a wildcard + */ +bool Cron::isWildCard(int position) { + return this->params[position][CRDOWN] == CR_WILDCARD_VALUE; +} + +/** + * @brief Check if a cron position is a single value + * + * @param position Position inside the param array + * @return true if is a single value + */ +bool Cron::isSingleValue(int position) { + return this->params[position][CRUP] == CR_WILDCARD_VALUE; +} + +/** + * @brief Check if a cron position is an interval with down lower than up + * + * @param position Position inside the param array + * @return true if is a normal interval + * @return false if is an inverse interval + */ +bool Cron::isNormalInterval (int position) { + // Wildcard and single value will be treated like normal interval + if ( + this->params[position][CRDOWN] == CR_WILDCARD_VALUE || + this->params[position][CRUP] == CR_WILDCARD_VALUE + ) { + return true; + } + return (this->params[position][CRUP] >= this->params[position][CRDOWN]); +} + +/** + * @brief Get the reset value on a cron position + * + * @param position + * @return int Reset value + */ +int Cron::getResetValue (int position) { + int default_value = 0; + // Days start in 1 + if (position == 2) default_value = 1; + return isWildCard(position) + ? default_value + : this->params[position][CRDOWN]; +} + +/** + * @brief Check if cron module should be executed at a given time + * + * @param date + * @return true if should execute + * @return false if should not execute + */ +bool Cron::shouldExecuteAt (time_t date) { + return this->utimestamp < date; +} + +/** + * @brief Check if a module should be executed when utimestamp is not calculated yet + * + * @param date Current date + * @return true It is not first time and current date fit in cron + * @return false Don't execute first time + */ +bool Cron::shouldExecuteAtFirst (time_t date) { + + // Return true if it is not first + if (this->utimestamp != 0) return true; + + // Check current date in cron + return isInCron(date); +} + +/** + * @brief Update the cron utimestamp + * + * @param date Timestamp "from" to update cron utimestamp + * @param interval Module interval + */ +void Cron::update (time_t date, int interval) { + time_t next_time = getNextExecutionFrom(date, interval); + + // Check the day of the week + struct tm * timeinfo = localtime(&next_time); + int count = 0; // Avoid infinite loops + while ((!isBetweenParams(timeinfo->tm_wday, 4)) && (count++ < CR_MAX_ITERS)){ + next_time = getNextExecutionFrom(next_time + CR_SECONDS_ONE_DAY, 0); + timeinfo = localtime(&next_time); + } + if (count >= CR_MAX_ITERS) { + Pandora::pandoraLog( + "Module with cron %s will be executed at timestamp: %d, but it can be incorrect", + this->cronString.c_str(), + this->utimestamp + ); + } + + // Security about values + if (next_time < date) { + this->utimestamp = date + interval; + this->cronInterval = interval; + Pandora::pandoraLog("Cron update fails in Module with cron %s", this->cronString.c_str()); + } + + // Save the data + this->utimestamp = next_time; + this->cronInterval = next_time - date; + Pandora::pandoraDebug( + "Module with cron %s will be executed at timestamp: %d.", + this->cronString.c_str(), + this->utimestamp + ); + return; +} + +/** + * @brief Get next execution date given a certain date. + * + * @param date Date when start the search for a new date + * @param interval Module interval + * @return time_t Timestamp when module should be executed next time + * @remarks It does not look for day of the week + */ +time_t Cron::getNextExecutionFrom(time_t date, int interval) { + time_t nex_time = date + interval; + if (isInCron(nex_time)) { + return nex_time; + } + + // Copy tm struct values to an empty struct to avoid conflicts + struct tm * timeinfo_first = localtime(&nex_time); + struct tm * timeinfo = new tm(); + timeinfo->tm_sec = 0; + timeinfo->tm_min = timeinfo_first->tm_min; + timeinfo->tm_hour = timeinfo_first->tm_hour; + timeinfo->tm_mday = timeinfo_first->tm_mday; + timeinfo->tm_mon = timeinfo_first->tm_mon; + timeinfo->tm_year = timeinfo_first->tm_year; + + // Update minutes + timeinfo->tm_min = getResetValue(0); + nex_time = mktime(timeinfo); + if (nex_time >= date && isInCron(nex_time)) { + return nex_time; + } + + if (nex_time == CRINVALID_DATE) { + // Update the month day if overflow + timeinfo->tm_hour = 0; + timeinfo->tm_mday++; + nex_time = mktime(timeinfo); + if (nex_time == CRINVALID_DATE) { + // Update the month if overflow + timeinfo->tm_mday = 1; + timeinfo->tm_mon++; + nex_time = mktime(timeinfo); + if (nex_time == CRINVALID_DATE) { + // Update the year if overflow + timeinfo->tm_mon = 0; + timeinfo->tm_year++; + nex_time = mktime(timeinfo); + } + } + } + + // Check the hour + if (isInCron(nex_time)) { + return nex_time; + } + + // Update hour if fails + timeinfo->tm_hour = getResetValue(1); + + // When an overflow is passed check the hour update again + nex_time = mktime(timeinfo); + if (nex_time >= date && isInCron(nex_time)) { + return nex_time; + } + + // Check if next day is in cron + timeinfo->tm_mday++; + nex_time = mktime(timeinfo); + if (nex_time == CRINVALID_DATE) { + // Update the month if overflow + timeinfo->tm_mday = 1; + timeinfo->tm_mon++; + nex_time = mktime(timeinfo); + if (nex_time == CRINVALID_DATE) { + // Update the year if overflow + timeinfo->tm_mon = 0; + timeinfo->tm_year++; + nex_time = mktime(timeinfo); + } + } + + // Check the day + if (isInCron(nex_time)){ + return nex_time; + } + + // Update the day if fails + timeinfo->tm_mday = getResetValue(2); + + // When an overflow is passed check the day update in the next execution + nex_time = mktime(timeinfo); + if (nex_time >= date && isInCron(nex_time)) { + return nex_time; + } + + // Check if next month is in cron + timeinfo->tm_mon++; + nex_time = mktime(timeinfo); + if (nex_time == CRINVALID_DATE) { + // Update the year if overflow + timeinfo->tm_mon = 0; + timeinfo->tm_year++; + nex_time = mktime(timeinfo); + } + + // Check the month + if (isInCron(nex_time)) { + return nex_time; + } + + // Update the month if fails + timeinfo->tm_mon = getResetValue(3); + + // When an overflow is passed check the month update in the next execution + nex_time = mktime(timeinfo); + if (nex_time >= date) { + return nex_time; + } + + // Update the year if fails + timeinfo->tm_year++; + nex_time = mktime(timeinfo); + + return nex_time; +} \ No newline at end of file diff --git a/pandora_agents/win32/misc/cron.h b/pandora_agents/win32/misc/cron.h new file mode 100644 index 0000000000..022bf1bb41 --- /dev/null +++ b/pandora_agents/win32/misc/cron.h @@ -0,0 +1,81 @@ +/* Pandora cron manager for Win32. + + Copyright (C) 2018 Artica ST. + Written by Fermin Hernandez. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _CRON_PANDORA_H_ +#define _CRON_PANDORA_H_ + +#include +#include +#include +#include + +using namespace std; + +const string CRON_DEFAULT_STRING = "* * * * *"; +const int CR_WILDCARD_VALUE = -1; +const int CRDOWN = 0; +const int CRUP = 1; +const int CRINVALID_DATE = -1; +const int CR_SECONDS_ONE_DAY = 86400; +const int CR_MAX_ITERS = 60; + +class Cron { + private: + // Properties + time_t utimestamp; + /** + * @brief Stored cron values array + * + * First index: minutes, hours, months, days, month + * Second index: bottom, top + * + * Wildcard (*): Bottom and top are -1 + * Single value: Bottom is set and top is -1 + * Interval: Bottom and top are set + */ + int params[5][2]; + bool isSet; + string cronString; + time_t cronInterval; + + // Methods + time_t getNextExecutionFrom(time_t date, int interval); + bool isInCron(time_t date); + bool isBetweenParams(int value, int position); + bool isWildCard(int position); + bool isSingleValue(int position); + bool isNormalInterval(int position); + int getResetValue(int position); + + public: + // Constructor + Cron(string cron_string); + // Getter & setters + bool getIsSet(); + string getCronString(); + string getCronIntervalStr(); + + // Other methods + void update(time_t date, int interval); + bool shouldExecuteAt(time_t date); + bool shouldExecuteAtFirst(time_t date); +}; + +#endif diff --git a/pandora_agents/win32/modules/pandora_module.cc b/pandora_agents/win32/modules/pandora_module.cc index 99b0d47f88..d7d5fb63c0 100644 --- a/pandora_agents/win32/modules/pandora_module.cc +++ b/pandora_agents/win32/modules/pandora_module.cc @@ -740,10 +740,14 @@ Pandora_Module::getXml () { } /* Module Crontab */ - if (this->module_crontab != "") { + if (this->cron->getIsSet()) { module_xml += "\t"; - module_xml += this->module_crontab; + module_xml += this->cron->getCronString(); module_xml += "\n"; + + module_xml += "\tcron->getCronIntervalStr(); + module_xml += "]]>\n"; } /* Write module data */ @@ -1565,156 +1569,29 @@ Pandora_Module::evaluateIntensiveConditions () { * * @return 1 if the module should run, 0 if not. */ -int -Pandora_Module::checkCron (int module_interval, int agent_interval) { - int i, time_params[5]; - time_t current_time, offset; - struct tm *time_struct; - Cron *cron = this->cron; +bool +Pandora_Module::checkCron (int interval) { - // No cron - if (cron == NULL) { - return 1; - } + // Execute always if cron is not configured + if (!this->cron->getIsSet()) return true; - // Get current time - current_time = time (NULL); + time_t now = time(NULL); + if (!this->cron->shouldExecuteAt(now)) return false; - // Check if the module was already executed - if (current_time <= cron->utimestamp) { - return 0; - } - - // Break current time - time_struct = localtime(¤t_time); - if (time_struct == NULL) { - return 1; - } - - time_params[0] = time_struct->tm_min; - time_params[1] = time_struct->tm_hour; - time_params[2] = time_struct->tm_mday; - time_params[3] = time_struct->tm_mon; - time_params[4] = time_struct->tm_wday; + // Check if should execute this module at first before update cron params + bool execute = this->cron->shouldExecuteAtFirst(now); - // Fix month (localtime retuns 0..11 and we need 1..12) - time_params[3] += 1; - - // Check cron parameters - for (i = 0; i < 5; i++) { - - // Wildcard - if (cron->params[i][0] < 0) { - continue; - } - - // Check if next execution will overflow the cron (only minutes overflow) - // If overflow, execute the module - bool overflow_cron = false; - if (i == 0) { - int start_cron_seconds = cron->params[i][0]*60; - int current_exec_seconds = time_params[i]*60; - int next_exec_seconds = time_params[i]*60 + module_interval*agent_interval; - if (current_exec_seconds > start_cron_seconds && current_exec_seconds > next_exec_seconds) { - start_cron_seconds += 3600; - } - if ((current_exec_seconds <= start_cron_seconds) && (start_cron_seconds <= next_exec_seconds)) { - overflow_cron = true; - } - } - - // Check interval - if (cron->params[i][0] <= cron->params[i][1]) { - if ((time_params[i] < cron->params[i][0] || time_params[i] > cron->params[i][1]) && !overflow_cron) { - return 0; - } - } else { - if ((time_params[i] < cron->params[i][0] && time_params[i] > cron->params[i][1]) && !overflow_cron) { - return 0; - } - } - } + this->cron->update(now, interval); - // Do not check in the next minute, hour, day or month. - offset = 0; - if (cron->interval >= 0) { - offset = cron->interval; - } else if(cron->params[0][0] >= 0) { - // 1 minute - offset = 60; - } else if(cron->params[1][0] >= 0) { - // 1 hour - offset = 3600; - } else if(cron->params[2][0] >=0 || cron->params[4][0] >= 0) { - // 1 day - offset = 86400; - } else if(cron->params[3][0] >= 0) { - // 31 days - offset = 2678400; - } - - cron->utimestamp = current_time + offset; - return 1; + return execute; } /** * Sets the module cron from a string. - * - * @return 1 if the module should run, 0 if not. */ void Pandora_Module::setCron (string cron_string) { - int i, value; - char cron_params[5][256], bottom[256], top[256]; - - /* Create the new cron if necessary */ - if (this->cron == NULL) { - this->cron = new Cron (); - } - - /* Parse the cron string */ - if (sscanf (cron_string.c_str (), "%255s %255s %255s %255s %255s", cron_params[0], cron_params[1], cron_params[2], cron_params[3], cron_params[4]) != 5) { - pandoraDebug ("Invalid cron string: %s", cron_string.c_str ()); - return; - } - - /* Fill the cron structure */ - this->cron->utimestamp = 0; - this->cron->interval = -1; - for (i = 0; i < 5; i++) { - - /* Wildcard */ - if (cron_params[i][0] == '*') { - this->cron->params[i][0] = -1; - - /* Interval */ - } else if (sscanf (cron_params[i], "%255[^-]-%255s", bottom, top) == 2) { - value = atoi (bottom); - this->cron->params[i][0] = value; - value = atoi (top); - this->cron->params[i][1] = value; - - /* Single value */ - } else { - value = atoi (cron_params[i]); - this->cron->params[i][0] = value; - this->cron->params[i][1] = value; - } - } -} - -/** - * Sets the interval of the module cron. - * - * @param interval Module cron interval in seconds. - */ -void -Pandora_Module::setCronInterval (int interval) { - if (this->cron == NULL) { - this->cron = new Cron (); - } - - this->cron->interval = interval; + this->cron = new Cron(cron_string); } /** diff --git a/pandora_agents/win32/modules/pandora_module.h b/pandora_agents/win32/modules/pandora_module.h index 2fbeb52e41..9fb29e1183 100644 --- a/pandora_agents/win32/modules/pandora_module.h +++ b/pandora_agents/win32/modules/pandora_module.h @@ -22,6 +22,7 @@ #define __PANDORA_MODULE_H__ #include "../pandora.h" +#include "../misc/cron.h" #include "pandora_data.h" #include "boost/regex.h" #include @@ -108,15 +109,6 @@ namespace Pandora_Modules { regex_t regexp; } Condition; - /** - * Defines the structure that holds the module cron. - */ - typedef struct { - time_t utimestamp; - int interval; - int params[5][2]; - } Cron; - const string module_exec_str = "module_exec"; const string module_proc_str = "module_proc"; const string module_service_str = "module_service"; @@ -298,9 +290,8 @@ namespace Pandora_Modules { void addIntensiveCondition (string intensivecondition); int evaluatePreconditions (); void evaluateConditions (); - int checkCron (int module_interval, int agent_interval); + bool checkCron (int interval); void setCron (string cron_string); - void setCronInterval (int interval); int evaluateCondition (string string_value, double double_value, Condition *condition); int evaluateIntensiveConditions (); int hasOutput (); diff --git a/pandora_agents/win32/modules/pandora_module_factory.cc b/pandora_agents/win32/modules/pandora_module_factory.cc index 90c82d5457..658ff724fd 100644 --- a/pandora_agents/win32/modules/pandora_module_factory.cc +++ b/pandora_agents/win32/modules/pandora_module_factory.cc @@ -94,7 +94,6 @@ using namespace Pandora_Strutils; #define TOKEN_SAVE ("module_save ") #define TOKEN_CONDITION ("module_condition ") #define TOKEN_CRONTAB ("module_crontab ") -#define TOKEN_CRONINTERVAL ("module_cron_interval ") #define TOKEN_PRECONDITION ("module_precondition ") #define TOKEN_NOSEEKEOF ("module_noseekeof ") #define TOKEN_PING ("module_ping ") @@ -168,7 +167,7 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { string module_perfcounter, module_tcpcheck; string module_port, module_timeout, module_regexp; string module_plugin, module_save, module_condition, module_precondition; - string module_crontab, module_cron_interval, module_post_process; + string module_crontab, module_post_process; string module_min_critical, module_max_critical, module_min_warning, module_max_warning; string module_disabled, module_min_ff_event, module_noseekeof; string module_ping, module_ping_count, module_ping_timeout; @@ -222,7 +221,6 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { module_save = ""; module_condition = ""; module_crontab = ""; - module_cron_interval = ""; module_post_process = ""; module_precondition = ""; module_min_critical = ""; @@ -423,9 +421,6 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { if (module_crontab == "") { module_crontab = parseLine (line, TOKEN_CRONTAB); } - if (module_cron_interval == "") { - module_cron_interval = parseLine (line, TOKEN_CRONINTERVAL); - } if (module_noseekeof == "") { module_noseekeof = parseLine (line, TOKEN_NOSEEKEOF); } @@ -904,13 +899,6 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { } } - if (module_cron_interval != "") { - pos_macro = module_cron_interval.find(macro_name); - if (pos_macro != string::npos){ - module_cron_interval.replace(pos_macro, macro_name.size(), macro_value); - } - } - if (module_noseekeof != "") { pos_macro = module_noseekeof.find(macro_name); if (pos_macro != string::npos){ @@ -1319,14 +1307,7 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) { } /* Module cron */ - if (module_crontab != "") { - module->setCron (module_crontab); - - /* Set the cron interval */ - if (module_cron_interval != "") { - module->setCronInterval (atoi (module_cron_interval.c_str ())); - } - } + module->setCron (module_crontab); /* Plugins do not have a module type */ if (module_plugin == "") { diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index 9afe1e2a32..5b1e18770d 100644 --- a/pandora_agents/win32/pandora.cc +++ b/pandora_agents/win32/pandora.cc @@ -30,7 +30,7 @@ using namespace Pandora; using namespace Pandora_Strutils; #define PATH_SIZE _MAX_PATH+1 -#define PANDORA_VERSION ("7.0NG.719(Build 180226)") +#define PANDORA_VERSION ("7.0NG.719(Build 180228)") string pandora_path; string pandora_dir; diff --git a/pandora_agents/win32/pandora_windows_service.cc b/pandora_agents/win32/pandora_windows_service.cc index cad177411a..1abe51491a 100644 --- a/pandora_agents/win32/pandora_windows_service.cc +++ b/pandora_agents/win32/pandora_windows_service.cc @@ -1884,8 +1884,8 @@ Pandora_Windows_Service::pandora_run_broker (string config) { continue; } - /* Check preconditions */ - if (module->checkCron (module->getInterval (), atoi (conf->getValue ("interval").c_str())) == 0) { + /* Check cron */ + if (!module->checkCron (module->getInterval () * atoi (conf->getValue ("interval").c_str()))) { pandoraDebug ("Cron not matched for module %s", module->getName ().c_str ()); module->setNoOutput (); this->broker_modules->goNext (); @@ -2012,8 +2012,8 @@ Pandora_Windows_Service::pandora_run (int forced_run) { continue; } - /* Check preconditions */ - if (module->checkCron (module->getInterval (), atoi (conf->getValue ("interval").c_str())) == 0) { + /* Check cron */ + if (!module->checkCron (module->getInterval () * atoi (conf->getValue ("interval").c_str()))) { pandoraDebug ("Cron not matched for module %s", module->getName ().c_str ()); module->setNoOutput (); this->modules->goNext (); diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc index dcee24bb35..4fa5009cd3 100644 --- a/pandora_agents/win32/versioninfo.rc +++ b/pandora_agents/win32/versioninfo.rc @@ -11,7 +11,7 @@ BEGIN VALUE "LegalCopyright", "Artica ST" VALUE "OriginalFilename", "PandoraAgent.exe" VALUE "ProductName", "Pandora FMS Windows Agent" - VALUE "ProductVersion", "(7.0NG.719(Build 180226))" + VALUE "ProductVersion", "(7.0NG.719(Build 180228))" VALUE "FileVersion", "1.0.0.0" END END diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control index ce8be97e8c..e382c27ae1 100644 --- a/pandora_console/DEBIAN/control +++ b/pandora_console/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-console -Version: 7.0NG.719-180226 +Version: 7.0NG.719-180228 Architecture: all Priority: optional Section: admin diff --git a/pandora_console/DEBIAN/make_deb_package.sh b/pandora_console/DEBIAN/make_deb_package.sh index e4412ceb18..d307396a37 100644 --- a/pandora_console/DEBIAN/make_deb_package.sh +++ b/pandora_console/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.719-180226" +pandora_version="7.0NG.719-180228" package_pear=0 package_pandora=1 diff --git a/pandora_console/extensions/agents_modules.php b/pandora_console/extensions/agents_modules.php index 4da2ad8238..da8f1c5550 100644 --- a/pandora_console/extensions/agents_modules.php +++ b/pandora_console/extensions/agents_modules.php @@ -585,245 +585,6 @@ function mainAgentsModules() { else{ $pure_var = 0; } - echo " - - - - "; } extensions_add_operation_menu_option(__("Agents/Modules view"), 'estado', 'agents_modules/icon_menu.png', "v1r1","view"); @@ -831,4 +592,241 @@ extensions_add_main_function('mainAgentsModules'); $ignored_params['refresh']=''; -?> \ No newline at end of file +?> + + + \ No newline at end of file diff --git a/pandora_console/godmode/agentes/configurar_agente.php b/pandora_console/godmode/agentes/configurar_agente.php index 25e7d43c05..3e0aac7af1 100644 --- a/pandora_console/godmode/agentes/configurar_agente.php +++ b/pandora_console/godmode/agentes/configurar_agente.php @@ -1183,6 +1183,9 @@ if ($update_module || $create_module) { $mday_to = get_parameter('mday_to'); $month_to = get_parameter('month_to'); $wday_to = get_parameter('wday_to'); + + $http_user = get_parameter('http_user'); + $http_pass = get_parameter('http_pass'); if ($hour_to != "*") { $hour_to = "-" . $hour_to; @@ -1258,6 +1261,7 @@ if ($update_module || $create_module) { if ($update_module) { $id_agent_module = (int) get_parameter ('id_agent_module'); + $values = array ( 'id_agente_modulo' => $id_agent_module, 'descripcion' => $description, @@ -1320,6 +1324,27 @@ if ($update_module) { 'id_category' => $id_category, 'disabled_types_event' => addslashes($disabled_types_event), 'module_macros' => $module_macros); + + if($id_module_type == 30 || $id_module_type == 31 || $id_module_type == 32 || $id_module_type == 33){ + + $plugin_parameter_split = explode(" ", $values['plugin_parameter']); + + $values['plugin_parameter'] = ''; + + foreach ($plugin_parameter_split as $key => $value) { + + if($key == 1){ + $values['plugin_parameter'] .= 'http_auth_user '.$http_user.' '; + $values['plugin_parameter'] .= 'http_auth_pass '.$http_pass.' '; + $values['plugin_parameter'] .= $value." "; + } + else{ + $values['plugin_parameter'] .= $value." "; + } + + } + + } // In local modules, the interval is updated by agent $module_kind = (int) get_parameter ('moduletype'); @@ -1397,6 +1422,7 @@ if ($update_module) { // MODULE INSERT // ================= if ($create_module) { + if (isset ($_POST["combo_snmp_oid"])) { $combo_snmp_oid = get_parameter_post ("combo_snmp_oid"); } @@ -1481,6 +1507,27 @@ if ($create_module) { 'disabled_types_event' => addslashes($disabled_types_event), 'module_macros' => $module_macros); + if($id_module_type == 30 || $id_module_type == 31 || $id_module_type == 32 || $id_module_type == 33){ + + $plugin_parameter_split = explode(" ", $values['plugin_parameter']); + + $values['plugin_parameter'] = ''; + + foreach ($plugin_parameter_split as $key => $value) { + + if($key == 1){ + $values['plugin_parameter'] .= 'http_auth_user '.$http_user.' '; + $values['plugin_parameter'] .= 'http_auth_pass '.$http_pass.' '; + $values['plugin_parameter'] .= $value." "; + } + else{ + $values['plugin_parameter'] .= $value." "; + } + + } + + } + if ($prediction_module == 3 && $serialize_ops == '') { $id_agent_module = false; } diff --git a/pandora_console/godmode/massive/massive_edit_modules.php b/pandora_console/godmode/massive/massive_edit_modules.php index db07eee465..b0889bd5ea 100755 --- a/pandora_console/godmode/massive/massive_edit_modules.php +++ b/pandora_console/godmode/massive/massive_edit_modules.php @@ -568,7 +568,7 @@ foreach ($targets2 as $t) { $table->data['edit6'][1] = html_print_select ($targets, 'id_export', '','', __('No change'), '', true, false, false); $table->data['edit6'][2] = __('Unit'); -$table->data['edit6'][3] = html_print_extended_select_for_unit('unit','', '', '', '0', '15', true, false, false); +$table->data['edit6'][3] = html_print_extended_select_for_unit('unit','-1', '', '', '0', '15', true, false, false, false , 1); /* FF stands for Flip-flop */ @@ -640,6 +640,53 @@ $table->data['edit11'][3] = html_print_input_text( 'max_timeout', '', '', 5, 10, true) . ' ' . ui_print_help_tip ( __('Seconds that agent will wait for the execution of the module.'), true); + +$table->data['edit16'][0] = __('Retries'); +$table->data['edit16'][1] = html_print_input_text ('max_retries', '', '', 5, 10, true) . ' ' . + ui_print_help_tip ( + __('Number of retries that the module will attempt to run.'), true); + + + $table->data['edit22'][0] = __('Web checks').ui_print_help_icon ("web_checks", true);; + $table->data['edit22'][1] = ''; + +$table->data['edit16'][2] = __('Port'); +$table->data['edit16'][3] = html_print_input_text ('tcp_port', '', '', 5, 20, true); + +$table->data['edit17'][0] = __('TCP send') . ' ' . ui_print_help_icon ("tcp_send", true); +$table->data['edit17'][1] = html_print_textarea ('tcp_send', 2, 65, '', '', true); + +$table->data['edit17'][2] = __('TCP receive'); +$table->data['edit17'][3] = html_print_textarea ('tcp_rcv', 2, 65, '', '', true); + +$table->data['edit18'][0] = __('WMI query') . ui_print_help_icon ('wmiquery', true); +$table->data['edit18'][1] = html_print_input_text ('snmp_oid', '', '', 35, 255, true); + +$table->data['edit18'][2] = __('Key string'); +$table->data['edit18'][3] = html_print_input_text ('snmp_community', '', '', 20, 60, true); + +$table->data['edit19'][0] = __('Field number') . ui_print_help_icon ('wmifield', true); +$table->data['edit19'][1] = html_print_input_text ('tcp_port', '', '', 5, 15, true); + +$table->data['edit20'][0] = __('Plugin') . ui_print_help_icon ('plugin_macros', true); +$table->data['edit20'][1] = html_print_select_from_sql ('SELECT id, name FROM tplugin ORDER BY name', + 'id_plugin', '', 'changePluginSelect();', __('None'), 0, true, false, false); + + + // Store the macros in base64 into a hidden control to move between pages + $table->data['edit21'][0] = html_print_input_hidden('macros',base64_encode($macros),true); + + if (!empty($id_plugin)) { + $preload = db_get_sql ("SELECT description FROM tplugin WHERE id = $id_plugin"); + $preload = io_safe_output ($preload); + $preload = str_replace ("\n", "
", $preload); + } + else { + $preload = ""; + } + + $table->data['edit21'][1] = ''.$preload.''; + echo '
+ +