From 9e54f9517bd01301ffdf4d3d0db1377a2cb96e10 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Thu, 18 Mar 2021 16:12:39 +0100 Subject: [PATCH 1/7] WIP: Backup upload --- .../extras/delete_files/delete_files.txt | 7 +- pandora_server/conf/pandora_server.conf.new | 4 +- .../lib/PandoraFMS/Goliat/GoliatCURL.pm | 365 +++++++++++++ .../lib/PandoraFMS/Goliat/GoliatConfig.pm | 265 ++++++++++ .../lib/PandoraFMS/Goliat/GoliatLWP.pm | 478 ++++++++++++++++++ .../lib/PandoraFMS/Goliat/GoliatTools.pm | 222 ++++++++ pandora_server/lib/PandoraFMS/WebServer.pm | 294 +++++++++++ 7 files changed, 1632 insertions(+), 3 deletions(-) create mode 100755 pandora_server/lib/PandoraFMS/Goliat/GoliatCURL.pm create mode 100755 pandora_server/lib/PandoraFMS/Goliat/GoliatConfig.pm create mode 100755 pandora_server/lib/PandoraFMS/Goliat/GoliatLWP.pm create mode 100755 pandora_server/lib/PandoraFMS/Goliat/GoliatTools.pm create mode 100644 pandora_server/lib/PandoraFMS/WebServer.pm diff --git a/pandora_console/extras/delete_files/delete_files.txt b/pandora_console/extras/delete_files/delete_files.txt index f21a69a040..7832042fda 100644 --- a/pandora_console/extras/delete_files/delete_files.txt +++ b/pandora_console/extras/delete_files/delete_files.txt @@ -73,4 +73,9 @@ enterprise/extensions/ipam.php enterprise/extensions/ipam enterprise/extensions/disabled/visual_console_manager.php enterprise/extensions/visual_console_manager.php -pandora_console/extensions/net_tools.php \ No newline at end of file +pandora_console/extensions/net_tools.php +pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/Goliat/GoliatCURL.pm +pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/Goliat/GoliatConfig.pm +pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/Goliat/GoliatLWP.pm +pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/Goliat/GoliatTools.pm +pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/PandoraFMS/WebServer.pm \ No newline at end of file diff --git a/pandora_server/conf/pandora_server.conf.new b/pandora_server/conf/pandora_server.conf.new index 2bff2b9d98..b4c8f5bc2c 100644 --- a/pandora_server/conf/pandora_server.conf.new +++ b/pandora_server/conf/pandora_server.conf.new @@ -424,11 +424,11 @@ update_parent 1 # openstreetmaps_description 1 -# Enable (1) or disable (0) Pandora FMS Web Server/Goliat (PANDORA FMS ENTERPRISE ONLY). +# Enable (1) or disable (0) Pandora FMS Web Server/Goliat. webserver 1 -# Number of threads for the Web Server/Goliat (PANDORA FMS ENTERPRISE ONLY). +# Number of threads for the Web Server/Goliat. web_threads 1 diff --git a/pandora_server/lib/PandoraFMS/Goliat/GoliatCURL.pm b/pandora_server/lib/PandoraFMS/Goliat/GoliatCURL.pm new file mode 100755 index 0000000000..6f82ba3a00 --- /dev/null +++ b/pandora_server/lib/PandoraFMS/Goliat/GoliatCURL.pm @@ -0,0 +1,365 @@ +################################################################################## +# Goliath Tools CURL Module +################################################################################## +# Copyright (c) 2013-2021 Artica Soluciones Tecnologicas S.L +# This code is not free or OpenSource. Please don't redistribute. +################################################################################## + +package Goliat::GoliatCURL; + +use Goliat::GoliatTools; + +use strict; +use warnings; +use Data::Dumper; +use PandoraFMS::DB; + +use IO::Socket::INET6; +use URI::Escape; +use Time::Local; +use Time::HiRes qw ( gettimeofday ); + +# Japanese encoding support +use Encode::Guess qw/euc-jp shiftjis iso-2022-jp/; + +require Exporter; + +our @ISA = ("Exporter"); +our %EXPORT_TAGS = ( 'all' => [ qw() ] ); +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); +our @EXPORT = qw( + g_http_task + @task_requests + @task_reqsec + @task_fails + @task_time + @task_end + @task_sessions + @task_ssec + @task_get_string + @task_get_content + @task_session_fails +); + +our @task_requests; +our @task_reqsec; +our @task_fails ; +our @task_time; +our @task_end; +our @task_sessions; +our @task_ssec; +our @task_get_string; +our @task_get_content; +our @task_session_fails; +our $goliat_abort; + +# Returns a string than can be safely used as a command line parameter for CURL +sub safe_param ($) { + my $string = shift; + + $string =~ s/'/"/g; + return "'" . $string . "'"; +} + +sub g_http_task { + my ( $config, $thread_id, @work_list ) = @_; + my ( $ax, $bx, $cx ); # used in FOR loop + my ( $ttime1, $ttime2, $ttime_tot ); + + my $resp; # HTTP Response + my $total_requests = 0; + my $total_valid_requests = 0; + my $total_invalid_request = 0; + my $cookie_file = "/tmp/gtc_".$thread_id."_".g_trash_ascii (3); + my $check_string = 1; + my $get_string = ""; + my $get_content = ""; + my $get_content_advanced = ""; + my $timeout = 10; + + #my $ua = new LWP::UserAgent; + $task_requests [$thread_id] = 0 ; + $task_sessions [$thread_id] = 0 ; + $task_reqsec[$thread_id] = 0; + $task_fails[$thread_id] = 0; + $task_session_fails[$thread_id] = 0; + $task_ssec[$thread_id] = 0; + $task_end[$thread_id] = 0; + $task_time[$thread_id] = 0; + $task_get_string[$thread_id] = ""; + $task_get_content[$thread_id] = ""; + + # Set command line options for CURL + my $curl_opts; + + # Follow redirects + $curl_opts .= " --location-trusted"; + + # User agent + if ($config->{"agent"} ne '') { + $curl_opts .= " -A " . safe_param($config->{"agent"}) + } + + # Prevent pages from being cached + $curl_opts .= " -H 'Pragma: no-cache'"; + + # Timeout + if (defined ($config->{"timeout"}) && $config->{"timeout"} > 0) { + $timeout = $config->{"timeout"}; + } + + # Maximum file size + if (defined($config->{"maxsize"}) && $config->{"maxsize"} > 0) { + $curl_opts .= " --max-filesize " . $config->{"maxsize"}; + } + + # Disable SSL certificate host verification + $curl_opts .= " -k"; + + # Proxy + if ($config->{'proxy'} ne ""){ + $curl_opts .= " -x " . safe_param($config->{'proxy'}); + } + + # Proxy HTTP authentication + if ($config->{'auth_user'} ne "") { + $curl_opts .= " --proxy-anyauth -U " . safe_param($config->{'auth_user'} . ':' . $config->{'auth_pass'}); + } + + # Delete existing cookies + my $cookie_carry_on = 0; + if ( -e $cookie_file){ + unlink ($cookie_file); + } + + $ttime1 = Time::HiRes::gettimeofday(); + for ($ax = 0; $ax != $config->{'retries'}; $ax++){ + for ($bx = 0; $bx < $config->{"work_items"}; $bx++){ + if ($config->{'con_delay'} > 0){ + sleep ($config->{'con_delay'}); + } + $total_requests++; + # Start to count! + $check_string = 1; + # Prepare parameters + my $task_curl_opts = $curl_opts; + my $params = ""; + $cx = 0; + while (defined($work_list[$bx]->{'variable_name'}[$cx])){ + if ($cx > 0){ + $params = $params."&"; + } + $params = $params . $work_list[$bx]->{'variable_name'}[$cx] . "=" . uri_escape($work_list[$bx]->{'variable_value'}[$cx]); + $cx++; + } + + # Cookie carry on + if (defined ($work_list[$bx]->{'cookie'}) && $work_list[$bx]->{'cookie'} == 1){ + $cookie_carry_on = 1; + } + + if ($cookie_carry_on == 1) { + $task_curl_opts .= " -c " . safe_param ($cookie_file); + $task_curl_opts .= " -b " . safe_param ($cookie_file); + } + + # HTTP authentication + if ($work_list[$bx]->{'http_auth_user'} ne "" && $work_list[$bx]->{'http_auth_pass'} ne "") { + + if($config->{'http_check_type'} == 0){ + $task_curl_opts .= " --anyauth -u " . safe_param($work_list[$bx]->{'http_auth_user'} . ':' . $work_list[$bx]->{'http_auth_pass'}); + } + + if ($config->{'http_check_type'} == 1) { + $task_curl_opts .= " --ntlm -u " . safe_param($work_list[$bx]->{'http_auth_user'} . ':' . $work_list[$bx]->{'http_auth_pass'}); + } + + if ($config->{'http_check_type'} == 2) { + $task_curl_opts .= " --digest -u " . safe_param($work_list[$bx]->{'http_auth_user'} . ':' . $work_list[$bx]->{'http_auth_pass'}); + } + + if ($config->{'http_check_type'} == 3) { + $task_curl_opts .= " --basic -u " . safe_param($work_list[$bx]->{'http_auth_user'} . ':' . $work_list[$bx]->{'http_auth_pass'}); + } + + + } + + # GET + if ($work_list[$bx]->{'type'} eq "GET"){ + $task_curl_opts .= " -H 'Accept: text/html'"; + if ($cx > 0){ + $params = $work_list[$bx]->{'url'} . "?" . $params; + } else { + $params = $work_list[$bx]->{'url'}; + } + + $resp = curl ($config->{"plugin_exec"}, $timeout, $task_curl_opts, $params, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'}, $config->{"moduleId"}, $config->{"dbh"}); + + # POST + } elsif ($work_list[$bx]->{'type'} eq "POST") { + $task_curl_opts .= " -d " . safe_param($params); + $task_curl_opts .= " -H 'Content-type: application/x-www-form-urlencoded'"; + $resp = curl ($config->{"plugin_exec"}, $timeout, $task_curl_opts, $work_list[$bx]->{'url'}, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'}, $config->{"moduleId"}, $config->{"dbh"}); + + # HEAD + } else { + $task_curl_opts .= " -I"; + if ($cx > 0){ + $params = $work_list[$bx]->{'url'} . "?" . uri_escape($params); + } else { + $params = $work_list[$bx]->{'url'}; + } + $resp = curl ($config->{"plugin_exec"}, $timeout, $task_curl_opts, $params, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'}, $config->{"moduleId"}, $config->{"dbh"}); + } + + # Get string ? + if (defined($work_list[$bx]->{'get_string'})) { + my $temp = $work_list[$bx]->{'get_string'}; + if ($resp =~ m/($temp)/) { + $task_get_string[$thread_id] = $1; + } + } + + # Get response ? + if ($work_list[$bx]->{'get_content_advanced'} ne "") { + my $temp = $work_list[$bx]->{'get_content_advanced'}; + if ($resp =~ m/$temp/) { + $task_get_content[$thread_id] = $1 if defined ($1); + } + } elsif ($work_list[$bx]->{'get_content'} ne "") { + my $temp = $work_list[$bx]->{'get_content'}; + if ($resp =~ m/($temp)/) { + $task_get_content[$thread_id] = $1; + } + } else { + $task_get_content[$thread_id] = $resp; + } + + # Resource bashing + #if ((defined($work_list[$bx]->{'get_resources'})) && ($work_list[$bx]->{'get_resources'} == 1)){ + # $total_requests = g_get_all_links ($config, $ua, $resp, $total_requests, $work_list[$bx]->{'url'}, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'}); + #} + + # CHECKSTRING check + $cx = 0; + while (defined($work_list[$bx]->{'checkstring'}[$cx])) { + my $match_string = $work_list[$bx]->{'checkstring'}[$cx]; + my $as_string = $resp; + my $guess = Encode::Guess::guess_encoding($as_string); + if (ref $guess) { + $as_string = $guess->decode($as_string); + } + unless (utf8::is_utf8($match_string)) { + utf8::decode($match_string); + } + + if ( $as_string =~ m/$match_string/i ){ + $total_valid_requests++; + } else { + $total_invalid_request++; + $bx = $config->{"work_items"}; # Abort session remaining request + $check_string=0; + } + $cx++; + } + + # CHECKNOTSTRING check + $cx = 0; + while (defined($work_list[$bx]->{'checknotstring'}[$cx])) { + my $match_string = $work_list[$bx]->{'checknotstring'}[$cx]; + my $as_string = $resp; + + my $guess = Encode::Guess::guess_encoding($as_string); + if (ref $guess) { + $as_string = $guess->decode($as_string); + } + unless (utf8::is_utf8($match_string)) { + utf8::decode($match_string); + } + + if ( $as_string !~ m/$match_string/i ){ + $total_valid_requests++; + } else { + $total_invalid_request++; + $bx = $config->{"work_items"}; # Abort session remaining request + $check_string=0; + } + $cx++; + } + + # End just now by pressing CTRL-C or Kill Signal ! + #if ($goliat_abort == 1){ + #$ax = $config->{'retries'}; + #$bx = $config->{'items'}; + #goto END_LOOP; + #} + } #main work_detail loop + $ttime2 = Time::HiRes::gettimeofday(); + + $ttime_tot = $ttime2 - $ttime1; # Total time for this task + $task_time[$thread_id] = $ttime_tot; + $task_requests [$thread_id] = $total_requests; + if ($ttime_tot > 0 ){ + $task_reqsec[$thread_id] = $total_requests / $ttime_tot; + } else { + $task_reqsec[$thread_id] = $total_requests; + } + $task_fails[$thread_id] = $total_invalid_request; + if ($check_string == 0){ + $task_session_fails[$thread_id]++ + } + $task_sessions [$thread_id]++; + if ($task_sessions [$thread_id] > 0 ){ + $task_ssec[$thread_id] = $ttime_tot / $task_sessions [$thread_id]; + } else { + $task_ssec[$thread_id] = $task_sessions[$thread_id]; + } + sleep $config->{'ses_delay'}; + } +END_LOOP: + + if ( -f $cookie_file){ + unlink ($cookie_file); + } + + $task_end[$thread_id] = 1; +} + +# Call CURL and return its output. +sub curl { + my ($exec, $timeout, $curl_opts, $url, $headers, $debug, $moduleId, $dbh) = @_; + + while (my ($header, $value) = each %{$headers}) { + $curl_opts .= " -H " . safe_param($header . ':' . $value); + } + + my $cmd = "curl $curl_opts " . safe_param($url); + my $response = `"$exec" $timeout $cmd 2>/dev/null`; + + # Curl command stored for live debugging feature. + set_update_agentmodule ($dbh, $moduleId, { 'debug_content' => $cmd }) if defined($dbh); + + return $response if ($debug eq ''); + + # Debug + if (open (DEBUG, '>>', $debug . '.req')) { + print DEBUG "[Goliat debug " . time () . "]\n"; + print DEBUG $cmd; + print "\n"; + close (DEBUG); + } + if (open (DEBUG, '>>', $debug . '.res')) { + print DEBUG "[Goliat debug " . time () . "]\n"; + print DEBUG $response; + print "\n"; + close (DEBUG); + } + return $response; +} + +# End of function declaration +# End of defined Code + +1; +__END__ diff --git a/pandora_server/lib/PandoraFMS/Goliat/GoliatConfig.pm b/pandora_server/lib/PandoraFMS/Goliat/GoliatConfig.pm new file mode 100755 index 0000000000..25ae73b30f --- /dev/null +++ b/pandora_server/lib/PandoraFMS/Goliat/GoliatConfig.pm @@ -0,0 +1,265 @@ +########################################################################## +# Goliat Config package +########################################################################## +# Copyright (c) 2007-2021 Artica Soluciones Tecnologicas S.L +# This code is not free or OpenSource. Please don't redistribute. +########################################################################## + +package Goliat::GoliatConfig; + +use strict; +use warnings; +use Goliat::GoliatTools; +use PandoraFMS::Tools; + +require Exporter; +our @ISA = ("Exporter"); +our %EXPORT_TAGS = ( 'all' => [ qw( ) ] ); +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); +our @EXPORT = qw( g_help_screen + g_init + g_load_config ); + +my $g_version = "1.0"; +my $g_build = "110929"; +our $VERSION = $g_version." ".$g_build; + + +sub g_load_config { + my ( $config , $work_list )= @_ ; + my $archivo_cfg = $config->{'config_file'}; + my $buffer_line; + my $task_block = 0; + my $commit_block = 0; + my $task_url = ""; + my $task_cookie = 0; + my $task_resources = 1; + my $task_type = ""; + my $task_headers = {}; + my $task_debug = ""; + my $http_auth_user = ""; + my $http_auth_pass = ""; + my $http_auth_realm = ""; + my $http_auth_serverport = ""; + my $get_string = ""; + my $get_content = ""; + my $get_content_advanced = ""; + my @task_variable_name; + my @task_variable_value; + my @task_check_string; + my @task_check_not_string; + my $parametro; + my $temp1; + + # Default options + $config->{'con_delay'} =0; + $config->{'ses_delay'} =0; + if (!defined($config->{'agent'})){ + $config->{'agent'}="PandoraFMS/Goliat 4.0; Linux)"; + } + if (!defined($config->{'proxy'})){ + $config->{'proxy'}=""; + } + + if (!defined($config->{'retries'})){ + $config->{'retries'} = 1; + } + + if ((!is_numeric($config->{'retries'})) || ($config->{'retries'} == 0)){ + $config->{'retries'} = 1; + } + + $config->{'refresh'} = "5"; + $config->{"max_depth"} = 25; + $config->{'log_file'}="/var/log/pandora/pandora_goliat.log"; + $config->{'log_output'} = 0; + + # Collect items from config file and put in an array + open (CFG, "< $archivo_cfg"); + while (){ + $buffer_line = $_; + if ($buffer_line =~ /^[a-zA-Z]/){ # begins with letters + $parametro = $buffer_line; + } else { + $parametro = ""; + } + # Need to commit block ?? + if (($commit_block == 1) && ($task_block == 1)) { + my %work_item; + $work_item{'url'} = $task_url; + $work_item{'cookie'} = $task_cookie; + $work_item{'type'} = $task_type; + $work_item{'get_resources'} = $task_resources; + $work_item{'get_string'} = $get_string; + $work_item{'get_content'} = $get_content; + $work_item{'get_content_advanced'} = $get_content_advanced; + $work_item{'http_auth_user'} = $http_auth_user; + $work_item{'http_auth_pass'} = $http_auth_pass; + $work_item{'http_auth_realm'} = $http_auth_realm; + $work_item{'http_auth_serverport'} = $http_auth_serverport; + $work_item{'headers'} = $task_headers; + $work_item{'debug'} = $task_debug; + + my $ax=0; + while ($#task_check_string >= 0){ + $temp1 = pop (@task_check_string); + $work_item{'checkstring'}[$ax] = $temp1; + $ax++; + } + $ax=0; + while ($#task_check_not_string >= 0){ + $temp1 = pop (@task_check_not_string); + $work_item{'checknotstring'}[$ax] = $temp1; + $ax++; + } + $ax=0; + while ($#task_variable_name >= 0){ + $temp1 = pop (@task_variable_name); + $work_item{'variable_name'}[$ax] = $temp1; + $ax++; + } + $ax=0; + while ($#task_variable_value >= 0){ + $temp1 = pop (@task_variable_value); + $work_item{'variable_value'}[$ax] = $temp1; + $ax++; + + } + push @{$work_list}, \%work_item; + $commit_block = 0; + $task_block = 0; + $task_url = ""; + $task_cookie = 0; + $task_resources = 0; + $task_type = ""; + $task_headers = {}; + $task_debug = ""; + $config->{"work_items"}++; + $commit_block = 0; + $task_block = 0; + $http_auth_user = ""; + $http_auth_pass = ""; + $http_auth_realm = ""; + $get_string = ""; + $get_content = ""; + $get_content_advanced = ""; + } + # ~~~~~~~~~~~~~~ + # Main setup items + # ~~~~~~~~~~~~~~ + + if ($parametro =~ m/^task_begin/i) { + $task_block = 1; + } + elsif ($parametro =~ m/^task_end/i) { + $commit_block = 1; + } + elsif ($parametro =~ m/^ses_delay\s(.*)/i) { + $config->{'ses_delay'} = $1; + } + elsif ($parametro =~ m/^con_delay\s(.*)/i) { + $config->{'con_delay'} = $1; + } + elsif ($parametro =~ m/^agent\s(.*)/i) { + $config->{'agent'} = $1; + } + elsif ($parametro =~ m/^proxy\s(.*)/i) { + $config->{'proxy'} = $1; + } + elsif ($parametro =~ m/^max_depth\s(.*)/i) { + $config->{'max_depth'} = $1; + } + elsif ($parametro =~ m/^log_file\s(.*)/i) { + $config->{"log_file"} = $1; + } + elsif ($parametro =~ m/^log_output\s(.*)/i) { + $config->{"log_output"} = $1; + } + elsif ($parametro =~ m/^log_http\s(.*)/i) { + $config->{"log_http"} = $1; + } + elsif ($parametro =~ m/^retries\s(.*)/i) { + $config->{"retries"} = $1; + } + # ~~~~~~~~~~~~~~ + # Task items + # ~~~~~~~~~~~~~~ + elsif ($parametro =~ m/^variable_name\s(.*)/i) { + push (@task_variable_name, $1); + } + elsif ($parametro =~ m/^variable_value\s(.*)/i) { + push (@task_variable_value, $1); + } + elsif ($parametro =~ m/^check_string\s(.*)/i) { + push (@task_check_string, $1); + } + elsif ($parametro =~ m/^check_not_string\s(.*)/i) { + push (@task_check_not_string, $1); + } + elsif ($parametro =~ m/^get\s(.*)/i) { + $task_type = "GET"; + $task_url = $1; + } + elsif ($parametro =~ m/^post\s(.*)/i) { + $task_type = "POST"; + $task_url = $1; + } + elsif ($parametro =~ m/^head\s(.*)/i) { + $task_type = "HEAD"; + $task_url = $1; + } + # New in 4.0 version + elsif ($parametro =~ m/^get_string\s(.*)/i) { + $get_string = $1; + } + elsif ($parametro =~ m/^get_content\s(.*)/i) { + $get_content = $1; + } + elsif ($parametro =~ m/^get_content_advanced\s(.*)/i) { + $get_content_advanced = $1; + } + elsif ($parametro =~ m/^http_auth_user\s(.*)/i) { + $http_auth_user = $1; + } + elsif ($parametro =~ m/^http_auth_pass\s(.*)/i) { + $http_auth_pass = $1; + } + elsif ($parametro =~ m/^http_auth_realm\s(.*)/i) { + $http_auth_realm = $1; + } + elsif ($parametro =~ m/^http_auth_serverport\s(.*)/i) { + $http_auth_serverport = $1; + } + elsif ($parametro =~ m/^cookie\s(.*)/i) { + if ($1 =~ m/1/i){ + $task_cookie = 1; + } else { + $task_cookie = 0; + } + } + elsif ($parametro =~ m/^resource\s(.*)/i) { + if ($1 =~ m/1/i){ + $task_resources = 1; + } else { + $task_resources = 0; + } + } + # New in 5.0 version + elsif ($parametro =~ m/^header\s+(\S+)\s(.*)/i) { + $task_headers->{$1} = $2; + } + elsif ($parametro =~ m/^debug\s+(.*)/i) { + $task_debug = $1; + } + + } + close (CFG); +} + +# End of function declaration +# End of defined Code + +1; +__END__ + + diff --git a/pandora_server/lib/PandoraFMS/Goliat/GoliatLWP.pm b/pandora_server/lib/PandoraFMS/Goliat/GoliatLWP.pm new file mode 100755 index 0000000000..7b66d2457e --- /dev/null +++ b/pandora_server/lib/PandoraFMS/Goliat/GoliatLWP.pm @@ -0,0 +1,478 @@ +################################################################################## +# Goliath Tools LWP Module +################################################################################## +# Copyright (c) 2007-2021 Artica Soluciones Tecnologicas S.L +# This code is not free or OpenSource. Please don't redistribute. +################################################################################## + +package Goliat::GoliatLWP; + +use Goliat::GoliatTools; + +use strict; +use warnings; +use Data::Dumper; + +use IO::Socket::INET6; +use LWP::UserAgent; +use LWP::ConnCache; +use HTTP::Request::Common; +use HTTP::Response; +use HTML::TreeBuilder; +use HTML::Element; +use HTTP::Cookies; +use URI::URL; +use Time::Local; +use Time::HiRes qw ( gettimeofday ); + +# For IPv6 support in Net::HTTP. +BEGIN { + $Net::HTTP::SOCKET_CLASS = 'IO::Socket::INET6'; + require Net::HTTP; +} + +# Japanese encoding support +use Encode::Guess qw/euc-jp shiftjis iso-2022-jp/; + +require Exporter; + +our @ISA = ("Exporter"); +our %EXPORT_TAGS = ( 'all' => [ qw() ] ); +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); +our @EXPORT = qw( + g_http_task + @task_requests + @task_reqsec + @task_fails + @task_time + @task_end + @task_sessions + @task_ssec + @task_get_string + @task_get_content + @task_session_fails +); + +our @task_requests; +our @task_reqsec; +our @task_fails; +our @task_time; +our @task_end; +our @task_sessions; +our @task_ssec; +our @task_get_string; +our @task_get_content; +our @task_session_fails; +our $goliat_abort; + +sub parse_html ($;$) +{ + my $p = $_[1]; + $p = _new_tree_maker() unless $p; + $p->parse($_[0]); +} + + +sub parse_htmlfile ($;$) +{ + my($file, $p) = @_; + local(*HTML); + open(HTML, $file) or return undef; + $p = _new_tree_maker() unless $p; + $p->parse_file(\*HTML); +} + +sub _new_tree_maker +{ + my $p = HTML::TreeBuilder->new(implicit_tags => 1, + ignore_unknown => 1, + ignore_text => 0, + 'warn' => 0, + ); + $p->strict_comment(1); + $p; +} + + +sub g_http_task { + my ( $config, $thread_id, @work_list ) = @_; + my ( $ax, $bx, $cx ); # used in FOR loop + my ( $ttime1, $ttime2, $ttime_tot ); + + my $resp; # HTTP Response + my $total_requests = 0; + my $total_valid_requests = 0; + my $total_invalid_request = 0; + my $cookie_file = "/tmp/gtc_".$thread_id."_".g_trash_ascii (3); + my $check_string = 1; + my $get_string = ""; + my $get_content = ""; + my $get_content_advanced = ""; + + my $ua = new LWP::UserAgent; + $task_requests [$thread_id] = 0 ; + $task_sessions [$thread_id] = 0 ; + $task_reqsec[$thread_id] = 0; + $task_fails[$thread_id] = 0; + $task_session_fails[$thread_id] = 0; + $task_ssec[$thread_id] = 0; + $task_end[$thread_id] = 0; + $task_time[$thread_id] = 0; + $task_get_string[$thread_id] = ""; + $task_get_content[$thread_id] = ""; + + $ua->agent($config->{"agent"}); + $ua->protocols_allowed( ['http', 'https'] ); + $ua->default_headers->push_header('pragma' => "no-cache"); + $ua->timeout ($config->{"timeout"}); + $ua->max_size($config->{"maxsize"}); + $ua->use_alarm($config->{"alarm"}); + + # Disable SSL certificate host verification + if ($ua->can ('ssl_opts')) { + $ua->ssl_opts("verify_hostname" => 0); + } + + # Set proxy + + if ($config->{'proxy'} ne ""){ + $ua->proxy(['http','https'], $config->{'proxy'}); + } + + # Set HTTP Proxy auth + if ($config->{'auth_user'} ne "") { + $ua->credentials( + $config->{'auth_server'}, + $config->{'auth_realm'}, + $config->{'auth_user'} => $config->{'auth_pass'} ); + } + + if ( -e $cookie_file){ + unlink ($cookie_file); + } + my $cookies = HTTP::Cookies->new ('file' => $cookie_file, 'autosave' => '0'); + + $ttime1 = Time::HiRes::gettimeofday(); + for ($ax = 0; $ax != $config->{'retries'}; $ax++){ + for ($bx = 0; $bx < $config->{"work_items"}; $bx++){ + if ($config->{'con_delay'} > 0){ + sleep ($config->{'con_delay'}); + } + $total_requests++; + # Start to count! + $check_string = 1; + # Prepare parameters + my $params = ""; + $cx = 0; + while (defined($work_list[$bx]->{'variable_name'}[$cx])){ + if ($cx > 0){ + $params = $params."&"; + } + $params = $params . $work_list[$bx]->{'variable_name'}[$cx] . "=" . $work_list[$bx]->{'variable_value'}[$cx]; + $cx++; + } + + if ( (defined($work_list[$bx]->{'http_auth_realm'})) && (defined($work_list[$bx]->{'http_auth_serverport'}))&& (defined($work_list[$bx]->{'http_auth_user'})) && (defined($work_list[$bx]->{'http_auth_pass'}))) { + if ($work_list[$bx]->{'http_auth_realm'} ne "") { + $ua->credentials( + $work_list[$bx]->{'http_auth_serverport'}, + $work_list[$bx]->{'http_auth_realm'}, + $work_list[$bx]->{'http_auth_user'} => $work_list[$bx]->{'http_auth_pass'} + ); + } + } + + # GET + if ($work_list[$bx]->{'type'} eq "GET"){ + if ($cx > 0){ + $params = $work_list[$bx]->{'url'} . "?" . $params; + } else { + $params = $work_list[$bx]->{'url'}; + } + $resp = g_get_page ( $ua, $params, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'}); + + # POST + } elsif ($work_list[$bx]->{'type'} eq "POST") { + $resp = g_post_page ( $ua, $work_list[$bx]->{'url'}, $params, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'}); + + # HEAD + } else { + if ($cx > 0){ + $params = $work_list[$bx]->{'url'} . "?" . $params; + } else { + $params = $work_list[$bx]->{'url'}; + } + $resp = g_head_page ( $ua, $params, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'}); + } + + # Check for errors. + if ($resp->code() == 500) { + $total_invalid_request++; + $bx = $config->{"work_items"}; + $check_string=0; + last; + } + + # Get string ? + if (defined($work_list[$bx]->{'get_string'})) { + my $as_string = $resp->as_string; + my $temp = $work_list[$bx]->{'get_string'}; + if ($as_string =~ m/($temp)/) { + $task_get_string[$thread_id] = $1; + } + } + + # Get response ? + if ($work_list[$bx]->{'get_content_advanced'} ne "") { + my $content = $resp->decoded_content; + my $temp = $work_list[$bx]->{'get_content_advanced'}; + if ($content =~ m/$temp/) { + $task_get_content[$thread_id] = $1 if defined ($1); + } + } elsif ($work_list[$bx]->{'get_content'} ne "") { + my $content = $resp->decoded_content; + my $temp = $work_list[$bx]->{'get_content'}; + if ($content =~ m/($temp)/) { + $task_get_content[$thread_id] = $1; + } + } + + # Resource bashing + if ((defined($work_list[$bx]->{'get_resources'})) && ($work_list[$bx]->{'get_resources'} == 1)){ + $total_requests = g_get_all_links ($config, $ua, $resp, $total_requests, $work_list[$bx]->{'url'}, $work_list[$bx]->{'headers'}, $work_list[$bx]->{'debug'}); + } + + # CHECKSTRING check + $cx = 0; + while (defined($work_list[$bx]->{'checkstring'}[$cx])) { + my $match_string = $work_list[$bx]->{'checkstring'}[$cx]; + my $as_string = $resp->as_string; + + my $guess = Encode::Guess::guess_encoding($as_string); + if (ref $guess) { + $as_string = $guess->decode($as_string); + } + unless (utf8::is_utf8($match_string)) { + utf8::decode($match_string); + } + + if ( $as_string =~ m/$match_string/i ){ + $total_valid_requests++; + } else { + $total_invalid_request++; + $bx = $config->{"work_items"}; # Abort session remaining request + $check_string=0; + } + $cx++; + } + + # CHECKNOTSTRING check + $cx = 0; + while (defined($work_list[$bx]->{'checknotstring'}[$cx])) { + my $match_string = $work_list[$bx]->{'checknotstring'}[$cx]; + my $as_string = $resp->as_string; + + my $guess = Encode::Guess::guess_encoding($as_string); + if (ref $guess) { + $as_string = $guess->decode($as_string); + } + unless (utf8::is_utf8($match_string)) { + utf8::decode($match_string); + } + + if ( $as_string !~ m/$match_string/i ){ + $total_valid_requests++; + } else { + $total_invalid_request++; + $bx = $config->{"work_items"}; # Abort session remaining request + $check_string=0; + } + $cx++; + } + + # Cookie carry on + if (defined ($work_list[$bx]->{'cookie'}) && $work_list[$bx]->{'cookie'} == 1){ + $cookies->extract_cookies($resp); + $ua->cookie_jar($cookies); + } + + # End just now by pressing CTRL-C or Kill Signal ! + #if ($goliat_abort == 1){ + #$ax = $config->{'retries'}; + #$bx = $config->{'items'}; + #goto END_LOOP; + #} + } #main work_detail loop + $ttime2 = Time::HiRes::gettimeofday(); + + $ttime_tot = $ttime2 - $ttime1; # Total time for this task + $task_time[$thread_id] = $ttime_tot; + $task_requests [$thread_id] = $total_requests; + if ($ttime_tot > 0 ){ + $task_reqsec[$thread_id] = $total_requests / $ttime_tot; + } else { + $task_reqsec[$thread_id] = $total_requests; + } + $task_fails[$thread_id] = $total_invalid_request; + if ($check_string == 0){ + $task_session_fails[$thread_id]++ + } + $task_sessions [$thread_id]++; + if ($task_sessions [$thread_id] > 0 ){ + $task_ssec[$thread_id] = $ttime_tot / $task_sessions [$thread_id]; + } else { + $task_ssec[$thread_id] = $task_sessions[$thread_id]; + } + sleep $config->{'ses_delay'}; + } +END_LOOP: + + $cookies->clear; + + if ( -f $cookie_file){ + unlink ($cookie_file); + } + + $task_end[$thread_id] = 1; +} + + +sub g_get_all_links { + my ($config, $ua, $response, $counter, $myurl, $headers, $debug) = @_; + my $html; + + if ($response->is_success) { + $html = $response->content; + } else { + return $counter; + } + # Beware this funcion, needs to be destroyed after use it !!! + my $parsed_html = parse_html($html); + #$ua->conn_cache(LWP::ConnCache->new()); + + my @url_list; + my $url = ""; + my $link; + my $full_url; + + for (@{ $parsed_html->extract_links( ) }) { + $link=$_->[0]; + if (($link =~ m/.png/i) || ($link =~ m/.gif/i) || ($link =~ m/.htm/i) || + ($link =~ m/.html/i) || ($link =~ m/.pdf/i) || ($link =~ m/.jpg/i) + || ($link =~ m/.ico/i)){ + $url = new URI::URL $link; + $full_url = $url->abs($myurl); + @url_list = $full_url; + } + + } + $parsed_html->delete; + my $ax = 0; + while ($full_url = pop(@url_list)) { + g_get_page ($ua, $full_url, $headers, $debug); + $counter++; + $ax++; + if ($ax > $config->{"max_depth"}){ + return $counter; + } + } + return $counter; +} + +sub g_get_page { + my $ua = $_[0]; + my $url = $_[1]; + my $headers = $_[2]; + my $debug = $_[3]; + + my $req = HTTP::Request->new(GET => $url); + $req->header('Accept' => 'text/html'); + while (my ($header, $value) = each %{$headers}) { + $req->header($header => $value); + } + my $response = $ua->request($req); + return $response if ($debug eq ''); + + # Debug + if (open (DEBUG, '>>', $debug . '.req')) { + print DEBUG "[Goliat debug " . time () . "]\n"; + print DEBUG $req->as_string (); + print "\n"; + close (DEBUG); + } + if (open (DEBUG, '>>', $debug . '.res')) { + print DEBUG "[Goliat debug " . time () . "]\n"; + print DEBUG $response->as_string (); + print "\n"; + close (DEBUG); + } + return $response; +} + +sub g_head_page { + my $ua = $_[0]; + my $url = $_[1]; + my $headers = $_[2]; + my $debug = $_[3]; + + my $req = HTTP::Request->new(HEAD => $url); + $req->header('Accept' => 'text/html'); + while (my ($header, $value) = each %{$headers}) { + $req->header($header => $value); + } + my $response = $ua->request($req); + return $response if ($debug eq ''); + + # Debug + if (open (DEBUG, '>>', $debug . '.req')) { + print DEBUG "[Goliat debug " . time () . "]\n"; + print DEBUG $req->as_string (); + print "\n"; + close (DEBUG); + } + if (open (DEBUG, '>>', $debug . '.res')) { + print DEBUG "[Goliat debug " . time () . "]\n"; + print DEBUG $response->as_string (); + print "\n"; + close (DEBUG); + } + return $response; +} + +sub g_post_page { + my $ua = $_[0]; + my $url = $_[1]; + my $content = $_[2]; + my $headers = $_[3]; + my $debug = $_[4]; + + my $req = HTTP::Request->new(POST => $url); + $req->content_type('application/x-www-form-urlencoded'); + $req->content ($content); + while (my ($header, $value) = each %{$headers}) { + $req->header($header => $value); + } + my $response = $ua->request($req); + return $response if ($debug eq ''); + + # Debug + if (open (DEBUG, '>>', $debug . '.req')) { + print DEBUG "[Goliat debug " . time () . "]\n"; + print DEBUG $req->as_string (); + print "\n"; + close (DEBUG); + } + if (open (DEBUG, '>>', $debug . '.res')) { + print DEBUG "[Goliat debug " . time () . "]\n"; + print DEBUG $response->as_string (); + print "\n"; + close (DEBUG); + } + return $response; +} + +# End of function declaration +# End of defined Code + +1; +__END__ diff --git a/pandora_server/lib/PandoraFMS/Goliat/GoliatTools.pm b/pandora_server/lib/PandoraFMS/Goliat/GoliatTools.pm new file mode 100755 index 0000000000..42e1cc0836 --- /dev/null +++ b/pandora_server/lib/PandoraFMS/Goliat/GoliatTools.pm @@ -0,0 +1,222 @@ +############################################################################### +# Goliath Tools Module +############################################################################### +# Copyright (c) 2007-2021 Artica Soluciones Tecnologicas S.L +# This code is not free or OpenSource. Please don't redistribute. +############################################################################### + +package Goliat::GoliatTools; + +use 5.008004; +use strict; +use warnings; +use integer; + +require Exporter; + +our @ISA = ("Exporter"); +our %EXPORT_TAGS = ( 'all' => [ qw() ] ); +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); +our @EXPORT = qw( + g_clean_string + g_clean_string_unicode + g_random_string + g_trash_ascii + g_trash_unicode + g_unicode ); + +# Delaracion de funciones publicas + +############################################################################## +# clean_string (string) - Purge a string for any forbidden characters (esc, etc) +############################################################################## +sub g_clean_string { + my $micadena; + $micadena = $_[0]; + $micadena =~ s/[^\-\:\;\.\,\_\s\a\*\=\(\)a-zA-Z0-9]/ /g; + $micadena =~ s/[\n\l\f]/ /g; + return $micadena; +} + +############################################################################## +# limpia_cadena_unicode (string) - Purge a string for any unicode character +############################################################################## +sub g_clean_string_unicode { + my $micadena; + $micadena = $_[0]; + $micadena =~ s/[%]/%%/g; + return $micadena; +} + +############################################################################# +# Hex converter - Convert dec value in hex representation (00 - FF) +############################################################################# +sub g_decToHex { #return a 16bit (o uno de 8bit) hex value + my @hex = (0,1,2,3,4,5,6,7,8,9,"A","B","C","D","E","F"); + my @dec = @_; + my $s3 = $hex[($dec[0]/4096)%16]; + my $s2 = $hex[($dec[0]/256)%16]; + my $s1 = $hex[($dec[0]/16)%16]; + my $s0 = $hex[$dec[0]%16]; + return "$s1$s0"; +} + +############################################################################# +# unicode - Generate unicode string (recursive) +############################################################################# + +sub g_unicode { + my $config_word = $_[0]; + my $config_depth = $_[1]; + my $config_char="%"; + if ($config_depth == 0) { + return $config_word; + } + + my $a; + my $pos=0; + my $output=""; + my $len; + + for ($a=0;$a<$config_depth;$a++){ + $len = length($config_word); + while ($pos < $len ) { + my $item; + $item = substr($config_word,$pos,1); + $output = $output.$config_char.decToHex(ord($item)); + $pos++; + } + $config_word = $output; + } + return $output +} + +############################################################################# +# trash - Generate "unicode" style trash string +############################################################################# + +sub g_trash_unicode { + my $config_depth = $_[0]; + my $config_char="%"; + my $a; + my $output; + + for ($a=0;$a<$config_depth;$a++){ + $output = $output.$config_char.decToHex(int(rand(25)+97)); + } + return $output +} + +############################################################################# +# trash_ascii - Generate ASCII random strings +############################################################################# + +sub g_trash_ascii { + my $config_depth = $_[0]; + my $config_char="%"; + my $a; + my $output; + + for ($a=0;$a<$config_depth;$a++){ + $output = $output.chr(int(rand(25)+97)); + } + return $output +} + +############################################################################# +# random_string (min, max, type) - Generate ASCII alphanumeric string, +# from min and max +############################################################################# + +sub g_random_string { + my $config_min = $_[0]; + my $config_max = $_[1]; + my $config_type = $_[2]; # alphanumeric, alpha, numeric, lowalpha, highalpha + my $a; + my $output = ""; + my @valid_chars; + my $rango; + + # First fill list of valid chars (A-Z, a-z, 0-9) + if (($config_type eq "alphanumeric") || ($config_type eq "numeric")){ + for ($a=48;$a<58;$a++){ # numeric + push @valid_chars, chr($a); + } + } + + if (($config_type eq "alphanumeric") || ($config_type eq "alpha") || + ($config_type eq "highalpha") || ($config_type eq "lowalpha") ){ + if (($config_type eq "alphanumeric") || ($config_type eq "highalpha") || ($config_type eq "alpha")){ + for ($a=65;$a<91;$a++){ # alpha (CAPS) + push @valid_chars, chr($a); + } + } + if (($config_type eq "alphanumeric") || ($config_type eq "lowalpha") || ($config_type eq "alpha")){ + for ($a=97;$a<123;$a++){ # alpha (low) + push @valid_chars, chr($a); + } + } + } + + $rango = @valid_chars; + + # Fill min. value + for ($a=0;$a<$config_min;$a++){ + $output = $output.$valid_chars[(int(rand($rango)))]; + } + + # Fill to max; + if (($config_max - $config_min) != 0){ + for ($a=0;$aslerena@Egmail.com + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2005 by Sancho Lerena + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.8.4 or, +at your option, any later version of Perl 5 you may have available. + +Licenced under GPL + +=cut diff --git a/pandora_server/lib/PandoraFMS/WebServer.pm b/pandora_server/lib/PandoraFMS/WebServer.pm new file mode 100644 index 0000000000..5b08e26b9d --- /dev/null +++ b/pandora_server/lib/PandoraFMS/WebServer.pm @@ -0,0 +1,294 @@ +package PandoraFMS::WebServer; + +########################################################################## +# Pandora FMS Web Server. +########################################################################## +# Copyright (c) 2007-2021 Artica Soluciones Tecnologicas S.L +# This code is not free or OpenSource. Please don't redistribute. +########################################################################## + +use strict; +use warnings; + +use threads; +use threads::shared; +use Thread::Semaphore; + +use File::Temp qw(tempfile); +use HTML::Entities; +use POSIX qw(strftime); + +# Default lib dir for RPM and DEB packages +use lib '/usr/lib/perl5'; + +use PandoraFMS::Goliat::GoliatTools; +use PandoraFMS::Goliat::GoliatConfig; + +use PandoraFMS::Tools; +use PandoraFMS::DB; +use PandoraFMS::Core; +use PandoraFMS::ProducerConsumerServer; + +# Inherits from PandoraFMS::ProducerConsumerServer +our @ISA = qw(PandoraFMS::ProducerConsumerServer); + +# Global variables +my @TaskQueue :shared; +my %PendingTasks :shared; +my $Sem :shared; +my $TaskSem :shared; + +######################################################################################## +# Web Server class constructor. +######################################################################################## +sub new ($$;$) { + my ($class, $config, $dbh) = @_; + + return undef unless defined ($config->{'webserver'}) and ($config->{'webserver'} == 1); + + # Initialize semaphores and queues + @TaskQueue = (); + %PendingTasks = (); + $Sem = Thread::Semaphore->new; + $TaskSem = Thread::Semaphore->new (0); + + # Call the constructor of the parent class + my $self = $class->SUPER::new($config, WEBSERVER, \&PandoraFMS::WebServer::data_producer, \&PandoraFMS::WebServer::data_consumer, $dbh); + + bless $self, $class; + return $self; +} + +############################################################################### +# Run. +############################################################################### +sub run ($) { + my $self = shift; + my $pa_config = $self->getConfig (); + + print_message ($pa_config, " [*] Starting " . $pa_config->{'rb_product_name'} . " Web Server.", 1); + + # Use Goliat with CURL + if ($pa_config->{'web_engine'} eq 'curl') { + require Goliat::GoliatCURL; + Goliat::GoliatCURL->import; + + # Check for CURL binary + if (system ("curl -V >$DEVNULL 2>&1") >> 8 != 0) { + logger ($pa_config, ' [E] CURL binary not found. Install CURL or uncomment the web_engine configuration token to use LWP.', 1); + print_message ($pa_config, ' [E] CURL binary not found. Install CURL or uncomment the web_engine configuration token to use LWP.', 1); + return undef; + } + # Check for pandora_exec binary + if (system ("\"" . $pa_config->{'plugin_exec'} . "\" 10 echo >$DEVNULL 2>&1") >> 8 != 0) { + logger ($pa_config, ' [E] ' . $pa_config->{'plugin_exec'} . ' not found. Please install it or add it to the PATH.', 1); + print_message ($pa_config, ' [E] ' . $pa_config->{'plugin_exec'} . ' not found. Please install it or add it to the PATH.', 1); + return undef; + } + } + # Use LWP by default + else { + require Goliat::GoliatLWP; + Goliat::GoliatLWP->import; + + if (! LWP::UserAgent->can('ssl_opts')) { + logger($pa_config, "LWP version $LWP::VERSION does not support SSL. Make sure version 6.0 or higher is installed.", 1); + print_message ($pa_config, " [W] LWP version $LWP::VERSION does not support SSL. Make sure version 6.0 or higher is installed.", 1); + } + } + + $self->setNumThreads ($pa_config->{'web_threads'}); + $self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem); +} + +############################################################################### +# Data producer. +############################################################################### +sub data_producer ($) { + my $self = shift; + my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ()); + + my @tasks; + my @rows; + + if (pandora_is_master($pa_config) == 0) { + @rows = get_db_rows ($dbh, 'SELECT tagente_modulo.id_agente_modulo, tagente_modulo.flag, tagente_estado.current_interval + tagente_estado.last_execution_try AS time_left, last_execution_try + FROM tagente, tagente_modulo, tagente_estado + WHERE server_name = ? + AND tagente_modulo.id_agente = tagente.id_agente + AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo + AND tagente.disabled = 0 + AND tagente_modulo.id_modulo = 7 + AND tagente_modulo.disabled = 0 + AND (tagente_modulo.flag = 1 OR ((tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP())) + ORDER BY tagente_modulo.flag DESC, time_left ASC, last_execution_try ASC ', $pa_config->{'servername'}); + } else { + @rows = get_db_rows ($dbh, 'SELECT DISTINCT(tagente_modulo.id_agente_modulo), tagente_modulo.flag, tagente_estado.current_interval + tagente_estado.last_execution_try AS time_left, last_execution_try + FROM tagente, tagente_modulo, tagente_estado, tserver + WHERE ((server_name = ?) OR (server_name = ANY(SELECT server_name FROM tserver WHERE status = 0 AND server_type = ?))) + AND tagente_modulo.id_agente = tagente.id_agente + AND tagente.disabled = 0 + AND tagente_modulo.disabled = 0 + AND tagente_modulo.id_modulo = 7 + AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo + AND ((tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP() OR tagente_modulo.flag = 1 ) + ORDER BY tagente_modulo.flag DESC, time_left ASC, last_execution_try ASC', $pa_config->{'servername'}, WEBSERVER); + } + + foreach my $row (@rows) { + + # Reset forced execution flag + if ($row->{'flag'} == 1) { + db_do ($dbh, 'UPDATE tagente_modulo SET flag = 0 WHERE id_agente_modulo = ?', $row->{'id_agente_modulo'}); + } + + push (@tasks, $row->{'id_agente_modulo'}); + } + + return @tasks; +} + +############################################################################### +# Data consumer. +############################################################################### +sub data_consumer ($$) { + my ($self, $module_id) = @_; + my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ()); + our (@task_fails, @task_time, @task_ssec, @task_get_content); # Defined in GoliatLWP.pm and GoliatCURL. + + # Retrieve module data + my $module = get_db_single_row ($dbh, 'SELECT * FROM tagente_modulo WHERE id_agente_modulo = ?', $module_id); + return unless defined ($module); + + # Retrieve agent data + my $agent = get_db_single_row ($dbh, 'SELECT * FROM tagente WHERE id_agente = ?', $module->{'id_agente'}); + return unless defined $agent; + + # Save Goliat config to a temporary file + my ($fh, $temp_file) = tempfile(); + return unless defined ($fh); + + # Read the Goliat task + my $task = safe_output($module->{'plugin_parameter'}); + + # Delete any carriage returns + $task =~ s/\r//g; + + # Agent and module macros + my %macros = (_agent_ => (defined ($agent)) ? $agent->{'alias'} : '', + _agentdescription_ => (defined ($agent)) ? $agent->{'comentarios'} : '', + _agentstatus_ => (defined ($agent)) ? get_agent_status ($pa_config, $dbh, $agent->{'id_agente'}) : '', + _address_ => (defined ($agent)) ? $agent->{'direccion'} : '', + _module_ => (defined ($module)) ? $module->{'nombre'} : '', + _modulegroup_ => (defined ($module)) ? (get_module_group_name ($dbh, $module->{'id_module_group'}) || '') : '', + _moduledescription_ => (defined ($module)) ? $module->{'descripcion'} : '', + _modulestatus_ => (defined ($module)) ? get_agentmodule_status($pa_config, $dbh, $module->{'id_agente_modulo'}) : '', + _moduletags_ => (defined ($module)) ? pandora_get_module_url_tags ($pa_config, $dbh, $module->{'id_agente_modulo'}) : '', + _id_agent_ => (defined ($module)) ? $module->{'id_agente'} : '', + _interval_ => (defined ($module) && $module->{'module_interval'} != 0) ? $module->{'module_interval'} : (defined ($agent)) ? $agent->{'intervalo'} : '', + _target_ip_ => (defined ($agent)) ? $agent->{'direccion'} : '', + _target_port_ => (defined ($module)) ? $module->{'tcp_port'} : '', + _policy_ => (defined ($module)) ? enterprise_hook('get_policy_name', [$dbh, $module->{'id_policy_module'}]) : '', + _plugin_parameters_ => (defined ($module)) ? $module->{'plugin_parameter'} : '', + _email_tag_ => (defined ($module)) ? pandora_get_module_email_tags ($pa_config, $dbh, $module->{'id_agente_modulo'}) : '', + _phone_tag_ => (defined ($module)) ? pandora_get_module_phone_tags ($pa_config, $dbh, $module->{'id_agente_modulo'}) : '', + _name_tag_ => (defined ($module)) ? pandora_get_module_tags ($pa_config, $dbh, $module->{'id_agente_modulo'}) : '', + ); + $task = subst_alert_macros ($task, \%macros); + + # Goliat has some trouble parsing conf files without the newlines + $fh->print ("\n\n" . $task . "\n\n"); + close ($fh); + + # Global vars needed by Goliat + my (%config, @work_list, $check_string); + + # Goliat config defaults + $config{'verbosity'} = 1; + $config{'slave'} = 0; + $config{'port'} = 80; + $config{'log_file'} = "$DEVNULL"; + $config{'log_output'} = 0; + $config{'log_http'} = 0; + $config{'work_items'} = 0; + $config{'config_file'} = $temp_file; + $config{'agent'} = safe_output($module->{'plugin_user'}); + if ($module->{'max_retries'} != 0) { + $config{'retries'} = $module->{'max_retries'}; + } + if ($module->{'max_timeout'} != 0) { + $config{'timeout'} = $module->{'max_timeout'}; + } else { + $config{'timeout'} = $pa_config->{'web_timeout'}; + } + + $config{'proxy'} = $module->{'snmp_oid'}; + $config{'auth_user'} = safe_output($module->{'tcp_send'}); + $config{'auth_pass'} = safe_output($module->{'tcp_rcv'}); + $config{'auth_server'} = $module->{'ip_target'}; + $config{'auth_realm'} = $module->{'snmp_community'}; + $config{'http_check_type'} = $module->{'tcp_port'}; + $config{'moduleId'} = $module_id; + $config{'dbh'} = $dbh; + + # Pandora FMS variables passed to Goliat. + $config{'plugin_exec'} = $pa_config->{'plugin_exec'}; + + eval { + # Load Goliat config + g_load_config(\%config, \@work_list); + + # Run Goliat task + g_http_task (\%config, 0, @work_list); + }; + + if ($@) { + pandora_update_module_on_error ($pa_config, $module, $dbh); + unlink ($temp_file); + return; + } + + unlink ($temp_file); + + my $utimestamp = time (); + my $timestamp = strftime ("%Y-%m-%d %H:%M:%S", localtime($utimestamp)); + + # Get module type + my $module_type = get_db_value ($dbh, 'SELECT nombre FROM ttipo_modulo WHERE id_tipo = ?', $module->{'id_tipo_modulo'}); + + # Get data from Goliat + my $module_data; + { + no strict 'vars'; + if ($module_type eq 'web_proc') { + $module_data = ($task_fails[0] == 0 && $task_get_content[0] ne "") ? 1 : 0; + } + elsif ($module_type eq 'web_data') { + $module_data = $task_ssec[0]; + } elsif ($module_type eq 'web_server_status_code_string') { + my @resp_lines = split "\r\n", $task_get_content[0]; + $module_data = $resp_lines[0]; + } else { + $module_data = $task_get_content[0]; + } + } + + my %data = ("data" => $module_data); + pandora_process_module ($pa_config, \%data, undef, $module, $module_type, $timestamp, $utimestamp, $self->getServerID (), $dbh); + + my $agent_os_version = get_db_value ($dbh, 'SELECT os_version FROM tagente WHERE id_agente = ?', $module->{'id_agente'}); + + if (! defined ($agent_os_version) || $agent_os_version eq '') { + $agent_os_version = $pa_config->{'servername'}.'_Web'; + } + + # Todo: Implement here + # 1. Detect if exists a module with the same name, but with type generic_string. + # 2. If not, create the module, get the id's + # 3. Insert data coming from $task_get_string in that module + + pandora_update_agent ($pa_config, $timestamp, $module->{'id_agente'}, undef, undef, -1, $dbh); +} + +1; +__END__ From d43c51cc665d3278ae080afb37b31408d884caa1 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 22 Mar 2021 17:37:15 +0100 Subject: [PATCH 2/7] WIP: Backup upload --- .../extras/delete_files/delete_files.txt | 6 +- .../agentes/module_manager_editor_web.php | 468 ++++++++++++++++++ .../include/ajax/web_server_module_debug.php | 74 +++ .../class/WebServerModuleDebug.class.php | 407 +++++++++++++++ .../include/styles/WebServerModuleDebug.css | 10 + 5 files changed, 964 insertions(+), 1 deletion(-) create mode 100644 pandora_console/godmode/agentes/module_manager_editor_web.php create mode 100644 pandora_console/include/ajax/web_server_module_debug.php create mode 100644 pandora_console/include/class/WebServerModuleDebug.class.php create mode 100644 pandora_console/include/styles/WebServerModuleDebug.css diff --git a/pandora_console/extras/delete_files/delete_files.txt b/pandora_console/extras/delete_files/delete_files.txt index 7832042fda..7c4d3b401b 100644 --- a/pandora_console/extras/delete_files/delete_files.txt +++ b/pandora_console/extras/delete_files/delete_files.txt @@ -78,4 +78,8 @@ pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/Goliat/GoliatCURL.pm pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/Goliat/GoliatConfig.pm pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/Goliat/GoliatLWP.pm pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/Goliat/GoliatTools.pm -pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/PandoraFMS/WebServer.pm \ No newline at end of file +pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/PandoraFMS/WebServer.pm +pandora_console/enterprise/godmode/agentes/module_manager_editor_web.php +pandora_console/enterprise/include/ajax/web_server_module_debug.php +pandora_console/enterprise/include/class/WebServerModuleDebug.class.php +pandora_console/enterprise/include/styles/WebServerModuleDebug.css \ No newline at end of file diff --git a/pandora_console/godmode/agentes/module_manager_editor_web.php b/pandora_console/godmode/agentes/module_manager_editor_web.php new file mode 100644 index 0000000000..a15da07caa --- /dev/null +++ b/pandora_console/godmode/agentes/module_manager_editor_web.php @@ -0,0 +1,468 @@ + 'modal', + 'style' => 'display: none;', + ] +); + +require_once $config['homedir'].'/include/ajax/web_server_module_debug.php'; + +define('ID_NETWORK_COMPONENT_TYPE', 7); + +if (!$tcp_port && !$id_agent_module) { + $tcp_port = 80; +} + +// plugin_server is the browser id +if ($plugin_user == '' && !$id_agent_module) { + $plugin_user = get_product_name().' / Webcheck'; +} + +// plugin_server is the referer +if ($plugin_pass == '' && !$id_agent_module) { + $plugin_pass = 1; +} + +if (empty($update_module_id)) { + // Function in module_manager_editor_common.php + add_component_selection(ID_NETWORK_COMPONENT_TYPE); +} else { + // TODO: Print network component if available +} + +$data = []; +$data[0] = __('Web checks'); + +$adopt = false; +if (isset($id_agent_module)) { + $adopt = policies_is_module_adopt($id_agent_module); +} + +$id_policy_module = (int) get_parameter('id_policy_module', ''); +if ($id_policy_module) { + $module = policies_get_module($id_policy_module); + $plugin_parameter = $module['plugin_parameter']; +} + +if (!$adopt) { + $data[1] = html_print_textarea( + 'plugin_parameter', + 15, + 65, + $plugin_parameter, + $disabledTextBecauseInPolicy, + true + ); +} else { + $data[1] = html_print_textarea( + 'plugin_parameter', + 15, + 65, + $plugin_parameter, + false, + true + ); +} + +$table_simple->colspan['web_checks'][1] = 2; + +// Disable debug button if module has not started. +if ($id_agent_module > 0 + && db_get_value_filter( + 'debug_content', + 'tagente_modulo', + ['id_agente_modulo' => $id_agent_module] + ) !== null +) { + $disableDebug = false; + $hintDebug = __('Debug remotely this module'); +} else { + $disableDebug = true; + $hintDebug = __('Debug this module once it has been initialized'); +} + +$suc_err_check = ' '; +$suc_err_check .= ' '; +$data[2] = html_print_button( + __('Load basic'), + 'btn_loadbasic', + false, + '', + 'class="sub config"', + true +).ui_print_help_tip(__('Load a basic structure on Web Checks'), true); +$data[2] .= '

'.html_print_button( + __('Check'), + 'btn_checkconf', + false, + '', + 'class="sub upd"', + true +).ui_print_help_tip(__('Check the correct structure of the WebCheck'), true).$suc_err_check; +$data[2] .= '

'.html_print_button( + __('Debug'), + 'btn_debugModule', + $disableDebug, + '', + 'class="sub config" onClick="loadDebugWindow()"', + true +).ui_print_help_tip($hintDebug, true); + + +push_table_simple($data, 'web_checks'); + +$http_checks_type = [ + 0 => 'Anyauth', + 1 => 'NTLM', + 2 => 'DIGEST', + 3 => 'BASIC', +]; + +$data = []; +$data[0] = __('Check type'); +$data[1] = html_print_select($http_checks_type, 'tcp_port', $tcp_port, false, '', '', true, false, false); + +push_table_advanced($data, 'web_0'); + +$data = []; +$data[0] = __('Requests'); +$data[1] = html_print_input_text('plugin_pass', $plugin_pass, '', 10, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy); +$data[2] = ''; +$data[3] = __('Agent browser id'); +$data[4] = html_print_input_text('plugin_user', $plugin_user, '', 30, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy); + +push_table_advanced($data, 'web_1'); + +$data = []; +$data[0] = __('HTTP auth (login)'); +$data[1] = html_print_input_text('http_user', $plugin_parameter_http_user, '', 10, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy); +$data[2] = ''; +$data[3] = __('HTTP auth (password)'); +$data[4] = html_print_input_password('http_pass', $plugin_parameter_http_pass, '', 30, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy); + +push_table_advanced($data, 'web_2'); + +$data = []; + +$data[0] = __('Proxy URL'); +$data[1] = html_print_input_text('snmp_oid', $snmp_oid, '', 30, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy); +$data[2] = $data[3] = $data[4] = ''; +push_table_advanced($data, 'web_3'); + +$data = []; + +$data[0] = __('Proxy auth (login)'); +$data[1] = html_print_input_text('tcp_send', $tcp_send, '', 30, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy); + +$data[2] = ''; +$data[3] = __('Proxy auth (pass)'); +$data[4] = html_print_input_password('tcp_rcv', $tcp_rcv, '', 30, 0, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy); + +push_table_advanced($data, 'web_4'); + +$data = []; + +$data[0] = __('Proxy auth (server)'); +$data[1] = html_print_input_text('ip_target', $ip_target, '', 30, 100, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy); + +$data[2] = ''; +$data[3] = __('Proxy auth (realm)'); +$data[4] = html_print_input_text('snmp_community', $snmp_community, '', 30, 100, true, $disabledBecauseInPolicy, false, '', $classdisabledBecauseInPolicy); + +push_table_advanced($data, 'web_5'); + +// Add some strings to be used from javascript +$texts = [ + 'lines_before_begin' => __('First line must be "task_begin"'), + 'missed_begin' => __('Webchecks configuration is empty'), + 'missed_end' => __('Last line must be "task_end"'), + 'lines_after_end' => __('Last line must be "task_end"'), + 'unknown_token' => __("There is a line with a unknown token 'token_fail'."), + 'missed_get_post' => __("There isn't get or post"), + 'correct' => __('Web checks are built correctly'), +]; + +foreach ($texts as $code => $text) { + echo ''; +} +?> + \ No newline at end of file diff --git a/pandora_console/include/ajax/web_server_module_debug.php b/pandora_console/include/ajax/web_server_module_debug.php new file mode 100644 index 0000000000..d243257cbd --- /dev/null +++ b/pandora_console/include/ajax/web_server_module_debug.php @@ -0,0 +1,74 @@ + '[WebServerModuleDebug]'.$e->getMessage() ]); + exit; + } else { + echo '[WebServerModuleDebug]'.$e->getMessage(); + } + + // Stop this execution, but continue 'globally'. + return; +} + +// AJAX controller. +if (is_ajax()) { + $method = get_parameter('method'); + + if (method_exists($obj, $method) === true) { + $obj->{$method}(); + } else { + $obj->error('Method not found. ['.$method.']'); + } + + // Stop any execution. + exit; +} else { + // Run. + $obj->run(); +} diff --git a/pandora_console/include/class/WebServerModuleDebug.class.php b/pandora_console/include/class/WebServerModuleDebug.class.php new file mode 100644 index 0000000000..e0e6f23c84 --- /dev/null +++ b/pandora_console/include/class/WebServerModuleDebug.class.php @@ -0,0 +1,407 @@ + 'noaccess']); + } + + include 'general/noaccess.php'; + exit; + } + + // Parameter assigments. + $this->ajaxController = $ajaxController; + $this->query = ''; + $this->idAgentModule = $idAgentModule; + // Hardcoded request timeout. + $this->requestTimeout = 15; + + return $this; + + } + + + /** + * Run Module Debug window. + * + * @return void + */ + public function run() + { + // Added all necessary basic files for QueryResult. + ui_require_css_file('ace'); + ui_require_javascript_file('ace', 'include/javascript/ace/'); + // Load Javascript. + $this->loadJS(); + // CSS. + ui_require_css_file('wizard'); + ui_require_css_file('discovery'); + // Specific CSS for this feature. + ui_require_css_file('WebServerModuleDebug', '/include/styles/', true); + + } + + + /** + * Show the modal with the QueryResult. + * + * @return void + */ + public function showWebServerDebug() + { + // Show QueryResult editor. + ui_query_result_editor('webserverdebug'); + // Spinner for wait loads. + html_print_div( + [ + 'id' => 'WebServerDebugSpinner', + 'style' => 'visibility: hidden;', + 'content' => __('Performing query. Please wait.').' '.html_print_image('images/spinner.gif', true), + ] + ); + ?> + + + + $this->idAgentModule, + ] + ); + + $this->query = ($outputDebugQuery !== false) ? $outputDebugQuery : __('Please, wait for a first execution of module'); + + return $this->query; + } + + + /** + * Perform the cURL execution. + * + * @return void + * @throws Exception $e Error message. + */ + public function executeCommand() + { + try { + $executionForPerform = io_safe_output(get_parameter('text')); + // If the execution comes empty. + if (empty($executionForPerform) === true) { + throw new Exception('Execution failed'); + } + + // For security reasons, only allow the 'curl' command. + $executionForPerform = strstr($executionForPerform, 'curl'); + // Avoid pipes or concatenation of commands. + $unallowedChars = [ + '|', + '&', + '||', + '&&', + ';', + '\n', + ]; + $executionForPerform = str_replace( + $unallowedChars, + ' ', + $executionForPerform + ); + // Set execution timeout. + $executionForPerform .= sprintf( + $executionForPerform.' -m %d', + $this->requestTimeout + ); + + // Perform the execution. + system($executionForPerform, $returnCode); + // If execution does not got well. + if ($returnCode != 0) { + switch ($returnCode) { + case '2': + throw new Exception('Failed to initialize. Review the syntax.'); + + case '3': + throw new Exception('URL malformed. The syntax was not correct.'); + + case '5': + throw new Exception('Couldn\'t resolve proxy. The given proxy host could not be resolved.'); + + case '6': + throw new Exception('Couldn\'t resolve host. The given remote host could not be resolved.'); + + case '7': + throw new Exception('Failed to connect to host.'); + + default: + throw new Exception('Failed getting data.'); + } + } + } catch (Exception $e) { + // Show execution error message. + echo __($e->getMessage()); + } + + exit; + } + + + /** + * Loads JS and return code. + * + * @return string + */ + public function loadJS() + { + $str = ''; + ob_start(); + ?> + + + + Date: Mon, 22 Mar 2021 17:39:24 +0100 Subject: [PATCH 3/7] WIP: Backup upload --- .../godmode/agentes/module_manager.php | 164 ++++++++++++------ .../godmode/agentes/module_manager_editor.php | 16 ++ pandora_server/bin/pandora_server | 2 + pandora_server/lib/PandoraFMS/WebServer.pm | 20 ++- 4 files changed, 144 insertions(+), 58 deletions(-) diff --git a/pandora_console/godmode/agentes/module_manager.php b/pandora_console/godmode/agentes/module_manager.php index 91c6395b96..6f2747de19 100644 --- a/pandora_console/godmode/agentes/module_manager.php +++ b/pandora_console/godmode/agentes/module_manager.php @@ -1,22 +1,38 @@ '; } else { echo '
'; @@ -73,25 +89,31 @@ echo '
'; $network_available = db_get_sql( 'SELECT count(*) FROM tserver - WHERE server_type = 1' + WHERE server_type = '.SERVER_TYPE_NETWORK ); // POSTGRESQL AND ORACLE COMPATIBLE. $wmi_available = db_get_sql( 'SELECT count(*) FROM tserver - WHERE server_type = 6' + WHERE server_type = '.SERVER_TYPE_WMI ); // POSTGRESQL AND ORACLE COMPATIBLE. $plugin_available = db_get_sql( 'SELECT count(*) FROM tserver - WHERE server_type = 4' + WHERE server_type = '.SERVER_TYPE_PLUGIN ); // POSTGRESQL AND ORACLE COMPATIBLE. $prediction_available = db_get_sql( 'SELECT count(*) FROM tserver - WHERE server_type = 5' + WHERE server_type = '.SERVER_TYPE_PREDICTION +); +// POSTGRESQL AND ORACLE COMPATIBLE. +$web_available = db_get_sql( + 'SELECT count(*) +FROM tserver +WHERE server_type = '.SERVER_TYPE_WEB ); // POSTGRESQL AND ORACLE COMPATIBLE. // Development mode to use all servers. @@ -122,6 +144,10 @@ if ($prediction_available) { $modules['predictionserver'] = __('Create a new prediction server module'); } +if ($web_available) { + $modules['webserver'] = __('Create a new web Server module'); +} + if (enterprise_installed()) { set_enterprise_module_types($modules); } @@ -298,6 +324,7 @@ if ($module_action === 'delete') { switch ($config['dbtype']) { case 'mysql': case 'postgresql': + default: $result = db_process_sql_delete( 'tagente_estado', ['id_agente_modulo' => $id_agent_module_del] @@ -388,10 +415,8 @@ if ($module_action === 'delete') { } } - // Check for errors. - if ($error != 0) { - } else { + if ((int) $error == 0) { $count_correct_delete_modules++; } } @@ -489,6 +514,7 @@ switch ($sortField) { switch ($config['dbtype']) { case 'mysql': case 'postgresql': + default: $order[] = [ 'field' => 'tagente_modulo.nombre', 'order' => 'ASC', @@ -509,6 +535,7 @@ switch ($sortField) { switch ($config['dbtype']) { case 'mysql': case 'postgresql': + default: $order[] = [ 'field' => 'tagente_modulo.nombre', 'order' => 'DESC', @@ -523,6 +550,10 @@ switch ($sortField) { break; } break; + + default: + // Do none. + break; } break; @@ -543,6 +574,10 @@ switch ($sortField) { 'order' => 'DESC', ]; break; + + default: + // Do none. + break; } break; @@ -563,6 +598,10 @@ switch ($sortField) { 'order' => 'DESC', ]; break; + + default: + // Do none. + break; } break; @@ -583,6 +622,10 @@ switch ($sortField) { 'order' => 'DESC', ]; break; + + default: + // Do none. + break; } break; @@ -598,6 +641,7 @@ switch ($sortField) { switch ($config['dbtype']) { case 'mysql': case 'postgresql': + default: $order[] = [ 'field' => 'nombre', 'order' => 'ASC', @@ -622,7 +666,7 @@ if (!empty($order)) { $first = true; foreach ($order as $ord) { - if ($first) { + if ($first === true) { $first = false; } else { $order_sql .= ','; @@ -635,31 +679,35 @@ foreach ($order as $ord) { $limit = (int) $config['block_size']; $offset = (int) get_parameter('offset'); -$params = ($checked) ? 'tagente_modulo.*, tmodule_group.*' : implode( - ',', - [ - 'tagente_modulo.id_agente_modulo', - 'id_tipo_modulo', - 'descripcion', - 'nombre', - 'max', - 'min', - 'module_interval', - 'id_modulo', - 'id_module_group', - 'disabled', - 'max_warning', - 'min_warning', - 'str_warning', - 'max_critical', - 'min_critical', - 'str_critical', - 'quiet', - 'critical_inverse', - 'warning_inverse', - 'id_policy_module', - ] -); +if ((bool) $checked === true) { + $params = 'tagente_modulo.*, tmodule_group.*'; +} else { + $params = implode( + ',', + [ + 'tagente_modulo.id_agente_modulo', + 'id_tipo_modulo', + 'descripcion', + 'nombre', + 'max', + 'min', + 'module_interval', + 'id_modulo', + 'id_module_group', + 'disabled', + 'max_warning', + 'min_warning', + 'str_warning', + 'max_critical', + 'min_critical', + 'str_critical', + 'quiet', + 'critical_inverse', + 'warning_inverse', + 'id_policy_module', + ] + ); +} $where = sprintf('delete_pending = 0 AND id_agente = %s', $id_agente); @@ -686,7 +734,11 @@ if (isset($config['paginate_module'])) { if ($paginate_module) { if (!isset($limit_sql)) { - $limit_sql = " LIMIT $offset, $limit "; + $limit_sql = sprintf( + 'LIMIT %s, %s', + $offset, + $limit + ); } } else { $limit_sql = ''; @@ -732,7 +784,13 @@ if ($modules === false) { } // Prepare pagination. -$url = '?'.'sec=gagente&'.'tab=module&'.'sec2=godmode/agentes/configurar_agente&'.'id_agente='.$id_agente.'&'.'sort_field='.$sortField.'&'.'&sort='.$sort.'&'.'search_string='.urlencode($search_string); +$url = sprintf( + '?sec=gagente&tab=module&sec2=godmode/agentes/configurar_agente&id_agente=%s&sort_field=%s&sort=%s&search_string=%s', + $id_agente, + $sortField, + $sort, + urlencode($search_string) +); if ($paginate_module) { ui_pagination($total_modules, $url); diff --git a/pandora_console/godmode/agentes/module_manager_editor.php b/pandora_console/godmode/agentes/module_manager_editor.php index c350866cf0..1310fa80bb 100644 --- a/pandora_console/godmode/agentes/module_manager_editor.php +++ b/pandora_console/godmode/agentes/module_manager_editor.php @@ -682,6 +682,22 @@ switch ($moduletype) { include 'module_manager_editor_wmi.php'; break; + case 'webserver': + case MODULE_WEB: + $moduletype = MODULE_WEB; + // Remove content of $ip_target when it is ip_agent because + // it is used as HTTP auth (server) ....ONLY IN NEW MODULE!!! + if (empty($id_agent_module) + && ($ip_target === agents_get_address($id_agente)) + ) { + $ip_target = ''; + } + + $categories = [9]; + include 'module_manager_editor_common.php'; + include 'module_manager_editor_web.php'; + break; + // WARNING: type 7 is reserved on enterprise. default: if (enterprise_include( diff --git a/pandora_server/bin/pandora_server b/pandora_server/bin/pandora_server index d82944f93b..44d1e4dd33 100755 --- a/pandora_server/bin/pandora_server +++ b/pandora_server/bin/pandora_server @@ -38,6 +38,7 @@ use PandoraFMS::DiscoveryServer; use PandoraFMS::WMIServer; use PandoraFMS::PluginServer; use PandoraFMS::PredictionServer; +use PandoraFMS::WebServer; # Constants for Win32 services. use constant WIN32_SERVICE_STOPPED => 0x01; @@ -123,6 +124,7 @@ sub pandora_startup () { push (@Servers, new PandoraFMS::WMIServer (\%Config, $DBH)); push (@Servers, new PandoraFMS::PluginServer (\%Config, $DBH)); push (@Servers, new PandoraFMS::PredictionServer (\%Config, $DBH)); + push (@Servers, new PandoraFMS::WebServer (\%Config, $DBH)); } else { # Metaconsole service modules are run by the prediction server push (@Servers, new PandoraFMS::PredictionServer (\%Config, $DBH)); diff --git a/pandora_server/lib/PandoraFMS/WebServer.pm b/pandora_server/lib/PandoraFMS/WebServer.pm index 5b08e26b9d..6723848d9f 100644 --- a/pandora_server/lib/PandoraFMS/WebServer.pm +++ b/pandora_server/lib/PandoraFMS/WebServer.pm @@ -1,10 +1,20 @@ package PandoraFMS::WebServer; - ########################################################################## # Pandora FMS Web Server. +# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org ########################################################################## # Copyright (c) 2007-2021 Artica Soluciones Tecnologicas S.L -# This code is not free or OpenSource. Please don't redistribute. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; version 2 +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ########################################################################## use strict; @@ -21,14 +31,14 @@ use POSIX qw(strftime); # Default lib dir for RPM and DEB packages use lib '/usr/lib/perl5'; -use PandoraFMS::Goliat::GoliatTools; -use PandoraFMS::Goliat::GoliatConfig; - use PandoraFMS::Tools; use PandoraFMS::DB; use PandoraFMS::Core; use PandoraFMS::ProducerConsumerServer; +use Goliat::GoliatTools; +use Goliat::GoliatConfig; + # Inherits from PandoraFMS::ProducerConsumerServer our @ISA = qw(PandoraFMS::ProducerConsumerServer); From 4ee0c580bb8aad79b1bd66e7d7fd6e5e46aab649 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 22 Mar 2021 17:52:11 +0100 Subject: [PATCH 4/7] WIP: Backup upload --- .../godmode/agentes/module_manager_editor_web.php | 6 +++--- pandora_console/include/ajax/web_server_module_debug.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pandora_console/godmode/agentes/module_manager_editor_web.php b/pandora_console/godmode/agentes/module_manager_editor_web.php index a15da07caa..3d02289160 100644 --- a/pandora_console/godmode/agentes/module_manager_editor_web.php +++ b/pandora_console/godmode/agentes/module_manager_editor_web.php @@ -92,16 +92,16 @@ $data[0] = __('Web checks'); $adopt = false; if (isset($id_agent_module)) { - $adopt = policies_is_module_adopt($id_agent_module); + $adopt = enterprise_hook('policies_is_module_adopt', [$id_agent_module]); } $id_policy_module = (int) get_parameter('id_policy_module', ''); if ($id_policy_module) { - $module = policies_get_module($id_policy_module); + $module = enterprise_hook('policies_get_module', [$id_policy_module]); $plugin_parameter = $module['plugin_parameter']; } -if (!$adopt) { +if ((bool) $adopt === false) { $data[1] = html_print_textarea( 'plugin_parameter', 15, diff --git a/pandora_console/include/ajax/web_server_module_debug.php b/pandora_console/include/ajax/web_server_module_debug.php index d243257cbd..36d82165fe 100644 --- a/pandora_console/include/ajax/web_server_module_debug.php +++ b/pandora_console/include/ajax/web_server_module_debug.php @@ -33,7 +33,7 @@ global $id_agent_module; require_once $config['homedir'].'/include/class/WebServerModuleDebug.class.php'; // This page. -$ajaxPage = '/include/ajax/web_server_module_debug'; +$ajaxPage = $config['homedir'].'/include/ajax/web_server_module_debug'; // Control call flow for debug window. try { From 3cb504397f3d727ac8bb12673204fc724c57a4d2 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Tue, 23 Mar 2021 15:15:07 +0100 Subject: [PATCH 5/7] Solve issues for compilation --- pandora_server/lib/PandoraFMS/Goliat/GoliatCURL.pm | 4 ++-- pandora_server/lib/PandoraFMS/Goliat/GoliatConfig.pm | 4 ++-- pandora_server/lib/PandoraFMS/Goliat/GoliatLWP.pm | 4 ++-- pandora_server/lib/PandoraFMS/Goliat/GoliatTools.pm | 2 +- pandora_server/lib/PandoraFMS/WebServer.pm | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/Goliat/GoliatCURL.pm b/pandora_server/lib/PandoraFMS/Goliat/GoliatCURL.pm index 6f82ba3a00..63fe5ca5de 100755 --- a/pandora_server/lib/PandoraFMS/Goliat/GoliatCURL.pm +++ b/pandora_server/lib/PandoraFMS/Goliat/GoliatCURL.pm @@ -5,9 +5,9 @@ # This code is not free or OpenSource. Please don't redistribute. ################################################################################## -package Goliat::GoliatCURL; +package PandoraFMS::Goliat::GoliatCURL; -use Goliat::GoliatTools; +use PandoraFMS::Goliat::GoliatTools; use strict; use warnings; diff --git a/pandora_server/lib/PandoraFMS/Goliat/GoliatConfig.pm b/pandora_server/lib/PandoraFMS/Goliat/GoliatConfig.pm index 25ae73b30f..da3247c1e8 100755 --- a/pandora_server/lib/PandoraFMS/Goliat/GoliatConfig.pm +++ b/pandora_server/lib/PandoraFMS/Goliat/GoliatConfig.pm @@ -5,12 +5,12 @@ # This code is not free or OpenSource. Please don't redistribute. ########################################################################## -package Goliat::GoliatConfig; +package PandoraFMS::Goliat::GoliatConfig; use strict; use warnings; -use Goliat::GoliatTools; use PandoraFMS::Tools; +use PandoraFMS::Goliat::GoliatTools; require Exporter; our @ISA = ("Exporter"); diff --git a/pandora_server/lib/PandoraFMS/Goliat/GoliatLWP.pm b/pandora_server/lib/PandoraFMS/Goliat/GoliatLWP.pm index 7b66d2457e..3117ab1515 100755 --- a/pandora_server/lib/PandoraFMS/Goliat/GoliatLWP.pm +++ b/pandora_server/lib/PandoraFMS/Goliat/GoliatLWP.pm @@ -5,9 +5,9 @@ # This code is not free or OpenSource. Please don't redistribute. ################################################################################## -package Goliat::GoliatLWP; +package PandoraFMS::Goliat::GoliatLWP; -use Goliat::GoliatTools; +use PandoraFMS::Goliat::GoliatTools; use strict; use warnings; diff --git a/pandora_server/lib/PandoraFMS/Goliat/GoliatTools.pm b/pandora_server/lib/PandoraFMS/Goliat/GoliatTools.pm index 42e1cc0836..2c320477dc 100755 --- a/pandora_server/lib/PandoraFMS/Goliat/GoliatTools.pm +++ b/pandora_server/lib/PandoraFMS/Goliat/GoliatTools.pm @@ -5,7 +5,7 @@ # This code is not free or OpenSource. Please don't redistribute. ############################################################################### -package Goliat::GoliatTools; +package PandoraFMS::Goliat::GoliatTools; use 5.008004; use strict; diff --git a/pandora_server/lib/PandoraFMS/WebServer.pm b/pandora_server/lib/PandoraFMS/WebServer.pm index 6723848d9f..69ae4dbf93 100644 --- a/pandora_server/lib/PandoraFMS/WebServer.pm +++ b/pandora_server/lib/PandoraFMS/WebServer.pm @@ -36,8 +36,8 @@ use PandoraFMS::DB; use PandoraFMS::Core; use PandoraFMS::ProducerConsumerServer; -use Goliat::GoliatTools; -use Goliat::GoliatConfig; +use PandoraFMS::Goliat::GoliatTools; +use PandoraFMS::Goliat::GoliatConfig; # Inherits from PandoraFMS::ProducerConsumerServer our @ISA = qw(PandoraFMS::ProducerConsumerServer); From 90573feb1b158fefe5143cb74cade1689525f769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= Date: Wed, 12 May 2021 09:35:35 +0200 Subject: [PATCH 6/7] Issue with Perl5 paths --- pandora_server/lib/PandoraFMS/WebServer.pm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/WebServer.pm b/pandora_server/lib/PandoraFMS/WebServer.pm index 69ae4dbf93..b900c21fb9 100644 --- a/pandora_server/lib/PandoraFMS/WebServer.pm +++ b/pandora_server/lib/PandoraFMS/WebServer.pm @@ -80,8 +80,8 @@ sub run ($) { # Use Goliat with CURL if ($pa_config->{'web_engine'} eq 'curl') { - require Goliat::GoliatCURL; - Goliat::GoliatCURL->import; + require PandoraFMS::Goliat::GoliatCURL; + PandoraFMS::Goliat::GoliatCURL->import; # Check for CURL binary if (system ("curl -V >$DEVNULL 2>&1") >> 8 != 0) { @@ -98,8 +98,8 @@ sub run ($) { } # Use LWP by default else { - require Goliat::GoliatLWP; - Goliat::GoliatLWP->import; + require PandoraFMS::Goliat::GoliatLWP; + PandoraFMS::Goliat::GoliatLWP->import; if (! LWP::UserAgent->can('ssl_opts')) { logger($pa_config, "LWP version $LWP::VERSION does not support SSL. Make sure version 6.0 or higher is installed.", 1); From 3758c800193de8481d0ac02c81aef167f0f2f2ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Gonz=C3=A1lez?= <79-jose.gonzalez@users.noreply.brutus.artica.es> Date: Wed, 12 May 2021 13:07:45 +0000 Subject: [PATCH 7/7] Fixed delete_files entries. --- .../extras/delete_files/delete_files.txt | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/pandora_console/extras/delete_files/delete_files.txt b/pandora_console/extras/delete_files/delete_files.txt index 4249b8c0c2..50d4b78c33 100644 --- a/pandora_console/extras/delete_files/delete_files.txt +++ b/pandora_console/extras/delete_files/delete_files.txt @@ -74,15 +74,10 @@ enterprise/extensions/ipam enterprise/extensions/disabled/visual_console_manager.php enterprise/extensions/visual_console_manager.php pandora_console/extensions/net_tools.php -pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/Goliat/GoliatCURL.pm -pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/Goliat/GoliatConfig.pm -pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/Goliat/GoliatLWP.pm -pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/Goliat/GoliatTools.pm -pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/PandoraFMS/WebServer.pm -pandora_console/enterprise/godmode/agentes/module_manager_editor_web.php -pandora_console/enterprise/include/ajax/web_server_module_debug.php -pandora_console/enterprise/include/class/WebServerModuleDebug.class.php -pandora_console/enterprise/include/styles/WebServerModuleDebug.css +enterprise/godmode/agentes/module_manager_editor_web.php +enterprise/include/ajax/web_server_module_debug.php +enterprise/include/class/WebServerModuleDebug.class.php +enterprise/include/styles/WebServerModuleDebug.css include/lib/WSManager.php include/lib/WebSocketServer.php include/lib/WebSocketUser.php