diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control index 574eee22ca..7ebaf6a9c8 100644 --- a/pandora_agents/unix/DEBIAN/control +++ b/pandora_agents/unix/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-agent-unix -Version: 7.0NG.751-201214 +Version: 7.0NG.751-201223 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 bff802b841..6ddaba4b8d 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.751-201214" +pandora_version="7.0NG.751-201223" 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 acbe5910be..4c02f4f0b9 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -20,6 +20,977 @@ Version 6.0 =cut +=pod + This section is copied from PandoraFMS::Omnishell. Do not develop anything here + Go to Omnishell.pm to apply all fixes you need, and then copy entire library + here to allow pandora_agent run from this single + +=cut +BEGIN { + package PandoraFMS::Omnishell; + ################################################################################ + # Pandora FMS Omnishell common functions. + # + # (c) Fco de Borja Sánchez + # + ################################################################################ + use strict; + use warnings; + + use File::Copy; + use Scalar::Util qw(looks_like_number); + use lib '/usr/lib/perl5'; + + ################################################################################ + # Erase blank spaces before and after the string + ################################################################################ + sub trim { + my $string = shift; + if (empty($string)){ + return ""; + } + + $string =~ s/\r//g; + + chomp($string); + $string =~ s/^\s+//g; + $string =~ s/\s+$//g; + + return $string; + } + + ################################################################################ + # Empty + ################################################################################ + sub empty { + my $str = shift; + + if (!(defined($str)) ){ + return 1; + } + + if(looks_like_number($str)){ + return 0; + } + + if (ref($str) eq "ARRAY") { + return (($#{$str}<0)?1:0); + } + + if (ref($str) eq "HASH") { + my @tmp = keys %{$str}; + return (($#tmp<0)?1:0); + } + + if ($str =~ /^\ *[\n\r]{0,2}\ *$/) { + return 1; + } + return 0; + } + + ################################################################################ + # initialize plugin (advanced - hashed configuration) + ################################################################################ + sub init { + my $options = shift; + my $conf; + + eval { + $conf = init_system($options); + + if (defined($options->{lwp_enable})) { + if (empty($options->{lwp_timeout})) { + $options->{lwp_timeout} = 3; + } + + $conf->{'__system'}->{ua} = LWP::UserAgent->new((keep_alive => "10")); + $conf->{'__system'}->{ua}->timeout($options->{lwp_timeout}); + # Enable environmental proxy settings + $conf->{'__system'}->{ua}->env_proxy; + # Enable in-memory cookie management + $conf->{'__system'}->{ua}->cookie_jar( {} ); + if ( defined($options->{ssl_verify}) && ( ($options->{ssl_verify} eq "no") || (!is_enabled($options->{ssl_verify})) ) ) { + # Disable verify host certificate (only needed for self-signed cert) + $conf->{'__system'}->{ua}->ssl_opts( 'verify_hostname' => 0 ); + $conf->{'__system'}->{ua}->ssl_opts( 'SSL_verify_mode' => 0x00 ); + + # Disable library extra checks + BEGIN { + $ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS} = "Net::SSL"; + $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0; + } + } + } + }; + if($@) { + # Failed + return { + error => $@ + }; + } + + return $conf; + } + + ################################################################################ + # initialize plugin (basic) + ################################################################################ + sub init_system { + my ($conf) = @_; + + my %system; + + if ($^O =~ /win/i ){ + $system{devnull} = "NUL"; + $system{cat} = "type"; + $system{os} = "Windows"; + $system{ps} = "tasklist"; + $system{grep} = "findstr"; + $system{echo} = "echo"; + $system{wcl} = "wc -l"; + $system{tmp} = ".\\"; + $system{cmdsep} = "\&"; + } + else { + $system{devnull} = "/dev/null"; + $system{cat} = "cat"; + $system{os} = "Linux"; + $system{ps} = "ps -eo pmem,pcpu,comm"; + $system{grep} = "grep"; + $system{echo} = "echo"; + $system{wcl} = "wc -l"; + $system{tmp} = "/tmp"; + $system{cmdsep} = ";"; + + if ($^O =~ /hpux/i) { + $system{os} = "HPUX"; + $system{ps} = "ps -eo pmem,pcpu,comm"; + } + + if ($^O =~ /solaris/i ) { + $system{os} = "solaris"; + $system{ps} = "ps -eo pmem,pcpu,comm"; + } + } + + $conf->{'__system'} = \%system; + return $conf; + } + + ################################################################################ + ## Reads a file and returns entire content or undef if error. + ################################################################################ + sub read_file { + my $path = shift; + + my $_FILE; + if( !open($_FILE, "<", $path) ) { + + # failed to open, return undef + return undef; + } + + # Slurp configuration file content. + my $content = do { local $/; <$_FILE> }; + + # Close file + close($_FILE); + + return $content; + } + + ################################################################################ + # Mix hashses + ################################################################################ + sub merge_hashes { + my $_h1 = shift; + my $_h2 = shift; + + if (ref($_h1) ne "HASH") { + return \%{$_h2} if (ref($_h2) eq "HASH"); + } + + if (ref($_h2) ne "HASH") { + return \%{$_h1} if (ref($_h1) eq "HASH"); + } + + if ((ref($_h1) ne "HASH") && (ref($_h2) ne "HASH")) { + return {}; + } + + my %ret = (%{$_h1}, %{$_h2}); + + return \%ret; + } + + ################################################################################ + # is Enabled + ################################################################################ + sub is_enabled { + my $value = shift; + + if ((defined ($value)) && looks_like_number($value) && ($value > 0)){ + # return true + return 1; + } + #return false + return 0; + + } + + ################################################################################ + # Parses any configuration, from file (1st arg to program) or direct arguments + # + # Custom evals are defined in an array reference of hash references: + # + # $custom_eval = [ + # { + # 'exp' => 'regular expression to match', + # 'target' => \&target_custom_method_to_parse_line + # }, + # { + # 'exp' => 'another regular expression to search', + # 'target' => \&target_custom_method_to_parse_line2 + # }, + # ] + # + # Target is an user defined function wich will be invoked with following + # arguments: + # + # $config : The configuration read to the point the regex matches + # $exp : The matching regex which fires this action + # $line : The complete line readed from the file + # $file_pointer : A pointer to the file which is being parsed. + # $current_entity : The current_entity (optional) when regex matches + # + # E.g. + # + # sub target_custom_method_to_parse_line { + # my ($config, $exp, $line, $file_pointer, $current_entity) = @_; + # + # if ($line =~ /$exp/) { + # $config->{'my_key'} = complex_operation_on_data($1,$2,$3); + # } + # + # return $config; + # } + # + ################################################################################ + sub read_configuration { + my ($config, $separator, $custom_eval) = @_; + + if ((!empty(@ARGV)) && (-f $ARGV[0])) { + $config = merge_hashes($config, parse_configuration(shift @ARGV, $separator, $custom_eval)); + } + $config = merge_hashes($config, parse_arguments(\@ARGV)); + + if(is_enabled($config->{'as_agent_plugin'})) { + $config->{'as_server_plugin'} = 0 if (empty($config->{'as_server_plugin'})); + } + else { + $config->{'as_server_plugin'} = 1 if (empty($config->{'as_server_plugin'})); + } + + if(is_enabled($config->{'as_server_plugin'})) { + $config->{'as_agent_plugin'} = 0 if (empty($config->{'as_agent_plugin'})); + } + else { + $config->{'as_agent_plugin'} = 1 if (empty($config->{'as_agent_plugin'})); + } + + return $config; + } + + my $YAML = 0; + # Dynamic load. Avoid unwanted behaviour. + eval { + eval 'require YAML::Tiny;1' or die('YAML::Tiny lib not found, commands feature won\'t be available'); + }; + if ($@) { + $YAML = 0; + } else { + $YAML = 1; + } + + use lib '/usr/lib/perl5'; + + our @ISA = ("Exporter"); + our %EXPORT_TAGS = ( 'all' => [ qw( ) ] ); + our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + our @EXPORT = qw(); + + # 2 to the power of 32. + use constant POW232 => 2**32; + + ################################################################################ + # Return the MD5 checksum of the given string as a hex string. + # Pseudocode from: http://en.wikipedia.org/wiki/MD5#Pseudocode + ################################################################################ + my @S = ( + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 + ); + my @K = ( + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 + ); + sub md5 { + my $str = shift; + + # No input! + if (!defined($str)) { + return ""; + } + + # Note: All variables are unsigned 32 bits and wrap modulo 2^32 when + # calculating. + + # Initialize variables. + my $h0 = 0x67452301; + my $h1 = 0xEFCDAB89; + my $h2 = 0x98BADCFE; + my $h3 = 0x10325476; + + # Pre-processing. + my $msg = unpack ("B*", pack ("A*", $str)); + my $bit_len = length ($msg); + + # Append "1" bit to message. + $msg .= '1'; + + # Append "0" bits until message length in bits ≡ 448 (mod 512). + $msg .= '0' while ((length ($msg) % 512) != 448); + + # Append bit /* bit, not byte */ length of unpadded message as 64-bit + # little-endian integer to message. + $msg .= unpack ("B32", pack ("V", $bit_len)); + $msg .= unpack ("B32", pack ("V", ($bit_len >> 16) >> 16)); + + # Process the message in successive 512-bit chunks. + for (my $i = 0; $i < length ($msg); $i += 512) { + + my @w; + my $chunk = substr ($msg, $i, 512); + + # Break chunk into sixteen 32-bit little-endian words w[i], 0 <= i <= + # 15. + for (my $j = 0; $j < length ($chunk); $j += 32) { + push (@w, unpack ("V", pack ("B32", substr ($chunk, $j, 32)))); + } + + # Initialize hash value for this chunk. + my $a = $h0; + my $b = $h1; + my $c = $h2; + my $d = $h3; + my $f; + my $g; + + # Main loop. + for (my $y = 0; $y < 64; $y++) { + if ($y <= 15) { + $f = $d ^ ($b & ($c ^ $d)); + $g = $y; + } + elsif ($y <= 31) { + $f = $c ^ ($d & ($b ^ $c)); + $g = (5 * $y + 1) % 16; + } + elsif ($y <= 47) { + $f = $b ^ $c ^ $d; + $g = (3 * $y + 5) % 16; + } + else { + $f = $c ^ ($b | (0xFFFFFFFF & (~ $d))); + $g = (7 * $y) % 16; + } + + my $temp = $d; + $d = $c; + $c = $b; + $b = ($b + leftrotate (($a + $f + $K[$y] + $w[$g]) % POW232, $S[$y])) % POW232; + $a = $temp; + } + + # Add this chunk's hash to result so far. + $h0 = ($h0 + $a) % POW232; + $h1 = ($h1 + $b) % POW232; + $h2 = ($h2 + $c) % POW232; + $h3 = ($h3 + $d) % POW232; + } + + # Digest := h0 append h1 append h2 append h3 #(expressed as little-endian) + return unpack ("H*", pack ("V", $h0)) . + unpack ("H*", pack ("V", $h1)) . + unpack ("H*", pack ("V", $h2)) . + unpack ("H*", pack ("V", $h3)); + } + + ################################################################################ + # MD5 leftrotate function. See: http://en.wikipedia.org/wiki/MD5#Pseudocode + ################################################################################ + sub leftrotate { + my ($x, $c) = @_; + + return (0xFFFFFFFF & ($x << $c)) | ($x >> (32 - $c)); + } + + ################################################################################ + # return last error. + ################################################################################ + sub get_last_error { + my ($self) = @_; + + if (!empty($self->{'last_error'})) { + return $self->{'last_error'}; + } + + return ''; + } + + ################################################################################ + # Update last error. + ################################################################################ + sub set_last_error { + my ($self, $error) = @_; + + $self->{'last_error'} = $error; + } + + ################################################################################ + # Try to load extra libraries.c + ################################################################################ + sub load_libraries { + my $self = shift; + + # Dynamic load. Avoid unwanted behaviour. + eval {eval 'require YAML::Tiny;1' or die('YAML::Tiny lib not found, commands feature won\'t be available');}; + if ($@) { + $self->set_last_error($@); + return 0; + } else { + return 1; + } + } + + ################################################################################ + # Create new omnishell handler. + ################################################################################ + sub new { + my ($class, $args) = @_; + + if (ref($args) ne 'HASH') { + return undef; + } + + my $system = init(); + my $self = { + 'server_ip' => 'localhost', + 'server_path' => '/var/spool/pandora/data_in', + 'server_port' => 41121, + 'transfer_mode' => 'tentacle', + 'transfer_mode_user' => 'apache', + 'transfer_timeout' => 30, + 'server_user' => 'pandora', + 'server_pwd' => '', + 'server_ssl' => '0', + 'server_opts' => '', + 'delayed_startup' => 0, + 'pandora_nice' => 10, + 'cron_mode' => 0, + 'last_error' => undef, + %{$system}, + %{$args}, + }; + + $self->{'temporal'} =~ s/\"|\'//g; + $self = bless($self, $class); + $self->prepare_commands(); + + return $self; + } + + ################################################################################ + # Run all, output mode 'xml' will dump to STDOUT and return an array of strings + #, any other option will return an array with all results. + ################################################################################ + sub run { + my ($self, $output_mode) = @_; + + my @results; + + foreach my $ref (keys %{$self->{'commands'}}) { + my $rs = $self->runCommand($ref, $output_mode); + if ($rs) { + push @results, $rs; + } + } + + if ($output_mode eq 'xml') { + print join("\n",@results); + } + + return \@results; + } + + ################################################################################ + # Run command, output mode 'xml' will dump to STDOUT, other will return a hash + # with all results. + ################################################################################ + sub runCommand { + my ($self, $ref, $output_mode) = @_; + + if($self->load_libraries()) { + # Functionality possible. + my $command = $self->{'commands'}->{$ref}; + my $result = $self->evaluate_command($ref); + if (ref($result) eq "HASH") { + # Process command result. + if (defined($output_mode) && $output_mode eq 'xml') { + my $output = ''; + $output .= "\n"; + $output .= " \n"; + $output .= " {'name'}."]]>\n"; + $output .= " \n"; + $output .= " {'error_level'}."]]>\n"; + $output .= " {'stdout'}."]]>\n"; + $output .= " {'stderr'}."]]>\n"; + $output .= " \n"; + $output .= "\n"; + + return $output; + } + return $result; + } else { + $self->set_last_error('Failed to process ['.$ref.']: '.$result); + } + } + + return undef; + } + + ################################################################################ + # Check for remote commands defined. + ################################################################################ + sub prepare_commands { + my ($self) = @_; + + if ($YAML == 0) { + $self->set_last_error('Cannot use commands without YAML dependency, please install it.'); + return; + } + + # Force configuration file read. + my $commands = $self->{'commands'}; + + if (empty($commands)) { + $self->{'commands'} = {}; + } else { + foreach my $rcmd (keys %{$commands}) { + $self->{'commands'}->{trim($rcmd)} = {}; + } + } + + # Cleanup old commands. Not registered. + $self->cleanup_old_commands(); + + foreach my $ref (keys %{$self->{'commands'}}) { + my $file_content; + my $download = 0; + my $rcmd_file = $self->{'ConfDir'}.'/commands/'.$ref.'.rcmd'; + + # Search for local .rcmd file + if (-e $rcmd_file) { + my $remote_md5_file = $self->{'temporal'}.'/'.$ref.'.md5'; + + $file_content = read_file($rcmd_file); + if ($self->recv_file($ref.'.md5', $remote_md5_file) != 0) { + # Remote file could not be retrieved, skip. + delete $self->{'commands'}->{$ref}; + next; + } + + my $local_md5 = md5($file_content); + my $remote_md5 = md5(read_file($remote_md5_file)); + + if ($local_md5 ne $remote_md5) { + # Must be downloaded again. + $download = 1; + } + } else { + $download = 1; + } + + # Search for remote .rcmd file + if ($download == 1) { + # Download .rcmd file + if ($self->recv_file($ref.'.rcmd') != 0) { + # Remote file could not be retrieved, skip. + delete $self->{'commands'}->{$ref}; + next; + } else { + # Success + move($self->{'temporal'}.'/'.$ref.'.rcmd', $rcmd_file); + } + } + + # Parse and prepare in memory skel. + eval { + $self->{'commands'}->{$ref} = YAML::Tiny->read($rcmd_file); + }; + if ($@) { + # Failed. + $self->set_last_error('Failed to decode command. ' . "\n".$@); + delete $self->{'commands'}->{$ref}; + next; + } + + } + } + + ################################################################################ + # Command report. + ################################################################################ + sub report_command { + my ($self, $ref, $err_level) = @_; + + # Retrieve content from .stdout and .stderr + my $stdout_file = $self->{'temporal'}.'/'.$ref.'.stdout'; + my $stderr_file = $self->{'temporal'}.'/'.$ref.'.stderr'; + + my $return; + eval { + $return = { + 'error_level' => $err_level, + 'stdout' => read_file($stdout_file), + 'stderr' => read_file($stderr_file), + }; + + $return->{'name'} = $self->{'commands'}->{$ref}->[0]->{'name'}; + }; + if ($@) { + $self->set_last_error('Failed to report command output. ' . $@); + } + + # Cleanup + unlink($stdout_file) if (-e $stdout_file); + unlink($stderr_file) if (-e $stderr_file); + + # Mark command as done. + open (my $R_FILE, '> '.$self->{'ConfDir'}.'/commands/'.$ref.'.rcmd.done'); + print $R_FILE $err_level; + close($R_FILE); + + + $return->{'stdout'} = '' unless defined ($return->{'stdout'}); + $return->{'stderr'} = '' unless defined ($return->{'stderr'}); + + return $return; + } + + ################################################################################ + # Cleanup unreferenced rcmd and rcmd.done files. + ################################################################################ + sub cleanup_old_commands { + my ($self) = @_; + + # Cleanup old .rcmd and .rcmd.done files. + my %registered = map { $_.'.rcmd' => 1 } keys %{$self->{'commands'}}; + if(opendir(my $dir, $self->{'ConfDir'}.'/commands/')) { + while (my $item = readdir($dir)) { + + # Skip other files. + next if ($item !~ /\.rcmd$/); + + # Clean .rcmd.done file if its command is not referenced in conf. + if (!defined($registered{$item})) { + if (-e $self->{'ConfDir'}.'/commands/'.$item) { + unlink($self->{'ConfDir'}.'/commands/'.$item); + } + if (-e $self->{'ConfDir'}.'/commands/'.$item.'.done') { + unlink($self->{'ConfDir'}.'/commands/'.$item.'.done'); + } + } + } + + # Close dir. + closedir($dir); + } + + } + + ################################################################################ + # Executes a command using defined timeout. + ################################################################################ + sub execute_command_timeout { + my ($self, $cmd, $timeout) = @_; + + if (!defined($timeout) + || !looks_like_number($timeout) + || $timeout <= 0 + ) { + `$cmd`; + return $?>>8; + } + + my $remaining_timeout = $timeout; + + my $RET; + my $output; + + my $pid = open ($RET, "-|"); + if (!defined($pid)) { + # Failed to fork. + $self->set_last_error('[command] Failed to fork.'); + return undef; + } + if ($pid == 0) { + # Child. + my $ret; + eval { + local $SIG{ALRM} = sub { die "timeout\n" }; + alarm $timeout; + `$cmd`; + alarm 0; + }; + + my $result = ($?>>8); + return $result; + + # Exit child. + # Child finishes. + exit; + + } else { + # Parent waiting. + while( --$remaining_timeout > 0 ){ + if (wait == -1) { + last; + } + # Wait child up to timeout seconds. + sleep 1; + } + } + + if ($remaining_timeout > 0) { + # Retrieve output from child. + $output = do { local $/; <$RET> }; + $output = $output>>8; + } + else { + # Timeout expired. + return 124; + } + + close($RET); + + return $output; + } + + ################################################################################ + # Executes a block of commands, returns error level, leaves output in + # redirection set by $std_files. E.g: + # $std_files = ' >> /tmp/stdout 2>> /tmp/stderr + ################################################################################ + sub execute_command_block { + my ($self, $commands, $std_files, $timeout, $retry) = @_; + + return 0 unless defined($commands); + + my $retries = $retry; + + $retries = 1 unless looks_like_number($retries) && $retries > 0; + + my $err_level = 0; + $std_files = '' unless defined ($std_files); + + if (ref($commands) ne "ARRAY") { + return 0 if $commands eq ''; + + do { + $err_level = $self->execute_command_timeout( + "($commands) $std_files", + $timeout + ); + + # Do not retry if success. + last if looks_like_number($err_level) && $err_level == 0; + } while ((--$retries) > 0); + + } else { + foreach my $comm (@{$commands}) { + next unless defined($comm); + $retries = $retry; + $retries = 1 unless looks_like_number($retries) && $retries > 0; + + do { + $err_level = $self->execute_command_timeout( + "($comm) $std_files", + $timeout + ); + + # Do not retry if success. + $retries = 0 if looks_like_number($err_level) && $err_level == 0; + + } while ((--$retries) > 0); + + # Do not continue evaluating block if failed. + last unless ($err_level == 0); + } + } + + return $err_level; + } + + ################################################################################ + # Evalate given command. + ################################################################################ + sub evaluate_command { + my ($self, $ref) = @_; + + # Not found. + return "undefined command" unless defined $self->{'commands'}->{$ref}; + + # Already completed. + return "already executed" if (-e $self->{'ConfDir'}.'/commands/'.$ref.'.rcmd.done'); + + # [0] because how library works. + my $cmd = $self->{'commands'}->{$ref}->[0]; + + my $std_files = ' >> "'.$self->{'temporal'}.'/'.$ref.'.stdout" '; + $std_files .= ' 2>> "'.$self->{'temporal'}.'/'.$ref.'.stderr" '; + + # Check preconditions + my $err_level; + + $err_level = $self->execute_command_block( + $cmd->{'preconditions'}, + $std_files, + $cmd->{'timeout'} + ); + + # Precondition not satisfied. + return $self->report_command($ref, $err_level) unless ($err_level == 0); + + # Main run. + $err_level = $self->execute_command_block( + $cmd->{'script'}, + $std_files, + $cmd->{'timeout'} + ); + + # Script not success. + return $self->report_command($ref, $err_level) unless ($err_level == 0); + + # Check postconditions + $err_level = $self->execute_command_block( + $cmd->{'postconditions'}, + $std_files, + $cmd->{'timeout'} + ); + + # Return results. + return $self->report_command($ref, $err_level); + } + + ################################################################################ + # File transference and imported methods + ################################################################################ + ################################################################################ + ## Remove any trailing / from directory names. + ################################################################################ + sub fix_directory ($) { + my $dir = shift; + + my $char = chop($dir); + return $dir if ($char eq '/'); + return $dir . $char; + } + + ################################################################################ + # Receive a file from the server. + ################################################################################ + sub recv_file { + my ($self, $file, $relative) = @_; + my $output; + + my $DevNull = $self->{'__system'}->{'devnull'}; + my $CmdSep = $self->{'__system'}->{'cmdsep'}; + + my $pid = fork(); + return 1 unless defined $pid; + + # Fix remote dir to some transfer mode + my $remote_dir = $self->{'server_path'}; + $remote_dir .= "/" . fix_directory($relative) if defined($relative); + + if ($pid == 0) { + # execute the transfer program by child process. + eval { + local $SIG{'ALRM'} = sub {die}; + alarm ($self->{'transfer_timeout'}); + if ($self->{'transfer_mode'} eq 'tentacle') { + $output = `cd "$self->{'temporal'}"$CmdSep tentacle_client -v -g -a $self->{'server_ip'} -p $self->{'server_port'} $self->{'server_opts'} $file 2>&1 >$DevNull` + } elsif ($self->{'transfer_mode'} eq 'ssh') { + $output = `scp -P $self->{'server_port'} pandora@"$self->{'server_ip'}:$self->{'server_path'}/$file" $self->{'temporal'} 2>&1 >$DevNull`; + } elsif ($self->{'transfer_mode'} eq 'ftp') { + my $base = basename ($file); + my $dir = dirname ($file); + + $output = `ftp -n $self->{'server_opts'} $self->{'server_ip'} $self->{'server_port'} 2>&1 >$DevNull <{'server_user'} + quote PASS $self->{'server_pwd'} + lcd "$self->{'temporal'}" + cd "$self->{'server_path'}" + get "$file" + quit + FEOF1` + } elsif ($self->{'transfer_mode'} eq 'local') { + $output = `cp "$remote_dir/$file" $self->{'temporal'} 2>&1 >$DevNull`; + } + alarm (0); + }; + + if ($@) { + $self->set_last_error("Error retrieving file: '.$file.' File transfer command is not responding."); + exit 1; + } + + # Get the errorlevel + my $rc = $? >> 8; + if ($rc != 0) { + $self->set_last_error("Error retrieving file: '$file' $output"); + } + exit $rc; + } + + # Wait the child process termination and get the errorlevel + waitpid ($pid, 0); + my $rc = $? >> 8; + + return $rc; + } + + 1; +} + +package main; use strict; use warnings; @@ -34,7 +1005,6 @@ use Sys::Syslog; use Time::Local; use lib '/usr/lib/perl5'; -use PandoraFMS::Omnishell; # Agent XML data my $Xml; @@ -46,7 +1016,7 @@ my $Sem = undef; my $ThreadSem = undef; use constant AGENT_VERSION => '7.0NG.751'; -use constant AGENT_BUILD => '201214'; +use constant AGENT_BUILD => '201223'; # Agent log default file size maximum and instances use constant DEFAULT_MAX_LOG_SIZE => 600000; @@ -3401,3 +4371,5 @@ This is released under the GNU Lesser General Public License. Copyright (c) 2005-2010 Artica Soluciones Tecnologicas S.L =cut + + diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec index 937cfeeaa5..44a0a8733c 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.751 -%define release 201214 +%define release 201223 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 b2ac5156c9..524a430ae5 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.751 -%define release 201214 +%define release 201223 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 4381afe964..fb32e199be 100755 --- a/pandora_agents/unix/pandora_agent_installer +++ b/pandora_agents/unix/pandora_agent_installer @@ -10,7 +10,7 @@ # ********************************************************************** PI_VERSION="7.0NG.751" -PI_BUILD="201214" +PI_BUILD="201223" OS_NAME=`uname -s` FORCE=0 diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi index 45a685c9a6..ef05566ff3 100644 --- a/pandora_agents/win32/installer/pandora.mpi +++ b/pandora_agents/win32/installer/pandora.mpi @@ -186,7 +186,7 @@ UpgradeApplicationID {} Version -{201214} +{201223} ViewReadme {Yes} diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index 9f27196e30..205c9a0423 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.751(Build 201214)") +#define PANDORA_VERSION ("7.0NG.751(Build 201223)") string pandora_path; string pandora_dir; diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc index 83d8aeda8b..433faa9530 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.751(Build 201214))" + VALUE "ProductVersion", "(7.0NG.751(Build 201223))" VALUE "FileVersion", "1.0.0.0" END END diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control index 4148a9c841..baad26c271 100644 --- a/pandora_console/DEBIAN/control +++ b/pandora_console/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-console -Version: 7.0NG.751-201214 +Version: 7.0NG.751-201223 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 46274c3dd8..ff815eff98 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.751-201214" +pandora_version="7.0NG.751-201223" package_pear=0 package_pandora=1 diff --git a/pandora_console/extras/mr/44.sql b/pandora_console/extras/mr/44.sql new file mode 100644 index 0000000000..a1dc6dc1b7 --- /dev/null +++ b/pandora_console/extras/mr/44.sql @@ -0,0 +1,15 @@ +START TRANSACTION; + +ALTER TABLE `talert_templates` +ADD COLUMN `field16` TEXT NOT NULL AFTER `field15` +,ADD COLUMN `field17` TEXT NOT NULL AFTER `field16` +,ADD COLUMN `field18` TEXT NOT NULL AFTER `field17` +,ADD COLUMN `field19` TEXT NOT NULL AFTER `field18` +,ADD COLUMN `field20` TEXT NOT NULL AFTER `field19` +,ADD COLUMN `field16_recovery` TEXT NOT NULL AFTER `field15_recovery` +,ADD COLUMN `field17_recovery` TEXT NOT NULL AFTER `field16_recovery` +,ADD COLUMN `field18_recovery` TEXT NOT NULL AFTER `field17_recovery` +,ADD COLUMN `field19_recovery` TEXT NOT NULL AFTER `field18_recovery` +,ADD COLUMN `field20_recovery` TEXT NOT NULL AFTER `field19_recovery`; + +COMMIT; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index 8d096e4845..bae705f725 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -1267,11 +1267,21 @@ ALTER TABLE talert_templates ADD COLUMN `field12` TEXT NOT NULL DEFAULT ""; ALTER TABLE talert_templates ADD COLUMN `field13` TEXT NOT NULL DEFAULT ""; ALTER TABLE talert_templates ADD COLUMN `field14` TEXT NOT NULL DEFAULT ""; ALTER TABLE talert_templates ADD COLUMN `field15` TEXT NOT NULL DEFAULT ""; +ALTER TABLE talert_templates ADD COLUMN `field16` TEXT NOT NULL DEFAULT ""; +ALTER TABLE talert_templates ADD COLUMN `field17` TEXT NOT NULL DEFAULT ""; +ALTER TABLE talert_templates ADD COLUMN `field18` TEXT NOT NULL DEFAULT ""; +ALTER TABLE talert_templates ADD COLUMN `field19` TEXT NOT NULL DEFAULT ""; +ALTER TABLE talert_templates ADD COLUMN `field20` TEXT NOT NULL DEFAULT ""; ALTER TABLE talert_templates ADD COLUMN `field11_recovery` TEXT NOT NULL DEFAULT ""; ALTER TABLE talert_templates ADD COLUMN `field12_recovery` TEXT NOT NULL DEFAULT ""; ALTER TABLE talert_templates ADD COLUMN `field13_recovery` TEXT NOT NULL DEFAULT ""; ALTER TABLE talert_templates ADD COLUMN `field14_recovery` TEXT NOT NULL DEFAULT ""; ALTER TABLE talert_templates ADD COLUMN `field15_recovery` TEXT NOT NULL DEFAULT ""; +ALTER TABLE talert_templates ADD COLUMN `field16_recovery` TEXT NOT NULL DEFAULT ""; +ALTER TABLE talert_templates ADD COLUMN `field17_recovery` TEXT NOT NULL DEFAULT ""; +ALTER TABLE talert_templates ADD COLUMN `field18_recovery` TEXT NOT NULL DEFAULT ""; +ALTER TABLE talert_templates ADD COLUMN `field19_recovery` TEXT NOT NULL DEFAULT ""; +ALTER TABLE talert_templates ADD COLUMN `field20_recovery` TEXT NOT NULL DEFAULT ""; ALTER TABLE `talert_templates` ADD COLUMN `disable_event` tinyint(1) DEFAULT 0; -- --------------------------------------------------------------------- diff --git a/pandora_console/general/header.php b/pandora_console/general/header.php index efc8bc1545..1f573749e7 100644 --- a/pandora_console/general/header.php +++ b/pandora_console/general/header.php @@ -1,15 +1,18 @@ , }, success: function (data) { $('#result_order').html(data); diff --git a/pandora_console/general/login_page.php b/pandora_console/general/login_page.php index a8fb0327bb..2bef8403ff 100755 --- a/pandora_console/general/login_page.php +++ b/pandora_console/general/login_page.php @@ -159,11 +159,31 @@ echo '