Windows: Revisión general Pandora - Discovery

This commit is contained in:
fbsanchez 2019-09-24 19:07:55 +02:00 committed by Alejandro Fraguas
parent 8e728eed6b
commit 746f817fe4
7 changed files with 188 additions and 129 deletions

View File

@ -873,18 +873,20 @@ class ConsoleSupervisor
{
global $config;
$remote_config_dir = io_safe_output($config['remote_config']);
if (enterprise_installed()
&& isset($config['license_nms'])
&& $config['license_nms'] != 1
) {
if (is_readable($config['remote_config']) !== true) {
if (is_readable($remote_config_dir) !== true) {
$this->notify(
[
'type' => 'NOTIF.PERMISSIONS.REMOTE_CONFIG',
'title' => __('Remote configuration directory is not readable'),
'message' => __(
'Remote configuration directory %s is not readable. Please, adjust configuration.',
$config['remote_config']
$remote_config_dir
),
'url' => ui_get_full_url('index.php?sec=general&sec2=godmode/setup/setup&section=general'),
]
@ -896,14 +898,14 @@ class ConsoleSupervisor
);
}
if (is_writable($config['remote_config'].'/conf') !== true) {
if (is_writable($remote_config_dir.'/conf') !== true) {
$this->notify(
[
'type' => 'NOTIF.PERMISSIONS.REMOTE_CONFIG.CONF',
'title' => __('Remote configuration directory is not writable'),
'message' => __(
'Remote configuration directory %s is not writable. Please, adjust configuration.',
$config['remote_config'].'/conf'
$remote_config_dir.'/conf'
),
'url' => ui_get_full_url('index.php?sec=general&sec2=godmode/setup/setup&section=general'),
]
@ -914,14 +916,14 @@ class ConsoleSupervisor
);
}
if (is_writable($config['remote_config'].'/collections') !== true) {
if (is_writable($remote_config_dir.'/collections') !== true) {
$this->notify(
[
'type' => 'NOTIF.PERMISSIONS.REMOTE_CONFIG.COLLECTIONS',
'title' => __('Remote collections directory is not writable'),
'message' => __(
'Collections directory %s is not writable. Please, adjust configuration.',
$config['remote_config'].'/collections'
$remote_config_dir.'/collections'
),
'url' => ui_get_full_url('index.php?sec=general&sec2=godmode/setup/setup&section=general'),
]
@ -932,14 +934,14 @@ class ConsoleSupervisor
);
}
if (is_writable($config['remote_config'].'/md5') !== true) {
if (is_writable($remote_config_dir.'/md5') !== true) {
$this->notify(
[
'type' => 'NOTIF.PERMISSIONS.REMOTE_CONFIG.MD5',
'title' => __('Remote md5 directory is not writable'),
'message' => __(
'MD5 directory %s is not writable. Please, adjust configuration.',
$config['remote_config'].'/md5'
$remote_config_dir.'/md5'
),
'url' => ui_get_full_url('index.php?sec=general&sec2=godmode/setup/setup&section=general'),
]
@ -957,7 +959,7 @@ class ConsoleSupervisor
$MAX_BADXML_FILES_DATA_IN = 150;
$filecount = $this->countFiles(
$config['remote_config'],
$remote_config_dir,
'',
$MAX_FILES_DATA_IN
);
@ -970,7 +972,7 @@ class ConsoleSupervisor
'message' => __(
'There are more than %d files in %s. Consider checking DataServer performance',
$MAX_FILES_DATA_IN,
$config['remote_config']
$remote_config_dir
),
'url' => ui_get_full_url('index.php?sec=general&sec2=godmode/setup/setup&section=perf'),
]
@ -980,7 +982,7 @@ class ConsoleSupervisor
}
$filecount = $this->countFiles(
$config['remote_config'],
$remote_config_dir,
'/^.*BADXML$/',
$MAX_BADXML_FILES_DATA_IN
);
@ -993,7 +995,7 @@ class ConsoleSupervisor
'message' => __(
'There are more than %d files in %s. Consider checking software agents.',
$MAX_BADXML_FILES_DATA_IN,
$config['remote_config']
$remote_config_dir
),
'url' => ui_get_full_url('index.php?sec=general&sec2=godmode/setup/setup&section=perf'),
]
@ -1266,7 +1268,8 @@ class ConsoleSupervisor
$PHPSerialize_precision = ini_get('serialize_precision');
// PhantomJS status.
$result_ejecution = exec($config['phantomjs_bin'].'/phantomjs --version');
$phantomjs_dir = io_safe_output($config['phantomjs_bin']);
$result_ejecution = exec($phantomjs_dir.'/phantomjs --version');
// PHP version checks.
$php_version = phpversion();
@ -1451,8 +1454,9 @@ class ConsoleSupervisor
'type' => 'NOTIF.PHP.SERIALIZE_PRECISION',
'title' => sprintf(
__("Not recommended '%s' value in PHP configuration"),
'serialze_precision'
), 'message' => sprintf(
'serialize_precision'
),
'message' => sprintf(
__('Recommended value is: %s'),
sprintf('-1')
).'<br><br>'.__('Please, change it on your PHP configuration file (php.ini) or contact with administrator'),
@ -2061,8 +2065,10 @@ class ConsoleSupervisor
{
global $config;
if (($config['fontpath'] == '')
|| (file_exists($config['fontpath']) === false)
$fontpath = io_safe_output($config['fontpath']);
if (($fontpath == '')
|| (file_exists($fontpath) === false)
) {
$this->notify(
[

View File

@ -1500,7 +1500,7 @@ function config_process_config()
if (!isset($config['remote_config'])) {
if ($is_windows) {
$default = 'C:\\PandoraFMS\\Pandora_Server\\data_in';
$default = 'C:\PandoraFMS\Pandora_Server\data_in';
} else {
$default = '/var/spool/pandora/data_in';
}
@ -1510,7 +1510,7 @@ function config_process_config()
if (!isset($config['phantomjs_bin'])) {
if ($is_windows) {
$default = 'C:\\PandoraFMS\\phantomjs';
$default = 'C:\PandoraFMS\Pandora_Server\bin';
} else {
$default = '/usr/bin';
}
@ -1760,7 +1760,13 @@ function config_process_config()
}
if (!isset($config['auditdir'])) {
config_update_value('auditdir', '/var/www/html/pandora_console');
$auditdir = '/var/www/html/pandora_console';
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
// Windows.
$auditdir = $config['homedir'];
}
config_update_value('auditdir', $auditdir);
}
if (!isset($config['elasticsearch_ip'])) {
@ -1794,6 +1800,7 @@ function config_process_config()
/*
* Parse the ACL IP list for access API
*/
$temp_list_ACL_IPs_for_API = [];
if (isset($config['list_ACL_IPs_for_API'])) {
if (!empty($config['list_ACL_IPs_for_API'])) {
@ -1804,13 +1811,16 @@ function config_process_config()
$config['list_ACL_IPs_for_API'] = $temp_list_ACL_IPs_for_API;
$keysConfig = array_keys($config);
// This is not set here. The first time, when no
// setup is done, update_manager extension manage it
// the first time make a conenction and disable itself
// Not Managed here !
// if (!isset ($config["autoupdate"])) {
// config_update_value ('autoupdate', true);.
// }
/*
* This is not set here. The first time, when no
* setup is done, update_manager extension manage it
* the first time make a conenction and disable itself
* Not Managed here !
* if (!isset ($config["autoupdate"])) {
* config_update_value ('autoupdate', true);.
* }
*/
include_once $config['homedir'].'/include/auth/mysql.php';
include_once $config['homedir'].'/include/functions_io.php';
@ -1819,10 +1829,16 @@ function config_process_config()
// user, and should be in pandora root. By default, Pandora adds
// /attachment to this, so by default is the pandora console home
// dir.
$attachment_store_path = $config['homedir'].'/attachment';
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
// Windows.
$attachment_store_path = $config['homedir'].'\attachment';
}
if (!isset($config['attachment_store'])) {
config_update_value(
'attachment_store',
io_safe_input($config['homedir']).'/attachment'
$attachment_store_path
);
} else {
// Fixed when the user moves the pandora console to another dir
@ -1830,16 +1846,23 @@ function config_process_config()
if (!is_dir($config['attachment_store'])) {
config_update_value(
'attachment_store',
$config['homedir'].'/attachment'
$attachment_store_path
);
}
}
if (!isset($config['fontpath'])) {
$home = str_replace('\\', '/', $config['homedir']);
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
// Windows.
$fontpath = $config['homedir'].'\include\fonts\smallfont.ttf';
} else {
$home = str_replace('\\', '/', $config['homedir']);
$fontpath = $home.'/include/fonts/smallfont.ttf';
}
config_update_value(
'fontpath',
$home.'/include/fonts/smallfont.ttf'
$fontpath
);
}
@ -2077,7 +2100,7 @@ function config_process_config()
if (!isset($config['netflow_path'])) {
if ($is_windows) {
$default = 'C:\\PandoraFMS\\Pandora_Server\\data_in\\netflow';
$default = 'C:\PandoraFMS\Pandora_Server\data_in\netflow';
} else {
$default = '/var/spool/pandora/data_in/netflow';
}

View File

@ -104,7 +104,7 @@ class gettext_reader {
* @param boolean enable_cache Enable or disable caching of strings (default on)
*/
function gettext_reader($Reader, $enable_cache = true) {
$machine = @shell_exec('uname -m');
$machine = php_uname("m");
$enabled64Bits = false;
if (preg_match('/64/', $machine)) {

View File

@ -357,6 +357,14 @@ sub pandora_load_config {
# Xprobe2 for recon OS fingerprinting and tcpscan (optional)
$pa_config->{"xprobe2"} = "/usr/bin/xprobe2";
# Winexe allows to exec commands on remote windows systems (optional)
$pa_config->{"winexe"} = "/usr/bin/winexe";
# PsExec allows to exec commands on remote windows systems from windows servers (optional)
$pa_config->{"psexec"} = 'C:\PandoraFMS\Pandora_Server\bin\PsExec.exe';
# plink allows to exec commands on remote linux systems from windows servers (optional)
$pa_config->{"plink"} = 'C:\PandoraFMS\Pandora_Server\bin\plink.exe';
# Snmpget for snmpget system command (optional)
$pa_config->{"snmpget"} = "/usr/bin/snmpget";
@ -838,6 +846,15 @@ sub pandora_load_config {
elsif ($parametro =~ m/^xprobe2\s(.*)/i) {
$pa_config->{'xprobe2'}= clean_blank($1);
}
elsif ($parametro =~ m/^winexe\s(.*)/i) {
$pa_config->{'winexe'}= clean_blank($1);
}
elsif ($parametro =~ m/^psexec\s(.*)/i) {
$pa_config->{'psexec'}= clean_blank($1);
}
elsif ($parametro =~ m/^plink\s(.*)/i) {
$pa_config->{'plink'}= clean_blank($1);
}
elsif ($parametro =~ m/^snmpget\s(.*)/i) {
$pa_config->{'snmpget'}= clean_blank($1);
}

View File

@ -343,6 +343,9 @@ sub exec_recon_script ($$$) {
sub PandoraFMS::Recon::Base::guess_os($$) {
my ($self, $device) = @_;
$DEVNULL = '/dev/null' if (!defined($DEVNULL));
$DEVNULL = '/NUL' if ($^O =~ /win/i && !defined($DEVNULL));
# OS detection disabled. Use the device type.
if ($self->{'os_detection'} == 0) {
my $device_type = $self->get_device_type($device);
@ -354,17 +357,20 @@ sub PandoraFMS::Recon::Base::guess_os($$) {
}
# Use xprobe2 if available
if (-e $self->{pa_config}->{xprobe2}) {
my $output = `"$self->{pa_config}->{xprobe2}" $device 2>$DEVNULL | grep 'Running OS' | head -1`;
if (-x $self->{'pa_config'}->{'xprobe2'}) {
my $return = `"$self->{pa_config}->{xprobe2}" $device 2>$DEVNULL`;
if ($? == 0) {
my ($output) = $a =~ /Running OS:(.*)/;
return pandora_get_os($self->{'dbh'}, $output);
}
}
# Use nmap by default
if (-e $self->{pa_config}->{nmap}) {
my $output = `"$self->{pa_config}->{nmap}" -F -O $device 2>$DEVNULL | grep 'Aggressive OS guesses'`;
if (-x $self->{'pa_config'}->{'nmap'}) {
my $return = `"$self->{pa_config}->{nmap}" -F -O $device 2>$DEVNULL`;
return OS_OTHER if ($? != 0);
my ($output) = $return =~ /Aggressive OS guesses:\s*(.*)/;
return pandora_get_os($self->{'dbh'}, $output);
}
@ -377,7 +383,11 @@ sub PandoraFMS::Recon::Base::guess_os($$) {
sub PandoraFMS::Recon::Base::tcp_scan ($$) {
my ($self, $host) = @_;
my $open_ports = `"$self->{pa_config}->{nmap}" -p$self->{recon_ports} $host | grep open | wc -l`;
my $r = `"$self->{pa_config}->{nmap}" -p$self->{recon_ports} $host`;
# Same as ""| grep open | wc -l" but multi-OS;
my $open_ports = () = $r =~ /open/gm;
return $open_ports;
}

View File

@ -36,7 +36,7 @@ use constant {
DISCOVERY_DEPLOY_AGENTS => 9,
};
# /dev/null
# $DEVNULL
my $DEVNULL = ($^O eq 'MSWin32') ? '/Nul' : '/dev/null';
# Some useful OIDs.
@ -852,7 +852,7 @@ sub get_routes($) {
$self->{'routes'} = [];
# Parse route's output.
my @output = `route -n 2>/dev/null`;
my @output = `route -n 2>$DEVNULL`;
foreach my $line (@output) {
chomp($line);
if ($line =~ /^0\.0\.0\.0\s+(\d+\.\d+\.\d+\.\d+).*/) {
@ -1220,7 +1220,7 @@ sub snmp_responds_v3($$) {
sub local_arp($) {
my ($self) = @_;
my @output = `arp -an 2>/dev/null`;
my @output = `arp -an 2>$DEVNULL`;
foreach my $line (@output) {
next unless ($line =~ m/\((\S+)\) at ([0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+)/);
$self->add_mac(parse_mac($2), $1);
@ -1286,7 +1286,7 @@ sub ping ($$$) {
for (my $i = 0; $i < $retries; $i++) {
# Note: There is no timeout option.
`$ping_command -s -n $host 56 $packets >/dev/null 2>&1`;
`$ping_command -s -n $host 56 $packets >$DEVNULL 2>&1`;
return 1 if ($? == 0);
}
@ -1299,7 +1299,7 @@ sub ping ($$$) {
for (my $i = 0; $i < $retries; $i++) {
# Note: There is no timeout option for ping6.
`$ping_command -q -n -c $packets $host >/dev/null 2>&1`;
`$ping_command -q -n -c $packets $host >$DEVNULL 2>&1`;
return 1 if ($? == 0);
}
@ -1312,7 +1312,7 @@ sub ping ($$$) {
for (my $i = 0; $i < $retries; $i++) {
# Note: There is no timeout option for ping6.
`$ping_command -q -n -c $packets $host >/dev/null 2>&1`;
`$ping_command -q -n -c $packets $host >$DEVNULL 2>&1`;
if ($? == 0) {
return 1;
}
@ -1324,7 +1324,7 @@ sub ping ($$$) {
# Assume Linux by default.
my $ping_command = $host =~ /\d+:|:\d+/ ? "ping6" : "ping";
for (my $i = 0; $i < $retries; $i++) {
`$ping_command -q -W $timeout -n -c $packets $host >/dev/null 2>&1`;
`$ping_command -q -W $timeout -n -c $packets $host >$DEVNULL 2>&1`;
return 1 if ($? == 0);
}
@ -1529,99 +1529,101 @@ sub app_scan($) {
$self->{'task_data'}
);
if (!$dbObj->is_connected()) {
call('message', 'Cannot connect to target ' . $target, 3);
$global_percent += $global_step;
$self->{'c_network_percent'} = 90;
# Update progress
$self->call('update_progress', $global_percent + (90 / (scalar @targets)));
$self->{'summary'}->{'not_alive'} += 1;
push @modules, {
name => $type . ' connection',
type => 'generic_proc',
data => 0,
description => $type . ' availability'
};
if (defined($dbObj)) {
if (!$dbObj->is_connected()) {
call('message', 'Cannot connect to target ' . $target, 3);
$global_percent += $global_step;
$self->{'c_network_percent'} = 90;
# Update progress
$self->call('update_progress', $global_percent + (90 / (scalar @targets)));
$self->{'summary'}->{'not_alive'} += 1;
push @modules, {
name => $type . ' connection',
type => 'generic_proc',
data => 0,
description => $type . ' availability'
};
} else {
my $dbObjCfg = $dbObj->get_config();
} else {
my $dbObjCfg = $dbObj->get_config();
$self->{'summary'}->{'discovered'} += 1;
$self->{'summary'}->{'alive'} += 1;
$self->{'summary'}->{'discovered'} += 1;
$self->{'summary'}->{'alive'} += 1;
push @modules, {
name => $type . ' connection',
type => 'generic_proc',
data => 1,
description => $type . ' availability'
};
push @modules, {
name => $type . ' connection',
type => 'generic_proc',
data => 1,
description => $type . ' availability'
};
# Analyze.
$self->{'step'} = STEP_STATISTICS;
$self->{'c_network_percent'} = 30;
$self->call('update_progress', $global_percent + (30 / (scalar @targets)));
$self->{'c_network_name'} = $dbObj->get_host();
# Analyze.
$self->{'step'} = STEP_STATISTICS;
$self->{'c_network_percent'} = 30;
$self->call('update_progress', $global_percent + (30 / (scalar @targets)));
$self->{'c_network_name'} = $dbObj->get_host();
# Retrieve connection statistics.
# Retrieve uptime statistics
# Retrieve query stats
# Retrieve connections
# Retrieve innodb
# Retrieve cache
$self->{'c_network_percent'} = 50;
$self->call('update_progress', $global_percent + (50 / (scalar @targets)));
push @modules, $dbObj->get_statistics();
# Retrieve connection statistics.
# Retrieve uptime statistics
# Retrieve query stats
# Retrieve connections
# Retrieve innodb
# Retrieve cache
$self->{'c_network_percent'} = 50;
$self->call('update_progress', $global_percent + (50 / (scalar @targets)));
push @modules, $dbObj->get_statistics();
# Custom queries.
$self->{'step'} = STEP_CUSTOM_QUERIES;
$self->{'c_network_percent'} = 80;
$self->call('update_progress', $global_percent + (80 / (scalar @targets)));
push @modules, $dbObj->execute_custom_queries();
# Custom queries.
$self->{'step'} = STEP_CUSTOM_QUERIES;
$self->{'c_network_percent'} = 80;
$self->call('update_progress', $global_percent + (80 / (scalar @targets)));
push @modules, $dbObj->execute_custom_queries();
if (defined($dbObjCfg->{'scan_databases'})
&& $dbObjCfg->{'scan_databases'} == 1) {
# Skip database scan in Oracle tasks
next if $self->{'type'} == DISCOVERY_APP_ORACLE;
if (defined($dbObjCfg->{'scan_databases'})
&& "$dbObjCfg->{'scan_databases'}" eq "1") {
# Skip database scan in Oracle tasks
next if $self->{'type'} == DISCOVERY_APP_ORACLE;
my $__data = $dbObj->scan_databases();
my $__data = $dbObj->scan_databases();
if (ref($__data) eq "ARRAY") {
if (defined($dbObjCfg->{'agent_per_database'})
&& $dbObjCfg->{'agent_per_database'} == 1) {
# Agent per database detected.
push @data, @{$__data};
} else {
# Merge modules into engine agent.
my @_modules = map {
map { $_ } @{$_->{'module_data'}}
} @{$__data};
if (ref($__data) eq "ARRAY") {
if (defined($dbObjCfg->{'agent_per_database'})
&& $dbObjCfg->{'agent_per_database'} == 1) {
# Agent per database detected.
push @data, @{$__data};
} else {
# Merge modules into engine agent.
my @_modules = map {
map { $_ } @{$_->{'module_data'}}
} @{$__data};
push @modules, @_modules;
push @modules, @_modules;
}
}
}
}
# Put engine agent at the beginning of the list.
my $version = $dbObj->get_version();
unshift @data,{
'agent_data' => {
'agent_name' => $dbObj->get_agent_name(),
'os' => $type,
'os_version' => (defined($version) ? $version : 'Discovery'),
'interval' => $self->{'task_data'}->{'interval_sweep'},
'id_group' => $self->{'task_data'}->{'id_group'},
'address' => $dbObj->get_host(),
'description' => '',
},
'module_data' => \@modules,
};
$self->call('create_agents', \@data);
# Destroy item.
undef($dbObj);
}
# Put engine agent at the beginning of the list.
my $version = $dbObj->get_version();
unshift @data,{
'agent_data' => {
'agent_name' => $dbObj->get_agent_name(),
'os' => $type,
'os_version' => (defined($version) ? $version : 'Discovery'),
'interval' => $self->{'task_data'}->{'interval_sweep'},
'id_group' => $self->{'task_data'}->{'id_group'},
'address' => $dbObj->get_host(),
'description' => '',
},
'module_data' => \@modules,
};
$self->call('create_agents', \@data);
# Destroy item.
undef($dbObj);
$global_percent += $global_step;
$self->{'c_network_percent'} = 100;
$self->call('update_progress', $global_percent);
@ -1674,7 +1676,7 @@ sub deploy_scan($) {
##########################################################################
sub scan($) {
my ($self) = @_;
my ($progress, $step);
my ($progress, $step) = 1, 0;
# 1%
$self->call('update_progress', 1);
@ -1697,7 +1699,7 @@ sub scan($) {
}
# Find devices.
$self->call('message', "[1/5] Scanning the network...", 3);
$self->call('message', "[1/4] Scanning the network...", 3);
$self->{'step'} = STEP_SCANNING;
$self->call('update_progress', $progress);
$self->scan_subnet();
@ -1713,7 +1715,7 @@ sub scan($) {
$self->call('delete_connections');
# Connectivity from address forwarding tables.
$self->call('message', "[1/4] Finding address forwarding table connectivity...", 3);
$self->call('message', "[2/4] Finding address forwarding table connectivity...", 3);
$self->{'step'} = STEP_AFT;
($progress, $step) = (50, 20.0 / scalar(@hosts)); # From 50% to 70%.
for (my $i = 0; defined($hosts[$i]); $i++) {
@ -1831,7 +1833,7 @@ sub snmp_get_command {
my ($self, $device, $oid, $community, $vlan) = @_;
$vlan = defined($vlan) ? "\@" . $vlan : '';
my $command = "snmpwalk -M/dev/null -r$self->{'snmp_checks'} -t$self->{'snmp_timeout'} -v$self->{'snmp_version'} -On -Oe ";
my $command = "snmpwalk -M$DEVNULL -r$self->{'snmp_checks'} -t$self->{'snmp_timeout'} -v$self->{'snmp_version'} -On -Oe ";
if ($self->{'snmp_version'} eq "3") {
if ($self->{'community'}) { # Context
$command .= " -N $self->{'community'} ";
@ -1847,7 +1849,7 @@ sub snmp_get_command {
$command .= " -c$community$vlan ";
}
return "$command $device $oid 2>/dev/null";
return "$command $device $oid 2>$DEVNULL";
}

View File

@ -994,7 +994,8 @@ sub load_average {
$load_average = ((split(/\s+/, `/sbin/sysctl -n vm.loadavg`))[1]);
} elsif ($OSNAME eq "MSWin32") {
# Windows hasn't got load average.
$load_average = undef;
$load_average = `powershell "(Get-WmiObject win32_processor | Measure-Object -property LoadPercentage -Average).average"`;
chop($load_average);
}
# by default LINUX calls
else {