From f0a71e01de5ab022b052e5974ae75c59336b42f6 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Wed, 11 Mar 2020 13:35:31 +0100 Subject: [PATCH 001/111] minor fixes --- .../godmode/wizards/HostDevices.class.php | 22 +- .../godmode/wizards/Wizard.main.php | 2 +- pandora_server/lib/PandoraFMS/Recon/Base.pm | 300 +++++++++--------- 3 files changed, 162 insertions(+), 162 deletions(-) diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php index fd7811f2e9..d40e174573 100755 --- a/pandora_console/godmode/wizards/HostDevices.class.php +++ b/pandora_console/godmode/wizards/HostDevices.class.php @@ -58,7 +58,6 @@ class HostDevices extends Wizard public $pageLabelsNetScan = [ 'NetScan definition', 'NetScan features', - ]; /** @@ -269,6 +268,8 @@ class HostDevices extends Wizard */ public function parseNetScan() { + global $config; + if ($this->page == 0) { // Check if we're updating a task. $task_id = get_parameter('task', null); @@ -333,18 +334,14 @@ class HostDevices extends Wizard if ($task_id !== null && $taskname == null && $server_id == null - && $id_group == null - && $server == null - && $datacenter == '' - && $user == '' - && $pass == '' - && $encrypt == null - && $interval == 0 + && empty($id_group) === true + && empty($network) === true + && $interval === 0 ) { // Default values, no data received. // User is accesing directly to this page. if (check_acl( - $config['id_usuario'], + $config['id_user'], $this->task['id_group'], $this->access ) != true @@ -562,7 +559,7 @@ class HostDevices extends Wizard // Check ACL. If user is not able to manage target task, // redirect him to main page. if (check_acl( - $config['id_usuario'], + $config['id_user'], $this->task['id_group'], $this->access ) != true @@ -878,7 +875,9 @@ class HostDevices extends Wizard ]; $form['inputs'][] = [ - 'extra' => '

Please, configure task '.io_safe_output($this->task['name']).'

', + 'extra' => '

Please, configure task '.io_safe_output( + $this->task['name'] + ).'

', ]; $form['inputs'][] = [ @@ -893,6 +892,7 @@ class HostDevices extends Wizard 'selected' => $this->task['id_network_profile'], 'nothing_value' => 0, 'nothing' => __('None'), + 'multiple' => true, ], ]; diff --git a/pandora_console/godmode/wizards/Wizard.main.php b/pandora_console/godmode/wizards/Wizard.main.php index 2fe34770ad..8f8b518069 100644 --- a/pandora_console/godmode/wizards/Wizard.main.php +++ b/pandora_console/godmode/wizards/Wizard.main.php @@ -41,7 +41,7 @@ class Wizard /** * Breadcrum * - * @var array. + * @var array */ public $breadcrum; diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index ce6048a6f9..9e3a437357 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -98,9 +98,9 @@ our @EXPORT = qw( $SYSUPTIME ); -####################################################################### +################################################################################ # Create a new ReconTask object. -####################################################################### +################################################################################ sub new { my $class = shift; @@ -289,18 +289,18 @@ sub new { return $self; } -######################################################################################## +################################################################################ # Add an address to a device. -######################################################################################## +################################################################################ sub add_addresses($$$) { my ($self, $device, $ip_address) = @_; $self->{'visited_devices'}->{$device}->{'addr'}->{$ip_address} = ''; } -######################################################################################## +################################################################################ # Add a MAC/IP address to the ARP cache. -######################################################################################## +################################################################################ sub add_mac($$$) { my ($self, $mac, $ip_addr) = @_; @@ -308,9 +308,9 @@ sub add_mac($$$) { $self->{'arp_cache'}->{$mac} = $ip_addr; } -######################################################################################## +################################################################################ # Add an interface/MAC to the interface cache. -######################################################################################## +################################################################################ sub add_iface($$$) { my ($self, $iface, $mac) = @_; @@ -318,9 +318,9 @@ sub add_iface($$$) { $self->{'ifaces'}->{$mac} = $iface; } -######################################################################################## +################################################################################ # Discover connectivity from address forwarding tables. -######################################################################################## +################################################################################ sub aft_connectivity($$) { my ($self, $switch) = @_; my (%mac_temp, @aft_temp); @@ -367,9 +367,9 @@ sub aft_connectivity($$) { } -######################################################################################## +################################################################################ # Return 1 if the given devices are connected to each other, 0 otherwise. -######################################################################################## +################################################################################ sub are_connected($$$$$) { my ($self, $dev_1, $if_1, $dev_2, $if_2) = @_; @@ -389,9 +389,9 @@ sub are_connected($$$$$) { return 0; } -######################################################################################## +################################################################################ # Discover as much information as possible from the given device using SNMP. -######################################################################################## +################################################################################ sub snmp_discovery($$) { my ($self, $device) = @_; @@ -434,9 +434,9 @@ sub snmp_discovery($$) { $self->call('create_agent', $device); } -####################################################################### +################################################################################ # Try to call the given function on the given object. -####################################################################### +################################################################################ sub call { my $self = shift; my $func = shift; @@ -447,18 +447,18 @@ sub call { } } -######################################################################################## +################################################################################ # Disable the VLAN cache. -######################################################################################## +################################################################################ sub disable_vlan_cache($$) { my ($self, $device) = @_; $self->{'__vlan_cache_enabled__'} = 0; } -######################################################################################## +################################################################################ # Enable the VLAN cache. -######################################################################################## +################################################################################ sub enable_vlan_cache($$) { my ($self, $device) = @_; @@ -466,9 +466,9 @@ sub enable_vlan_cache($$) { $self->{'__vlan_cache_enabled__'} = 1; } -########################################################################## +################################################################################ # Connect the given hosts to its gateway. -########################################################################## +################################################################################ sub gateway_connectivity($$) { my ($self, $host) = @_; @@ -486,9 +486,9 @@ sub gateway_connectivity($$) { $self->mark_connected($gw, '', $host, ''); } -######################################################################################## +################################################################################ # Find IP address aliases for the given device. -######################################################################################## +################################################################################ sub find_aliases($$) { my ($self, $device) = @_; @@ -518,9 +518,9 @@ sub find_aliases($$) { } } -######################################################################################## +################################################################################ # Find all the interfaces for the given host. -######################################################################################## +################################################################################ sub find_ifaces($$) { my ($self, $device) = @_; @@ -553,9 +553,9 @@ sub find_ifaces($$) { } } -######################################################################################## +################################################################################ # Find the device's VLANs and fill the VLAN cache. -######################################################################################## +################################################################################ sub find_vlans ($$) { my ($self, $device) = @_; my %vlan_hash; @@ -570,9 +570,9 @@ sub find_vlans ($$) { push(@{$self->{'vlan_cache'}->{$device}}, @vlans) if (scalar(@vlans) > 0); } -######################################################################################## +################################################################################ # Return the addresses of the given device as an array. -######################################################################################## +################################################################################ sub get_addresses($$) { my ($self, $device) = @_; @@ -584,9 +584,9 @@ sub get_addresses($$) { return ($device); } -######################################################################################## +################################################################################ # Return a device structure from an IP address. -######################################################################################## +################################################################################ sub get_device($$) { my ($self, $addr) = @_; @@ -597,9 +597,9 @@ sub get_device($$) { return undef; } -######################################################################################## +################################################################################ # Get the SNMP community of the given device. Returns undef if no community was found. -######################################################################################## +################################################################################ sub get_community($$) { my ($self, $device) = @_; @@ -612,27 +612,27 @@ sub get_community($$) { return ''; } -######################################################################################## +################################################################################ # Return the connection hash. -######################################################################################## +################################################################################ sub get_connections($) { my ($self) = @_; return $self->{'connections'}; } -######################################################################################## +################################################################################ # Return the parent relationship hash. -######################################################################################## +################################################################################ sub get_parents($) { my ($self) = @_; return $self->{'parents'}; } -######################################################################################## +################################################################################ # Get the type of the given device. -######################################################################################## +################################################################################ sub get_device_type($$) { my ($self, $device) = @_; @@ -644,18 +644,18 @@ sub get_device_type($$) { return 'host'; } -######################################################################################## +################################################################################ # Return all known hosts that are not switches or routers. -######################################################################################## +################################################################################ sub get_hosts($) { my ($self) = @_; return $self->{'hosts'}; } -######################################################################################## +################################################################################ # Add an interface/MAC to the interface cache. -######################################################################################## +################################################################################ sub get_iface($$) { my ($self, $mac) = @_; @@ -664,9 +664,9 @@ sub get_iface($$) { return $self->{'ifaces'}->{$mac}; } -######################################################################################## +################################################################################ # Get an interface name from an AFT entry. Returns undef on error. -######################################################################################## +################################################################################ sub get_if_from_aft($$$) { my ($self, $switch, $mac) = @_; @@ -687,9 +687,9 @@ sub get_if_from_aft($$$) { } -######################################################################################## +################################################################################ # Get an interface name from an IP address. -######################################################################################## +################################################################################ sub get_if_from_ip($$$) { my ($self, $device, $ip_addr) = @_; @@ -705,9 +705,9 @@ sub get_if_from_ip($$$) { return $if_name; } -######################################################################################## +################################################################################ # Get an interface name from a MAC address. -######################################################################################## +################################################################################ sub get_if_from_mac($$$) { my ($self, $device, $mac) = @_; @@ -735,9 +735,9 @@ sub get_if_from_mac($$$) { return ''; } -######################################################################################## +################################################################################ # Get an interface name from a port number. Returns '' on error. -######################################################################################## +################################################################################ sub get_if_from_port($$$) { my ($self, $switch, $port) = @_; @@ -753,9 +753,9 @@ sub get_if_from_port($$$) { return $if_name; } -######################################################################################## +################################################################################ # Returns the IP address of the given interface (by index). -######################################################################################## +################################################################################ sub get_if_ip($$$) { my ($self, $device, $if_index) = @_; @@ -768,9 +768,9 @@ sub get_if_ip($$$) { return ''; } -######################################################################################## +################################################################################ # Returns the MAC address of the given interface (by index). -######################################################################################## +################################################################################ sub get_if_mac($$$) { my ($self, $device, $if_index) = @_; @@ -783,9 +783,9 @@ sub get_if_mac($$$) { return $mac; } -######################################################################################## +################################################################################ # Returns the type of the given interface (by index). -######################################################################################## +################################################################################ sub get_if_type($$$) { my ($self, $device, $if_index) = @_; @@ -795,9 +795,9 @@ sub get_if_type($$$) { return $type; } -######################################################################################## +################################################################################ # Get an IP address from the ARP cache given the MAC address. -######################################################################################## +################################################################################ sub get_ip_from_mac($$) { my ($self, $mac_addr) = @_; @@ -808,9 +808,9 @@ sub get_ip_from_mac($$) { return undef; } -######################################################################################## +################################################################################ # Attemtps to find -######################################################################################## +################################################################################ sub get_mac_from_ip($$) { my ($self, $host) = @_; my $mac = undef; @@ -830,9 +830,9 @@ sub get_mac_from_ip($$) { $self->call('message', "Found MAC $mac for host $host in the local ARP cache.", 5); } -######################################################################################## +################################################################################ # Get a port number from an AFT entry. Returns undef on error. -######################################################################################## +################################################################################ sub get_port_from_aft($$$) { my ($self, $switch, $mac) = @_; @@ -843,9 +843,9 @@ sub get_port_from_aft($$$) { return $port; } -######################################################################################## +################################################################################ # Fill the route cache. -######################################################################################## +################################################################################ sub get_routes($) { my ($self) = @_; @@ -870,9 +870,9 @@ sub get_routes($) { } } -######################################################################################## +################################################################################ # Get the gateway to reach the given host. -######################################################################################## +################################################################################ sub get_gateway($) { my ($self, $host) = @_; @@ -890,29 +890,29 @@ sub get_gateway($) { return undef; } -######################################################################################## +################################################################################ # Return a pointer to an array containing configured subnets. -######################################################################################## +################################################################################ sub get_subnets($) { my ($self) = @_; return $self->{'subnets'}; } -######################################################################################## +################################################################################ # Get an array of all the visited devices. # NOTE: This functions returns the whole device structures, not just address # like get_hosts, get_switches, get_routers and get_all_devices. -######################################################################################## +################################################################################ sub get_visited_devices($) { my ($self) = @_; return $self->{'visited_devices'}; } -######################################################################################## +################################################################################ # Returns an array of found VLAN IDs. -######################################################################################## +################################################################################ sub get_vlans($$) { my ($self, $device) = @_; @@ -927,9 +927,9 @@ sub get_vlans($$) { return @{$self->{'vlan_cache'}->{$device}}; } -######################################################################################## +################################################################################ # Guess the type of the given device. -######################################################################################## +################################################################################ sub guess_device_type($$) { my ($self, $device) = @_; @@ -1004,9 +1004,9 @@ sub guess_device_type($$) { $self->set_device_type($device, $device_type); } -######################################################################################## +################################################################################ # Return 1 if the given device has children. -######################################################################################## +################################################################################ sub has_children($$) { my ($self, $device) = @_; @@ -1018,9 +1018,9 @@ sub has_children($$) { return 0; } -######################################################################################## +################################################################################ # Return 1 if the given device has a parent. -######################################################################################## +################################################################################ sub has_parent($$) { my ($self, $device) = @_; @@ -1032,9 +1032,9 @@ sub has_parent($$) { return 0; } -######################################################################################## +################################################################################ # Returns 1 if the device belongs to one of the scanned subnets. -######################################################################################## +################################################################################ sub in_subnet($$) { my ($self, $device) = @_; $device = ip_to_long($device); @@ -1051,10 +1051,10 @@ sub in_subnet($$) { return 0; } -########################################################################## +################################################################################ # Check for switches that are connected to other switches/routers and show # up in a switch/router's port. -########################################################################## +################################################################################ sub is_switch_connected($$$) { my ($self, $device, $iface) = @_; @@ -1066,9 +1066,9 @@ sub is_switch_connected($$$) { return 0; } -######################################################################################## +################################################################################ # Returns 1 if the given device has already been visited, 0 otherwise. -######################################################################################## +################################################################################ sub is_visited($$) { my ($self, $device) = @_; @@ -1082,10 +1082,10 @@ sub is_visited($$) { return 0; } -######################################################################################## +################################################################################ # Returns 1 if the given device has responded successfully to a snmp request # Returns 0 otherwise. -######################################################################################## +################################################################################ sub is_snmp_discovered($$) { my ($self, $device) = @_; @@ -1093,9 +1093,9 @@ sub is_snmp_discovered($$) { return (defined($self->{'discovered_cache'}->{$device})) ? 1 : 0; } -######################################################################################## +################################################################################ # Mark the given devices as connected to each other on the given interfaces. -######################################################################################## +################################################################################ sub mark_connected($$;$$$) { my ($self, $parent, $parent_if, $child, $child_if) = @_; @@ -1125,9 +1125,9 @@ sub mark_connected($$;$$$) { } } -######################################################################################## +################################################################################ # Mark the given switch as having a connection on the given interface. -######################################################################################## +################################################################################ sub mark_switch_connected($$$) { my ($self, $device, $iface) = @_; @@ -1136,9 +1136,9 @@ sub mark_switch_connected($$$) { $self->{'switch_to_switch'}->{"${device}\t${iface}"} = 1; } -######################################################################################## +################################################################################ # Mark the given device as visited. -######################################################################################## +################################################################################ sub mark_visited($$) { my ($self, $device) = @_; @@ -1148,20 +1148,20 @@ sub mark_visited($$) { }; } -######################################################################################## +################################################################################ # Mark the given device as snmp discovered. -######################################################################################## +################################################################################ sub mark_discovered($$) { my ($self, $device) = @_; $self->{'discovered_cache'}->{$device} = 1; } -######################################################################################## +################################################################################ # Validate the configuration for the given device. # Returns 1 if successfull snmp contact, 0 otherwise. # Updates the SNMP community cache on v1, v2 and v2c. -######################################################################################## +################################################################################ sub snmp_responds($$) { my ($self, $device) = @_; @@ -1172,10 +1172,10 @@ sub snmp_responds($$) { : $self->snmp_responds_v122c($device); } -######################################################################################## +################################################################################ # Looks for a working SNMP community for the given device. Returns 1 if one is # found, 0 otherwise. Updates the SNMP community cache. -######################################################################################## +################################################################################ sub snmp_responds_v122c($$) { my ($self, $device) = @_; @@ -1197,10 +1197,10 @@ sub snmp_responds_v122c($$) { } -######################################################################################## +################################################################################ # Validate the SNMP v3 configuration for a device. # Returns 1 if successfull snmp contact, 0 otherwise. -######################################################################################## +################################################################################ sub snmp_responds_v3($$) { my ($self, $device) = @_; @@ -1215,9 +1215,9 @@ sub snmp_responds_v3($$) { return 0; } -############################################################################## +################################################################################ # Parse the local ARP cache. -############################################################################## +################################################################################ sub local_arp($) { my ($self) = @_; @@ -1228,9 +1228,9 @@ sub local_arp($) { } } -############################################################################## +################################################################################ # Parse remote SNMP ARP caches. -############################################################################## +################################################################################ sub remote_arp($$) { my ($self, $device) = @_; @@ -1263,9 +1263,9 @@ sub remote_arp($$) { } } -############################################################################## +################################################################################ # Ping the given host. Returns 1 if the host is alive, 0 otherwise. -############################################################################## +################################################################################ sub ping ($$$) { my ($self, $host) = @_; my ($timeout, $retries, $packets) = ($self->{'icmp_timeout'},$self->{'icmp_checks'},1,); @@ -1332,9 +1332,9 @@ sub ping ($$$) { return 0; } -########################################################################## +################################################################################ # Scan the given subnet. -########################################################################## +################################################################################ sub scan_subnet($) { my ($self) = @_; my $progress = 1; @@ -1432,9 +1432,9 @@ sub scan_subnet($) { } -########################################################################## +################################################################################ # Perform a Cloud scan -########################################################################## +################################################################################ sub cloud_scan($) { my $self = shift; my ($progress, $step); @@ -1483,9 +1483,9 @@ sub cloud_scan($) { } -########################################################################## +################################################################################ # Performs a database scan. -########################################################################## +################################################################################ sub database_scan($$$) { my ($self, $type, $obj, $global_percent, $targets) = @_; @@ -1562,9 +1562,9 @@ sub database_scan($$$) { } -########################################################################## +################################################################################ # Perform an Application scan. -########################################################################## +################################################################################ sub app_scan($) { my ($self) = @_; my ($progress, $step); @@ -1717,9 +1717,9 @@ sub app_scan($) { } -########################################################################## +################################################################################ # Perform a deployment scan. -########################################################################## +################################################################################ sub deploy_scan($) { my $self = shift; my ($progress, $step); @@ -1753,9 +1753,9 @@ sub deploy_scan($) { } -########################################################################## +################################################################################ # Perform a network scan. -########################################################################## +################################################################################ sub scan($) { my ($self) = @_; my ($progress, $step) = 1, 0; @@ -1854,27 +1854,27 @@ sub scan($) { } } -######################################################################################## +################################################################################ # Set an SNMP community for the given device. -######################################################################################## +################################################################################ sub set_community($$$) { my ($self, $device, $community) = @_; $self->{'community_cache'}->{$device} = $community; } -######################################################################################## +################################################################################ # Set the type of the given device. -######################################################################################## +################################################################################ sub set_device_type($$$) { my ($self, $device, $type) = @_; $self->{'visited_devices'}->{$device}->{'type'} = $type; } -######################################################################################## +################################################################################ # Performs an SNMP WALK and returns the response as an array. -######################################################################################## +################################################################################ sub snmp_get($$$) { my ($self, $device, $oid) = @_; my @output; @@ -1911,9 +1911,9 @@ sub snmp_get($$$) { return @output; } -######################################################################################## +################################################################################ # Get the snmpwalk command seing version 1, 2, 2c or 3. -######################################################################################## +################################################################################ sub snmp_get_command { my ($self, $device, $oid, $community, $vlan) = @_; $vlan = defined($vlan) ? "\@" . $vlan : ''; @@ -1938,10 +1938,10 @@ sub snmp_get_command { } -######################################################################################## +################################################################################ # Performs an SNMP WALK and returns the value of the given OID. Returns undef # on error. -######################################################################################## +################################################################################ sub snmp_get_value($$$) { my ($self, $device, $oid) = @_; @@ -1954,9 +1954,9 @@ sub snmp_get_value($$$) { return undef; } -######################################################################################## +################################################################################ # Performs an SNMP WALK and returns an array of values. -######################################################################################## +################################################################################ sub snmp_get_value_array($$$) { my ($self, $device, $oid) = @_; my @values; @@ -1970,9 +1970,9 @@ sub snmp_get_value_array($$$) { return @values; } -######################################################################################## +################################################################################ # Performs an SNMP WALK and returns a hash of values. -######################################################################################## +################################################################################ sub snmp_get_value_hash($$$) { my ($self, $device, $oid) = @_; my %values; @@ -1985,9 +1985,9 @@ sub snmp_get_value_hash($$$) { return %values; } -########################################################################## +################################################################################ # Connect the given host to its parent using traceroute. -########################################################################## +################################################################################ sub traceroute_connectivity($$) { my ($self, $host) = @_; @@ -2025,10 +2025,10 @@ sub traceroute_connectivity($$) { } } -########################################################################## +################################################################################ # Returns the credentials with which the host responds to WMI queries or # undef if it does not respond to WMI. -########################################################################## +################################################################################ sub responds_to_wmi { my ($self, $target) = @_; @@ -2049,9 +2049,9 @@ sub responds_to_wmi { return undef; } -########################################################################## +################################################################################ # Add wmi modules to the given host. -########################################################################## +################################################################################ sub wmi_scan { my ($self, $target) = @_; @@ -2087,13 +2087,13 @@ sub wmi_scan { } } -########################################################################## +################################################################################ # Extra: WMI imported methods. DO NOT EXPORT TO AVOID DOUBLE DEF. -########################################################################## +################################################################################ -########################################################################## +################################################################################ # Performs a wmi get requests and returns the response as an array. -########################################################################## +################################################################################ sub wmi_get { my ($self, $target, $auth, $query) = @_; @@ -2110,10 +2110,10 @@ sub wmi_get { return @output; } -########################################################################## +################################################################################ # Performs a WMI request and returns the requested column of the first row. # Returns undef on error. -########################################################################## +################################################################################ sub wmi_get_value { my ($self, $target, $auth, $query, $column) = @_; my @result; @@ -2129,10 +2129,10 @@ sub wmi_get_value { return $columns[$column]; } -########################################################################## +################################################################################ # Performs a WMI request and returns row values for the requested column # in an array. -########################################################################## +################################################################################ sub wmi_get_value_array { my ($self, $target, $auth, $query, $column) = @_; my @result; @@ -2149,9 +2149,9 @@ sub wmi_get_value_array { return @result; } -########################################################################## +################################################################################ # END: WMI imported methods. -########################################################################## +################################################################################ 1; __END__ From ce11d89953de6a59180ee0aaf8bd51742e778c09 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Fri, 13 Mar 2020 14:03:50 +0100 Subject: [PATCH 002/111] Frontent changes --- pandora_console/extras/mr/37.sql | 5 + .../pandoradb_migrate_6.0_to_7.0.mysql.sql | 18 +- .../godmode/wizards/HostDevices.class.php | 39 +- .../include/javascript/jquery.caret.min.js | 2 + .../include/javascript/jquery.tag-editor.js | 370 ++++++++++++++++++ .../javascript/jquery.tag-editor.min.js | 3 + .../include/styles/jquery.tag-editor.css | 146 +++++++ pandora_console/include/styles/wizard.css | 33 +- pandora_console/operation/events/events.php | 7 +- 9 files changed, 611 insertions(+), 12 deletions(-) create mode 100644 pandora_console/extras/mr/37.sql create mode 100644 pandora_console/include/javascript/jquery.caret.min.js create mode 100644 pandora_console/include/javascript/jquery.tag-editor.js create mode 100644 pandora_console/include/javascript/jquery.tag-editor.min.js create mode 100644 pandora_console/include/styles/jquery.tag-editor.css diff --git a/pandora_console/extras/mr/37.sql b/pandora_console/extras/mr/37.sql new file mode 100644 index 0000000000..a2318348ef --- /dev/null +++ b/pandora_console/extras/mr/37.sql @@ -0,0 +1,5 @@ +START TRANSACTION; + +ALTER TABLE trecon_task modify column `id_network_profile` text; + +COMMIT; \ No newline at end of file diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index d9fe58ee64..2e1d1354a8 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -1656,7 +1656,23 @@ ALTER TABLE `trecon_task` ADD COLUMN `type` int(11) NOT NULL DEFAULT '0', MODIFY COLUMN `wmi_enabled` tinyint(1) unsigned NULL DEFAULT '0', MODIFY COLUMN `auth_strings` text NULL, MODIFY COLUMN `autoconfiguration_enabled` tinyint(1) unsigned NULL DEFAULT '0', - MODIFY COLUMN `summary` text NULL; + MODIFY COLUMN `summary` text NULL, + MODIFY COLUMN `id_network_profile` text; + +-- ---------------------------------------------------------------------- +-- Table `tdiscovery_tmp` +-- ---------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `tdiscovery_tmp` ( + `id` int(10) unsigned NOT NULL auto_increment, + `id_rt` int(10) unsigned NOT NULL, + `label` varchar(600) BINARY NOT NULL default '', + `data` text, + `review_date` datetime, + `created` int(1) unsigned NOT NULL default 0, + PRIMARY KEY (`id`), + FOREIGN KEY (`id_rt`) REFERENCES `trecon_task`(`id_rt`) + ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- --------------------------------------------------------------------- -- Table `twidget` AND Table `twidget_dashboard` diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php index d40e174573..265e48d821 100755 --- a/pandora_console/godmode/wizards/HostDevices.class.php +++ b/pandora_console/godmode/wizards/HostDevices.class.php @@ -1,6 +1,6 @@ task['snmp_community'] = $snmp_context; @@ -449,7 +449,14 @@ class HostDevices extends Wizard } $this->task['autoconfiguration_enabled'] = $autoconf_enabled; - $this->task['id_network_profile'] = $id_network_profile; + $this->task['id_network_profile'] = ''; + if (is_array($id_network_profile) === true) { + $this->task['id_network_profile'] = join( + ',', + $id_network_profile + ); + } + $this->task['snmp_enabled'] = $snmp_enabled; $this->task['os_detect'] = $os_detect; $this->task['parent_detection'] = $parent_detection; @@ -464,7 +471,13 @@ class HostDevices extends Wizard $this->task['snmp_privacy_pass'] = $snmp_privacy_pass; $this->task['snmp_auth_method'] = $snmp_auth_method; $this->task['snmp_security_level'] = $snmp_security_level; - $this->task['auth_strings'] = $auth_strings; + $this->task['auth_strings'] = ''; + if (is_array($auth_strings) === true) { + $this->task['auth_strings'] = join( + ',', + $auth_strings + ); + } if ($this->task['disabled'] == 2) { // Wizard finished. @@ -875,21 +888,29 @@ class HostDevices extends Wizard ]; $form['inputs'][] = [ - 'extra' => '

Please, configure task '.io_safe_output( + 'extra' => '

Please, customize task '.io_safe_output( $this->task['name'] ).'

', ]; $form['inputs'][] = [ - 'label' => __('Module template'), + 'label' => __('Module templates').ui_print_help_tip( + __( + 'Module Host Alive will be added to discovered agents by default.' + ), + true + ), 'arguments' => [ - 'name' => 'id_network_profile', + 'name' => 'id_network_profile[]', 'type' => 'select_from_sql', 'sql' => 'SELECT id_np, name FROM tnetwork_profile ORDER BY name', 'return' => true, - 'selected' => $this->task['id_network_profile'], + 'selected' => explode( + ',', + $this->task['id_network_profile'] + ), 'nothing_value' => 0, 'nothing' => __('None'), 'multiple' => true, diff --git a/pandora_console/include/javascript/jquery.caret.min.js b/pandora_console/include/javascript/jquery.caret.min.js new file mode 100644 index 0000000000..0f9ef48d6e --- /dev/null +++ b/pandora_console/include/javascript/jquery.caret.min.js @@ -0,0 +1,2 @@ +// http://code.accursoft.com/caret - 1.3.3 +!function(e){e.fn.caret=function(e){var t=this[0],n="true"===t.contentEditable;if(0==arguments.length){if(window.getSelection){if(n){t.focus();var o=window.getSelection().getRangeAt(0),r=o.cloneRange();return r.selectNodeContents(t),r.setEnd(o.endContainer,o.endOffset),r.toString().length}return t.selectionStart}if(document.selection){if(t.focus(),n){var o=document.selection.createRange(),r=document.body.createTextRange();return r.moveToElementText(t),r.setEndPoint("EndToEnd",o),r.text.length}var e=0,c=t.createTextRange(),r=document.selection.createRange().duplicate(),a=r.getBookmark();for(c.moveToBookmark(a);0!==c.moveStart("character",-1);)e++;return e}return t.selectionStart?t.selectionStart:0}if(-1==e&&(e=this[n?"text":"val"]().length),window.getSelection)n?(t.focus(),window.getSelection().collapse(t.firstChild,e)):t.setSelectionRange(e,e);else if(document.body.createTextRange)if(n){var c=document.body.createTextRange();c.moveToElementText(t),c.moveStart("character",e),c.collapse(!0),c.select()}else{var c=t.createTextRange();c.move("character",e),c.select()}return n||t.focus(),e}}(jQuery); diff --git a/pandora_console/include/javascript/jquery.tag-editor.js b/pandora_console/include/javascript/jquery.tag-editor.js new file mode 100644 index 0000000000..719ae04225 --- /dev/null +++ b/pandora_console/include/javascript/jquery.tag-editor.js @@ -0,0 +1,370 @@ +/* + jQuery tagEditor v1.0.21 + Copyright (c) 2014 Simon Steinberger / Pixabay + GitHub: https://github.com/Pixabay/jQuery-tagEditor + License: http://www.opensource.org/licenses/mit-license.php +*/ + +(function($){ + // auto grow input (stackoverflow.com/questions/931207) + $.fn.tagEditorInput=function(){var t=" ",e=$(this),n=parseInt(e.css("fontSize")),i=$("").css({position:"absolute",top:-9999,left:-9999,width:"auto",fontSize:e.css("fontSize"),fontFamily:e.css("fontFamily"),fontWeight:e.css("fontWeight"),letterSpacing:e.css("letterSpacing"),whiteSpace:"nowrap"}),s=function(){if(t!==(t=e.val())){i.text(t);var s=i.width()+n;20>s&&(s=20),s!=e.width()&&e.width(s)}};return i.insertAfter(e),e.bind("keyup keydown focus",s)}; + + // plugin with val as parameter for public methods + $.fn.tagEditor = function(options, val, blur){ + + // helper + function escape(tag) { + return tag.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); + } + + // build options dictionary with default values + var blur_result, o = $.extend({}, $.fn.tagEditor.defaults, options), selector = this; + + // store regex and default delimiter in options for later use + o.dregex = new RegExp('['+o.delimiter.replace('-', '\-')+']', 'g'); + + // public methods + if (typeof options == 'string') { + // depending on selector, response may contain tag lists of multiple editor instances + var response = []; + selector.each(function(){ + // the editor is the next sibling to the hidden, original field + var el = $(this), o = el.data('options'), ed = el.next('.tag-editor'); + if (options == 'getTags') + response.push({field: el[0], editor: ed, tags: ed.data('tags')}); + else if (options == 'addTag') { + if (o.maxTags && ed.data('tags').length >= o.maxTags) return false; + // insert new tag + $('
  •  '+o.delimiter[0]+'
  • ').appendTo(ed).find('.tag-editor-tag') + .html('').addClass('active').find('input').val(val).blur(); + if (!blur) ed.click(); + else $('.placeholder', ed).remove(); + } else if (options == 'removeTag') { + // trigger delete on matching tag, then click editor to create a new tag + $('.tag-editor-tag', ed).filter(function(){return $(this).text()==val;}).closest('li').find('.tag-editor-delete').click(); + if (!blur) ed.click(); + } else if (options == 'destroy') { + el.removeClass('tag-editor-hidden-src').removeData('options').off('focus.tag-editor').next('.tag-editor').remove(); + } + }); + return options == 'getTags' ? response : this; + } + + // delete selected tags on backspace, delete, ctrl+x + if (window.getSelection) $(document).off('keydown.tag-editor').on('keydown.tag-editor', function(e){ + if (e.which == 8 || e.which == 46 || e.ctrlKey && e.which == 88) { + try { + var sel = getSelection(), el = document.activeElement.tagName != 'INPUT' ? $(sel.getRangeAt(0).startContainer.parentNode).closest('.tag-editor') : 0; + } catch(e){ el = 0; } + if (sel.rangeCount > 0 && el && el.length) { + var tags = [], splits = sel.toString().split(el.prev().data('options').dregex); + for (i=0; i').insertAfter(el); + el.addClass('tag-editor-hidden-src') // hide original field + .data('options', o) // set data on hidden field + .on('focus.tag-editor', function(){ ed.click(); }); // simulate tabindex + + // add dummy item for min-height on empty editor + ed.append('
  •  
  • '); + + // markup for new tag + var new_tag = '
  •  '+o.delimiter[0]+'
  • '; + + // helper: update global data + function set_placeholder(){ + if (o.placeholder && !tag_list.length && !$('.deleted, .placeholder, input', ed).length) + ed.append('
  • '+o.placeholder+'
  • '); + } + + // helper: update global data + function update_globals(init){ + var old_tags = tag_list.toString(); + tag_list = $('.tag-editor-tag:not(.deleted)', ed).map(function(i, e) { + var val = $.trim($(this).hasClass('active') ? $(this).find('input').val() : $(e).text()); + if (val) return val; + }).get(); + ed.data('tags', tag_list); + el.val(tag_list.join(o.delimiter[0])); + // change callback except for plugin init + if (!init) if (old_tags != tag_list.toString()) o.onChange(el, ed, tag_list); + set_placeholder(); + } + + ed.click(function(e, closest_tag){ + var d, dist = 99999, loc; + + // do not create tag when user selects tags by text selection + if (window.getSelection && getSelection() != '') return; + + if (o.maxTags && ed.data('tags').length >= o.maxTags) { ed.find('input').blur(); return false; } + + blur_result = true + $('input:focus', ed).blur(); + if (!blur_result) return false; + blur_result = true + + // always remove placeholder on click + $('.placeholder', ed).remove(); + if (closest_tag && closest_tag.length) + loc = 'before'; + else { + // calculate tag closest to click position + $('.tag-editor-tag', ed).each(function(){ + var tag = $(this), to = tag.offset(), tag_x = to.left, tag_y = to.top; + if (e.pageY >= tag_y && e.pageY <= tag_y+tag.height()) { + if (e.pageX < tag_x) loc = 'before', d = tag_x - e.pageX; + else loc = 'after', d = e.pageX - tag_x - tag.width(); + if (d < dist) dist = d, closest_tag = tag; + } + }); + } + + if (loc == 'before') { + $(new_tag).insertBefore(closest_tag.closest('li')).find('.tag-editor-tag').click(); + } else if (loc == 'after') + $(new_tag).insertAfter(closest_tag.closest('li')).find('.tag-editor-tag').click(); + else // empty editor + $(new_tag).appendTo(ed).find('.tag-editor-tag').click(); + return false; + }); + + ed.on('click', '.tag-editor-delete', function(e){ + // delete icon is hidden when input is visible; place cursor near invisible delete icon on click + if ($(this).prev().hasClass('active')) { $(this).closest('li').find('input').caret(-1); return false; } + + var li = $(this).closest('li'), tag = li.find('.tag-editor-tag'); + if (o.beforeTagDelete(el, ed, tag_list, tag.text()) === false) return false; + tag.addClass('deleted').animate({width: 0}, o.animateDelete, function(){ li.remove(); set_placeholder(); }); + update_globals(); + return false; + }); + + // delete on right mouse click or ctrl+click + if (o.clickDelete) + ed.on('mousedown', '.tag-editor-tag', function(e){ + if (e.ctrlKey || e.which > 1) { + var li = $(this).closest('li'), tag = li.find('.tag-editor-tag'); + if (o.beforeTagDelete(el, ed, tag_list, tag.text()) === false) return false; + tag.addClass('deleted').animate({width: 0}, o.animateDelete, function(){ li.remove(); set_placeholder(); }); + update_globals(); + return false; + } + }); + + ed.on('click', '.tag-editor-tag', function(e){ + // delete on right click or ctrl+click -> exit + if (o.clickDelete && (e.ctrlKey || e.which > 1)) return false; + + if (!$(this).hasClass('active')) { + var tag = $(this).text(); + // guess cursor position in text input + var left_percent = Math.abs(($(this).offset().left - e.pageX)/$(this).width()), caret_pos = parseInt(tag.length*left_percent), + input = $(this).html('').addClass('active').find('input'); + input.data('old_tag', tag).tagEditorInput().focus().caret(caret_pos); + if (o.autocomplete) { + var aco = $.extend({}, o.autocomplete); + // extend user provided autocomplete select method + var ac_select = 'select' in aco ? o.autocomplete.select : ''; + aco.select = function(e, ui){ if (ac_select) ac_select(e, ui); setTimeout(function(){ + ed.trigger('click', [$('.active', ed).find('input').closest('li').next('li').find('.tag-editor-tag')]); + }, 20); }; + input.autocomplete(aco); + } + } + return false; + }); + + // helper: split into multiple tags, e.g. after paste + function split_cleanup(input){ + var li = input.closest('li'), sub_tags = input.val().replace(/ +/, ' ').split(o.dregex), + old_tag = input.data('old_tag'), old_tags = tag_list.slice(0), exceeded = false, cb_val; // copy tag_list + for (var i=0; i
     '+o.delimiter[0]+'
    '+escape(tag)+'
    '); + if (o.maxTags && old_tags.length >= o.maxTags) { exceeded = true; break; } + } + input.attr('maxlength', o.maxLength).removeData('old_tag').val('') + if (exceeded) input.blur(); else input.focus(); + update_globals(); + } + + ed.on('blur', 'input', function(e){ + e.stopPropagation(); + var input = $(this), old_tag = input.data('old_tag'), tag = $.trim(input.val().replace(/ +/, ' ').replace(o.dregex, o.delimiter[0])); + if (!tag) { + if (old_tag && o.beforeTagDelete(el, ed, tag_list, old_tag) === false) { + input.val(old_tag).focus(); + blur_result = false; + update_globals(); + return; + } + try { input.closest('li').remove(); } catch(e){} + if (old_tag) update_globals(); + } + else if (tag.indexOf(o.delimiter[0])>=0) { split_cleanup(input); return; } + else if (tag != old_tag) { + if (o.forceLowercase) tag = tag.toLowerCase(); + cb_val = o.beforeTagSave(el, ed, tag_list, old_tag, tag); + tag = cb_val || tag; + if (cb_val === false) { + if (old_tag) { + input.val(old_tag).focus(); + blur_result = false; + update_globals(); + return; + } + try { input.closest('li').remove(); } catch(e){} + if (old_tag) update_globals(); + } + // remove duplicates + else if (o.removeDuplicates) + $('.tag-editor-tag:not(.active)', ed).each(function(){ if ($(this).text() == tag) $(this).closest('li').remove(); }); + } + input.parent().html(escape(tag)).removeClass('active'); + if (tag != old_tag) update_globals(); + set_placeholder(); + }); + + var pasted_content; + ed.on('paste', 'input', function(e){ + $(this).removeAttr('maxlength'); + pasted_content = $(this); + setTimeout(function(){ split_cleanup(pasted_content); }, 30); + }); + + // keypress delimiter + var inp; + ed.on('keypress', 'input', function(e){ + if (o.delimiter.indexOf(String.fromCharCode(e.which))>=0) { + inp = $(this); + setTimeout(function(){ split_cleanup(inp); }, 20); + } + }); + + ed.on('keydown', 'input', function(e){ + var $t = $(this); + + // left/up key + backspace key on empty field + if ((e.which == 37 || !o.autocomplete && e.which == 38) && !$t.caret() || e.which == 8 && !$t.val()) { + var prev_tag = $t.closest('li').prev('li').find('.tag-editor-tag'); + if (prev_tag.length) prev_tag.click().find('input').caret(-1); + else if ($t.val() && !(o.maxTags && ed.data('tags').length >= o.maxTags)) $(new_tag).insertBefore($t.closest('li')).find('.tag-editor-tag').click(); + return false; + } + // right/down key + else if ((e.which == 39 || !o.autocomplete && e.which == 40) && ($t.caret() == $t.val().length)) { + var next_tag = $t.closest('li').next('li').find('.tag-editor-tag'); + if (next_tag.length) next_tag.click().find('input').caret(0); + else if ($t.val()) ed.click(); + return false; + } + // tab key + else if (e.which == 9) { + // shift+tab + if (e.shiftKey) { + var prev_tag = $t.closest('li').prev('li').find('.tag-editor-tag'); + if (prev_tag.length) prev_tag.click().find('input').caret(0); + else if ($t.val() && !(o.maxTags && ed.data('tags').length >= o.maxTags)) $(new_tag).insertBefore($t.closest('li')).find('.tag-editor-tag').click(); + // allow tabbing to previous element + else { + el.attr('disabled', 'disabled'); + setTimeout(function(){ el.removeAttr('disabled'); }, 30); + return; + } + return false; + // tab + } else { + var next_tag = $t.closest('li').next('li').find('.tag-editor-tag'); + if (next_tag.length) next_tag.click().find('input').caret(0); + else if ($t.val()) ed.click(); + else return; // allow tabbing to next element + return false; + } + } + // del key + else if (e.which == 46 && (!$.trim($t.val()) || ($t.caret() == $t.val().length))) { + var next_tag = $t.closest('li').next('li').find('.tag-editor-tag'); + if (next_tag.length) next_tag.click().find('input').caret(0); + else if ($t.val()) ed.click(); + return false; + } + // enter key + else if (e.which == 13) { + ed.trigger('click', [$t.closest('li').next('li').find('.tag-editor-tag')]); + + // trigger blur if maxTags limit is reached + if (o.maxTags && ed.data('tags').length >= o.maxTags) ed.find('input').blur(); + + return false; + } + // pos1 + else if (e.which == 36 && !$t.caret()) ed.find('.tag-editor-tag').first().click(); + // end + else if (e.which == 35 && $t.caret() == $t.val().length) ed.find('.tag-editor-tag').last().click(); + // esc + else if (e.which == 27) { + $t.val($t.data('old_tag') ? $t.data('old_tag') : '').blur(); + return false; + } + }); + + // create initial tags + var tags = o.initialTags.length ? o.initialTags : el.val().split(o.dregex); + for (var i=0; i= o.maxTags) break; + var tag = $.trim(tags[i].replace(/ +/, ' ')); + if (tag) { + if (o.forceLowercase) tag = tag.toLowerCase(); + tag_list.push(tag); + ed.append('
  •  '+o.delimiter[0]+'
    '+escape(tag)+'
  • '); + } + } + update_globals(true); // true -> no onChange callback + + // init sortable + if (o.sortable && $.fn.sortable) ed.sortable({ + distance: 5, cancel: '.tag-editor-spacer, input', helper: 'clone', + update: function(){ update_globals(); } + }); + }); + }; + + $.fn.tagEditor.defaults = { + initialTags: [], + maxTags: 0, + maxLength: 50, + delimiter: ',;', + placeholder: '', + forceLowercase: true, + removeDuplicates: true, + clickDelete: false, + animateDelete: 175, + sortable: true, // jQuery UI sortable + autocomplete: null, // options dict for jQuery UI autocomplete + + // callbacks + onChange: function(){}, + beforeTagSave: function(){}, + beforeTagDelete: function(){} + }; +}(jQuery)); diff --git a/pandora_console/include/javascript/jquery.tag-editor.min.js b/pandora_console/include/javascript/jquery.tag-editor.min.js new file mode 100644 index 0000000000..94293448f0 --- /dev/null +++ b/pandora_console/include/javascript/jquery.tag-editor.min.js @@ -0,0 +1,3 @@ +// jQuery tagEditor v1.0.21 +// https://github.com/Pixabay/jQuery-tagEditor +!function(t){t.fn.tagEditorInput=function(){var e=" ",i=t(this),a=parseInt(i.css("fontSize")),r=t("").css({position:"absolute",top:-9999,left:-9999,width:"auto",fontSize:i.css("fontSize"),fontFamily:i.css("fontFamily"),fontWeight:i.css("fontWeight"),letterSpacing:i.css("letterSpacing"),whiteSpace:"nowrap"}),l=function(){if(e!==(e=i.val())){r.text(e);var t=r.width()+a;20>t&&(t=20),t!=i.width()&&i.width(t)}};return r.insertAfter(i),i.bind("keyup keydown focus",l)},t.fn.tagEditor=function(e,a,r){function l(t){return t.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}var n,o=t.extend({},t.fn.tagEditor.defaults,e),c=this;if(o.dregex=new RegExp("["+o.delimiter.replace("-","-")+"]","g"),"string"==typeof e){var s=[];return c.each(function(){var i=t(this),l=i.data("options"),n=i.next(".tag-editor");if("getTags"==e)s.push({field:i[0],editor:n,tags:n.data("tags")});else if("addTag"==e){if(l.maxTags&&n.data("tags").length>=l.maxTags)return!1;t('
  •  '+l.delimiter[0]+'
  • ').appendTo(n).find(".tag-editor-tag").html('').addClass("active").find("input").val(a).blur(),r?t(".placeholder",n).remove():n.click()}else"removeTag"==e?(t(".tag-editor-tag",n).filter(function(){return t(this).text()==a}).closest("li").find(".tag-editor-delete").click(),r||n.click()):"destroy"==e&&i.removeClass("tag-editor-hidden-src").removeData("options").off("focus.tag-editor").next(".tag-editor").remove()}),"getTags"==e?s:this}return window.getSelection&&t(document).off("keydown.tag-editor").on("keydown.tag-editor",function(e){if(8==e.which||46==e.which||e.ctrlKey&&88==e.which){try{var a=getSelection(),r="INPUT"!=document.activeElement.tagName?t(a.getRangeAt(0).startContainer.parentNode).closest(".tag-editor"):0}catch(e){r=0}if(a.rangeCount>0&&r&&r.length){var l=[],n=a.toString().split(r.prev().data("options").dregex);for(i=0;i
    '+o.placeholder+"
    ")}function i(i){var a=c.toString();c=t(".tag-editor-tag:not(.deleted)",s).map(function(e,i){var a=t.trim(t(this).hasClass("active")?t(this).find("input").val():t(i).text());return a?a:void 0}).get(),s.data("tags",c),r.val(c.join(o.delimiter[0])),i||a!=c.toString()&&o.onChange(r,s,c),e()}function a(e){for(var a,n=e.closest("li"),d=e.val().replace(/ +/," ").split(o.dregex),g=e.data("old_tag"),f=c.slice(0),h=!1,u=0;u
     '+o.delimiter[0]+'
    '+l(v)+'
    '),o.maxTags&&f.length>=o.maxTags)){h=!0;break}e.attr("maxlength",o.maxLength).removeData("old_tag").val(""),h?e.blur():e.focus(),i()}var r=t(this),c=[],s=t("
      ').insertAfter(r);r.addClass("tag-editor-hidden-src").data("options",o).on("focus.tag-editor",function(){s.click()}),s.append('
    •  
    • ');var d='
    •  '+o.delimiter[0]+'
    • ';s.click(function(e,i){var a,r,l=99999;if(!window.getSelection||""==getSelection())return o.maxTags&&s.data("tags").length>=o.maxTags?(s.find("input").blur(),!1):(n=!0,t("input:focus",s).blur(),n?(n=!0,t(".placeholder",s).remove(),i&&i.length?r="before":t(".tag-editor-tag",s).each(function(){var n=t(this),o=n.offset(),c=o.left,s=o.top;e.pageY>=s&&e.pageY<=s+n.height()&&(e.pageXa&&(l=a,i=n))}),"before"==r?t(d).insertBefore(i.closest("li")).find(".tag-editor-tag").click():"after"==r?t(d).insertAfter(i.closest("li")).find(".tag-editor-tag").click():t(d).appendTo(s).find(".tag-editor-tag").click(),!1):!1)}),s.on("click",".tag-editor-delete",function(){if(t(this).prev().hasClass("active"))return t(this).closest("li").find("input").caret(-1),!1;var a=t(this).closest("li"),l=a.find(".tag-editor-tag");return o.beforeTagDelete(r,s,c,l.text())===!1?!1:(l.addClass("deleted").animate({width:0},o.animateDelete,function(){a.remove(),e()}),i(),!1)}),o.clickDelete&&s.on("mousedown",".tag-editor-tag",function(a){if(a.ctrlKey||a.which>1){var l=t(this).closest("li"),n=l.find(".tag-editor-tag");return o.beforeTagDelete(r,s,c,n.text())===!1?!1:(n.addClass("deleted").animate({width:0},o.animateDelete,function(){l.remove(),e()}),i(),!1)}}),s.on("click",".tag-editor-tag",function(e){if(o.clickDelete&&(e.ctrlKey||e.which>1))return!1;if(!t(this).hasClass("active")){var i=t(this).text(),a=Math.abs((t(this).offset().left-e.pageX)/t(this).width()),r=parseInt(i.length*a),n=t(this).html('').addClass("active").find("input");if(n.data("old_tag",i).tagEditorInput().focus().caret(r),o.autocomplete){var c=t.extend({},o.autocomplete),d="select"in c?o.autocomplete.select:"";c.select=function(e,i){d&&d(e,i),setTimeout(function(){s.trigger("click",[t(".active",s).find("input").closest("li").next("li").find(".tag-editor-tag")])},20)},n.autocomplete(c)}}return!1}),s.on("blur","input",function(d){d.stopPropagation();var g=t(this),f=g.data("old_tag"),h=t.trim(g.val().replace(/ +/," ").replace(o.dregex,o.delimiter[0]));if(h){if(h.indexOf(o.delimiter[0])>=0)return void a(g);if(h!=f)if(o.forceLowercase&&(h=h.toLowerCase()),cb_val=o.beforeTagSave(r,s,c,f,h),h=cb_val||h,cb_val===!1){if(f)return g.val(f).focus(),n=!1,void i();try{g.closest("li").remove()}catch(d){}f&&i()}else o.removeDuplicates&&t(".tag-editor-tag:not(.active)",s).each(function(){t(this).text()==h&&t(this).closest("li").remove()})}else{if(f&&o.beforeTagDelete(r,s,c,f)===!1)return g.val(f).focus(),n=!1,void i();try{g.closest("li").remove()}catch(d){}f&&i()}g.parent().html(l(h)).removeClass("active"),h!=f&&i(),e()});var g;s.on("paste","input",function(){t(this).removeAttr("maxlength"),g=t(this),setTimeout(function(){a(g)},30)});var f;s.on("keypress","input",function(e){o.delimiter.indexOf(String.fromCharCode(e.which))>=0&&(f=t(this),setTimeout(function(){a(f)},20))}),s.on("keydown","input",function(e){var i=t(this);if((37==e.which||!o.autocomplete&&38==e.which)&&!i.caret()||8==e.which&&!i.val()){var a=i.closest("li").prev("li").find(".tag-editor-tag");return a.length?a.click().find("input").caret(-1):!i.val()||o.maxTags&&s.data("tags").length>=o.maxTags||t(d).insertBefore(i.closest("li")).find(".tag-editor-tag").click(),!1}if((39==e.which||!o.autocomplete&&40==e.which)&&i.caret()==i.val().length){var l=i.closest("li").next("li").find(".tag-editor-tag");return l.length?l.click().find("input").caret(0):i.val()&&s.click(),!1}if(9==e.which){if(e.shiftKey){var a=i.closest("li").prev("li").find(".tag-editor-tag");if(a.length)a.click().find("input").caret(0);else{if(!i.val()||o.maxTags&&s.data("tags").length>=o.maxTags)return r.attr("disabled","disabled"),void setTimeout(function(){r.removeAttr("disabled")},30);t(d).insertBefore(i.closest("li")).find(".tag-editor-tag").click()}return!1}var l=i.closest("li").next("li").find(".tag-editor-tag");if(l.length)l.click().find("input").caret(0);else{if(!i.val())return;s.click()}return!1}if(!(46!=e.which||t.trim(i.val())&&i.caret()!=i.val().length)){var l=i.closest("li").next("li").find(".tag-editor-tag");return l.length?l.click().find("input").caret(0):i.val()&&s.click(),!1}if(13==e.which)return s.trigger("click",[i.closest("li").next("li").find(".tag-editor-tag")]),o.maxTags&&s.data("tags").length>=o.maxTags&&s.find("input").blur(),!1;if(36!=e.which||i.caret()){if(35==e.which&&i.caret()==i.val().length)s.find(".tag-editor-tag").last().click();else if(27==e.which)return i.val(i.data("old_tag")?i.data("old_tag"):"").blur(),!1}else s.find(".tag-editor-tag").first().click()});for(var h=o.initialTags.length?o.initialTags:r.val().split(o.dregex),u=0;u=o.maxTags);u++){var v=t.trim(h[u].replace(/ +/," "));v&&(o.forceLowercase&&(v=v.toLowerCase()),c.push(v),s.append('
    •  '+o.delimiter[0]+'
      '+l(v)+'
    • '))}i(!0),o.sortable&&t.fn.sortable&&s.sortable({distance:5,cancel:".tag-editor-spacer, input",helper:"clone",update:function(){i()}})})},t.fn.tagEditor.defaults={initialTags:[],maxTags:0,maxLength:50,delimiter:",;",placeholder:"",forceLowercase:!0,removeDuplicates:!0,clickDelete:!1,animateDelete:175,sortable:!0,autocomplete:null,onChange:function(){},beforeTagSave:function(){},beforeTagDelete:function(){}}}(jQuery); \ No newline at end of file diff --git a/pandora_console/include/styles/jquery.tag-editor.css b/pandora_console/include/styles/jquery.tag-editor.css new file mode 100644 index 0000000000..0823e50d2e --- /dev/null +++ b/pandora_console/include/styles/jquery.tag-editor.css @@ -0,0 +1,146 @@ +/* surrounding tag container */ +.tag-editor { + list-style-type: none; + padding: 0 5px 0 0; + margin: 0; + overflow: hidden; + border: 1px solid #eee; + cursor: text; + font: normal 14px sans-serif; + color: #555; + background: #fff; + line-height: 20px; +} + +/* core styles usually need no change */ +.tag-editor li { + display: block; + float: left; + overflow: hidden; + margin: 3px 0; +} +.tag-editor div { + float: left; + padding: 0 4px; +} +.tag-editor .placeholder { + padding: 0 8px; + color: #bbb; +} +.tag-editor .tag-editor-spacer { + padding: 0; + width: 8px; + overflow: hidden; + color: transparent; + background: none; +} +.tag-editor input { + vertical-align: inherit; + border: 0; + outline: none; + padding: 0; + margin: 0; + cursor: text; + font-family: inherit; + font-weight: inherit; + font-size: inherit; + font-style: inherit; + box-shadow: none; + background: none; + color: #444; +} +/* hide original input field or textarea visually to allow tab navigation */ +.tag-editor-hidden-src { + position: absolute !important; + left: -99999px; +} +/* hide IE10 "clear field" X */ +.tag-editor ::-ms-clear { + display: none; +} + +/* tag style */ +.tag-editor .tag-editor-tag { + padding-left: 5px; + color: #46799b; + background: #e0eaf1; + white-space: nowrap; + overflow: hidden; + cursor: pointer; + border-radius: 2px 0 0 2px; +} + +/* delete icon */ +.tag-editor .tag-editor-delete { + background: #e0eaf1; + cursor: pointer; + border-radius: 0 2px 2px 0; + padding-left: 3px; + padding-right: 4px; +} +.tag-editor .tag-editor-delete i { + line-height: 18px; + display: inline-block; +} +.tag-editor .tag-editor-delete i:before { + font-size: 16px; + color: #8ba7ba; + content: "×"; + font-style: normal; +} +.tag-editor .tag-editor-delete:hover i:before { + color: #d65454; +} +.tag-editor .tag-editor-tag.active + .tag-editor-delete, +.tag-editor .tag-editor-tag.active + .tag-editor-delete i { + visibility: hidden; + cursor: text; +} + +.tag-editor .tag-editor-tag.active { + background: none !important; +} + +/* jQuery UI autocomplete - code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css */ +.ui-autocomplete { + position: absolute; + top: 0; + left: 0; + cursor: default; + font-size: 14px; +} +.ui-front { + z-index: 9999; +} +.ui-menu { + list-style: none; + padding: 1px; + margin: 0; + display: block; + outline: none; +} +.ui-menu .ui-menu-item a { + text-decoration: none; + display: block; + padding: 2px 0.4em; + line-height: 1.4; + min-height: 0; /* support: IE7 */ +} +.ui-widget-content { + border: 1px solid #bbb; + background: #fff; + color: #555; +} +.ui-widget-content a { + color: #46799b; +} +.ui-widget-content .ui-state-hover, +.ui-widget-header .ui-state-hover, +.ui-state-focus, +.ui-widget-content .ui-state-focus, +.ui-widget-header .ui-state-focus { + background: #e0eaf1; +} +.ui-helper-hidden-accessible { + display: none; +} diff --git a/pandora_console/include/styles/wizard.css b/pandora_console/include/styles/wizard.css index 029addf5cb..366c60c1ae 100644 --- a/pandora_console/include/styles/wizard.css +++ b/pandora_console/include/styles/wizard.css @@ -23,6 +23,37 @@ ul.wizard li > textarea { font-family: monospace; } -.hidden { +.wizard .hidden { display: none; } + +.wizard .indented { + margin-left: 2em; +} + +/* override tag-editor styles */ +.wizard .tag-editor.ui-sortable { + width: 450px; + display: inline-block; +} + +.wizard .tag-editor .tag-editor-tag { + padding: 5px; + color: #fff; + background: #82b92e; +} + +.wizard .tag-editor .tag-editor-delete i { + line-height: inherit; +} +.wizard .tag-editor .tag-editor-delete i:before { + color: #ccc; +} +.wizard .tag-editor .tag-editor-delete:hover i:before { + color: #fff; +} + +.wizard .tag-editor .tag-editor-delete { + padding: 5px; + background: #e63c52; +} diff --git a/pandora_console/operation/events/events.php b/pandora_console/operation/events/events.php index 3c758fde12..ff7513fcff 100644 --- a/pandora_console/operation/events/events.php +++ b/pandora_console/operation/events/events.php @@ -328,6 +328,8 @@ if (is_ajax()) { $data = array_reduce( $events, function ($carry, $item) { + global $config; + $tmp = (object) $item; $tmp->meta = is_metaconsole(); if (is_metaconsole()) { @@ -360,7 +362,10 @@ if (is_ajax()) { true ); - $tmp->data = format_numeric($tmp->data, 1); + $tmp->data = format_numeric( + $tmp->data, + $config['graph_precision'] + ); $tmp->instructions = events_get_instructions($item); From 106f8bd1cffd5a54d22e9b6c0be8e377d5e58ce5 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 16 Mar 2020 20:48:38 +0100 Subject: [PATCH 003/111] Created new files with Module Blocks and changed Menu entries --- pandora_console/godmode/menu.php | 6 +- .../modules/manage_block_templates.php | 71 ++++++++++++ .../include/class/ManageBlock.class.php | 103 ++++++++++++++++++ 3 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 pandora_console/godmode/modules/manage_block_templates.php create mode 100644 pandora_console/include/class/ManageBlock.class.php diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index b370bc2ac9..9522c7cb58 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -137,10 +137,12 @@ if (!empty($sub)) { $sub = []; if (check_acl($config['id_user'], 0, 'PM')) { - $sub['godmode/modules/manage_network_components']['text'] = __('Network components'); + $sub['godmode/modules/manage_network_components']['text'] = __('Remote components'); $sub['godmode/modules/manage_network_components']['id'] = 'Network components'; enterprise_hook('components_submenu'); - $sub['godmode/modules/manage_network_templates']['text'] = __('Module templates'); + $sub['godmode/modules/manage_block_templates']['text'] = __('Module blocks'); + $sub['godmode/modules/manage_block_templates']['id'] = 'Module blocks'; + $sub['godmode/modules/manage_network_templates']['text'] = __('Module templates (legacy)'); $sub['godmode/modules/manage_network_templates']['id'] = 'Module templates'; enterprise_hook('inventory_submenu'); enterprise_hook('autoconfiguration_menu'); diff --git a/pandora_console/godmode/modules/manage_block_templates.php b/pandora_console/godmode/modules/manage_block_templates.php new file mode 100644 index 0000000000..46ffe791a4 --- /dev/null +++ b/pandora_console/godmode/modules/manage_block_templates.php @@ -0,0 +1,71 @@ +getMessage(); + /* + if (is_ajax()) { + echo json_encode(['error' => '[MiFuncionalidad]'.$e->getMessage() ]); + exit; + } else { + echo '[MiFuncionalidad]'.$e->getMessage(); + } + */ + // Stop this execution, but continue 'globally'. + return; +} + +// AJAX controller. +if (is_ajax()) { + $method = get_parameter('method'); + /* + if (method_exists($miFuncionalidad, $method) === true) { + if ($miFuncionalidad>ajaxMethod($method) === true) { + $miFuncionalidad>{$method}(); + } else { + $miFuncionalidad>error('Unavailable method.'); + } + } else { + $miFuncionalidad->error('Method not found. ['.$method.']'); + } + */ + // Stop any execution. + exit; +} else { + // Run. + $manageBlock->run(); +} diff --git a/pandora_console/include/class/ManageBlock.class.php b/pandora_console/include/class/ManageBlock.class.php new file mode 100644 index 0000000000..62399a5db7 --- /dev/null +++ b/pandora_console/include/class/ManageBlock.class.php @@ -0,0 +1,103 @@ + 'noaccess']); + } + + include 'general/noaccess.php'; + exit; + } + + $this->ajaxController = $ajax_controller; + + $this->setBreadcrum([]); + + return $this; + } + + + /** + * Run MiFuncionalidad (main page). + * + * @return void + */ + public function run() + { + $this->prepareBreadcrum( + [ + [ + 'link' => 'mishuevos', + // $this->url, + 'label' => __('Configuration'), + 'selected' => 0, + ], + [ + 'link' => 'url', + // $this->url, + 'label' => __('Module Blocks'), + 'selected' => 1, + ], + ], + true + ); + + ui_print_page_header( + __('Manage module blocks'), + '', + false, + '', + true, + '', + false, + '', + GENERIC_SIZE_TEXT, + '', + $this->printHeader(true) + ); + + // $this->printForm( + // [ + // 'form' => $form, + // 'inputs' => $inputs, + // ], + // true + // ); + + } + + +} From f3da919abcd79c0e0dbf30666972d0f2b8e2a0db Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 16 Mar 2020 23:52:20 +0100 Subject: [PATCH 004/111] WIP multiple changes --- pandora_console/extras/mr/37.sql | 34 +- .../pandoradb_migrate_6.0_to_7.0.mysql.sql | 44 +- pandora_console/godmode/servers/discovery.php | 32 +- .../wizards/DiscoveryTaskList.class.php | 401 +++++++++++++++- .../godmode/wizards/Wizard.main.php | 21 + .../include/ajax/task_list.ajax.php | 153 +----- pandora_console/include/class/HTML.class.php | 32 ++ pandora_console/include/constants.php | 3 + pandora_console/include/functions_ui.php | 47 +- .../include/javascript/pandora_taskList.js | 136 +++++- .../include/javascript/pandora_ui.js | 2 + pandora_console/include/javascript/simTree.js | 437 ++++++++++++++++++ pandora_console/include/styles/simTree.css | 124 +++++ pandora_console/include/styles/task_list.css | 12 + pandora_console/pandoradb.sql | 69 ++- pandora_server/lib/PandoraFMS/DB.pm | 7 +- .../lib/PandoraFMS/DiscoveryServer.pm | 176 +++++-- pandora_server/lib/PandoraFMS/Recon/Base.pm | 357 ++++++++------ pandora_server/lib/PandoraFMS/Recon/Util.pm | 24 +- pandora_server/lib/PandoraFMS/Tools.pm | 347 +++++++++----- 20 files changed, 1934 insertions(+), 524 deletions(-) create mode 100644 pandora_console/include/javascript/simTree.js create mode 100644 pandora_console/include/styles/simTree.css diff --git a/pandora_console/extras/mr/37.sql b/pandora_console/extras/mr/37.sql index a2318348ef..50b4c04306 100644 --- a/pandora_console/extras/mr/37.sql +++ b/pandora_console/extras/mr/37.sql @@ -1,5 +1,35 @@ START TRANSACTION; -ALTER TABLE trecon_task modify column `id_network_profile` text; +ALTER TABLE trecon_task MODIFY COLUMN `id_network_profile` TEXT; +ALTER TABLE `trecon_task` CHANGE COLUMN `create_incident` `direct_report` TINYINT(1) UNSIGNED DEFAULT 0; +UPDATE `trecon_task` SET `direct_report` = 1; -COMMIT; \ No newline at end of file +CREATE TABLE `tdiscovery_tmp_agents` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id_rt` int(10) unsigned NOT NULL, + `label` varchar(600) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `data` text, + `review_date` datetime DEFAULT NULL, + `created` int(1) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `id_rt` (`id_rt`), + INDEX `label` (`label`), + CONSTRAINT `tdta_trt` FOREIGN KEY (`id_rt`) REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `tdiscovery_tmp_connections` ( + `id_rt` int(10) unsigned NOT NULL, + `id1` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id2` int(10) unsigned NOT NULL, + `if1` text, + `if2` text, + PRIMARY KEY (`id1`,`id2`), + CONSTRAINT `tdtc_trt` FOREIGN KEY (`id_rt`) + REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `tdtc_tdta1` FOREIGN KEY (`id1`) + REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `tdtc_tdta2` FOREIGN KEY (`id2`) + REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +COMMIT; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index 2e1d1354a8..de53643ec9 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -1657,22 +1657,42 @@ ALTER TABLE `trecon_task` ADD COLUMN `type` int(11) NOT NULL DEFAULT '0', MODIFY COLUMN `auth_strings` text NULL, MODIFY COLUMN `autoconfiguration_enabled` tinyint(1) unsigned NULL DEFAULT '0', MODIFY COLUMN `summary` text NULL, - MODIFY COLUMN `id_network_profile` text; + MODIFY COLUMN `id_network_profile` text, + CHANGE COLUMN `create_incident` `direct_report` TINYINT(1) UNSIGNED DEFAULT 0; + +-- Old recon always report. +UPDATE `trecon_task` SET `direct_report` = 1; -- ---------------------------------------------------------------------- -- Table `tdiscovery_tmp` -- ---------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `tdiscovery_tmp` ( - `id` int(10) unsigned NOT NULL auto_increment, - `id_rt` int(10) unsigned NOT NULL, - `label` varchar(600) BINARY NOT NULL default '', - `data` text, - `review_date` datetime, - `created` int(1) unsigned NOT NULL default 0, - PRIMARY KEY (`id`), - FOREIGN KEY (`id_rt`) REFERENCES `trecon_task`(`id_rt`) - ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `tdiscovery_tmp_agents` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id_rt` int(10) unsigned NOT NULL, + `label` varchar(600) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `data` text, + `review_date` datetime DEFAULT NULL, + `created` int(1) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `id_rt` (`id_rt`), + INDEX `label` (`label`), + CONSTRAINT `tdta_trt` FOREIGN KEY (`id_rt`) REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `tdiscovery_tmp_connections` ( + `id_rt` int(10) unsigned NOT NULL, + `id1` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id2` int(10) unsigned NOT NULL, + `if1` text, + `if2` text, + PRIMARY KEY (`id1`,`id2`), + CONSTRAINT `tdtc_trt` FOREIGN KEY (`id_rt`) + REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `tdtc_tdta1` FOREIGN KEY (`id1`) + REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `tdtc_tdta2` FOREIGN KEY (`id2`) + REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- --------------------------------------------------------------------- -- Table `twidget` AND Table `twidget_dashboard` diff --git a/pandora_console/godmode/servers/discovery.php b/pandora_console/godmode/servers/discovery.php index 7215ee7dfb..39f07aa025 100755 --- a/pandora_console/godmode/servers/discovery.php +++ b/pandora_console/godmode/servers/discovery.php @@ -48,6 +48,9 @@ function get_wiz_class($str) case 'ctask': return 'ConsoleTasks'; + case 'deploymentCenter': + return 'DeploymentCenter'; + default: // Main, show header. ui_print_page_header( @@ -124,13 +127,28 @@ $classname_selected = get_wiz_class($wiz_in_use); // Else: class not found pseudo exception. if ($classname_selected !== null) { - $wiz = new $classname_selected($page); - $result = $wiz->run(); - if (is_array($result) === true) { - // Redirect control and messages to DiscoveryTasklist. - $classname_selected = 'DiscoveryTaskList'; - $wiz = new $classname_selected($page); - $result = $wiz->run($result['msg'], $result['result']); + $wiz = new $classname_selected((int) $page); + + // AJAX controller. + if (is_ajax()) { + $method = get_parameter('method'); + + if (method_exists($wiz, $method) === true) { + $wiz->{$method}(); + } else { + $wiz->error('Method not found. ['.$method.']'); + } + + // Stop any execution. + exit; + } else { + $result = $wiz->run(); + if (is_array($result) === true) { + // Redirect control and messages to DiscoveryTasklist. + $classname_selected = 'DiscoveryTaskList'; + $wiz = new $classname_selected($page); + $result = $wiz->run($result['msg'], $result['result']); + } } } diff --git a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php index da6f4e572e..eef0bb59a9 100644 --- a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php +++ b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php @@ -26,7 +26,9 @@ * ============================================================================ */ -require_once __DIR__.'/Wizard.main.php'; +global $config; + +require_once $config['homedir'].'/include/class/HTML.class.php'; require_once $config['homedir'].'/include/functions_users.php'; require_once $config['homedir'].'/include/functions_reports.php'; require_once $config['homedir'].'/include/functions_cron.php'; @@ -34,11 +36,13 @@ enterprise_include_once('include/functions_tasklist.php'); enterprise_include_once('include/functions_cron.php'); ui_require_css_file('task_list'); +ui_require_css_file('simTree'); +ui_require_javascript_file('simTree'); /** * Defined as wizard to guide user to explore running tasks. */ -class DiscoveryTaskList extends Wizard +class DiscoveryTaskList extends HTML { @@ -454,11 +458,20 @@ class DiscoveryTaskList extends Wizard if ($task['disabled'] == 0 && $server_name !== '') { if (check_acl($config['id_user'], 0, 'AW')) { - $data[0] = ''; + ); + $data[0] .= '\''; + if ($task['type'] == DISCOVERY_HOSTDEVICES) { + $title = __('Are you sure?'); + $message = 'This action will rescan the target networks.'; + $data[0] .= ', {title: \''.$title.'\', message: \''.$message.'\'}'; + } + + $data[0] .= ');" >'; $data[0] .= html_print_image('images/target.png', true, ['title' => __('Force')]); - $data[0] .= ''; + $data[0] .= '
      '; } } else if ($task['disabled'] == 2) { $data[0] = ui_print_help_tip( @@ -472,12 +485,12 @@ class DiscoveryTaskList extends Wizard // Name task. $data[1] = ''; if ($task['disabled'] != 2) { - $data[1] .= ''; + $data[1] .= ''; } $data[1] .= ''.$task['name'].''; if ($task['disabled'] != 2) { - $data[1] .= ''; + $data[1] .= '
      '; } $data[2] = $server_name; @@ -496,10 +509,20 @@ class DiscoveryTaskList extends Wizard $data[4] = '-'; } - if ($task['status'] <= 0) { - $data[5] = __('Done'); + if ($task['direct_report'] == 1) { + if ($task['status'] <= 0) { + $data[5] = __('Done'); + } else { + $data[5] = __('Pending'); + } } else { - $data[5] = __('Pending'); + if ($task['status'] <= 0) { + $data[5] = ''; + $data[5] .= __('Review'); + $data[5] .= ''; + } else { + $data[5] = __('Searching'); + } } switch ($task['type']) { @@ -595,7 +618,28 @@ class DiscoveryTaskList extends Wizard if ($task['status'] <= 0 || $task['status'] > 100) { $data[7] = '-'; } else { - $data[7] = ui_progress($task['status'], '100%', 1.5); + $data[7] = ui_progress( + $task['status'], + '100%', + 1.9, + // Color. + '#82b92e', + // Return. + true, + // Text. + '', + // Ajax. + [ + 'page' => 'godmode/servers/discovery', + 'interval' => 10, + 'simple' => 1, + 'data' => [ + 'wiz' => 'tasklist', + 'id' => $task['id_rt'], + 'method' => 'task_progress', + ], + ] + ); } if ($task['utimestamp'] > 0) { @@ -700,9 +744,15 @@ class DiscoveryTaskList extends Wizard // Div neccesary for modal map task. echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; unset($table); + ui_require_javascript_file('pandora_ui'); ui_require_javascript_file('pandora_taskList'); return $return; @@ -787,4 +837,333 @@ class DiscoveryTaskList extends Wizard } + /** + * Returns percent of completion of target task. + * + * @return void + */ + public function task_progress() + { + if (!is_ajax()) { + return ''; + } + + $id_task = get_parameter('id', 0); + + if ($id_task <= 0) { + echo json_encode(['error' => true]); + return; + } + + $status = db_get_value('status', 'trecon_task', 'id_rt', $id_task); + if ($status < 0) { + $status = 100; + } + + echo json_encode($status); + } + + + /** + * Generates charts for progress popup. + * + * @param array $task Task. + * + * @return string Charts in HTML. + */ + private function progress_task_graph($task) + { + $result .= '
      '; + $result .= '
      '; + $result .= ''._('Overall Progress').''; + + $result .= '
      '; + $result .= progress_circular_bar( + $task['id_rt'], + ($task['status'] < 0) ? 100 : $task['status'], + 200, + 200, + '#7eb641', + '%', + '', + '#3A3A3A', + 0 + ); + + $result .= '
      '; + + if ($task['status'] > 0) { + switch ($task['stats']['step']) { + case STEP_SCANNING: + $str = __('Scanning network'); + break; + + case STEP_AFT: + $str = __('Finding AFT connectivity'); + break; + + case STEP_TRACEROUTE: + $str = __('Finding traceroute connectivity'); + break; + + case STEP_GATEWAY: + $str = __('Finding gateway connectivity'); + break; + + case STEP_STATISTICS: + $str = __('Searching for devices...'); + break; + + case STEP_APP_SCAN: + $str = __('Analyzing application...'); + break; + + case STEP_CUSTOM_QUERIES: + $str = __('Executing custom queries...'); + break; + + default: + $str = ''; + break; + } + + $result .= '
      '; + $result .= '
      '; + $result .= ''.$str.' '; + if (!empty($str)) { + $result .= $task['stats']['c_network_name']; + } + + $result .= ''; + + $result .= '
      '; + $result .= progress_circular_bar( + $task['id_rt'].'_detail', + $task['stats']['c_network_percent'], + 200, + 200, + '#7eb641', + '%', + '', + '#3A3A3A', + 0 + ); + $result .= '
      '; + } + + $result .= '
      '; + + return $result; + } + + + /** + * Generates a summary table for given task. + * + * @param array $task Task. + * + * @return html code with summary. + */ + private function progress_task_summary($task) + { + global $config; + include_once $config['homedir'].'/include/graphs/functions_d3.php'; + + if (is_array($task) === false) { + return ''; + } + + $output = ''; + + if (is_array($task['stats'])) { + $i = 0; + $table = new StdClasS(); + $table->class = 'databox data'; + $table->width = '75%'; + $table->styleTable = 'margin: 2em auto 0;border: 1px solid #ddd;background: white;'; + $table->rowid = []; + $table->data = []; + + // Content. + $table->data[$i][0] = ''.__('Hosts discovered').''; + $table->data[$i][1] = ''; + $table->data[$i][1] .= $task['stats']['summary']['discovered']; + $table->data[$i++][1] .= ''; + + $table->data[$i][0] = ''.__('Alive').''; + $table->data[$i][1] = ''; + $table->data[$i][1] .= $task['stats']['summary']['alive']; + $table->data[$i++][1] .= ''; + + $table->data[$i][0] = ''.__('Not alive').''; + $table->data[$i][1] = ''; + $table->data[$i][1] .= $task['stats']['summary']['not_alive']; + $table->data[$i++][1] .= ''; + + $table->data[$i][0] = ''.__('Responding SNMP').''; + $table->data[$i][1] = ''; + $table->data[$i][1] .= $task['stats']['summary']['SNMP']; + $table->data[$i++][1] .= ''; + + $table->data[$i][0] = ''.__('Responding WMI').''; + $table->data[$i][1] = ''; + $table->data[$i][1] .= $task['stats']['summary']['WMI']; + $table->data[$i++][1] .= ''; + + $output = '
      '.__('Summary').'
      '; + $output .= html_print_table($table, true).''; + } + + return $output; + } + + + /** + * Content of modal 'task progress', ajax only. + * + * @return void + */ + public function progress_task_discovery() + { + if (!is_ajax()) { + return; + } + + $id_task = get_parameter('id', 0); + + if ($id_task <= 0) { + echo json_encode(['error' => true]); + return; + } + + $task = db_get_row('trecon_task', 'id_rt', $id_task); + $task['stats'] = json_decode($task['summary'], true); + $global_progress = $task['status']; + $summary = $this->progress_task_summary($task); + + $output = ''; + + // Header information. + if ((int) $task['status'] <= 0 && empty($summary)) { + $output .= ui_print_info_message( + __('This task has never executed'), + '', + true + ); + } else if ($task['status'] == 1 + || ($task['utimestamp'] == 0 && $task['interval_sweep']) + ) { + $output .= ui_print_info_message( + __('Task queued, please wait.'), + '', + true + ).''; + } else { + $output .= $this->progress_task_graph($task); + } + + $output .= $summary; + + echo json_encode(['html' => $output]); + } + + + /** + * Get a map of target task. + * + * @return void + */ + public function task_showmap() + { + global $config; + include_once $config['homedir'].'/include/class/NetworkMap.class.php'; + $id_task = get_parameter('id', 0); + + $map = new NetworkMap( + [ + 'id_task' => $id_task, + 'pure' => 1, + 'widget' => true, + ] + ); + $map->printMap(); + } + + + /** + * Shows a modal to review results found by discovery task. + * + * @return void + */ + public function show_task_review() + { + $id_task = get_parameter('id', 0); + if ($id_task <= 0) { + ui_print_error_message(__('Invalid task')); + return; + } + + $task = db_get_row('tdiscovery_tmp_agents', 'id_rt', $id_task); + + if (is_array($task)) { + $data = json_decode(base64_decode($task['data']), true); + $simple_data = array_reduce( + $data, + function ($carry, $item) { + $id = $item['agent']['nombre']; + $carry[] = [ + 'id' => $id, + 'name' => $item['agent']['nombre'], + ]; + + $childs = array_reduce( + $item['modules'], + function ($c, $i) use ($id) { + $c[] = [ + 'name' => $i['name'], + 'id' => $id.'-'.$i['name'], + 'pid' => $id, + ]; + return $c; + }, + [] + ); + $carry = array_merge( + $carry, + $childs + ); + + return $carry; + }, + [] + ); + + echo '
      '; + echo parent::printTree('tree', $simple_data); + } + + } + + + /** + * Processes a review over temporary results found by discovery task. + * + * @return void + */ + public function parse_task_review() + { + $id_task = get_parameter('id', 0); + if ($id_task <= 0) { + echo $this->error(__('Invalid task')); + return; + } + + $out = obhd($_REQUEST); + + echo json_encode( + ['result' => $out] + ); + } + + } diff --git a/pandora_console/godmode/wizards/Wizard.main.php b/pandora_console/godmode/wizards/Wizard.main.php index 8f8b518069..13da3c269d 100644 --- a/pandora_console/godmode/wizards/Wizard.main.php +++ b/pandora_console/godmode/wizards/Wizard.main.php @@ -233,6 +233,27 @@ class Wizard } + /** + * Return formatted html for error handler. + * + * @param string $message Error mesage. + * + * @return string + */ + public function error($message) + { + if (is_ajax()) { + echo json_encode( + [ + 'error' => ui_print_error_message($message, '', true), + ] + ); + } else { + return ui_print_error_message($message, '', true); + } + } + + /** * To be overwritten. * diff --git a/pandora_console/include/ajax/task_list.ajax.php b/pandora_console/include/ajax/task_list.ajax.php index 6d50b3c892..1c05ffee79 100644 --- a/pandora_console/include/ajax/task_list.ajax.php +++ b/pandora_console/include/ajax/task_list.ajax.php @@ -24,154 +24,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * ============================================================================ + * + * + * MOVED TO DiscoveryTaskList.class. */ - -require_once $config['homedir'].'/include/graphs/functions_d3.php'; - -$progress_task_discovery = (bool) get_parameter('progress_task_discovery', 0); -$showmap = (bool) get_parameter('showmap', 0); - -if ($progress_task_discovery) { - $id_task = get_parameter('id', 0); - - if ($id_task <= 0) { - echo json_encode(['error' => true]); - return; - } - - $task = db_get_row('trecon_task', 'id_rt', $id_task); - $global_progress = $task['status']; - $summary = json_decode($task['summary'], true); - - $result = '
      '; - if ($task['utimestamp']) { - $result .= '
      '; - $result .= '
      '; - $result .= ''._('Overall Progress').''; - - $result .= '
      '; - $result .= progress_circular_bar( - $id_task, - ($global_progress < 0) ? 100 : $global_progress, - 200, - 200, - '#7eb641', - '%', - '', - '#3A3A3A', - 0 - ); - - $result .= '
      '; - - if ($global_progress > 0) { - switch ($summary['step']) { - case STEP_SCANNING: - $str = __('Scanning network'); - break; - - case STEP_AFT: - $str = __('Finding AFT connectivity'); - break; - - case STEP_TRACEROUTE: - $str = __('Finding traceroute connectivity'); - break; - - case STEP_GATEWAY: - $str = __('Finding gateway connectivity'); - break; - - default: - $str = __('Searching for devices...'); - break; - } - - $result .= '
      '; - $result .= '
      '; - $result .= ''.$str.' '; - $result .= $summary['c_network_name']; - $result .= ''; - - $result .= '
      '; - $result .= progress_circular_bar( - $id_task.'_detail', - $summary['c_network_percent'], - 200, - 200, - '#7eb641', - '%', - '', - '#3A3A3A', - 0 - ); - $result .= '
      '; - } - - $result .= '
      '; - - $i = 0; - $table = new StdClasS(); - $table->class = 'databox data'; - $table->width = '75%'; - $table->styleTable = 'margin: 2em auto 0;border: 1px solid #ddd;background: white;'; - $table->rowid = []; - $table->data = []; - - // Content. - $table->data[$i][0] = ''.__('Hosts discovered').''; - $table->data[$i][1] = ''; - $table->data[$i][1] .= $summary['summary']['discovered']; - $table->data[$i++][1] .= ''; - - $table->data[$i][0] = ''.__('Alive').''; - $table->data[$i][1] = ''; - $table->data[$i][1] .= $summary['summary']['alive']; - $table->data[$i++][1] .= ''; - - $table->data[$i][0] = ''.__('Not alive').''; - $table->data[$i][1] = ''; - $table->data[$i][1] .= $summary['summary']['not_alive']; - $table->data[$i++][1] .= ''; - - $table->data[$i][0] = ''.__('Responding SNMP').''; - $table->data[$i][1] = ''; - $table->data[$i][1] .= $summary['summary']['SNMP']; - $table->data[$i++][1] .= ''; - - $table->data[$i][0] = ''.__('Responding WMI').''; - $table->data[$i][1] = ''; - $table->data[$i][1] .= $summary['summary']['WMI']; - $table->data[$i++][1] .= ''; - - $result .= '
      '.__('Summary').'
      '; - $result .= html_print_table($table, true).''; - } else { - $global_progress = -1; - $result .= ui_print_error_message( - __('No data to show'), - '', - true - ).''; - } - - $result_array['status'] = $global_progress; - $result_array['html'] = $result; - - echo json_encode($result_array); - return; -} - -if ($showmap) { - include_once $config['homedir'].'/include/class/NetworkMap.class.php'; - $id_task = get_parameter('id', 0); - - $map = new NetworkMap( - [ - 'id_task' => $id_task, - 'pure' => 1, - 'widget' => true, - ] - ); - $map->printMap(); -} diff --git a/pandora_console/include/class/HTML.class.php b/pandora_console/include/class/HTML.class.php index bc210abee7..049f86252e 100644 --- a/pandora_console/include/class/HTML.class.php +++ b/pandora_console/include/class/HTML.class.php @@ -1000,4 +1000,36 @@ class HTML } + /** + * Returns a n-dimensional array (data) into a html tree structure. + * + * @param string $target Target DOM id. + * @param array $data N-dimensional array. + * @param string $callback Callback function. + * + * @return string + */ + public static function printTree($target, $data, $callback='') + { + ui_require_css_file('simTree'); + ui_require_javascript_file('simTree'); + + $output = ' +'; + + return $output; + } + + } diff --git a/pandora_console/include/constants.php b/pandora_console/include/constants.php index 742fe1940d..8d83ac98f0 100644 --- a/pandora_console/include/constants.php +++ b/pandora_console/include/constants.php @@ -527,6 +527,9 @@ define('STEP_SCANNING', 1); define('STEP_AFT', 2); define('STEP_TRACEROUTE', 3); define('STEP_GATEWAY', 4); +define('STEP_STATISTICS', 1); +define('STEP_APP_SCAN', 2); +define('STEP_CUSTOM_QUERIES', 3); // Networkmap node types. define('NODE_AGENT', 0); diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index b503abca63..33f6e85ca6 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -2839,6 +2839,7 @@ function ui_print_status_sets( * [ * 'page' => 'operation/agentes/ver_agente', Target page. * 'interval' => 100 / $agent["intervalo"], Ask every interval seconds. + * 'simple' => 0, * 'data' => [ Data to be sent to target page. * 'id_agente' => $id_agente, * 'refresh_contact' => 1, @@ -2879,7 +2880,38 @@ function ui_progress( $output .= ''; if ($ajax !== false && is_array($ajax)) { - $output .= ''; + } else { + $output .= ''; + } } if (!$return) { diff --git a/pandora_console/include/javascript/pandora_taskList.js b/pandora_console/include/javascript/pandora_taskList.js index 75d95df026..83b5c9657b 100644 --- a/pandora_console/include/javascript/pandora_taskList.js +++ b/pandora_console/include/javascript/pandora_taskList.js @@ -22,7 +22,7 @@ function progress_task_list(id, title) { autoOpen: false, modal: false, resizable: false, - draggable: false, + draggable: true, closeOnEscape: true, width: 800, height: 600, @@ -35,19 +35,23 @@ function progress_task_list(id, title) { // Function var. var handleFetchTaskList = function(err, data) { if (err) { + console.error(err); + } + if (data.error) { // TODO: Show info about the problem. + $elem.html(data.error); + } else { + $elem.html(data.html); } - $elem.html(data.html); if (!$elem.dialog("isOpen")) $elem.dialog("open"); - - if (data.status != -1) { - timeoutRef = setTimeout(function() { - xhr = fetchTaskList(id, handleFetchTaskList); - }, 3000); - } }; + if (!$elem.dialog("isOpen")) + timeoutRef = setInterval(function() { + xhr = fetchTaskList(id, handleFetchTaskList); + }, 3000); + xhr = fetchTaskList(id, handleFetchTaskList); } @@ -60,12 +64,13 @@ function progress_task_list(id, title) { function fetchTaskList(id, callback) { return jQuery.ajax({ data: { - page: "include/ajax/task_list.ajax", - progress_task_discovery: 1, + page: "godmode/servers/discovery", + wiz: "tasklist", + method: "progress_task_discovery", id: id }, type: "POST", - url: "ajax.php", + url: $("#ajax-url").val(), dataType: "json", success: function(data) { callback(null, data); @@ -93,12 +98,13 @@ function show_map(id, name) { jQuery.ajax({ data: { - page: "include/ajax/task_list.ajax", - showmap: 1, + page: "godmode/servers/discovery", + wiz: "tasklist", + method: "task_showmap", id: id }, type: "POST", - url: "ajax.php", + url: $("#ajax-url").val(), dataType: "html", success: function(data) { $("#map_task") @@ -107,3 +113,105 @@ function show_map(id, name) { } }); } + +function show_review(id, name) { + load_modal({ + target: $("#task_review"), + form: "review", + url: $("#ajax-url").val(), + modal: { + title: "Review " + name, + ok: "OK", + cancel: "Cancel" + }, + ajax_callback: function(data) { + var title = $("#success-str").val(); + var text = ""; + var failed = 0; + try { + data = JSON.parse(data); + text = data["result"]; + } catch (err) { + title = $("#failed-str").val(); + text = err.message; + failed = 1; + } + if (!failed && data["error"] != undefined) { + title = $("#failed-str").val(); + text = data["error"]; + failed = 1; + } + if (data["report"] != undefined) { + data["report"].forEach(function(item) { + text += "
      " + item; + }); + } + + $("#msg").empty(); + $("#msg").html(text); + $("#msg").dialog({ + width: 450, + position: { + my: "center", + at: "center", + of: window, + collision: "fit" + }, + title: title, + buttons: [ + { + class: + "ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next", + text: "OK", + click: function(e) { + if (!failed) { + $(".ui-dialog-content").dialog("close"); + $(".info").hide(); + cleanupDOM(); + dt_keystore.draw(false); + } else { + $(this).dialog("close"); + } + } + } + ] + }); + }, + extradata: [ + { + name: "id", + value: id + }, + { + name: "wiz", + value: "tasklist" + } + ], + onshow: { + page: "godmode/servers/discovery", + method: "show_task_review" + }, + onsubmit: { + page: "godmode/servers/discovery", + method: "parse_task_review" + } + }); +} + +function force_task_run(url) { + window.location = url; +} + +function force_task(url, ask) { + if (ask != undefined) { + confirmDialog({ + title: ask.title, + message: ask.message, + onAccept: function() { + force_task_run(url); + } + }); + } else { + force_task_run(url); + } +} diff --git a/pandora_console/include/javascript/pandora_ui.js b/pandora_console/include/javascript/pandora_ui.js index 4342c8381e..606c574b1a 100644 --- a/pandora_console/include/javascript/pandora_ui.js +++ b/pandora_console/include/javascript/pandora_ui.js @@ -383,6 +383,7 @@ function confirmDialog(settings) { "ui-widget ui-state-default ui-corner-all ui-button-text-only sub upd submit-cancel", click: function() { $(this).dialog("close"); + $(this).remove(); if (typeof settings.onDeny == "function") settings.onDeny(); } }, @@ -392,6 +393,7 @@ function confirmDialog(settings) { "ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next", click: function() { $(this).dialog("close"); + $(this).remove(); if (typeof settings.onAccept == "function") settings.onAccept(); } } diff --git a/pandora_console/include/javascript/simTree.js b/pandora_console/include/javascript/simTree.js new file mode 100644 index 0000000000..c3817b31b3 --- /dev/null +++ b/pandora_console/include/javascript/simTree.js @@ -0,0 +1,437 @@ +!(function(e) { + var t = {}; + function i(s) { + if (t[s]) return t[s].exports; + var n = (t[s] = { i: s, l: !1, exports: {} }); + return e[s].call(n.exports, n, n.exports, i), (n.l = !0), n.exports; + } + (i.m = e), + (i.c = t), + (i.d = function(e, t, s) { + i.o(e, t) || Object.defineProperty(e, t, { enumerable: !0, get: s }); + }), + (i.r = function(e) { + "undefined" != typeof Symbol && + Symbol.toStringTag && + Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }), + Object.defineProperty(e, "__esModule", { value: !0 }); + }), + (i.t = function(e, t) { + if ((1 & t && (e = i(e)), 8 & t)) return e; + if (4 & t && "object" == typeof e && e && e.__esModule) return e; + var s = Object.create(null); + if ( + (i.r(s), + Object.defineProperty(s, "default", { enumerable: !0, value: e }), + 2 & t && "string" != typeof e) + ) + for (var n in e) + i.d( + s, + n, + function(t) { + return e[t]; + }.bind(null, n) + ); + return s; + }), + (i.n = function(e) { + var t = + e && e.__esModule + ? function() { + return e.default; + } + : function() { + return e; + }; + return i.d(t, "a", t), t; + }), + (i.o = function(e, t) { + return Object.prototype.hasOwnProperty.call(e, t); + }), + (i.p = ""), + i((i.s = 0)); +})([ + function(e, t, i) { + "use strict"; + i.r(t); + i(1); + !(function(e, t) { + if (!e || !e.document) throw new Error("simTree need window"); + !(function(e) { + var t, + i = e.document, + s = { + linkParent: !1, + response: { + name: "name", + id: "id", + pid: "pid", + checked: "checked", + open: "open", + disabled: "disabled" + } + }, + n = function(e) { + throw new Error(e); + }, + a = function(e, t) { + return e.replace(/\{\{(.+?)\}\}/g, function(e, i) { + return t[i] ? t[i] : ""; + }); + }, + r = function e(t) { + if ( + ("undefined" == typeof $ && n("simTreeneed jquery"), + $.isPlainObject(t)) + ) { + if ((t.el || n("你没有传el"), !(this instanceof e))) + return new e(t); + (this.options = $.extend(!0, {}, s, t)), this.init(); + } + }, + d = [], + o = []; + (r.prototype = { + version: "0.0.2", + constructor: r, + on: function(e, t, i) { + var s, n; + return ( + (this.handles[e] = this.handles[e] || []), + (s = this.handles[e].isTriggered), + (n = this.handles[e].args), + $.isFunction(t) && + (!0 === i ? (this.handles[e] = [t]) : this.handles[e].push(t), + s && t.call(this, n)), + this + ); + }, + off: function(e) { + return (this.handles[e] = []), this; + }, + trigger: function(e, t) { + var i, s; + for ( + this.handles[e] = this.handles[e] || [], + i = 0, + s = this.handles[e].length, + this.handles[e].isTriggered = !0, + this.handles[e].args = t; + i < s; + i++ + ) + this.handles[e][i].call(this, t); + }, + init: function() { + var e = this.options, + t = e.data; + (this.handles = {}), + (this.$el = $(e.el)), + (this.data = t), + this.event(), + this.render(); + }, + dataCallback: function() { + var e = arguments; + 1 === e.length ? this.render(e[0]) : this.doRender(e[0], e[1]); + }, + parse: function(e) { + var t = this.options, + i = t.response, + s = [], + n = {}, + a = 0, + r = e.length, + d = i.id, + o = i.pid; + if (t.childNodeAsy) return e; + for (; a < r; a++) { + var h = e[a], + c = h[d]; + if (h.children) return e; + c && (n[c] = h); + } + for (a = 0; a < r; a++) { + var h = e[a], + l = h[o], + u = n[l]; + l && u ? (u.children || (u.children = [])).push(h) : s.push(h); + } + return s; + }, + render: function(e) { + var e = e || this.data; + $.isFunction(e) && e({}, this.dataCallback.bind(this)), + $.isArray(e) && ((e = this.parse(e)), this.doRender(this.$el, e)); + }, + doRender: function(e, t, s) { + var n, + r, + h, + c, + l, + u = this, + f = this.options, + p = f.response, + m = t.length, + g = 0, + v = p.id, + k = p.name, + s = s || 1, + C = + '{{text}}', + b = e === this.$el, + y = $(i.createElement("ul")), + w = f.childNodeAsy ? "asy" : ""; + for ( + f.check || + (C = C.replace('', "")); + g < m; + g++ + ) + (n = t[g]), + (r = i.createElement("li")), + (c = !!n.children), + (l = n[p.disabled]), + (r.innerHTML = a(C, { + asy: w, + text: n[k], + spreadIcon: c ? "sim-icon-r" : "hidden" + })), + r.setAttribute("data-level", s), + r.setAttribute("data-id", n[v]), + l && r.setAttribute("class", "disabled"), + (h = $(r)).data("data", n), + y.append(h), + c && this.doRender(h, n.children, s + 1), + n[p.checked] && d.push(n[v]), + n[p.open] && o.push(n[v]); + m && e.append(y), + b + ? (y.addClass("sim-tree"), + this.trigger("done", t), + $.each(o, function(e, t) { + u.expandNode(t); + }), + this.setSelected(d)) + : f.childNodeAsy && + (this.hideLoading(e.find(".sim-tree-spread")), + y.addClass("show")); + }, + event: function() { + var e = this; + this.$el.off("click").on("click", function(t) { + var i = $(t.target); + return ( + i.hasClass("sim-tree-spread") && e.spread.call(e, i), + i.hasClass("sim-tree-checkbox") && (i = i.parent()), + "a" === i[0].tagName.toLowerCase() && e.clickNode.call(e, i), + !1 + ); + }), + this.$el.on("selectstart", function() { + return !1; + }), + this.options.done && this.on("done", this.options.done), + this.options.onClick && this.on("click", this.options.onClick), + this.options.onChange && this.on("change", this.options.onChange), + this.options.onSearch && this.on("search", this.options.onSearch); + }, + spread: function(e) { + e.hasClass("sim-icon-r") + ? this.doSpread(e, !0) + : this.doSpread(e, !1); + }, + showLoading: function(e) { + e.addClass("sim-loading"); + }, + hideLoading: function(e) { + e.removeClass("sim-loading"); + }, + doSpread: function(e, t) { + var i = e.parent(), + s = i.children("ul"), + n = i.data("data"); + n.children && + (t + ? (e.removeClass("sim-icon-r").addClass("sim-icon-d"), + "asy" === e.data("type") && + $.isFunction(this.data) && + (this.showLoading(e), + this.data(i.data("data"), this.dataCallback.bind(this, i)), + e.data("type", "")), + s.addClass("show")) + : (e.removeClass("sim-icon-d").addClass("sim-icon-r"), + s.removeClass("show"))); + }, + clickNode: function(e) { + var i, + s, + n, + a = this, + r = e.parent(), + d = this.$el.find("li"), + o = d.length, + h = 0, + c = [], + l = !1; + if (!r.hasClass("disabled")) { + if (this.options.check) + for ( + l = !0, + this.doCheck(e.find(".sim-tree-checkbox")), + this.options.linkParent && + ((s = r.children("ul")), + (n = s.find(".sim-tree-checkbox")), + $.each(n, function() { + a.doCheck($(this), r.data("checked"), !0); + })); + h < o; + h++ + ) + !0 === (i = d.eq(h).data()).checked && c.push(i.data); + else + t && t.css("font-weight", "normal"), + e.css("font-weight", "bold"), + (t = e), + (i = r.data("data")), + (c = [i]), + (l = !this.sels || !(this.sels[0] === i)); + (this.sels = c), + this.trigger("click", c), + l && this.trigger("change", c); + } + }, + doCheck: function(e, t, i) { + var s = e.closest("li"), + n = s.data(); + void 0 === t && (t = !n.checked), + !0 === t + ? e.removeClass("sim-tree-semi").addClass("checked") + : !1 === t + ? e.removeClass("checked sim-tree-semi") + : "semi" === t && + e.removeClass("checked").addClass("sim-tree-semi"), + s.data("checked", t), + !0 === this.options.linkParent && !i && this.setParentCheck(s); + }, + setParentCheck: function(e) { + var t, + i = e.parent("ul"), + s = i.parent("li"), + n = i.children("li"), + a = s.find(">a .sim-tree-checkbox"), + r = [], + d = n.length; + s.length && + (e.find(">a .sim-tree-checkbox").hasClass("sim-tree-semi") + ? this.doCheck(a, "semi") + : ($.each(n, function() { + !0 === $(this).data("checked") && r.push($(this)); + }), + (t = r.length), + d === t && this.doCheck(a, !0), + t || this.doCheck(a, !1), + t >= 1 && t < d && this.doCheck(a, "semi"))); + }, + search: function(e) { + if (this.$el) { + var t, + i, + s, + e = $.trim(e), + n = this.$el.find("li"), + a = 0, + r = n.length, + d = [], + o = new RegExp(e, "i"); + for ( + n + .hide() + .children(".sim-tree-spread") + .addClass("hidden"); + a < r; + a++ + ) + (i = n.eq(a)), + (t = i.children("a").text()), + (s = i.data("data")), + e + ? -1 !== t.search(o) && + (1 !== parseInt(i.data("level")) && + this.expandNode(s[this.options.response.pid]), + i + .parents("li") + .add(i) + .show(), + d.push(i)) + : (i.show(), + s.children && + i.children(".sim-tree-spread").removeClass("hidden")); + this.trigger("search", e); + } + }, + expandNode: function(e) { + var t = e.addClass ? e : this.$el.find("[data-id=" + e + "]"), + i = t.data("data"), + s = i[this.options.response.pid], + n = t.children(".sim-tree-spread"), + a = parseInt(t.data("level")); + i.children && + n.length && + (n.removeClass("hidden"), this.doSpread(n, !0)), + 1 !== a && this.expandNode(s); + }, + setSelected: function(e) { + var t = this, + i = e, + s = [], + n = []; + ("string" != typeof i && "number" != typeof i) || (i = [i]), + $.isArray(i) && + (this.options.check || (i = [i[0]]), + $.each(i, function(e, i) { + var a = t.$el.find("[data-id=" + i + "]"), + r = a.children("a"), + d = r.children(".sim-tree-checkbox"), + o = a.data("data"); + if (!a.length) return !0; + d.length ? t.doCheck(d, !0) : r.css("font-weight", "bold"), + 1 !== parseInt(a.data("level")) && + t.expandNode(o[t.options.response.pid]), + s.push(o), + n.push(a[0]); + }), + (t.sels = s), + t.trigger("click", s)); + }, + getSelected: function() { + return this.sels; + }, + disableNode: function(e) { + var t = this, + i = e; + ("string" != typeof i && "number" != typeof i) || (i = [i]), + $.isArray(i) && + $.each(i, function(e, i) { + var s = t.$el.find("[data-id=" + i + "]"); + s.addClass("disabled"); + }); + }, + destroy: function() { + for (var e in (this.$el.html(""), this)) delete this[e]; + }, + refresh: function(e) { + this.$el.html(""), this.render(e); + } + }), + (e.simTree = r), + ($.fn.simTree = function(e) { + return (e = $.extend(!0, { el: this }, e)), r(e); + }); + })(e); + })("undefined" != typeof window ? window : void 0); + }, + function(e, t, i) {} +]); diff --git a/pandora_console/include/styles/simTree.css b/pandora_console/include/styles/simTree.css new file mode 100644 index 0000000000..0cb03527c6 --- /dev/null +++ b/pandora_console/include/styles/simTree.css @@ -0,0 +1,124 @@ +.sim-tree { + list-style: none; + font-size: 14px; + color: #333; +} +.sim-tree ul, +.sim-tree li { + margin: 0; + padding: 0; +} +.sim-tree li { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + font-size: 0; +} +.sim-tree li ul { + display: none; + margin-left: 15px; +} +.sim-tree ul.show, +.sim-tree li.show { + display: block; +} +.sim-tree ul.none, +.sim-tree li.none { + display: none; +} +.sim-tree li.disabled > a { + color: #aaa; + cursor: not-allowed; +} +.sim-tree li.disabled > a .sim-tree-checkbox { + border-color: #eee; +} +.sim-tree a { + font-size: 14px; + color: #333; + text-decoration: none; + vertical-align: top; + line-height: 26px; +} +.sim-tree .sim-tree-spread { + width: 20px; + padding-left: 5px; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.sim-tree .sim-tree-spread.hidden { + visibility: hidden; +} +.sim-tree .sim-tree-spread, +.sim-tree a { + display: inline-block; + height: 26px; + cursor: pointer; +} +.sim-tree .sim-loading { + background: url(data:image/gif;base64,R0lGODlhEAAQAMQQAObm5uLi4unp6dHR0cnJydfX1+jo6O/v7/Dw8NPT0/39/crKyvr6+uDg4MfHx////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFAAAQACwAAAAAEAAQAAAFXeAjPkiTjGgaLI6Tvs9BtPAIMPH8KgK5DDhZSlFYlFrAGIrYMrUcyRGzdapZr6jE02FAyZ6JxrOrEAVnjgaCRS6IkjLjo9F2PaDBwLJAu+NfAix2LQsAMCVVYQgoIQAh+QQFAAAQACwJAAAABwAHAAAFFGDSIE/5OM7SmKhjsK55vjIt32UIACH5BAUAABAALAoAAwAGAAoAAAUaICQqgggpxYKcheM0qOskZm0/eA7luMibvRAAIfkEBQAAEAAsCQAJAAcABwAABRXgcxBOmTwi6TRouiAoIwbtI9d4/oQAIfkEBQAAEAAsAwAKAAoABgAABRsgJI7MKD6POJQnKjpD60IODKFzvQD3nDQISAgAIfkEBQAAEAAsAAAJAAcABwAABRPgI45kSSrFWTgj6rCisLwk0iQhACH5BAUAABAALAAAAwAHAAoAAAUcIPRAJPmco4mm61m+cJk4tGNATX0ryGK/jVspBAAh+QQFAAAQACwAAAAABwAHAAAFFOAjjmRpPgBDIsugio3juGIiz2oIADs=) + center center no-repeat; +} +.sim-tree .sim-loading.sim-icon-d:before, +.sim-tree .sim-loading.sim-icon-r:before { + display: none; +} +.sim-tree .sim-icon-d:before, +.sim-tree .sim-icon-r:before { + content: ""; + display: inline-block; + width: 0; + height: 0; + border: 6px solid transparent; + vertical-align: top; + position: relative; +} +.sim-tree .sim-icon-r:before { + border-left-width: 8px; + border-left-color: #333; + top: 7px; +} +.sim-tree .sim-icon-d:before { + margin-left: -4px; + border-top-color: #333; + top: 10px; +} +.sim-tree .sim-tree-checkbox { + display: inline-block; + border: 1px solid #ccc; + height: 16px; + width: 16px; + border-radius: 3px; + -webkit-box-sizing: border-box; + box-sizing: border-box; + text-align: center; + line-height: 16px; + background: #fff; + color: #fff; + vertical-align: middle; + margin-right: 6px; + margin-top: -2px; +} +.sim-tree .sim-tree-checkbox.sim-tree-semi, +.sim-tree .sim-tree-checkbox.checked { + border-color: #2b85e4; + background-color: #2b85e4; +} +.sim-tree .sim-tree-checkbox.sim-tree-semi { + position: relative; +} +.sim-tree .sim-tree-checkbox.sim-tree-semi:after { + content: ""; + display: block; + position: absolute; + width: 8px; + height: 2px; + background: #fff; + top: 6px; + left: 3px; +} +.sim-tree .sim-tree-checkbox.checked { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAMAAABhq6zVAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAPFBMVEUAAAD///////////////////////////////////////////////////////////////////////8AAADY904BAAAAE3RSTlMAOiE8877cHQkXr9cZQvUc20NAbrhSVAAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAA7SURBVAjXY2DADhiZEGxmFlYkNhs7KpuDE0mci5sHoYaXj5sHyOaHqOblE4CzGRgE+RBsBgYhfmxuAABcBQF5T7U3IwAAAABJRU5ErkJggg==); + background-repeat: no-repeat; + background-position: center center; +} diff --git a/pandora_console/include/styles/task_list.css b/pandora_console/include/styles/task_list.css index d3ffb5d546..7e7ab5a07f 100644 --- a/pandora_console/include/styles/task_list.css +++ b/pandora_console/include/styles/task_list.css @@ -40,3 +40,15 @@ ul.progress_task_discovery li span { font-size: 9pt; margin-left: 20px; } + +.ui-dialog.ui-widget-content { + cursor: initial; +} + +span.link { + cursor: pointer; +} + +span.link.review { + font-weight: bold; +} diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index e07fc5f6ad..360e3f8a3b 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -770,14 +770,14 @@ CREATE TABLE IF NOT EXISTS `trecon_task` ( `name` varchar(100) NOT NULL default '', `description` varchar(250) NOT NULL default '', `subnet` text NOT NULL, - `id_network_profile` int(10) unsigned NOT NULL default '0', - `create_incident` tinyint(3) unsigned NOT NULL default '0', - `id_group` int(10) unsigned NOT NULL default '1', - `utimestamp` bigint(20) unsigned NOT NULL default '0', - `status` tinyint(4) NOT NULL default '0', - `interval_sweep` int(10) unsigned NOT NULL default '0', - `id_recon_server` int(10) unsigned NOT NULL default '0', - `id_os` tinyint(4) NOT NULL default '0', + `id_network_profile` text, + `direct_report` tinyint(1) unsigned NOT NULL default 0, + `id_group` int(10) unsigned NOT NULL default 1, + `utimestamp` bigint(20) unsigned NOT NULL default 0, + `status` tinyint(4) NOT NULL default 0, + `interval_sweep` int(10) unsigned NOT NULL default 0, + `id_recon_server` int(10) unsigned NOT NULL default 0, + `id_os` tinyint(4) NOT NULL default 0, `recon_ports` varchar(250) NOT NULL default '', `snmp_community` varchar(64) NOT NULL default 'public', `id_recon_script` int(10), @@ -785,31 +785,62 @@ CREATE TABLE IF NOT EXISTS `trecon_task` ( `field2` varchar(250) NOT NULL default '', `field3` varchar(250) NOT NULL default '', `field4` varchar(250) NOT NULL default '', - `os_detect` tinyint(1) unsigned default '0', - `resolve_names` tinyint(1) unsigned default '0', - `parent_detection` tinyint(1) unsigned default '0', - `parent_recursion` tinyint(1) unsigned default '0', - `disabled` tinyint(1) unsigned NOT NULL DEFAULT '0', + `os_detect` tinyint(1) unsigned default 0, + `resolve_names` tinyint(1) unsigned default 0, + `parent_detection` tinyint(1) unsigned default 0, + `parent_recursion` tinyint(1) unsigned default 0, + `disabled` tinyint(1) unsigned NOT NULL DEFAULT 0, `macros` TEXT, - `alias_as_name` tinyint(2) NOT NULL default '0', - `snmp_enabled` tinyint(1) unsigned default '0', - `vlan_enabled` tinyint(1) unsigned default '0', - `snmp_version` varchar(5) NOT NULL default '1', + `alias_as_name` tinyint(2) NOT NULL default 0, + `snmp_enabled` tinyint(1) unsigned default 0, + `vlan_enabled` tinyint(1) unsigned default 0, + `snmp_version` varchar(5) NOT NULL default 1, `snmp_auth_user` varchar(255) NOT NULL default '', `snmp_auth_pass` varchar(255) NOT NULL default '', `snmp_auth_method` varchar(25) NOT NULL default '', `snmp_privacy_method` varchar(25) NOT NULL default '', `snmp_privacy_pass` varchar(255) NOT NULL default '', `snmp_security_level` varchar(25) NOT NULL default '', - `wmi_enabled` tinyint(1) unsigned DEFAULT '0', + `wmi_enabled` tinyint(1) unsigned DEFAULT 0, `auth_strings` text, - `autoconfiguration_enabled` tinyint(1) unsigned default '0', + `autoconfiguration_enabled` tinyint(1) unsigned default 0, `summary` text, `type` int NOT NULL default 0, PRIMARY KEY (`id_rt`), KEY `recon_task_daemon` (`id_recon_server`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- ---------------------------------------------------------------------- +-- Table `tdiscovery_tmp` +-- ---------------------------------------------------------------------- +CREATE TABLE `tdiscovery_tmp_agents` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id_rt` int(10) unsigned NOT NULL, + `label` varchar(600) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `data` text, + `review_date` datetime DEFAULT NULL, + `created` int(1) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `id_rt` (`id_rt`), + INDEX `label` (`label`), + CONSTRAINT `tdta_trt` FOREIGN KEY (`id_rt`) REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `tdiscovery_tmp_connections` ( + `id_rt` int(10) unsigned NOT NULL, + `id1` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id2` int(10) unsigned NOT NULL, + `if1` text, + `if2` text, + PRIMARY KEY (`id1`,`id2`), + CONSTRAINT `tdtc_trt` FOREIGN KEY (`id_rt`) + REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `tdtc_tdta1` FOREIGN KEY (`id1`) + REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `tdtc_tdta2` FOREIGN KEY (`id2`) + REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + -- ---------------------------------------------------------------------- -- Table `tmodule_relationship` -- ---------------------------------------------------------------------- diff --git a/pandora_server/lib/PandoraFMS/DB.pm b/pandora_server/lib/PandoraFMS/DB.pm index 63c756e5ae..b190c763da 100644 --- a/pandora_server/lib/PandoraFMS/DB.pm +++ b/pandora_server/lib/PandoraFMS/DB.pm @@ -20,6 +20,7 @@ package PandoraFMS::DB; use strict; use warnings; use DBI; +use Carp qw/croak/; use lib '/usr/lib/perl5'; use PandoraFMS::Tools; @@ -894,7 +895,7 @@ sub db_insert ($$$;@) { $insert_id = $dbh->{'mysql_insertid'}; } else { - die($exception); + croak (join(', ', @_)); } } @@ -917,7 +918,7 @@ sub db_update ($$;@) { $rows = $dbh->do($query, undef, @values); } else { - die($exception); + croak (join(', ', @_)); } } @@ -1163,7 +1164,7 @@ sub db_do ($$;@) { $dbh->do($query, undef, @values); } else { - die($exception); + croak (join(', ', @_)); } } } diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index 87b1df711e..ae857deefd 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -1,8 +1,8 @@ package PandoraFMS::DiscoveryServer; -########################################################################## +################################################################################ # Pandora FMS Discovery Server. # Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org -########################################################################## +################################################################################ # Copyright (c) 2005-2009 Artica Soluciones Tecnologicas S.L # # This program is free software; you can redistribute it and/or @@ -15,7 +15,7 @@ package PandoraFMS::DiscoveryServer; # 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; use warnings; @@ -77,9 +77,9 @@ use constant { DISCOVERY_APP_SAP => 10, }; -######################################################################################## +################################################################################ # Discovery Server class constructor. -######################################################################################## +################################################################################ sub new ($$$$$$) { my ($class, $config, $dbh) = @_; @@ -113,9 +113,9 @@ sub new ($$$$$$) { return $self; } -############################################################################### +################################################################################ # Run. -############################################################################### +################################################################################ sub run ($) { my $self = shift; my $pa_config = $self->getConfig (); @@ -132,9 +132,9 @@ sub run ($) { $self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem); } -############################################################################### +################################################################################ # Data producer. -############################################################################### +################################################################################ sub data_producer ($) { my $self = shift; my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ()); @@ -174,9 +174,9 @@ sub data_producer ($) { return @tasks; } -############################################################################### +################################################################################ # Data consumer. -############################################################################### +################################################################################ sub data_consumer ($$) { my ($self, $task_id) = @_; my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ()); @@ -300,18 +300,18 @@ sub data_consumer ($$) { } } -########################################################################## +################################################################################ # Update recon task status. -########################################################################## +################################################################################ sub update_recon_task ($$$) { my ($dbh, $id_task, $status) = @_; db_do ($dbh, 'UPDATE trecon_task SET utimestamp = ?, status = ? WHERE id_rt = ?', time (), $status, $id_task); } -########################################################################## +################################################################################ # Executes recon scripts -########################################################################## +################################################################################ sub exec_recon_script ($$$) { my ($pa_config, $dbh, $task) = @_; @@ -380,9 +380,9 @@ sub exec_recon_script ($$$) { return 0; } -########################################################################## +################################################################################ # Guess the OS using xprobe2 or nmap. -########################################################################## +################################################################################ sub PandoraFMS::Recon::Base::guess_os($$) { my ($self, $device) = @_; @@ -422,9 +422,9 @@ sub PandoraFMS::Recon::Base::guess_os($$) { return OS_OTHER; } -############################################################################## +################################################################################ # Returns the number of open ports from the given list. -############################################################################## +################################################################################ sub PandoraFMS::Recon::Base::tcp_scan ($$) { my ($self, $host) = @_; @@ -436,14 +436,23 @@ sub PandoraFMS::Recon::Base::tcp_scan ($$) { return $open_ports; } -########################################################################## +################################################################################ # Create network profile modules for the given agent. -########################################################################## +################################################################################ sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) { my ($self, $agent_id, $device) = @_; - - return unless ($self->{'id_network_profile'} > 0); - + + # + # Plugin + # SNMP + # WMI + # ICMP + # + + return if empty($self->{'id_network_profile'}); + + my @templates = split /,/, $self->{'id_network_profile'}; + # Get network components associated to the network profile. my @np_components = get_db_rows($self->{'dbh'}, 'SELECT * FROM tnetwork_profile_component WHERE id_np = ?', $self->{'id_network_profile'}); foreach my $np_component (@np_components) { @@ -455,6 +464,10 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) { next; } + ## XXX Puede tener varios penes. + #next if (defined($template->{'pen'}) + # && get_enterprise_oid($device) != $template->{'pen'} ); + # Use snmp_community from network task instead the component snmp_community $component->{'snmp_community'} = safe_output($self->get_community($device)); $component->{'tcp_send'} = $self->{'snmp_version'}; @@ -469,9 +482,84 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) { } } -########################################################################## +################################################################################ +# Create agents and modules reported by Recon::Base. +################################################################################ +sub PandoraFMS::Recon::Base::report_scanned_agents($) { + my ($self) = @_; + + if(defined($self->{'task_data'}{'direct_report'}) + && $self->{'task_data'}{'direct_report'} eq "2" + ) { + # Load cache. + my @rows = get_db_rows( + $self->{'dbh'}, + 'SELECT * FROM tdiscovery_tmp_agents WHERE `id_rt`=?', + $self->{'task_data'}{'id_rt'} + ); + + foreach my $row (@rows) { + my $name = safe_output($row->{'label'}); + my $data; + eval { + $data = decode_json(decode_base64($row->{'data'})); + }; + + # Store. + $self->{'agents_found'}{$name} = $data; + } + } + + foreach my $label (keys %{$self->{'agents_found'}}) { + if (!is_enabled($self->{'direct_report'})) { + # Store temporally. Wait user approval. + my $encoded; + eval { + local $SIG{__DIE__}; + $encoded = encode_base64(encode_json($self->{'agents_found'})); + }; + + my $id = get_db_value( + $self->{'dbh'}, + 'SELECT id FROM tdiscovery_tmp_agents WHERE id_rt = ? AND label = ?', + $self->{'task_data'}{'id_rt'}, + safe_input($label) + ); + + if (defined($id)) { + # Already defined. + $self->{'agents_found'}{$label}{'id'} = $id; + + db_do( + $self->{'dbh'}, + 'UPDATE tdiscovery_tmp_agents SET `data` = ? ' + .'WHERE `id_rt` = ? AND `label` = ?', + $encoded, + $self->{'task_data'}{'id_rt'}, + safe_input($label) + ); + next; + } + + # Insert. + $self->{'agents_found'}{$label}{'id'} = db_insert( + $self->{'dbh'}, + 'id', + 'INSERT INTO tdiscovery_tmp_agents (`id_rt`,`label`,`data`,`created`) ' + .'VALUES (?, ?, ?, now())', + $self->{'task_data'}{'id_rt'}, + safe_input($label), + $encoded + ); + } else { + # Create agents. + } + } +} + +################################################################################ # Connect the given devices in the Pandora FMS database. -########################################################################## +################################################################################ sub PandoraFMS::Recon::Base::connect_agents($$$$$) { my ($self, $dev_1, $if_1, $dev_2, $if_2) = @_; @@ -490,12 +578,12 @@ sub PandoraFMS::Recon::Base::connect_agents($$$$$) { return unless defined($agent_2); # Use ping modules by default. - $if_1 = 'ping' if ($if_1 eq ''); - $if_2 = 'ping' if ($if_2 eq ''); + $if_1 = 'Host Alive' if ($if_1 eq ''); + $if_2 = 'Host Alive' if ($if_2 eq ''); # Check whether the modules exists. - my $module_name_1 = $if_1 eq 'ping' ? 'ping' : "${if_1}_ifOperStatus"; - my $module_name_2 = $if_2 eq 'ping' ? 'ping' : "${if_2}_ifOperStatus"; + my $module_name_1 = $if_1 eq 'Host Alive' ? 'Host Alive' : "${if_1}_ifOperStatus"; + my $module_name_2 = $if_2 eq 'Host Alive' ? 'Host Alive' : "${if_2}_ifOperStatus"; my $module_id_1 = get_agent_module_id($self->{'dbh'}, $module_name_1, $agent_1->{'id_agente'}); if ($module_id_1 <= 0) { $self->call('message', "ERROR: Module " . safe_output($module_name_1) . " does not exist for agent $dev_1.", 5); @@ -515,13 +603,13 @@ sub PandoraFMS::Recon::Base::connect_agents($$$$$) { } -########################################################################## +################################################################################ # Create agents from db_scan. Uses DataServer methods. # data = [ # 'agent_data' => {}, # 'module_data' => [] # ] -########################################################################## +################################################################################ sub PandoraFMS::Recon::Base::create_agents($$) { my ($self, $data) = @_; @@ -618,10 +706,10 @@ sub PandoraFMS::Recon::Base::create_agents($$) { } -########################################################################## +################################################################################ # Create an agent for the given device. Returns the ID of the new (or # existing) agent, undef on error. -########################################################################## +################################################################################ sub PandoraFMS::Recon::Base::create_agent($$) { my ($self, $device) = @_; @@ -930,9 +1018,9 @@ sub PandoraFMS::Recon::Base::create_agent($$) { return $agent_id; } -########################################################################## +################################################################################ # Delete already existing connections. -########################################################################## +################################################################################ sub PandoraFMS::Recon::Base::delete_connections($) { my ($self) = @_; @@ -940,18 +1028,18 @@ sub PandoraFMS::Recon::Base::delete_connections($) { db_do($self->{'dbh'}, 'DELETE FROM tmodule_relationship WHERE id_rt=?', $self->{'task_id'}); } -####################################################################### +################################################################################ # Print log messages. -####################################################################### +################################################################################ sub PandoraFMS::Recon::Base::message($$$) { my ($self, $message, $verbosity) = @_; logger($self->{'pa_config'}, "[Recon task " . $self->{'task_id'} . "] $message", $verbosity); } -########################################################################## +################################################################################ # Connect the given hosts to its parent. -########################################################################## +################################################################################ sub PandoraFMS::Recon::Base::set_parent($$$) { my ($self, $host, $parent) = @_; @@ -978,9 +1066,9 @@ sub PandoraFMS::Recon::Base::set_parent($$$) { db_do($self->{'dbh'}, 'UPDATE tagente SET id_parent=? WHERE id_agente=?', $agent_parent->{'id_agente'}, $agent->{'id_agente'}); } -########################################################################## +################################################################################ # Create a WMI module for the given agent. -########################################################################## +################################################################################ sub PandoraFMS::Recon::Base::wmi_module { my ($self, $agent_id, $target, $wmi_query, $wmi_auth, $column, $module_name, $module_description, $module_type, $unit) = @_; @@ -1007,9 +1095,9 @@ sub PandoraFMS::Recon::Base::wmi_module { pandora_create_module_from_hash($self->{'pa_config'}, \%module, $self->{'dbh'}); } -########################################################################## +################################################################################ # Update recon task status. -########################################################################## +################################################################################ sub PandoraFMS::Recon::Base::update_progress ($$) { my ($self, $progress) = @_; diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 9e3a437357..279c84e337 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -7,13 +7,14 @@ use strict; use warnings; # Default lib dir for RPM and DEB packages -use lib '/usr/lib/perl5'; - use NetAddr::IP; use POSIX qw/ceil/; +use Socket qw/inet_aton/; + +use lib '/usr/lib/perl5'; +use PandoraFMS::Tools; use PandoraFMS::Recon::NmapParser; use PandoraFMS::Recon::Util; -use Socket qw/inet_aton/; # Constants. use constant { @@ -67,6 +68,7 @@ our $SYSDESCR = ".1.3.6.1.2.1.1.1"; our $SYSSERVICES = ".1.3.6.1.2.1.1.7"; our $SYSUPTIME = ".1.3.6.1.2.1.1.3"; our $VTPVLANIFINDEX = ".1.3.6.1.4.1.9.9.46.1.3.1.1.18.1"; +our $PEN_OID = ".1.3.6.1.2.1.1.2.0"; our @ISA = ("Exporter"); our %EXPORT_TAGS = ( 'all' => [qw( )] ); @@ -389,6 +391,27 @@ sub are_connected($$$$$) { return 0; } +################################################################################ +# Initialize tmp pool for device. +# Already discovered by scan_subnet. +################################################################################ +sub icmp_discovery($$) { + my ($self, $addr) = @_; + + $self->prepare_agent($addr); + + $self->add_module($addr, 'icmp', + { + 'ip_target' => $addr, + 'name' => "Host Alive", + 'description' => '', + 'type' => 'generic_data', + 'id_modulo' => 2, + } + ); + +} + ################################################################################ # Discover as much information as possible from the given device using SNMP. ################################################################################ @@ -425,13 +448,15 @@ sub snmp_discovery($$) { # Check remote ARP caches. $self->remote_arp($device); + + # Get PEN. + $self->snmp_pen($device); } } # Create an agent for the device and add it to the list of known hosts. - push(@{$self->{'hosts'}}, $device); + $self->add_agent($device); - $self->call('create_agent', $device); } ################################################################################ @@ -816,12 +841,14 @@ sub get_mac_from_ip($$) { my $mac = undef; eval { - $mac = `arping -c 1 -r $host 2>$DEVNULL`; + $mac = `arping -c 1 $host 2>$DEVNULL`; $mac = undef unless ($? == 0); }; return unless defined($mac); + ($mac) = $mac =~ /\[(.*?)\]/ if defined($mac); + # Clean-up the MAC address. chomp($mac); $mac = parse_mac($mac); @@ -1104,11 +1131,11 @@ sub mark_connected($$;$$$) { $child = $self->{'aliases'}->{$child} if defined($self->{'aliases'}->{$child}); # Use ping modules when interfaces are unknown. - $parent_if = "ping" if $parent_if eq ''; - $child_if = "ping" if $child_if eq ''; + $parent_if = "Host Alive" if $parent_if eq ''; + $child_if = "Host Alive" if $child_if eq ''; # Do not connect devices using ping modules. A parent-child relationship is enough. - if ($parent_if ne "ping" || $child_if ne "ping") { + if ($parent_if ne "Host Alive" || $child_if ne "Host Alive") { $self->{'connections'}->{"${parent}\t${parent_if}\t${child}\t${child_if}"} = 1; $self->call('connect_agents', $parent, $parent_if, $child, $child_if); } @@ -1264,72 +1291,65 @@ sub remote_arp($$) { } ################################################################################ -# Ping the given host. Returns 1 if the host is alive, 0 otherwise. +# Add agent to pool (will be registered at the end of the scan). ################################################################################ -sub ping ($$$) { - my ($self, $host) = @_; - my ($timeout, $retries, $packets) = ($self->{'icmp_timeout'},$self->{'icmp_checks'},1,); +sub prepare_agent($$) { + my ($self, $addr) = @_; + $self->{'agents_found'} = {} if ref($self->{'agents_found'}) ne 'HASH'; - # Windows - if (($^O eq "MSWin32") || ($^O eq "MSWin32-x64") || ($^O eq "cygwin")){ - $timeout *= 1000; # Convert the timeout to milliseconds. - for (my $i = 0; $i < $retries; $i++) { - my $output = `ping -n $packets -w $timeout $host`; - return 1 if ($output =~ /TTL/); - } + # Already initialized. + return if ref($self->{'agents_found'}->{$addr}) eq 'HASH'; - return 0; + $self->{'agents_found'}->{$addr} = { + 'agent' => { + 'nombre' => $addr, + 'direccion' => $addr, + 'alias' => $addr, + }, + 'pen' => $self->{'pen'}{$addr}, + 'modules' => [], + }; +} + +################################################################################ +# Add agent to pool (will be registered at the end of the scan). +################################################################################ +sub add_agent($$) { + my ($self, $addr) = @_; + + $self->prepare_agent($addr); +} + +################################################################################ +# Add module to agent (tmp pool) (will be registered at the end of the scan). +################################################################################ +sub add_module($$$$) { + my ($self, $agent, $type, $data) = @_; + + $self->prepare_agent($agent); + + push @{$self->{'agents_found'}->{$agent}->{'modules'}}, $data; + +} + +################################################################################ +# Test target address (methods). +################################################################################ +sub test_capabilities($$) { + my ($self, $addr) = @_; + + $self->icmp_discovery($addr); + + if (is_enabled($self->{'snmp_enabled'})) { + # SNMP discovery. + $self->snmp_discovery($addr); } - # Solaris - if ($^O eq "solaris"){ - my $ping_command = $host =~ /\d+:|:\d+/ ? "ping -A inet6" : "ping"; - for (my $i = 0; $i < $retries; $i++) { - - # Note: There is no timeout option. - `$ping_command -s -n $host 56 $packets >$DEVNULL 2>&1`; - return 1 if ($? == 0); - } - - return 0; + # WMI discovery. + if (is_enabled($self->{'wmi_enabled'})) { + # Add wmi scan if enabled. + $self->wmi_scan($addr); } - - # FreeBSD - if ($^O eq "freebsd"){ - my $ping_command = $host =~ /\d+:|:\d+/ ? "ping6" : "ping -t $timeout"; - for (my $i = 0; $i < $retries; $i++) { - - # Note: There is no timeout option for ping6. - `$ping_command -q -n -c $packets $host >$DEVNULL 2>&1`; - return 1 if ($? == 0); - } - - return 0; - } - - # NetBSD - if ($^O eq "netbsd"){ - my $ping_command = $host =~ /\d+:|:\d+/ ? "ping6" : "ping -w $timeout"; - for (my $i = 0; $i < $retries; $i++) { - - # Note: There is no timeout option for ping6. - `$ping_command -q -n -c $packets $host >$DEVNULL 2>&1`; - if ($? == 0) { - return 1; - } - } - - return 0; - } - - # 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 >$DEVNULL 2>&1`; - return 1 if ($? == 0); - } - - return 0; } ################################################################################ @@ -1343,6 +1363,7 @@ sub scan_subnet($) { foreach my $subnet (@subnets) { $self->{'c_network_percent'} = 0; $self->{'c_network_name'} = $subnet; + $self->call('update_progress', ceil($progress)); # Clean blanks. $subnet =~ s/\s+//g; @@ -1357,81 +1378,82 @@ sub scan_subnet($) { my $network = $net_addr->network(); my $broadcast = $net_addr->broadcast(); - # fping scan. - if (-x $self->{'fping'} && $net_addr->num() > 1) { - $self->call('message', "Calling fping...", 5); + my @hosts = map { (split('/', $_))[0] } $net_addr->hostenum; + my $total_hosts = scalar(@hosts); + my %hosts_alive = (); - my @hosts = `"$self->{'fping'}" -ga "$subnet" 2>DEVNULL`; - next if (scalar(@hosts) == 0); + # By default 200, (20 * 10) + my $host_block_size = $self->{'block_size'}; - $self->{'summary'}->{'discovered'} += scalar(@hosts); + # The first 50% of the recon task approx. + my $step = 40.0 / scalar(@subnets) / (($total_hosts / $host_block_size)+1); + my $subnet_step = 50.0 / (($total_hosts / $host_block_size)+1); - my $step = 50.0 / scalar(@subnets) / scalar(@hosts); # The first 50% of the recon task approx. - my $subnet_step = 100.0 / scalar(@hosts); - foreach my $line (@hosts) { - chomp($line); + for (my $block_index=0; + $block_index < $total_hosts; + $block_index += $host_block_size + ) { + # Update the recon task + # Increase self summary.alive hosts. + $self->call('message', "Searching for hosts (".$block_index." / ".$total_hosts.")", 5); + my $to = $host_block_size + $block_index; + $to = $total_hosts if $to >= $total_hosts; - my @temp = split(/ /, $line); - if (scalar(@temp) != 1) { + my $c_block_size = $to - $block_index; + my @block = pandora_block_ping( + { + 'fping' => $self->{'fping'}, + # XXX CAMBIAR POR 0.5 + 'networktimeout' => 0.01 # use fping defaults + }, + @hosts[$block_index .. $to - 1] + ); - # Junk is shown for broadcast addresses. - # Increase summary.not_alive hosts. - $self->{'summary'}->{'not_alive'} += 1; - next; - } - my $host = $temp[0]; + # check alive hosts in current block + %hosts_alive = ( + %hosts_alive, + map {chomp; $_ => 1} @block + ); - # Skip network and broadcast addresses. - next if ($host eq $network->addr() || $host eq $broadcast->addr()); + $self->{'summary'}->{'not_alive'} += $c_block_size - (scalar @block); + $self->{'summary'}->{'alive'} += scalar @block; - # Increase self summary.alive hosts. - $self->{'summary'}->{'alive'} += 1; - $self->call('message', "Scanning host: $host", 5); - $self->call('update_progress', ceil($progress)); - $progress += $step; - $self->{'c_network_percent'} += $subnet_step; + # Update progress. + $progress += $step; + $self->{'c_network_percent'} += $subnet_step; - $self->snmp_discovery($host); - - # Add wmi scan if enabled. - $self->wmi_scan($host) if ($self->{'wmi_enabled'} == 1); - } + # Populate. + $self->call('update_progress', ceil($progress)); } - # ping scan. - else { - my @hosts = map { (split('/', $_))[0] } $net_addr->hostenum; - next if (scalar(@hosts) == 0); + # Update progress. + $self->call('message', "Searching for hosts (".$total_hosts." / ".$total_hosts.")", 5); + $progress = ceil($progress); + $self->{'c_network_percent'} = 50; - $self->{'summary'}->{'discovered'} += scalar(@hosts); + # Populate. + $self->call('update_progress', ceil($progress)); - my $step = 50.0 / scalar(@subnets) / scalar(@hosts); # The first 50% of the recon task approx. - my $subnet_step = 100.0 / scalar(@hosts); - foreach my $host (@hosts) { + $total_hosts = scalar keys %hosts_alive; + $step = 40.0 / scalar(@subnets) / $total_hosts; + $subnet_step = 50.0 / $total_hosts; + foreach my $addr (keys %hosts_alive) { + # Increase self summary.alive hosts. + $self->call('message', "Scanning host: $addr", 5); - $self->call('message', "Scanning host: $host", 5); - $self->call('update_progress', ceil($progress)); - $progress += $step; + # Update progress. + $progress += $step; + $self->{'c_network_percent'} += $subnet_step; - # Check if the host is up. - if ($self->ping($host) == 0) { - $self->{'summary'}->{'not_alive'} += 1; - next; - } + # Populate. + $self->call('update_progress', ceil($progress)); - $self->{'summary'}->{'alive'} += 1; - $self->{'c_network_percent'} += $subnet_step; - - $self->snmp_discovery($host); - - # Add wmi scan if enabled. - $self->wmi_scan($host) if ($self->{'wmi_enabled'} == 1); - } + # Enable/ disable capabilities. + $self->test_capabilities($addr); } } } - ################################################################################ # Perform a Cloud scan ################################################################################ @@ -1441,7 +1463,7 @@ sub cloud_scan($) { my $type = ''; - if ( $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_EC2 + if ( $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_EC2 || $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) { $type = 'Aws'; } else { @@ -1783,12 +1805,19 @@ sub scan($) { } } + if(defined($self->{'task_data'}{'direct_report'}) + && $self->{'task_data'}{'direct_report'} eq "2" + ) { + # Use Cached results. + return $self->call('report_scanned_agents'); + } + # Find devices. $self->call('message', "[1/4] Scanning the network...", 3); $self->{'step'} = STEP_SCANNING; $self->call('update_progress', $progress); - $self->scan_subnet(); + $self->scan_subnet(); # Read the local ARP cache. $self->local_arp(); @@ -1802,7 +1831,7 @@ sub scan($) { # Connectivity from address forwarding tables. $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%. + ($progress, $step) = (80, 8.0 / scalar(@hosts)); # From 50% to 70%. for (my $i = 0; defined($hosts[$i]); $i++) { $self->call('update_progress', $progress); $progress += $step; @@ -1812,7 +1841,7 @@ sub scan($) { # Connect hosts that are still unconnected using traceroute. $self->call('message', "[3/4] Finding traceroute connectivity.", 3); $self->{'step'} = STEP_TRACEROUTE; - ($progress, $step) = (70, 20.0 / scalar(@hosts)); # From 70% to 90%. + ($progress, $step) = (88, 8.0 / scalar(@hosts)); # From 70% to 90%. foreach my $host (@hosts) { $self->call('update_progress', $progress); $progress += $step; @@ -1823,7 +1852,7 @@ sub scan($) { # Connect hosts that are still unconnected using known gateways. $self->call('message', "[4/4] Finding host to gateway connectivity.", 3); $self->{'step'} = STEP_GATEWAY; - ($progress, $step) = (90, 10.0 / scalar(@hosts)); # From 70% to 90%. + ($progress, $step) = (94, 6.0 / scalar(@hosts)); # From 70% to 90%. $self->get_routes(); # Update the route cache. foreach my $host (@hosts) { $self->call('update_progress', $progress); @@ -1852,6 +1881,10 @@ sub scan($) { $dev_info .= ')'; $self->call('message', $dev_info, 3); } + + # Send agent information to Database (Discovery) or XML (satellite.). + $self->call('report_scanned_agents', $self->{'agents_found'}); + } ################################################################################ @@ -1872,6 +1905,22 @@ sub set_device_type($$$) { $self->{'visited_devices'}->{$device}->{'type'} = $type; } +################################################################################ +# Calculate +################################################################################ +sub snmp_pen($$) { + my ($self, $addr) = @_; + + $self->{'pen'} = {} if ref($self->{'pen'}) ne 'HASH'; + + $self->{'pen'}{$addr} = $self->snmp_get($addr, $PEN_OID); + + if(defined($self->{'pen'}{$addr})) { + ($self->{'pen'}{$addr}) = $self->{'pen'}{$addr} =~ /\.\d+\.\d+\.\d+\.\d+\.\d+\.\d+\.(\d+?)\./ + } + +} + ################################################################################ # Performs an SNMP WALK and returns the response as an array. ################################################################################ @@ -2015,7 +2064,7 @@ sub traceroute_connectivity($$) { my $parent = $hops[$i]->ipaddr(); # Create an agent for the parent. - $self->call('create_agent', $parent); + $self->add_agent($parent); $self->call('message', "Host $device is one hop away from host $parent.", 5); $self->mark_connected($parent, '', $device, ''); @@ -2064,27 +2113,61 @@ sub wmi_scan { $self->call('message', "[".$target."] WMI available.", 10); - # Create the agent if it does not exist. - my $agent_id = $self->call('create_agent', $target); - next unless defined($agent_id); + # Register agent. + $self->add_agent($target); + # Add modules. # CPU. my @cpus = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceId FROM Win32_Processor', 0); foreach my $cpu (@cpus) { - $self->call('wmi_module',($agent_id,$target,"SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId='$cpu'",$auth,1,"CPU Load $cpu","Load for $cpu (%)",'generic_data')); + $self->add_module($target, 'wmi', + { + 'target' => $target, + 'query' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId='$cpu'", + 'auth' => $auth, + 'column' => 1, + 'name' => "CPU Load $cpu", + 'description' => "Load for $cpu (%)", + 'type' => 'generic_data', + 'unit' => '%', + } + ); } # Memory. my $mem = $self->wmi_get_value($target, $auth, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0); if (defined($mem)) { - $self->call('wmi_module',($agent_id,$target,"SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem",$auth,0,'FreeMemory','Free memory','generic_data','KB')); + $self->add_module($target, 'wmi', + { + 'target' => $target, + 'query' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem", + 'auth' => $auth, + 'column' => 0, + 'name' => 'FreeMemory', + 'description' => 'Free memory', + 'type' => 'generic_data', + 'unit' => 'KB', + } + ); } # Disk. my @units = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceID FROM Win32_LogicalDisk', 0); foreach my $unit (@units) { - $self->call('wmi_module',($agent_id,$target,"SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'",$auth,1,"FreeDisk $unit",'Available disk space in kilobytes','generic_data','KB')); + $self->add_module($target, 'wmi', + { + 'target' => $target, + 'query' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'", + 'auth' => $auth, + 'column' => 1, + 'name' => "FreeDisk $unit", + 'description' => 'Available disk space in kilobytes', + 'type' => 'generic_data', + 'unit' => 'KB', + } + ); } + } ################################################################################ diff --git a/pandora_server/lib/PandoraFMS/Recon/Util.pm b/pandora_server/lib/PandoraFMS/Recon/Util.pm index 64cc7b28e6..32bc921806 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Util.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Util.pm @@ -23,9 +23,9 @@ our @EXPORT = qw( subnet_matches ); -######################################################################################## +################################################################################ # Return an Enterprise Recon object. -######################################################################################## +################################################################################ sub enterprise_new($$) { my ($class, $arguments) = @_; @@ -53,18 +53,18 @@ sub enterprise_new($$) { } -######################################################################################## +################################################################################ # Return the numeric representation of the given IP address. -######################################################################################## +################################################################################ sub ip_to_long($) { my $ip_address = shift; return unpack('N', inet_aton($ip_address)); } -######################################################################################## +################################################################################ # Returns 1 if the two given MAC addresses are the same. -######################################################################################## +################################################################################ sub mac_matches($$) { my ($mac_1, $mac_2) = @_; @@ -75,9 +75,9 @@ sub mac_matches($$) { return 0; } -######################################################################################## +################################################################################ # Convert a MAC address to decimal dotted notation. -######################################################################################## +################################################################################ sub mac_to_dec($) { my $mac = shift; @@ -91,9 +91,9 @@ sub mac_to_dec($) { return $dec_mac; } -######################################################################################## +################################################################################ # Make sure all MAC addresses are in the same format (00 11 22 33 44 55 66). -######################################################################################## +################################################################################ sub parse_mac($) { my ($mac) = @_; @@ -114,9 +114,9 @@ sub parse_mac($) { return $mac; } -######################################################################################## +################################################################################ # Returns 1 if the given IP address belongs to the given subnet. -######################################################################################## +################################################################################ sub subnet_matches($$;$) { my ($ipaddr, $subnet, $mask) = @_; my ($netaddr, $netmask); diff --git a/pandora_server/lib/PandoraFMS/Tools.pm b/pandora_server/lib/PandoraFMS/Tools.pm index 137b5dfb3b..a478ca6d67 100755 --- a/pandora_server/lib/PandoraFMS/Tools.pm +++ b/pandora_server/lib/PandoraFMS/Tools.pm @@ -1,8 +1,8 @@ package PandoraFMS::Tools; -######################################################################## +################################################################################ # Tools Package # Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org -######################################################################## +################################################################################ # Copyright (c) 2005-2011 Artica Soluciones Tecnologicas S.L # # This program is free software; you can redistribute it and/or @@ -15,7 +15,7 @@ package PandoraFMS::Tools; # 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 warnings; use Time::Local; @@ -109,8 +109,10 @@ our @EXPORT = qw( float_equal sqlWrap is_numeric + is_enabled is_metaconsole is_offline + is_empty to_number clean_blank credential_store_get_key @@ -128,6 +130,7 @@ our @EXPORT = qw( pandora_ping pandora_ping_latency pandora_block_ping + ping resolve_hostname ticks_totime safe_input @@ -361,9 +364,9 @@ my @ServerThreads; # Keep threads running. our $THRRUN :shared = 1; -########################################################################## +################################################################################ ## Reads a file and returns entire content or undef if error. -########################################################################## +################################################################################ sub read_file { my $path = shift; @@ -383,9 +386,9 @@ sub read_file { } -############################################################################### +################################################################################ # Sets user:group owner for the given file -############################################################################### +################################################################################ sub set_file_permissions($$;$) { my ($pa_config, $file, $grants) = @_; if ($^O !~ /win/i ) { # Only for Linux environments @@ -410,10 +413,10 @@ sub set_file_permissions($$;$) { } -######################################################################## +################################################################################ ## SUB pandora_trash_ascii # Generate random ascii strings with variable lenght -######################################################################## +################################################################################ sub pandora_trash_ascii { my $config_depth = $_[0]; @@ -426,9 +429,9 @@ sub pandora_trash_ascii { return $output } -######################################################################## +################################################################################ ## Convert the $value encode in html entity to clear char string. -######################################################################## +################################################################################ sub safe_input($) { my $value = shift; @@ -439,9 +442,9 @@ sub safe_input($) { return $value; } -######################################################################## +################################################################################ ## Convert the html entities to value encode to rebuild char string. -######################################################################## +################################################################################ sub safe_output($) { my $value = shift; @@ -452,10 +455,10 @@ sub safe_output($) { return $value; } -######################################################################## +################################################################################ # Sub daemonize () # Put program in background (for daemon mode) -######################################################################## +################################################################################ sub pandora_daemonize { my $pa_config = $_[0]; @@ -492,13 +495,13 @@ sub pandora_daemonize { # Pandora other General functions | # -------------------------------------------+ -######################################################################## +################################################################################ # SUB credential_store_get_key # Retrieve all information related to target identifier. # param1 - config hash # param2 - dbh link # param3 - string identifier -######################################################################## +################################################################################ sub credential_store_get_key($$$) { my ($pa_config, $dbh, $identifier) = @_; @@ -520,7 +523,7 @@ sub credential_store_get_key($$$) { } -######################################################################## +################################################################################ # SUB pandora_sendmail # Send a mail, connecting directly to MTA # param1 - config hash @@ -528,7 +531,7 @@ sub credential_store_get_key($$$) { # param3 - Email subject # param4 - Email Message body # param4 - Email content type -######################################################################## +################################################################################ sub pandora_sendmail { @@ -584,10 +587,10 @@ sub pandora_sendmail { }; } -########################################################################## +################################################################################ # SUB is_numeric # Return TRUE if given argument is numeric -########################################################################## +################################################################################ sub is_numeric { my $val = $_[0]; @@ -610,10 +613,56 @@ sub is_numeric { } } -########################################################################## +################################################################################ +# SUB is_enabled +# Return TRUE if given argument is defined, number and greater than 1. +################################################################################ +sub is_enabled { + my $value = shift; + + if ((defined ($value)) && is_numeric($value) && ($value > 0)){ + # return true + return 1; + } + #return false + return 0; + +} + +################################################################################ +# SUB is_empty +# Return TRUE if given argument is an empty string/array/hash or undefined. +################################################################################ +sub is_empty { + my $str = shift; + + if (! (defined ($str)) ){ + return 1; + } + + if(looks_like_number($str)){ + return 0; + } + + if (ref ($str) eq "ARRAY") { + return (($#{$str}<0)?1:0); + } + + if (ref ($str) eq "HASH") { + my @tmp = keys %{$str}; + return (($#tmp<0)?1:0); + } + + if ($str =~ /^\ *[\n\r]{0,2}\ *$/) { + return 1; + } + return 0; +} + +################################################################################ # SUB md5check (param_1, param_2) # Verify MD5 file .checksum -########################################################################## +################################################################################ # param_1 : Name of data file # param_2 : Name of md5 file @@ -647,10 +696,10 @@ sub md5check { } } -######################################################################## +################################################################################ # SUB logger (pa_config, message, level) # Log to file -######################################################################## +################################################################################ sub logger ($$;$) { my ($pa_config, $message, $level) = @_; @@ -701,10 +750,10 @@ sub logger ($$;$) { } } -######################################################################## +################################################################################ # SUB pandora_rotate_log (pa_config) # Log to file -######################################################################## +################################################################################ sub pandora_rotate_logfile ($) { my ($pa_config) = @_; @@ -720,9 +769,9 @@ sub pandora_rotate_logfile ($) { } } -######################################################################## +################################################################################ # limpia_cadena (string) - Purge a string for any forbidden characters (esc, etc) -######################################################################## +################################################################################ sub limpia_cadena { my $micadena; $micadena = $_[0]; @@ -736,9 +785,9 @@ sub limpia_cadena { } } -######################################################################## +################################################################################ # clean_blank (string) - Remove leading and trailing blanks -######################################################################## +################################################################################ sub clean_blank { my $input = $_[0]; $input =~ s/^\s+//g; @@ -746,10 +795,10 @@ sub clean_blank { return $input; } -######################################################################################## +################################################################################ # sub sqlWrap(texto) # Elimina comillas y caracteres problematicos y los sustituye por equivalentes -######################################################################################## +################################################################################ sub sqlWrap { my $toBeWrapped = shift(@_); @@ -760,21 +809,21 @@ sub sqlWrap { } } -########################################################################## +################################################################################ # sub float_equal (num1, num2, decimals) # This function make possible to compare two float numbers, using only x decimals # in comparation. # Taken from Perl Cookbook, O'Reilly. Thanks, guys. -########################################################################## +################################################################################ sub float_equal { my ($A, $B, $dp) = @_; return sprintf("%.${dp}g", $A) eq sprintf("%.${dp}g", $B); } -########################################################################## +################################################################################ # Tries to load the PandoraEnterprise module. Must be called once before # enterprise_hook (). -########################################################################## +################################################################################ sub enterprise_load ($) { my $pa_config = shift; @@ -809,9 +858,9 @@ sub enterprise_load ($) { return 1; } -########################################################################## +################################################################################ # Tries to call a PandoraEnterprise function. Returns undef if unsuccessful. -########################################################################## +################################################################################ sub enterprise_hook ($$) { my $func = shift; my @args = @{shift ()}; @@ -840,19 +889,19 @@ sub enterprise_hook ($$) { return $output; } -######################################################################## +################################################################################ # Prints a message to STDOUT at the given log level. -######################################################################## +################################################################################ sub print_message ($$$) { my ($pa_config, $message, $log_level) = @_; print STDOUT $message . "\n" if ($pa_config->{'verbosity'} >= $log_level); } -########################################################################## +################################################################################ # Returns the value of an XML tag from a hash returned by XMLin (one level # depth). -########################################################################## +################################################################################ sub get_tag_value ($$$;$) { my ($hash_ref, $tag, $def_value, $all_array) = @_; $all_array = 0 unless defined ($all_array); @@ -871,10 +920,10 @@ sub get_tag_value ($$$;$) { return $def_value; } -######################################################################## +################################################################################ # Initialize some variables needed by the MD5 algorithm. # See http://en.wikipedia.org/wiki/MD5#Pseudocode. -######################################################################## +################################################################################ my (@R, @K); sub md5_init () { @@ -890,10 +939,10 @@ sub md5_init () { } } -############################################################################### +################################################################################ # Return the MD5 checksum of the given string. # Pseudocode from http://en.wikipedia.org/wiki/MD5#Pseudocode. -############################################################################### +################################################################################ sub md5 ($) { my $str = shift; @@ -981,18 +1030,18 @@ sub md5 ($) { return unpack ("H*", pack ("V", $h0)) . unpack ("H*", pack ("V", $h1)) . unpack ("H*", pack ("V", $h2)) . unpack ("H*", pack ("V", $h3)); } -############################################################################### +################################################################################ # MD5 leftrotate function. See http://en.wikipedia.org/wiki/MD5#Pseudocode. -############################################################################### +################################################################################ sub leftrotate ($$) { my ($x, $c) = @_; return (0xFFFFFFFF & ($x << $c)) | ($x >> (32 - $c)); } -########################################################################## +################################################################################ ## Convert a date (yyy-mm-ddThh:ii:ss) to Timestamp. -########################################################################## +################################################################################ sub dateTimeToTimestamp { $_[0] =~ /(\d{4})-(\d{2})-(\d{2})([ |T])(\d{2}):(\d{2}):(\d{2})/; my($year, $mon, $day, $GMT, $hour, $min, $sec) = ($1, $2, $3, $4, $5, $6, $7); @@ -1002,10 +1051,10 @@ sub dateTimeToTimestamp { #print "BST\t" . mktime($sec, $min, $hour, $day, $mon - 1, $year - 1900, 0, 0) . "\n"; } -############################################################################## +################################################################################ # Below some "internal" functions for automonitoring feature # TODO: Implement the same for other systems like Solaris or BSD -############################################################################## +################################################################################ sub disk_free ($) { my $target = $_[0]; @@ -1082,10 +1131,10 @@ sub free_mem { return $free_mem; } -########################################################################## +################################################################################ ## SUB ticks_totime # Transform a snmp timeticks count in a date -########################################################################## +################################################################################ sub ticks_totime ($){ @@ -1109,7 +1158,7 @@ sub ticks_totime ($){ return "$days days, $hours hours, $minutes minutes, $seconds seconds"; } -############################################################################## +################################################################################ =head2 C<< pandora_ping (I<$pa_config>, I<$host>) >> Ping the given host. @@ -1118,7 +1167,7 @@ Returns: 0 otherwise. =cut -############################################################################## +################################################################################ sub pandora_ping ($$$$) { my ($pa_config, $host, $timeout, $retries) = @_; @@ -1236,13 +1285,13 @@ sub pandora_ping ($$$$) { return $output; } -######################################################################## +################################################################################ =head2 C<< pandora_ping_latency (I<$pa_config>, I<$host>) >> Ping the given host. Returns the average round-trip time. Returns undef if fails. =cut -######################################################################## +################################################################################ sub pandora_ping_latency ($$$$) { my ($pa_config, $host, $timeout, $retries) = @_; @@ -1375,32 +1424,118 @@ sub pandora_ping_latency ($$$$) { return $output; } -######################################################################## +################################################################################ =head2 C<< pandora_block_ping (I<$pa_config>, I<$hosts>) >> Ping all given hosts. Returns an array with all hosts detected as alive. =cut -######################################################################## +################################################################################ sub pandora_block_ping($@) { my ($pa_config, @hosts) = @_; + my ($cmd, $output); - # fping timeout in milliseconds - my $cmd = $pa_config->{'fping'} . " -a -q -t " . (1000 * $pa_config->{'networktimeout'}) . " " . (join (' ', @hosts)); - - my @output = `$cmd 2>$DEVNULL`; + if (-x $pa_config->{'fping'}) { + # fping timeout in milliseconds + $cmd = $pa_config->{'fping'} . " -a -q -t " . (1000 * $pa_config->{'networktimeout'}) . " " . (join (' ', @hosts)); + @output = `$cmd 2>$DEVNULL`; + } else { + # Ping scan + foreach my $host (@hosts) { + if (ping($pa_config, $host) > 0) { + push @output, $host; + } + } + } return @output; } -######################################################################## +################################################################################ +=head2 C<< ping (I<$pa_config>, I<$hosts>) >> + +Ping the given host. Returns 1 if the host is alive, 0 otherwise. + +=cut +################################################################################ +sub ping ($$) { + my ($pa_config, $host) = @_; + my ($timeout, $retries, $packets) = ( + $pa_config->{'networktimeout'}, + $pa_config->{'icmp_checks'}, + 1 + ); + + # Windows + if (($^O eq "MSWin32") || ($^O eq "MSWin32-x64") || ($^O eq "cygwin")){ + $timeout *= 1000; # Convert the timeout to milliseconds. + for (my $i = 0; $i < $retries; $i++) { + my $output = `ping -n $packets -w $timeout $host`; + return 1 if ($output =~ /TTL/); + } + + return 0; + } + + # Solaris + if ($^O eq "solaris"){ + my $ping_command = $host =~ /\d+:|:\d+/ ? "ping -A inet6" : "ping"; + for (my $i = 0; $i < $retries; $i++) { + + # Note: There is no timeout option. + `$ping_command -s -n $host 56 $packets >$DEVNULL 2>&1`; + return 1 if ($? == 0); + } + + return 0; + } + + # FreeBSD + if ($^O eq "freebsd"){ + my $ping_command = $host =~ /\d+:|:\d+/ ? "ping6" : "ping -t $timeout"; + for (my $i = 0; $i < $retries; $i++) { + + # Note: There is no timeout option for ping6. + `$ping_command -q -n -c $packets $host >$DEVNULL 2>&1`; + return 1 if ($? == 0); + } + + return 0; + } + + # NetBSD + if ($^O eq "netbsd"){ + my $ping_command = $host =~ /\d+:|:\d+/ ? "ping6" : "ping -w $timeout"; + for (my $i = 0; $i < $retries; $i++) { + + # Note: There is no timeout option for ping6. + `$ping_command -q -n -c $packets $host >$DEVNULL 2>&1`; + if ($? == 0) { + return 1; + } + } + + return 0; + } + + # 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 >$DEVNULL 2>&1`; + return 1 if ($? == 0); + } + + return 0; +} + +################################################################################ =head2 C<< month_have_days (I<$month>, I<$year>) >> Pass a $month (as january 0 number and each month with numbers) and the year as number (for example 1981). And return the days of this month. =cut -######################################################################## +################################################################################ sub month_have_days($$) { my $month= shift(@_); my $year= @_ ? shift(@_) : (1900 + (localtime())[5]); @@ -1428,9 +1563,9 @@ sub month_have_days($$) { return $monthDays[$month]; } -############################################################################### +################################################################################ # Convert a text obj tag to an OID and update the module configuration. -############################################################################### +################################################################################ sub translate_obj ($$$) { my ($pa_config, $dbh, $obj) = @_; @@ -1448,9 +1583,9 @@ sub translate_obj ($$$) { return $oid; } -############################################################################### +################################################################################ # Get the number of seconds left to the next execution of the given cron entry. -############################################################################### +################################################################################ sub cron_next_execution { my ($cron, $interval) = @_; @@ -1482,18 +1617,18 @@ sub cron_next_execution { return $nex_time - $cur_time; } -############################################################################### +################################################################################ # Get the number of seconds left to the next execution of the given cron entry. -############################################################################### +################################################################################ sub cron_check_syntax ($) { my ($cron) = @_; return 0 if !defined ($cron); return ($cron =~ m/^(\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+$/); } -############################################################################### +################################################################################ # Check if a value is inside an interval. -############################################################################### +################################################################################ sub cron_check_interval { my ($elem_cron, $elem_curr_time) = @_; @@ -1515,9 +1650,9 @@ sub cron_check_interval { return 1; } -############################################################################### +################################################################################ # Get the next execution date for the given cron entry in seconds since epoch. -############################################################################### +################################################################################ sub cron_next_execution_date { my ($cron, $cur_time, $interval) = @_; @@ -1646,11 +1781,11 @@ sub cron_next_execution_date { return $nex_time; } -############################################################################### +################################################################################ # Returns if a date is in a cron. Recursive. # Needs the cron like an array reference and # current time in cron format to works properly -############################################################################### +################################################################################ sub cron_is_in_cron { my ($elems_cron, $elems_curr_time) = @_; @@ -1687,11 +1822,11 @@ sub cron_get_next_time_element { ? $floor_data : $elem_down; } -############################################################################### +################################################################################ # Returns the interval of a cron element. If there is not a range, # returns an array with the first element in the first place of array # and the second place undefined. -############################################################################### +################################################################################ sub cron_get_interval { my ($element) = @_; @@ -1702,10 +1837,10 @@ sub cron_get_interval { return ($1, $2); } -############################################################################### +################################################################################ # Returns the closest number to the target inside the given range (including # the target itself). -############################################################################### +################################################################################ sub cron_get_closest_in_range ($$) { my ($target, $range) = @_; @@ -1727,9 +1862,9 @@ sub cron_get_closest_in_range ($$) { return $target; } -############################################################################### +################################################################################ # Check if a date is valid to get timelocal -############################################################################### +################################################################################ sub cron_valid_date { my ($min, $hour, $mday, $month, $year) = @_; my $utime; @@ -1743,9 +1878,9 @@ sub cron_valid_date { return $utime; } -############################################################################### +################################################################################ # Attempt to resolve the given hostname. -############################################################################### +################################################################################ sub resolve_hostname ($) { my ($hostname) = @_; @@ -1755,9 +1890,9 @@ sub resolve_hostname ($) { return inet_ntoa($resolved_hostname); } -############################################################################### +################################################################################ # Returns 1 if the given regular expression is valid, 0 otherwise. -############################################################################### +################################################################################ sub valid_regex ($) { my $regex = shift; @@ -1773,9 +1908,9 @@ sub valid_regex ($) { return 1; } -############################################################################### +################################################################################ # Returns 1 if a valid metaconsole license is configured, 0 otherwise. -############################################################################### +################################################################################ sub is_metaconsole ($) { my ($pa_config) = @_; @@ -1788,9 +1923,9 @@ sub is_metaconsole ($) { return 0; } -############################################################################### +################################################################################ # Returns 1 if a valid offline license is configured, 0 otherwise. -############################################################################### +################################################################################ sub is_offline ($) { my ($pa_config) = @_; @@ -1802,9 +1937,9 @@ sub is_offline ($) { return 0; } -############################################################################### +################################################################################ # Check if a given variable contents a number -############################################################################### +################################################################################ sub to_number($) { my $n = shift; if ($n =~ /[\d+,]*\d+\.\d+/) { @@ -1956,10 +2091,10 @@ sub generate_agent_name_hash { return sha256(join('|', ($agent_alias, $server_ip, time(), sprintf("%04d", rand(10000))))); } -############################################################################### +################################################################################ # Return the SHA256 checksum of the given string as a hex string. # Pseudocode from: http://en.wikipedia.org/wiki/SHA-2#Pseudocode -############################################################################### +################################################################################ my @K2 = ( 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, @@ -2079,34 +2214,34 @@ sub sha256 { unpack ("H*", pack ("N", $h7)); } -############################################################################### +################################################################################ # Rotate a 32-bit number a number of bits to the right. -############################################################################### +################################################################################ sub rightrotate { my ($x, $c) = @_; return (0xFFFFFFFF & ($x << (32 - $c))) | ($x >> $c); } -############################################################################### +################################################################################ # Returns IP address(v4) in longint format -############################################################################### -sub ip_to_long { +################################################################################ +sub ip_to_long($) { my $ip_str = shift; return unpack "N", inet_aton($ip_str); } -############################################################################### +################################################################################ # Returns IP address(v4) in longint format -############################################################################### +################################################################################ sub long_to_ip { my $ip_long = shift; return inet_ntoa pack("N", ($ip_long)); } -############################################################################### +################################################################################ # Returns a list with enabled servers. -############################################################################### +################################################################################ sub get_enabled_servers { my $conf = shift; From b58de4f60b7bbee62fc313e07ca5f62a3fc84885 Mon Sep 17 00:00:00 2001 From: Kike Date: Tue, 17 Mar 2020 12:29:02 +0100 Subject: [PATCH 005/111] wizard plugins --- .../util/plugin/wizard_snmp_module.pl | 308 ++++++++++++++++++ .../util/plugin/wizard_snmp_process.pl | 282 ++++++++++++++++ .../util/plugin/wizard_wmi_module.pl | 176 ++++++++++ 3 files changed, 766 insertions(+) create mode 100755 pandora_server/util/plugin/wizard_snmp_module.pl create mode 100755 pandora_server/util/plugin/wizard_snmp_process.pl create mode 100755 pandora_server/util/plugin/wizard_wmi_module.pl diff --git a/pandora_server/util/plugin/wizard_snmp_module.pl b/pandora_server/util/plugin/wizard_snmp_module.pl new file mode 100755 index 0000000000..ae1d739864 --- /dev/null +++ b/pandora_server/util/plugin/wizard_snmp_module.pl @@ -0,0 +1,308 @@ +#!/usr/bin/perl +# +################################################################################ +# +# SNMP wizard module +# +# Requirements: +# Net::SNMP +# Crypt::DES +# Digest::SHA1 +# +# (c) Enrique Martin Garcia +# +# 2020/03/10 +# +################################################################################ + +use strict; +use warnings; + +use POSIX qw(strftime); + +use Encode; +use Encode::Locale; +use Getopt::Long; +use Net::SNMP; + +my $HELP=<" -version "" [SNMP] [SNMPv3] -oidList "," -operation "" + +-host Target host +-version SNMP version (1, 2c, 3) + +-oidList Comma separated OIDs used +-operation Aritmetic operation to get data. + Macros _oN_ will be changed by OIDs in list. + Example: (_o1_ * 100) / _o2_ + +[SNMP] + -community Community (only version 1 and 2c) + -port Target UDP port (Default 161) + +[SNMPv3] + -user Username + -authMethod Authentication method (MD5, SHA) + -authPass Authentication password + -privMethod Privacy method (DES, AES) + -privPass Privacy password + -secLevel Security level (noAuthNoPriv, authNoPriv, authPriv) + +Example: $0 -host 192.168.80.43 -community public -version 1 -oidlist "1.3.6.1.2.1.2.2.1.10.1,1.3.6.1.2.1.2.2.1.16.1" -operation "_o1_ + _o2_" + +EO_HELP + +# +# FUNCTIONS +############## + +sub new_snmp_target { + my ($config) = @_; + my $target; + my $error; + + if ($config->{'version'} ne '3'){ + ($target, $error) = Net::SNMP->session( + -hostname => $config->{'host'}, + -port => $config->{'port'}, + -version => $config->{'version'}, + -timeout => $config->{'timeout'}, + -translate => 0, + -community => $config->{'community'} + ); + }else{ + if ($config->{'sec_level'} =~ /^noAuthNoPriv$/i){ + ($target, $error) = Net::SNMP->session( + -hostname => $config->{'host'}, + -port => $config->{'port'}, + -version => $config->{'version'}, + -timeout => $config->{'timeout'}, + -translate => 0, + -username => $config->{'user'} + ); + }elsif ($config->{'sec_level'} =~ /^authNoPriv$/i){ + ($target, $error) = Net::SNMP->session( + -hostname => $config->{'host'}, + -port => $config->{'port'}, + -version => $config->{'version'}, + -timeout => $config->{'timeout'}, + -translate => 0, + -username => $config->{'user'}, + -authpassword => $config->{'auth_pass'}, + -authprotocol => $config->{'auth_method'} + ); + }elsif ($config->{'sec_level'} =~ /^authPriv$/i){ + ($target, $error) = Net::SNMP->session( + -hostname => $config->{'host'}, + -port => $config->{'port'}, + -version => $config->{'version'}, + -timeout => $config->{'timeout'}, + -translate => 0, + -username => $config->{'user'}, + -authpassword => $config->{'auth_pass'}, + -authprotocol => $config->{'auth_method'}, + -privpassword => $config->{'priv_pass'}, + -privprotocol => $config->{'priv_method'} + ); + } + } + + + return ($target, $error); +} + +sub snmp_walk { + my ($target, $oid) = @_; + my $result = {}; + + my $walk = $target->get_table( + -baseoid => $oid, + ); + + if (defined($walk)){ + $result = $walk; + } + + return $result; +} + +sub snmp_get { + my ($target, $oid) = @_; + my $result = ''; + + my $get = $target->get_request( + -varbindlist => [$oid], + ); + + if (defined($get)){ + $result = $get->{$oid}; + } + + return $result; +} + +# +# MAIN +############## + +@ARGV = map { decode(locale => $_, 1) } @ARGV if -t STDIN; +binmode STDOUT, ":encoding(console_out)" if -t STDOUT; +binmode STDERR, ":encoding(console_out)" if -t STDERR; + +my %Param = (); +GetOptions( + \%Param, + # General + 'community=s', + 'version=s', + 'host=s', + 'port=s', + 'timeout=s', + # Version 3 + 'user=s', + 'authMethod=s', + 'authPass=s', + 'privMethod=s', + 'privPass=s', + 'secLevel=s', + # Operation + 'oidList=s', + 'operation=s', + # Help option + 'Help', +); + +if ($Param{Help}){ + print $HELP; + exit 0; +} + +my $config; + +# General parameters +$config->{'community'} = $Param{community} || ''; +$config->{'version'} = $Param{version} || ''; +$config->{'host'} = $Param{host} || ''; +$config->{'port'} = $Param{port} || '161'; +$config->{'timeout'} = $Param{timeout} || '2'; + +# Version 3 parameters +$config->{'auth_method'} = $Param{authMethod} || ''; +$config->{'user'} = $Param{user} || ''; +$config->{'auth_pass'} = $Param{authPass} || ''; +$config->{'priv_method'} = $Param{privMethod} || ''; +$config->{'priv_pass'} = $Param{privPass} || ''; +$config->{'sec_level'} = $Param{secLevel} || ''; + +$config->{'auth_method'} = uc($config->{'auth_method'}); +$config->{'priv_method'} = uc($config->{'priv_method'}); + +# Operation +my $operation = $Param{operation} || ''; + +# OIDs +my @oid_list = split /,/, $Param{oidList} || ''; + +# Verify parameters +if (!$config->{'host'} || !$config->{'version'} || !$operation || !@oid_list){ + print $HELP; + print "Host, version, OID list and operation are required.\n"; + exit 1; +} + +if ($config->{'version'} ne '1' && $config->{'version'} ne '2c' && $config->{'version'} ne '3'){ + print $HELP; + print "Invalid SNMP version provided.\n"; + exit 1; +} + +if ($config->{'version'} eq '1' || $config->{'version'} eq '2c'){ + if (!$config->{'community'}){ + print $HELP; + print "SNMP community required for version 1 or 2c.\n"; + exit 1; + } +} + +if ($config->{'version'} eq '3'){ + if ($config->{'sec_level'} =~ /^noAuthNoPriv$/i){ + if (!$config->{'user'}){ + print $HELP; + print "Username required for SNMP version 3 and security level 'noAuthNoPriv'.\n"; + exit 1; + } + }elsif ($config->{'sec_level'} =~ /^authNoPriv$/i){ + if (!$config->{'user'} && !$config->{'auth_pass'} && !$config->{'auth_method'}){ + print $HELP; + print "Username, authentication password and authentication method required for SNMP version 3 and security level 'authNoPriv'.\n"; + exit 1; + } + }elsif ($config->{'sec_level'} =~ /^authPriv$/i){ + if (!$config->{'user'} && !$config->{'auth_pass'} && !$config->{'auth_method'} && !$config->{'priv_pass'} && !$config->{'priv_method'}){ + print $HELP; + print "Username, authentication password, authentication method, privacy password and privacy method required for SNMP version 3 and security level 'authPriv'.\n"; + exit 1; + } + }else{ + print $HELP; + print "Invalid SNMP security level provided for version 3.\n"; + exit 1; + } + + if ($config->{'auth_method'} && $config->{'auth_method'} ne 'MD5' && $config->{'auth_method'} ne 'SHA'){ + print $HELP; + print "Invalid SNMP authentication method provided for version 3.\n"; + exit 1; + } + + if ($config->{'priv_method'} && $config->{'priv_method'} ne 'DES' && $config->{'priv_method'} ne 'AES'){ + print $HELP; + print "Invalid SNMP privacy method provided for version 3.\n"; + exit 1; + } +} + +# Verify operation (avoid code injection) +my @operation = split //, lc($operation); + +foreach my $op (@operation){ + if ($op !~ /\d/ && $op ne ' ' && $op ne '(' && $op ne ')' && $op ne '_' && $op ne '-' && $op ne '+' && $op ne '*' && $op ne '/' && $op ne 'o'){ + print $HELP; + print "Specified operation has invalid characters: " . $op . "\n"; + exit 1; + } +} + +# Create SNMP target +my ($target, $error) = new_snmp_target($config); + +if (!$target){ + print $error . "\n"; + exit 1; +} + +# Get OIDs values +my $oid_values = {}; +my $i = 1; +foreach my $oid (@oid_list){ + $oid_values->{'_o' . $i . '_'} = snmp_get($target, $oid); + $i++; +} + +# Change operation macros with values +$i = 1; +foreach my $k (keys %{$oid_values}){ + my $oid_macro = '_o' . $i . '_'; + my $value = $oid_values->{$oid_macro}; + $operation =~ s/$oid_macro/$value/g; + $i++; +} + +# Get operation result +my $result = eval $operation; +if (defined($result)){ + print $result . "\n"; +} \ No newline at end of file diff --git a/pandora_server/util/plugin/wizard_snmp_process.pl b/pandora_server/util/plugin/wizard_snmp_process.pl new file mode 100755 index 0000000000..c510de1171 --- /dev/null +++ b/pandora_server/util/plugin/wizard_snmp_process.pl @@ -0,0 +1,282 @@ +#!/usr/bin/perl +# +################################################################################ +# +# SNMP wizard process +# +# Requirements: +# Net::SNMP +# Crypt::DES +# Digest::SHA1 +# +# (c) Enrique Martin Garcia +# +# 2020/03/10 +# +################################################################################ + +use strict; +use warnings; + +use POSIX qw(strftime); + +use Encode; +use Encode::Locale; +use Getopt::Long; +use Net::SNMP; + +my $HELP=<" -version "" [SNMP] [SNMPv3] -process "" + +-host Target host +-version SNMP version (1, 2c, 3) + +-process Process name to check if is running (case sensitive) + +[SNMP] + -community Community (only version 1 and 2c) + -port Target UDP port (Default 161) + +[SNMPv3] + -user Username + -authMethod Authentication method (MD5, SHA) + -authPass Authentication password + -privMethod Privacy method (DES, AES) + -privPass Privacy password + -secLevel Security level (noAuthNoPriv, authNoPriv, authPriv) + +Example: $0 -host 192.168.80.43 -community public -version 1 -process "httpd" + +EO_HELP + +# +# FUNCTIONS +############## + +sub new_snmp_target { + my ($config) = @_; + my $target; + my $error; + + if ($config->{'version'} ne '3'){ + ($target, $error) = Net::SNMP->session( + -hostname => $config->{'host'}, + -port => $config->{'port'}, + -version => $config->{'version'}, + -timeout => $config->{'timeout'}, + -translate => 0, + -community => $config->{'community'} + ); + }else{ + if ($config->{'sec_level'} =~ /^noAuthNoPriv$/i){ + ($target, $error) = Net::SNMP->session( + -hostname => $config->{'host'}, + -port => $config->{'port'}, + -version => $config->{'version'}, + -timeout => $config->{'timeout'}, + -translate => 0, + -username => $config->{'user'} + ); + }elsif ($config->{'sec_level'} =~ /^authNoPriv$/i){ + ($target, $error) = Net::SNMP->session( + -hostname => $config->{'host'}, + -port => $config->{'port'}, + -version => $config->{'version'}, + -timeout => $config->{'timeout'}, + -translate => 0, + -username => $config->{'user'}, + -authpassword => $config->{'auth_pass'}, + -authprotocol => $config->{'auth_method'} + ); + }elsif ($config->{'sec_level'} =~ /^authPriv$/i){ + ($target, $error) = Net::SNMP->session( + -hostname => $config->{'host'}, + -port => $config->{'port'}, + -version => $config->{'version'}, + -timeout => $config->{'timeout'}, + -translate => 0, + -username => $config->{'user'}, + -authpassword => $config->{'auth_pass'}, + -authprotocol => $config->{'auth_method'}, + -privpassword => $config->{'priv_pass'}, + -privprotocol => $config->{'priv_method'} + ); + } + } + + + return ($target, $error); +} + +sub snmp_walk { + my ($target, $oid) = @_; + my $result = {}; + + my $walk = $target->get_table( + -baseoid => $oid, + ); + + if (defined($walk)){ + $result = $walk; + } + + return $result; +} + +sub snmp_get { + my ($target, $oid) = @_; + my $result = ''; + + my $get = $target->get_request( + -varbindlist => [$oid], + ); + + if (defined($get)){ + $result = $get->{$oid}; + } + + return $result; +} + +# +# MAIN +############## + +@ARGV = map { decode(locale => $_, 1) } @ARGV if -t STDIN; +binmode STDOUT, ":encoding(console_out)" if -t STDOUT; +binmode STDERR, ":encoding(console_out)" if -t STDERR; + +my %Param = (); +GetOptions( + \%Param, + # General + 'community=s', + 'version=s', + 'host=s', + 'port=s', + 'timeout=s', + # Version 3 + 'user=s', + 'authMethod=s', + 'authPass=s', + 'privMethod=s', + 'privPass=s', + 'secLevel=s', + # Process + 'process=s', + # Help option + 'Help', +); + +if ($Param{Help}){ + print $HELP; + exit 0; +} + +my $config; + +# General parameters +$config->{'community'} = $Param{community} || ''; +$config->{'version'} = $Param{version} || ''; +$config->{'host'} = $Param{host} || ''; +$config->{'port'} = $Param{port} || '161'; +$config->{'timeout'} = $Param{timeout} || '2'; + +# Version 3 parameters +$config->{'auth_method'} = $Param{authMethod} || ''; +$config->{'user'} = $Param{user} || ''; +$config->{'auth_pass'} = $Param{authPass} || ''; +$config->{'priv_method'} = $Param{privMethod} || ''; +$config->{'priv_pass'} = $Param{privPass} || ''; +$config->{'sec_level'} = $Param{secLevel} || ''; + +$config->{'auth_method'} = uc($config->{'auth_method'}); +$config->{'priv_method'} = uc($config->{'priv_method'}); + +# Operation +my $process = $Param{process} || ''; + +# Verify parameters +if (!$config->{'host'} || !$config->{'version'} || !$process){ + print $HELP; + print "Host, version and process are required.\n"; + exit 1; +} + +if ($config->{'version'} ne '1' && $config->{'version'} ne '2c' && $config->{'version'} ne '3'){ + print $HELP; + print "Invalid SNMP version provided.\n"; + exit 1; +} + +if ($config->{'version'} eq '1' || $config->{'version'} eq '2c'){ + if (!$config->{'community'}){ + print $HELP; + print "SNMP community required for version 1 or 2c.\n"; + exit 1; + } +} + +if ($config->{'version'} eq '3'){ + if ($config->{'sec_level'} =~ /^noAuthNoPriv$/i){ + if (!$config->{'user'}){ + print $HELP; + print "Username required for SNMP version 3 and security level 'noAuthNoPriv'.\n"; + exit 1; + } + }elsif ($config->{'sec_level'} =~ /^authNoPriv$/i){ + if (!$config->{'user'} && !$config->{'auth_pass'} && !$config->{'auth_method'}){ + print $HELP; + print "Username, authentication password and authentication method required for SNMP version 3 and security level 'authNoPriv'.\n"; + exit 1; + } + }elsif ($config->{'sec_level'} =~ /^authPriv$/i){ + if (!$config->{'user'} && !$config->{'auth_pass'} && !$config->{'auth_method'} && !$config->{'priv_pass'} && !$config->{'priv_method'}){ + print $HELP; + print "Username, authentication password, authentication method, privacy password and privacy method required for SNMP version 3 and security level 'authPriv'.\n"; + exit 1; + } + }else{ + print $HELP; + print "Invalid SNMP security level provided for version 3.\n"; + exit 1; + } + + if ($config->{'auth_method'} && $config->{'auth_method'} ne 'MD5' && $config->{'auth_method'} ne 'SHA'){ + print $HELP; + print "Invalid SNMP authentication method provided for version 3.\n"; + exit 1; + } + + if ($config->{'priv_method'} && $config->{'priv_method'} ne 'DES' && $config->{'priv_method'} ne 'AES'){ + print $HELP; + print "Invalid SNMP privacy method provided for version 3.\n"; + exit 1; + } +} + +# Create SNMP target +my ($target, $error) = new_snmp_target($config); + +if (!$target){ + print $error . "\n"; + exit 1; +} + +# Get all running processes +my $processes = snmp_walk($target, '.1.3.6.1.2.1.25.4.2.1.2'); + +my $result = 0; + +# Search process name +foreach my $k (keys %{$processes}){ + if ($processes->{$k} eq $process){ + $result = 1; + last; + } +} + +print $result . "\n"; \ No newline at end of file diff --git a/pandora_server/util/plugin/wizard_wmi_module.pl b/pandora_server/util/plugin/wizard_wmi_module.pl new file mode 100755 index 0000000000..3cb1661da9 --- /dev/null +++ b/pandora_server/util/plugin/wizard_wmi_module.pl @@ -0,0 +1,176 @@ +#!/usr/bin/perl +# +################################################################################ +# +# WMI wizard module +# +# Requirements: +# wmic +# +# (c) Enrique Martin Garcia +# +# 2020/03/10 +# +################################################################################ + +use strict; +use warnings; + +use POSIX qw(strftime); + +use Encode; +use Encode::Locale; +use Getopt::Long; + +use Data::Dumper; + +my $HELP=<"] -host "" [-namespace ""] -user "" -pass "" -wmiClass "" -fieldsList "" [-queryFilter ""] -operation "" + +-wmicPath Path to wmic command (Default: /usr/bin/wmic) + +-host Target host +-namespace WMI namespace +-user Windows username ([domain/]username) +-pass User password + +-wmiClass WMI class for query (Example: Win32_OperatingSystem) +-fieldsList Comma separated class fields list (Example: TotalVisibleMemorySize,FreePhysicalMemory) +-queryFilter WMI query class filter (Example: DeviceID = 3 AND DeviceType = 1) + +-operation Aritmetic operation to get data. + Macros _fN_ will be changed by fields in list. + Example: ((_f1_ - _f2_) * 100) / _f1_ + +Example: $0 -host "192.168.80.43" -user "pandora/Administrator" -pass "PandoraFMS1234" -wmiClass "Win32_OperatingSystem" -fieldsList "TotalVisibleMemorySize,FreePhysicalMemory" -operation "((_f1_ - _f2_) * 100) / _f1_" + +EO_HELP + +# +# MAIN +############## + +@ARGV = map { decode(locale => $_, 1) } @ARGV if -t STDIN; +binmode STDOUT, ":encoding(console_out)" if -t STDOUT; +binmode STDERR, ":encoding(console_out)" if -t STDERR; + +my %Param = (); +GetOptions( + \%Param, + # General + 'wmicPath=s', + 'host=s', + 'namespace=s', + 'user=s', + 'pass=s', + # Query + 'wmiClass=s', + 'fieldsList=s', + 'queryFilter=s', + # Operation + 'operation=s', + # Help option + 'Help', +); + +if ($Param{Help}){ + print $HELP; + exit 0; +} + +my $config; + +# General parameters +$config->{'wmicPath'} = $Param{wmicPath} || '/usr/bin/wmic'; +$config->{'host'} = $Param{host} || ''; +$config->{'namespace'} = $Param{namespace} || ''; +$config->{'user'} = $Param{user} || ''; +$config->{'pass'} = $Param{pass} || ''; + +# Query parameters +$config->{'wmiClass'} = $Param{wmiClass} || ''; +$config->{'queryFilter'} = $Param{queryFilter} || ''; +$config->{'fieldsList'} = $Param{fieldsList} || ''; + +# Operation +my $operation = $Param{operation} || ''; + +# Fields +my @fields_list = split /,/, $config->{'fieldsList'} || ''; + +# Verify parameters +if (!$config->{'host'} || !$config->{'user'} || !$config->{'pass'} || !$config->{'wmiClass'} || !@fields_list || !$operation){ + print $HELP; + print "Host, user, password, WMI class, fields list and operation are required.\n"; + exit 1; +} + +# Verify operation (avoid code injection) +my @operation = split //, lc($operation); + +foreach my $op (@operation){ + if ($op !~ /\d/ && $op ne ' ' && $op ne '(' && $op ne ')' && $op ne '_' && $op ne '-' && $op ne '+' && $op ne '*' && $op ne '/' && $op ne 'f'){ + print $HELP; + print "Specified operation has invalid characters: " . $op . "\n"; + exit 1; + } +} + +# Build WMI query +my $wmi_query = 'SELECT ' . $config->{'fieldsList'} . ' FROM ' . $config->{'wmiClass'} . ($config->{'queryFilter'} ? ' WHERE ' . $config->{'queryFilter'} : ''); + +# Build wmic command +my $wmi_command = $config->{'wmicPath'} . ' -U ' . $config->{'user'} . '%' . $config->{'pass'} . ($config->{'namespace'} ? ' --namespace="' . $config->{'namespace'} . '"' : '') . ' //' . $config->{'host'} . ' "' . $wmi_query . '"'; + +# Run wmic and parse output +my $output = `$wmi_command 2>/dev/null`; + +my @data = split("\n", $output); + +if ($data[0] ne 'CLASS: ' . $config->{'wmiClass'}){ + print $output; + exit 1; +} + +# Parse fields positions +my @fields_pos; + +my $i = 0; +foreach my $field (split /\|/, $data[1]){ + my $x = 1; + foreach my $f (@fields_list){ + $f =~ s/^\s*//; + $f =~ s/\s*$//; + if (lc($field) eq lc($f)){ + $fields_pos[$i] = $x; + } + $x++; + } + $i++; +} + +# Get fields values +my $fields_values = {}; +$i = 0; +foreach my $field_value (split /\|/, $data[2]){ + $fields_values->{'_f' . $fields_pos[$i] . '_'} = $field_value; + $i++; +} + +# Change operation macros with values +$i = 1; +foreach my $k (keys %{$fields_values}){ + my $field_macro = '_f' . $i . '_'; + my $value = $fields_values->{$field_macro}; + $operation =~ s/$field_macro/$value/g; + $i++; +} + +# Get operation result +my $result = eval $operation; +if (defined($result)){ + print $result . "\n"; +} \ No newline at end of file From 142823eef66b2a717681ec9def2b33af66313823 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Tue, 17 Mar 2020 13:46:10 +0100 Subject: [PATCH 006/111] WIP: Backup upload --- pandora_console/godmode/menu.php | 2 +- .../modules/manage_network_templates.php | 6 + .../include/class/ManageBlock.class.php | 151 ++++++++++++++++-- 3 files changed, 146 insertions(+), 13 deletions(-) diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index 9522c7cb58..d400f25cf1 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -142,7 +142,7 @@ if (check_acl($config['id_user'], 0, 'PM')) { enterprise_hook('components_submenu'); $sub['godmode/modules/manage_block_templates']['text'] = __('Module blocks'); $sub['godmode/modules/manage_block_templates']['id'] = 'Module blocks'; - $sub['godmode/modules/manage_network_templates']['text'] = __('Module templates (legacy)'); + $sub['godmode/modules/manage_network_templates']['text'] = __('Module templates (legacy)'); $sub['godmode/modules/manage_network_templates']['id'] = 'Module templates'; enterprise_hook('inventory_submenu'); enterprise_hook('autoconfiguration_menu'); diff --git a/pandora_console/godmode/modules/manage_network_templates.php b/pandora_console/godmode/modules/manage_network_templates.php index eebf408caa..16b52aa2d0 100644 --- a/pandora_console/godmode/modules/manage_network_templates.php +++ b/pandora_console/godmode/modules/manage_network_templates.php @@ -46,6 +46,12 @@ ui_print_page_header( 'modulemodal' ); +ui_print_info_message( + __( + 'This section is maintained only for legacy use. Please, keep in mind use %s for manage template blocks.', + 'Module Blocks' + ) +); require_once 'include/functions_network_profiles.php'; diff --git a/pandora_console/include/class/ManageBlock.class.php b/pandora_console/include/class/ManageBlock.class.php index 62399a5db7..8b9e604420 100644 --- a/pandora_console/include/class/ManageBlock.class.php +++ b/pandora_console/include/class/ManageBlock.class.php @@ -14,14 +14,47 @@ global $config; require_once $config['homedir'].'/include/class/HTML.class.php'; - +/** + * Class ManageBlock + */ class ManageBlock extends HTML { - private $ajax_controller; + /** + * Var that contain very cool stuff + * + * @var string + */ + private $ajaxController; + + /** + * Undocumented function + * + * @param array $ajax_controller + */ + private $countNetworkTemplates; + + /** + * Undocumented variable + * + * @var [type] + */ + private $offset; + + /** + * Table with module blocks + * + * @var [type] + */ + private $resultModuleBlocksTable; - public function __construct($ajax_controller) + /** + * Constructor + * + * @param string $ajax_controller Pues hace cosas to wapas. + */ + public function __construct(string $ajax_controller) { global $config; @@ -42,34 +75,50 @@ class ManageBlock extends HTML exit; } - $this->ajaxController = $ajax_controller; + $this->offset = (int) get_parameter('offset', 0); - $this->setBreadcrum([]); + $this->countNetworkTemplates = db_get_value( + 'count(*)', + 'tnetwork_profile' + ); + + $this->resultModuleBlocksTable = db_get_all_rows_filter( + 'tnetwork_profile', + [ + 'order' => 'name', + 'limit' => $config['block_size'], + 'offset' => $this->offset, + ] + ); + + $this->ajaxController = $ajax_controller; return $this; } /** - * Run MiFuncionalidad (main page). + * Run main page. * * @return void */ public function run() { + // Header section. + // Breadcrums. + $this->setBreadcrum([]); + $this->prepareBreadcrum( [ [ - 'link' => 'mishuevos', - // $this->url, + 'link' => '', 'label' => __('Configuration'), - 'selected' => 0, + 'selected' => false, ], [ - 'link' => 'url', - // $this->url, + 'link' => $this->url, 'label' => __('Module Blocks'), - 'selected' => 1, + 'selected' => true, ], ], true @@ -89,6 +138,10 @@ class ManageBlock extends HTML $this->printHeader(true) ); + ui_pagination($this->countNetworkTemplates, false, $this->offset); + + echo $this->moduleBlockList(); + // $this->printForm( // [ // 'form' => $form, @@ -100,4 +153,78 @@ class ManageBlock extends HTML } + /** + * Undocumented function + * + * @return html Formed table + */ + public function moduleBlockList() + { + // Create the table with Module Block list. + $table = new StdClasS(); + $table->class = 'databox data'; + $table->width = '75%'; + $table->styleTable = 'margin: 2em auto 0;border: 1px solid #ddd;background: white;'; + $table->rowid = []; + $table->data = []; + + $table->cellpadding = 0; + $table->cellspacing = 0; + $table->width = '100%'; + $table->class = 'info_table'; + + $table->head = []; + $table->head[0] = html_print_checkbox('all_delete', 0, false, true, false); + ; + $table->head[1] = __('Name'); + $table->head[2] = __('Description'); + $table->head[3] = ''.__('Action').''; + $table->size = []; + $table->size[0] = '20px'; + $table->size[2] = '65%'; + $table->size[3] = '15%'; + + $table->align = []; + $table->align[3] = 'left'; + + $table->data = []; + + hd($this->resultModuleBlocksTable); + + foreach ($this->resultModuleBlocksTable as $row) { + $data = []; + $data[0] = $row['id_np']; + $data[1] = ''.io_safe_output($row['name']).''; + $data[2] = 'description'; + // $data[2] = ui_print_truncate_text(io_safe_output($row['description']), 'description', true, true, true, '[…]'); + $table->cellclass[][3] = 'action_buttons'; + $data[3] = html_print_input_image( + 'delete_profile', + 'images/cross.png', + $row['id_np'], + '', + true, + ['onclick' => 'if (!confirm(\''.__('Are you sure?').'\')) return false;'] + ); + $data[3] .= html_print_input_image( + 'export_profile', + 'images/csv.png', + $row['id_np'], + '', + true, + ['title' => 'Export to CSV'] + ); + $data[3] = ''.html_print_image('images/cross.png', true, ['title' => __('Delete')]).''; + $data[3] .= ''.html_print_image('images/csv.png', true, ['title' => __('Export to CSV')]).''; + + array_push($table->data, $data); + } + + $output = '
      '.__('Summary').'
      '; + $output .= html_print_table($table, true).''; + + return $output; + } + + } From 40958ae69d8bbbcfe778cdb63bf7e280532acd94 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Tue, 17 Mar 2020 16:24:17 +0100 Subject: [PATCH 007/111] WIP: Backup upload --- .../modules/manage_block_templates.php | 25 ++++-- .../include/class/ManageBlock.class.php | 83 +++++++++++++------ 2 files changed, 78 insertions(+), 30 deletions(-) diff --git a/pandora_console/godmode/modules/manage_block_templates.php b/pandora_console/godmode/modules/manage_block_templates.php index 46ffe791a4..540dc7b5b3 100644 --- a/pandora_console/godmode/modules/manage_block_templates.php +++ b/pandora_console/godmode/modules/manage_block_templates.php @@ -12,6 +12,13 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Load global vars +// TESTING +/* + ini_set('display_errors', 1); + ini_set('display_startup_errors', 1); +error_reporting(E_ALL); */ +$cipotes = false; +// END global $config; check_login(); @@ -25,12 +32,8 @@ if (! check_acl($config['id_user'], 0, 'PM')) { return; } -ini_set('display_errors', 1); -ini_set('display_startup_errors', 1); -error_reporting(E_ALL); - require_once $config['homedir'].'/include/class/ManageBlock.class.php'; -// $ajaxPage = ENTERPRISE_DIR.'/godmode/agentes/ManageBlock'; +$ajaxPage = ENTERPRISE_DIR.'/godmode/agentes/ManageBlock'; // Control call flow. try { // User access and validation is being processed on class constructor. @@ -66,6 +69,18 @@ if (is_ajax()) { // Stop any execution. exit; } else { + // Get all parameters + $id_np = get_parameter('id_np', ''); // Run. $manageBlock->run(); + + // List all Module Block + // Show the id_np selected + // Create new id_np + if ($id_np == 0) { + $manageBlock->moduleTemplateForm(); + echo 'hola'; + } else { + $manageBlock->moduleBlockList(); + } } diff --git a/pandora_console/include/class/ManageBlock.class.php b/pandora_console/include/class/ManageBlock.class.php index 8b9e604420..7dba375d0e 100644 --- a/pandora_console/include/class/ManageBlock.class.php +++ b/pandora_console/include/class/ManageBlock.class.php @@ -1,16 +1,31 @@ countNetworkTemplates, false, $this->offset); - echo $this->moduleBlockList(); - + // echo $this->moduleBlockList(); // $this->printForm( // [ // 'form' => $form, @@ -154,7 +168,7 @@ class ManageBlock extends HTML /** - * Undocumented function + * Create * * @return html Formed table */ @@ -189,14 +203,11 @@ class ManageBlock extends HTML $table->data = []; - hd($this->resultModuleBlocksTable); - foreach ($this->resultModuleBlocksTable as $row) { $data = []; - $data[0] = $row['id_np']; - $data[1] = ''.io_safe_output($row['name']).''; - $data[2] = 'description'; - // $data[2] = ui_print_truncate_text(io_safe_output($row['description']), 'description', true, true, true, '[…]'); + $data[0] = html_print_checkbox_extended('delete_multiple[]', $row['id_np'], false, false, '', 'class="check_delete"', true); + $data[1] = ''.io_safe_output($row['name']).''; + $data[2] = ui_print_truncate_text(io_safe_output($row['description']), 'description', true, true, true, '[…]'); $table->cellclass[][3] = 'action_buttons'; $data[3] = html_print_input_image( 'delete_profile', @@ -214,16 +225,38 @@ class ManageBlock extends HTML true, ['title' => 'Export to CSV'] ); - $data[3] = ''.html_print_image('images/cross.png', true, ['title' => __('Delete')]).''; - $data[3] .= ''.html_print_image('images/csv.png', true, ['title' => __('Export to CSV')]).''; + $data[3] = ''.html_print_image('images/cross.png', true, ['title' => __('Delete')]).''; + $data[3] .= ''.html_print_image('images/csv.png', true, ['title' => __('Export to CSV')]).''; array_push($table->data, $data); } - $output = '
      '.__('Summary').'
      '; - $output .= html_print_table($table, true).''; + echo html_print_table($table, true); - return $output; + echo '
      '; + + $this->printForm( + [ + 'form' => [ + 'method' => 'POST', + 'action' => 'index.php?sec=gmodules&sec2=godmode/modules/manage_block_templates', + ], + 'inputs' => [ + [ + 'class' => 'w100p', + 'arguments' => [ + 'name' => 'crt', + 'label' => __('Create'), + 'type' => 'submit', + 'attributes' => 'class="sub next"', + 'return' => true, + ], + ], + ], + ] + ); + + echo '
      '; } From c1337a4318cd2fe4b4748cb17dd1f16cb0dd4d99 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Tue, 17 Mar 2020 18:27:56 +0100 Subject: [PATCH 008/111] WIP: Backup upload --- .../modules/manage_block_templates.php | 11 ++-- .../include/class/ManageBlock.class.php | 59 +++++++++++++++++-- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/pandora_console/godmode/modules/manage_block_templates.php b/pandora_console/godmode/modules/manage_block_templates.php index 540dc7b5b3..d1ec375f86 100644 --- a/pandora_console/godmode/modules/manage_block_templates.php +++ b/pandora_console/godmode/modules/manage_block_templates.php @@ -13,10 +13,9 @@ // GNU General Public License for more details. // Load global vars // TESTING -/* ini_set('display_errors', 1); ini_set('display_startup_errors', 1); -error_reporting(E_ALL); */ +error_reporting(E_ALL); $cipotes = false; // END global $config; @@ -74,13 +73,13 @@ if (is_ajax()) { // Run. $manageBlock->run(); - // List all Module Block - // Show the id_np selected - // Create new id_np if ($id_np == 0) { + // Create new id_np $manageBlock->moduleTemplateForm(); - echo 'hola'; + } else if ($id_np > 0) { + // Show the id_np selected } else { + // List all Module Block $manageBlock->moduleBlockList(); } } diff --git a/pandora_console/include/class/ManageBlock.class.php b/pandora_console/include/class/ManageBlock.class.php index 7dba375d0e..e69898321d 100644 --- a/pandora_console/include/class/ManageBlock.class.php +++ b/pandora_console/include/class/ManageBlock.class.php @@ -63,6 +63,13 @@ class ManageBlock extends HTML */ private $resultModuleBlocksTable; + /** + * Base URL for internal purposes + * + * @var string + */ + private $baseUrl; + /** * Constructor @@ -108,6 +115,9 @@ class ManageBlock extends HTML $this->ajaxController = $ajax_controller; + // Set baseUrl for use it in several locations in this class + $this->baseUrl = 'index.php?sec=gmodules&sec2=godmode/modules/manage_block_templates'; + return $this; } @@ -206,7 +216,7 @@ class ManageBlock extends HTML foreach ($this->resultModuleBlocksTable as $row) { $data = []; $data[0] = html_print_checkbox_extended('delete_multiple[]', $row['id_np'], false, false, '', 'class="check_delete"', true); - $data[1] = ''.io_safe_output($row['name']).''; + $data[1] = ''.io_safe_output($row['name']).''; $data[2] = ui_print_truncate_text(io_safe_output($row['description']), 'description', true, true, true, '[…]'); $table->cellclass[][3] = 'action_buttons'; $data[3] = html_print_input_image( @@ -225,12 +235,14 @@ class ManageBlock extends HTML true, ['title' => 'Export to CSV'] ); - $data[3] = ''.html_print_image('images/cross.png', true, ['title' => __('Delete')]).''; - $data[3] .= ''.html_print_image('images/csv.png', true, ['title' => __('Export to CSV')]).''; + $data[3] = ''.html_print_image('images/cross.png', true, ['title' => __('Delete')]).''; + $data[3] .= ''.html_print_image('images/csv.png', true, ['title' => __('Export to CSV')]).''; array_push($table->data, $data); } + // Sé que los echo son basurientos, pero de momento, me valen para ir montando + // LOS QUITARÉ, PROMESA DE CORONAVIRUS echo html_print_table($table, true); echo '
      '; @@ -239,7 +251,7 @@ class ManageBlock extends HTML [ 'form' => [ 'method' => 'POST', - 'action' => 'index.php?sec=gmodules&sec2=godmode/modules/manage_block_templates', + 'action' => $this->baseUrl, ], 'inputs' => [ [ @@ -260,4 +272,43 @@ class ManageBlock extends HTML } + /** + * Prints Form for template + * + * @param integer $id_np If not carried + * @return void + */ + public function moduleTemplateForm(int $id_np=0) + { + if ($id_np == 0) { + $formButtonName = 'crt'; + $formButtonLabel = __('Create'); + } else { + $formButtonName = 'upd'; + $formButtonLabel = __('Update'); + } + + $this->printForm( + [ + 'form' => [ + 'method' => 'POST', + 'action' => $this->baseUrl, + ], + 'inputs' => [ + [ + 'class' => 'w100p', + 'arguments' => [ + 'name' => $formButtonName, + 'label' => $formButtonLabel, + 'type' => 'submit', + 'attributes' => 'class="sub next"', + 'return' => true, + ], + ], + ], + ] + ); + } + + } From b860c4938326aa1a85b87de0a4c22d63dd3b97f4 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Tue, 17 Mar 2020 18:34:30 +0100 Subject: [PATCH 009/111] target selections --- .../wizards/DiscoveryTaskList.class.php | 267 ++++++++++++++---- pandora_console/include/class/HTML.class.php | 70 ++++- pandora_console/include/constants.php | 5 + .../include/javascript/pandora_taskList.js | 17 +- .../include/javascript/pandora_ui.js | 6 + pandora_console/include/javascript/simTree.js | 10 +- pandora_console/include/styles/task_list.css | 42 +++ 7 files changed, 341 insertions(+), 76 deletions(-) diff --git a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php index eef0bb59a9..2134da1f37 100644 --- a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php +++ b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php @@ -123,8 +123,9 @@ class DiscoveryTaskList extends HTML } $force_run = (bool) get_parameter('force_run'); - if ($force_run === true) { - return $this->forceConsoleTask(); + $force = (bool) get_parameter('force'); + if ($force_run === true || $force === true) { + return $this->forceTask(); } $delete_console_task = (bool) get_parameter('delete_console_task'); @@ -241,7 +242,7 @@ class DiscoveryTaskList extends HTML * * @return void */ - public function forceConsoleTask() + public function forceTask() { global $config; @@ -256,12 +257,46 @@ class DiscoveryTaskList extends HTML $id_console_task = (int) get_parameter('id_console_task'); - if ($id_console_task !== null) { + if ($id_console_task != null) { + // -------------------------------- + // FORCE A CONSOLE TASK + // -------------------------------- enterprise_hook('cron_task_run', [$id_console_task, true]); // Trick to avoid double execution. header('Location: '.$this->url); - } + } else { + // -------------------------------- + // FORCE A RECON TASK + // -------------------------------- + if (check_acl($config['id_user'], 0, 'AW')) { + if (isset($_GET['force'])) { + $id = (int) get_parameter_get('force', 0); + // Schedule execution. + $direct_report = db_get_value( + 'direct_report', + 'trecon_task', + 'id_rt', + $id + ); + if ($direct_report != DISCOVERY_STANDARD) { + // Force re-scan for supervised tasks. + $direct_report = DISCOVERY_SEARCH; + } + + db_process_sql_update( + 'trecon_task', + [ + 'utimestamp' => 0, + 'status' => 1, + 'direct_report' => DISCOVERY_RESULTS, + ], + ['id_rt' => $id] + ); + header('Location: '.$this->url); + } + } + } } @@ -334,28 +369,7 @@ class DiscoveryTaskList extends HTML include_once $config['homedir'].'/include/functions_servers.php'; include_once $config['homedir'].'/include/functions_network_profiles.php'; - $modules_server = 0; - $total_modules = 0; - $total_modules_data = 0; - - // -------------------------------- - // FORCE A RECON TASK - // -------------------------------- - if (check_acl($config['id_user'], 0, 'AW')) { - if (isset($_GET['force'])) { - $id = (int) get_parameter_get('force', 0); - servers_force_recon_task($id); - header( - 'Location: '.ui_get_full_url( - 'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=tasklist' - ) - ); - } - } - $recon_tasks = db_get_all_rows_sql('SELECT * FROM trecon_task'); - $user_groups = implode(',', array_keys(users_get_groups())); - // Show network tasks for Recon Server. if ($recon_tasks === false) { $recon_tasks = []; @@ -636,7 +650,7 @@ class DiscoveryTaskList extends HTML 'data' => [ 'wiz' => 'tasklist', 'id' => $task['id_rt'], - 'method' => 'task_progress', + 'method' => 'taskProgress', ], ] ); @@ -842,10 +856,11 @@ class DiscoveryTaskList extends HTML * * @return void */ - public function task_progress() + public function taskProgress() { if (!is_ajax()) { - return ''; + echo json_encode(['error' => true]); + return; } $id_task = get_parameter('id', 0); @@ -871,11 +886,11 @@ class DiscoveryTaskList extends HTML * * @return string Charts in HTML. */ - private function progress_task_graph($task) + private function progressTaskGraph($task) { $result .= '
      '; - $result .= '
      '; - $result .= ''._('Overall Progress').''; + $result .= '
      '; + $result .= ''._('Overall Progress').''; $result .= '
      '; $result .= progress_circular_bar( @@ -928,8 +943,8 @@ class DiscoveryTaskList extends HTML } $result .= '
      '; - $result .= '
      '; - $result .= ''.$str.' '; + $result .= '
      '; + $result .= ''.$str.' '; if (!empty($str)) { $result .= $task['stats']['c_network_name']; } @@ -964,7 +979,7 @@ class DiscoveryTaskList extends HTML * * @return html code with summary. */ - private function progress_task_summary($task) + private function progressTaskSummary($task) { global $config; include_once $config['homedir'].'/include/graphs/functions_d3.php'; @@ -975,6 +990,10 @@ class DiscoveryTaskList extends HTML $output = ''; + if (is_array($task['stats']) === false) { + $task['stats'] = json_decode($task['summary'], true); + } + if (is_array($task['stats'])) { $i = 0; $table = new StdClasS(); @@ -1010,7 +1029,7 @@ class DiscoveryTaskList extends HTML $table->data[$i][1] .= $task['stats']['summary']['WMI']; $table->data[$i++][1] .= ''; - $output = '
      '.__('Summary').'
      '; + $output = '
      '.__('Summary').'
      '; $output .= html_print_table($table, true).'
      '; } @@ -1023,7 +1042,7 @@ class DiscoveryTaskList extends HTML * * @return void */ - public function progress_task_discovery() + public function progressTaskDiscovery() { if (!is_ajax()) { return; @@ -1038,8 +1057,7 @@ class DiscoveryTaskList extends HTML $task = db_get_row('trecon_task', 'id_rt', $id_task); $task['stats'] = json_decode($task['summary'], true); - $global_progress = $task['status']; - $summary = $this->progress_task_summary($task); + $summary = $this->progressTaskSummary($task); $output = ''; @@ -1059,7 +1077,7 @@ class DiscoveryTaskList extends HTML true ).'
      '; } else { - $output .= $this->progress_task_graph($task); + $output .= $this->progressTaskGraph($task); } $output .= $summary; @@ -1073,7 +1091,7 @@ class DiscoveryTaskList extends HTML * * @return void */ - public function task_showmap() + public function taskShowmap() { global $config; include_once $config['homedir'].'/include/class/NetworkMap.class.php'; @@ -1095,7 +1113,7 @@ class DiscoveryTaskList extends HTML * * @return void */ - public function show_task_review() + public function showTaskReview() { $id_task = get_parameter('id', 0); if ($id_task <= 0) { @@ -1103,28 +1121,56 @@ class DiscoveryTaskList extends HTML return; } - $task = db_get_row('tdiscovery_tmp_agents', 'id_rt', $id_task); + $task_data = db_get_row('tdiscovery_tmp_agents', 'id_rt', $id_task); + $task = db_get_row('trecon_task', 'id_rt', $id_task); - if (is_array($task)) { - $data = json_decode(base64_decode($task['data']), true); + if (is_array($task_data)) { + $data = json_decode(base64_decode($task_data['data']), true); $simple_data = array_reduce( $data, function ($carry, $item) { $id = $item['agent']['nombre']; - $carry[] = [ - 'id' => $id, - 'name' => $item['agent']['nombre'], + + $tmp = [ + 'id' => $id, + 'name' => $item['agent']['nombre'], + 'checked' => $item['checked'], ]; + if (empty($item['agent']['agent_id'])) { + $agent_id = agents_get_agent_id($id, true); + if ($agent_id > 0) { + $tmp['disabled'] = 1; + $tmp['checked'] = 1; + $tmp['agent_id'] = $agent_id; + } + } + + $carry[] = $tmp; $childs = array_reduce( $item['modules'], - function ($c, $i) use ($id) { - $c[] = [ - 'name' => $i['name'], - 'id' => $id.'-'.$i['name'], - 'pid' => $id, - ]; - return $c; + function ($c, $i) use ($id, $agent_id) { + $tmp = [ + 'name' => $i['name'], + 'id' => $id.'-'.$i['name'], + 'pid' => $id, + 'checked' => $i['checked'], + ]; + + if (empty($i['agentmodule_id'])) { + $agentmodule_id = modules_get_agentmodule_id( + io_safe_input($i['name']), + $agent_id + ); + if ($agentmodule_id > 0) { + $tmp['disabled'] = 1; + $tmp['checked'] = 1; + $tmp['module_id'] = $agentmodule_id; + } + } + + $c[] = $tmp; + return $c; }, [] ); @@ -1138,8 +1184,29 @@ class DiscoveryTaskList extends HTML [] ); + echo '
      '; + echo $this->progressTaskSummary($task); + echo '
      '; + echo '
      '; + echo ''; + echo __('Please select devices to be monitored'); + echo '
      '; + echo ''; + echo ''; + echo '
      '; + echo '
      '; + + echo '
      '; echo '
      '; - echo parent::printTree('tree', $simple_data); + echo parent::printTree( + 'tree', + $simple_data + ); + echo '
      '; } } @@ -1150,7 +1217,7 @@ class DiscoveryTaskList extends HTML * * @return void */ - public function parse_task_review() + public function parseTaskReview() { $id_task = get_parameter('id', 0); if ($id_task <= 0) { @@ -1158,7 +1225,91 @@ class DiscoveryTaskList extends HTML return; } - $out = obhd($_REQUEST); + $selection = io_safe_output(get_parameter('tree-data-tree', '')); + if (empty($selection)) { + $ids = []; + } else { + $selection = json_decode($selection, true); + $ids = array_reduce( + $selection, + function ($carry, $item) { + $carry[] = $item['id']; + return $carry; + } + ); + } + + $task_data = db_get_row('tdiscovery_tmp_agents', 'id', $id_task); + + if (is_array($task_data)) { + $data = json_decode(base64_decode($task_data['data']), true); + } + + $summary = []; + if (is_array($data)) { + foreach ($data as $agent_name => $row) { + if (in_array($agent_name, $ids)) { + $data[$agent_name]['checked'] = 1; + if ($data[$agent_name]['checked'] != 1) { + $summary[] = '
    • '.$agent_name.'
    • '; + } + } else { + if ($data[$agent_name]['checked'] == 1) { + $summary[] = '
    • '.__('Removed').' '.$agent_name.'
    • '; + } + + $data[$agent_name]['checked'] = 0; + } + + if (is_array($row['modules'])) { + $n_modules = count($row['modules']); + for ($i = 0; $i < $n_modules; $i++) { + $module_name = $row['modules'][$i]['name']; + if (in_array($agent_name.'-'.$module_name, $ids)) { + $data[$agent_name]['modules'][$i]['checked'] = 1; + if ($row['modules'][$i]['checked'] != 1) { + $summary[] = '
    • '.$agent_name.' - '.$module_name.'
    • '; + } + } else { + if ($row['modules'][$i]['checked'] == 1) { + $summary[] = '
    • '.__('Removed').' '.$agent_name.' - '.$module_name.'
    • '; + } + + $data[$agent_name]['modules'][$i]['checked'] = 0; + } + } + } + } + + // Update targets. + db_process_sql_update( + 'tdiscovery_tmp_agents', + [ + 'data' => base64_encode(json_encode($data)), + ], + ['id_rt' => $id_task] + ); + + // Schedule execution. + db_process_sql_update( + 'trecon_task', + [ + 'utimestamp' => 0, + 'status' => 1, + 'direct_report' => DISCOVERY_RESULTS, + ], + ['id_rt' => $id_task] + ); + } + + if (empty($summary)) { + $out .= __('No changes'); + } else { + $out .= __('Summary'); + $out .= '
        '; + $out .= join('', $summary); + $out .= '
      '; + } echo json_encode( ['result' => $out] diff --git a/pandora_console/include/class/HTML.class.php b/pandora_console/include/class/HTML.class.php index 049f86252e..6394951af8 100644 --- a/pandora_console/include/class/HTML.class.php +++ b/pandora_console/include/class/HTML.class.php @@ -38,7 +38,7 @@ class HTML /** * Breadcrum * - * @var array. + * @var array */ public $breadcrum; @@ -119,7 +119,7 @@ class HTML /** * Add an element to breadcrum array. * - * @param string $breads Elements to add to breadcrum. + * @param array $breads Elements to add to breadcrum. * * @return void */ @@ -335,6 +335,27 @@ class HTML } + /** + * Return formatted html for error handler. + * + * @param string $message Error mesage. + * + * @return string + */ + public function error($message) + { + if (is_ajax()) { + echo json_encode( + [ + 'error' => ui_print_error_message($message, '', true), + ] + ); + } else { + return ui_print_error_message($message, '', true); + } + } + + /** * Print input using functions html lib. * @@ -1003,27 +1024,62 @@ class HTML /** * Returns a n-dimensional array (data) into a html tree structure. * + * Advanced documentation: + * https://www.jqueryscript.net/other/Checkable-Hierarchical-Tree.html + * * @param string $target Target DOM id. * @param array $data N-dimensional array. - * @param string $callback Callback function. + * @param string $onclick Onclick function. + * @param string $onchange Onchange function. * * @return string */ - public static function printTree($target, $data, $callback='') - { + public static function printTree( + $target, + $data, + $onclick='', + $onchange='' + ) { ui_require_css_file('simTree'); ui_require_javascript_file('simTree'); + /* + * SAMPLE SELECT ALL. + * + * echo '
      '; + * echo ''; + * echo __('Please select devices to be monitored'); + * echo '
      '; + * echo ''; + * echo ''; + * echo '
      '; + * echo '
      '; + * + * END SAMPLE SELECT ALL. + */ + $output = ' '; diff --git a/pandora_console/include/constants.php b/pandora_console/include/constants.php index 8d83ac98f0..e8bb022233 100644 --- a/pandora_console/include/constants.php +++ b/pandora_console/include/constants.php @@ -597,6 +597,11 @@ define('DISCOVERY_DEPLOY_AGENTS', 9); define('DISCOVERY_APP_SAP', 10); +// Force task build tmp results. +define('DISCOVERY_SEARCH', 0); +define('DISCOVERY_STANDARD', 1); +define('DISCOVERY_RESULTS', 2); + // Discovery types matching definition. define('DISCOVERY_SCRIPT_HOSTDEVICES_CUSTOM', 0); // Standard applications. diff --git a/pandora_console/include/javascript/pandora_taskList.js b/pandora_console/include/javascript/pandora_taskList.js index 83b5c9657b..be10ffe773 100644 --- a/pandora_console/include/javascript/pandora_taskList.js +++ b/pandora_console/include/javascript/pandora_taskList.js @@ -50,7 +50,7 @@ function progress_task_list(id, title) { if (!$elem.dialog("isOpen")) timeoutRef = setInterval(function() { xhr = fetchTaskList(id, handleFetchTaskList); - }, 3000); + }, 300000); xhr = fetchTaskList(id, handleFetchTaskList); } @@ -66,7 +66,7 @@ function fetchTaskList(id, callback) { data: { page: "godmode/servers/discovery", wiz: "tasklist", - method: "progress_task_discovery", + method: "progressTaskDiscovery", id: id }, type: "POST", @@ -100,7 +100,7 @@ function show_map(id, name) { data: { page: "godmode/servers/discovery", wiz: "tasklist", - method: "task_showmap", + method: "taskShowmap", id: id }, type: "POST", @@ -157,6 +157,7 @@ function show_review(id, name) { of: window, collision: "fit" }, + maxHeight: 400, title: title, buttons: [ { @@ -166,9 +167,8 @@ function show_review(id, name) { click: function(e) { if (!failed) { $(".ui-dialog-content").dialog("close"); - $(".info").hide(); - cleanupDOM(); - dt_keystore.draw(false); + $("#task_review").empty(); + location.reload(); } else { $(this).dialog("close"); } @@ -189,11 +189,12 @@ function show_review(id, name) { ], onshow: { page: "godmode/servers/discovery", - method: "show_task_review" + method: "showTaskReview", + maxHeight: 800 }, onsubmit: { page: "godmode/servers/discovery", - method: "parse_task_review" + method: "parseTaskReview" } }); } diff --git a/pandora_console/include/javascript/pandora_ui.js b/pandora_console/include/javascript/pandora_ui.js index 606c574b1a..7730b2faf1 100644 --- a/pandora_console/include/javascript/pandora_ui.js +++ b/pandora_console/include/javascript/pandora_ui.js @@ -335,6 +335,12 @@ function load_modal(settings) { ? settings.onshow.maxHeight : "auto", overlay: settings.modal.overlay, + position: { + my: "top+20%", + at: "top", + of: window, + collision: "fit" + }, buttons: required_buttons, closeOnEscape: true, open: function() { diff --git a/pandora_console/include/javascript/simTree.js b/pandora_console/include/javascript/simTree.js index c3817b31b3..7dfdd35739 100644 --- a/pandora_console/include/javascript/simTree.js +++ b/pandora_console/include/javascript/simTree.js @@ -1,3 +1,7 @@ +/** + * IMPORTANT. Official plugin does not allow string ids + * This modificated one yes. + */ !(function(e) { var t = {}; function i(s) { @@ -373,7 +377,7 @@ } }, expandNode: function(e) { - var t = e.addClass ? e : this.$el.find("[data-id=" + e + "]"), + var t = e.addClass ? e : this.$el.find("[data-id='" + e + "']"), i = t.data("data"), s = i[this.options.response.pid], n = t.children(".sim-tree-spread"), @@ -392,7 +396,7 @@ $.isArray(i) && (this.options.check || (i = [i[0]]), $.each(i, function(e, i) { - var a = t.$el.find("[data-id=" + i + "]"), + var a = t.$el.find("[data-id='" + i + "']"), r = a.children("a"), d = r.children(".sim-tree-checkbox"), o = a.data("data"); @@ -415,7 +419,7 @@ ("string" != typeof i && "number" != typeof i) || (i = [i]), $.isArray(i) && $.each(i, function(e, i) { - var s = t.$el.find("[data-id=" + i + "]"); + var s = t.$el.find("[data-id='" + i + "']"); s.addClass("disabled"); }); }, diff --git a/pandora_console/include/styles/task_list.css b/pandora_console/include/styles/task_list.css index 7e7ab5a07f..cdf147e5c4 100644 --- a/pandora_console/include/styles/task_list.css +++ b/pandora_console/include/styles/task_list.css @@ -36,6 +36,48 @@ ul.progress_task_discovery { flex-direction: column; } +div.subtitle { + width: 100%; + margin-top: 40px; + text-align: center; +} + +div.subtitle span { + font-size: 1.9em; + font-family: "lato-bolder", "Open Sans", sans-serif; +} + +div.subtitle div.manage { + text-align: center; + padding-top: 2em; + padding-bottom: 1em; +} + +div.subtitle div.manage button { + font-size: 1.2em; + font-family: "lato", "Open Sans", sans-serif; + display: inline-block; + padding: 5px; + margin-right: 1em; + cursor: pointer; + text-align: left; +} + +#msg ul li { + margin-left: 3em; +} + +li.added { + list-style: url("../../images/header_ready.png"); +} +li.removed { + list-style: url("../../images/header_down.png"); +} + +#msg ul { + list-style: url("../../images/header_ready.png"); +} + ul.progress_task_discovery li span { font-size: 9pt; margin-left: 20px; From 6504fe49b5f37c5a17de7e2f01f2acdbfbcb9cd0 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Wed, 18 Mar 2020 10:28:50 +0100 Subject: [PATCH 010/111] intentation to spaces (2) and minor fix --- .../include/javascript/pandora_taskList.js | 2 +- .../lib/PandoraFMS/DiscoveryServer.pm | 1745 +++++------ pandora_server/lib/PandoraFMS/Recon/Base.pm | 2609 +++++++++-------- 3 files changed, 2182 insertions(+), 2174 deletions(-) diff --git a/pandora_console/include/javascript/pandora_taskList.js b/pandora_console/include/javascript/pandora_taskList.js index be10ffe773..0a61e1a831 100644 --- a/pandora_console/include/javascript/pandora_taskList.js +++ b/pandora_console/include/javascript/pandora_taskList.js @@ -50,7 +50,7 @@ function progress_task_list(id, title) { if (!$elem.dialog("isOpen")) timeoutRef = setInterval(function() { xhr = fetchTaskList(id, handleFetchTaskList); - }, 300000); + }, 3000); xhr = fetchTaskList(id, handleFetchTaskList); } diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index ae857deefd..b9ccafbf2a 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -54,552 +54,555 @@ my $TaskSem :shared; # IDs from tconfig_os. use constant { - OS_OTHER => 10, - OS_ROUTER => 17, - OS_SWITCH => 18, - STEP_SCANNING => 1, - STEP_AFT => 2, - STEP_TRACEROUTE => 3, - STEP_GATEWAY => 4, - STEP_STATISTICS => 1, - STEP_APP_SCAN => 2, - STEP_CUSTOM_QUERIES => 3, - DISCOVERY_HOSTDEVICES => 0, - DISCOVERY_HOSTDEVICES_CUSTOM => 1, - DISCOVERY_CLOUD_AWS => 2, - DISCOVERY_APP_VMWARE => 3, - DISCOVERY_APP_MYSQL => 4, - DISCOVERY_APP_ORACLE => 5, - DISCOVERY_CLOUD_AWS_EC2 => 6, - DISCOVERY_CLOUD_AWS_RDS => 7, - DISCOVERY_CLOUD_AZURE_COMPUTE => 8, - DISCOVERY_DEPLOY_AGENTS => 9, - DISCOVERY_APP_SAP => 10, + OS_OTHER => 10, + OS_ROUTER => 17, + OS_SWITCH => 18, + STEP_SCANNING => 1, + STEP_AFT => 2, + STEP_TRACEROUTE => 3, + STEP_GATEWAY => 4, + STEP_STATISTICS => 1, + STEP_APP_SCAN => 2, + STEP_CUSTOM_QUERIES => 3, + DISCOVERY_HOSTDEVICES => 0, + DISCOVERY_HOSTDEVICES_CUSTOM => 1, + DISCOVERY_CLOUD_AWS => 2, + DISCOVERY_APP_VMWARE => 3, + DISCOVERY_APP_MYSQL => 4, + DISCOVERY_APP_ORACLE => 5, + DISCOVERY_CLOUD_AWS_EC2 => 6, + DISCOVERY_CLOUD_AWS_RDS => 7, + DISCOVERY_CLOUD_AZURE_COMPUTE => 8, + DISCOVERY_DEPLOY_AGENTS => 9, + DISCOVERY_APP_SAP => 10, + DISCOVERY_SEARCH => 0, + DISCOVERY_STANDARD => 1, + DISCOVERY_RESULTS => 2, }; ################################################################################ # Discovery Server class constructor. ################################################################################ sub new ($$$$$$) { - my ($class, $config, $dbh) = @_; - - return undef unless (defined($config->{'reconserver'}) && $config->{'reconserver'} == 1) - || (defined($config->{'discoveryserver'}) && $config->{'discoveryserver'} == 1); - - if (! -e $config->{'nmap'}) { - logger ($config, ' [E] ' . $config->{'nmap'} . " needed by " . $config->{'rb_product_name'} . " Discovery Server not found.", 1); - print_message ($config, ' [E] ' . $config->{'nmap'} . " needed by " . $config->{'rb_product_name'} . " Discovery Server not found.", 1); - return undef; - } + my ($class, $config, $dbh) = @_; + + return undef unless (defined($config->{'reconserver'}) && $config->{'reconserver'} == 1) + || (defined($config->{'discoveryserver'}) && $config->{'discoveryserver'} == 1); + + if (! -e $config->{'nmap'}) { + logger ($config, ' [E] ' . $config->{'nmap'} . " needed by " . $config->{'rb_product_name'} . " Discovery Server not found.", 1); + print_message ($config, ' [E] ' . $config->{'nmap'} . " needed by " . $config->{'rb_product_name'} . " Discovery Server not found.", 1); + return undef; + } - # Initialize semaphores and queues - @TaskQueue = (); - %PendingTasks = (); - $Sem = Thread::Semaphore->new; - $TaskSem = Thread::Semaphore->new (0); - - # Restart automatic recon tasks. - db_do ($dbh, 'UPDATE trecon_task SET utimestamp = 0 WHERE id_recon_server = ? AND status <> -1 AND interval_sweep > 0', - get_server_id ($dbh, $config->{'servername'}, DISCOVERYSERVER)); + # Initialize semaphores and queues + @TaskQueue = (); + %PendingTasks = (); + $Sem = Thread::Semaphore->new; + $TaskSem = Thread::Semaphore->new (0); + + # Restart automatic recon tasks. + db_do ($dbh, 'UPDATE trecon_task SET utimestamp = 0 WHERE id_recon_server = ? AND status <> -1 AND interval_sweep > 0', + get_server_id ($dbh, $config->{'servername'}, DISCOVERYSERVER)); - # Reset (but do not restart) manual recon tasks. - db_do ($dbh, 'UPDATE trecon_task SET status = -1 WHERE id_recon_server = ? AND status <> -1 AND interval_sweep = 0', - get_server_id ($dbh, $config->{'servername'}, DISCOVERYSERVER)); + # Reset (but do not restart) manual recon tasks. + db_do ($dbh, 'UPDATE trecon_task SET status = -1 WHERE id_recon_server = ? AND status <> -1 AND interval_sweep = 0', + get_server_id ($dbh, $config->{'servername'}, DISCOVERYSERVER)); - # Call the constructor of the parent class - my $self = $class->SUPER::new($config, DISCOVERYSERVER, \&PandoraFMS::DiscoveryServer::data_producer, \&PandoraFMS::DiscoveryServer::data_consumer, $dbh); - - bless $self, $class; - return $self; + # Call the constructor of the parent class + my $self = $class->SUPER::new($config, DISCOVERYSERVER, \&PandoraFMS::DiscoveryServer::data_producer, \&PandoraFMS::DiscoveryServer::data_consumer, $dbh); + + bless $self, $class; + return $self; } ################################################################################ # Run. ################################################################################ sub run ($) { - my $self = shift; - my $pa_config = $self->getConfig (); - my $dbh = $self->getDBH(); - - print_message ($pa_config, " [*] Starting " . $pa_config->{'rb_product_name'} . " Discovery Server.", 1); - my $threads = $pa_config->{'recon_threads'}; + my $self = shift; + my $pa_config = $self->getConfig (); + my $dbh = $self->getDBH(); + + print_message ($pa_config, " [*] Starting " . $pa_config->{'rb_product_name'} . " Discovery Server.", 1); + my $threads = $pa_config->{'recon_threads'}; - # Use hightest value - if ($pa_config->{'discovery_threads'} > $pa_config->{'recon_threads'}) { - $threads = $pa_config->{'discovery_threads'}; - } - $self->setNumThreads($threads); - $self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem); + # Use hightest value + if ($pa_config->{'discovery_threads'} > $pa_config->{'recon_threads'}) { + $threads = $pa_config->{'discovery_threads'}; + } + $self->setNumThreads($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 $server_id = get_server_id ($dbh, $pa_config->{'servername'}, $self->getServerType ()); - return @tasks unless defined ($server_id); - - # Manual tasks have interval_sweep = 0 - # Manual tasks are "forced" like the other, setting the utimestamp to 1 - # By default, after create a tasks it takes the utimestamp to 0 - # Status -1 means "done". - my @rows; - if (pandora_is_master($pa_config) == 0) { - @rows = get_db_rows ($dbh, 'SELECT * FROM trecon_task - WHERE id_recon_server = ? - AND disabled = 0 - AND ((utimestamp = 0 AND interval_sweep != 0 OR status = 1) - OR (status = -1 AND interval_sweep > 0 AND (utimestamp + interval_sweep) < UNIX_TIMESTAMP()))', $server_id); - } else { - @rows = get_db_rows ($dbh, 'SELECT * FROM trecon_task - WHERE (id_recon_server = ? OR id_recon_server = ANY(SELECT id_server FROM tserver WHERE status = 0 AND server_type = ?)) - AND disabled = 0 - AND ((utimestamp = 0 AND interval_sweep != 0 OR status = 1) - OR (status = -1 AND interval_sweep > 0 AND (utimestamp + interval_sweep) < UNIX_TIMESTAMP()))', $server_id, DISCOVERYSERVER); - } + my $self = shift; + my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ()); + + my @tasks; + + my $server_id = get_server_id ($dbh, $pa_config->{'servername'}, $self->getServerType ()); + return @tasks unless defined ($server_id); + + # Manual tasks have interval_sweep = 0 + # Manual tasks are "forced" like the other, setting the utimestamp to 1 + # By default, after create a tasks it takes the utimestamp to 0 + # Status -1 means "done". + my @rows; + if (pandora_is_master($pa_config) == 0) { + @rows = get_db_rows ($dbh, 'SELECT * FROM trecon_task + WHERE id_recon_server = ? + AND disabled = 0 + AND ((utimestamp = 0 AND interval_sweep != 0 OR status = 1) + OR (status = -1 AND interval_sweep > 0 AND (utimestamp + interval_sweep) < UNIX_TIMESTAMP()))', $server_id); + } else { + @rows = get_db_rows ($dbh, 'SELECT * FROM trecon_task + WHERE (id_recon_server = ? OR id_recon_server = ANY(SELECT id_server FROM tserver WHERE status = 0 AND server_type = ?)) + AND disabled = 0 + AND ((utimestamp = 0 AND interval_sweep != 0 OR status = 1) + OR (status = -1 AND interval_sweep > 0 AND (utimestamp + interval_sweep) < UNIX_TIMESTAMP()))', $server_id, DISCOVERYSERVER); + } - foreach my $row (@rows) { - - # Update task status - update_recon_task ($dbh, $row->{'id_rt'}, 1); - - push (@tasks, $row->{'id_rt'}); - } + foreach my $row (@rows) { - return @tasks; + # Update task status + update_recon_task ($dbh, $row->{'id_rt'}, 1); + + push (@tasks, $row->{'id_rt'}); + } + + return @tasks; } ################################################################################ # Data consumer. ################################################################################ sub data_consumer ($$) { - my ($self, $task_id) = @_; - my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ()); + my ($self, $task_id) = @_; + my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ()); - # Get server id. - my $server_id = get_server_id($dbh, $pa_config->{'servername'}, $self->getServerType()); + # Get server id. + my $server_id = get_server_id($dbh, $pa_config->{'servername'}, $self->getServerType()); - # Get recon task data - my $task = get_db_single_row ($dbh, 'SELECT * FROM trecon_task WHERE id_rt = ?', $task_id); - return -1 unless defined ($task); + # Get recon task data + my $task = get_db_single_row ($dbh, 'SELECT * FROM trecon_task WHERE id_rt = ?', $task_id); + return -1 unless defined ($task); - # Is it a recon script? - if (defined ($task->{'id_recon_script'}) && ($task->{'id_recon_script'} != 0)) { - exec_recon_script ($pa_config, $dbh, $task); - return; - } else { - logger($pa_config, 'Starting recon task for net ' . $task->{'subnet'} . '.', 10); + # Is it a recon script? + if (defined ($task->{'id_recon_script'}) && ($task->{'id_recon_script'} != 0)) { + exec_recon_script ($pa_config, $dbh, $task); + return; + } else { + logger($pa_config, 'Starting recon task for net ' . $task->{'subnet'} . '.', 10); + } + + eval { + my @subnets = split(/,/, safe_output($task->{'subnet'})); + my @communities = split(/,/, safe_output($task->{'snmp_community'})); + my @auth_strings = (); + if(defined($task->{'auth_strings'})) { + @auth_strings = split(/,/, safe_output($task->{'auth_strings'})); } - eval { - my @subnets = split(/,/, safe_output($task->{'subnet'})); - my @communities = split(/,/, safe_output($task->{'snmp_community'})); - my @auth_strings = (); - if(defined($task->{'auth_strings'})) { - @auth_strings = split(/,/, safe_output($task->{'auth_strings'})); - } + my $main_event = pandora_event($pa_config, "[Discovery] Execution summary",$task->{'id_group'}, 0, 0, 0, 0, 'system', 0, $dbh); - my $main_event = pandora_event($pa_config, "[Discovery] Execution summary",$task->{'id_group'}, 0, 0, 0, 0, 'system', 0, $dbh); - - my %cnf_extra; - - my $r = enterprise_hook('discovery_generate_extra_cnf',[$pa_config, $dbh, $task, \%cnf_extra]); - if (defined($r) && $r eq 'ERR') { - # Could not generate extra cnf, skip this task. - return; - } - - - if ($task->{'type'} == DISCOVERY_APP_SAP) { - # SAP TASK, retrieve license. - $task->{'sap_license'} = pandora_get_config_value( - $dbh, - 'sap_license' - ); - - # Retrieve credentials for task (optional). - if (defined($task->{'auth_strings'}) - && $task->{'auth_strings'} ne '' - ) { - my $key = credential_store_get_key( - $pa_config, - $dbh, - $task->{'auth_strings'} - ); - - # Inside an eval, here it shouln't fail unless bad configured. - $task->{'username'} = $key->{'username'}; - $task->{'password'} = $key->{'password'}; - - } - } - - my $recon = new PandoraFMS::Recon::Base( - communities => \@communities, - dbh => $dbh, - group_id => $task->{'id_group'}, - id_os => $task->{'id_os'}, - id_network_profile => $task->{'id_network_profile'}, - os_detection => $task->{'os_detect'}, - parent_detection => $task->{'parent_detection'}, - parent_recursion => $task->{'parent_recursion'}, - pa_config => $pa_config, - recon_ports => $task->{'recon_ports'}, - resolve_names => $task->{'resolve_names'}, - snmp_auth_user => $task->{'snmp_auth_user'}, - snmp_auth_pass => $task->{'snmp_auth_pass'}, - snmp_auth_method => $task->{'snmp_auth_method'}, - snmp_checks => $task->{'snmp_checks'}, - snmp_enabled => $task->{'snmp_enabled'}, - snmp_privacy_method => $task->{'snmp_privacy_method'}, - snmp_privacy_pass => $task->{'snmp_privacy_pass'}, - snmp_security_level => $task->{'snmp_security_level'}, - snmp_timeout => $task->{'snmp_timeout'}, - snmp_version => $task->{'snmp_version'}, - subnets => \@subnets, - task_id => $task->{'id_rt'}, - vlan_cache_enabled => $task->{'vlan_enabled'}, - wmi_enabled => $task->{'wmi_enabled'}, - auth_strings_array => \@auth_strings, - autoconfiguration_enabled => $task->{'autoconfiguration_enabled'}, - main_event_id => $main_event, - server_id => $server_id, - %{$pa_config}, - task_data => $task, - public_url => PandoraFMS::Config::pandora_get_tconfig_token($dbh, 'public_url', ''), - %cnf_extra - ); - - $recon->scan(); - - # Clean tmp file. - if (defined($cnf_extra{'creds_file'}) - && -f $cnf_extra{'creds_file'}) { - unlink($cnf_extra{'creds_file'}); - } - - - # Clean one shot tasks - if ($task->{'type'} eq DISCOVERY_DEPLOY_AGENTS) { - db_delete_limit($dbh, ' trecon_task ', ' id_rt = ? ', 1, $task->{'id_rt'}); - } - }; - if ($@) { - logger( - $pa_config, - 'Cannot execute Discovery task: ' . safe_output($task->{'name'}) . $@, - 10 - ); - update_recon_task ($dbh, $task_id, -1); - return; + my %cnf_extra; + + my $r = enterprise_hook('discovery_generate_extra_cnf',[$pa_config, $dbh, $task, \%cnf_extra]); + if (defined($r) && $r eq 'ERR') { + # Could not generate extra cnf, skip this task. + return; } + + + if ($task->{'type'} == DISCOVERY_APP_SAP) { + # SAP TASK, retrieve license. + $task->{'sap_license'} = pandora_get_config_value( + $dbh, + 'sap_license' + ); + + # Retrieve credentials for task (optional). + if (defined($task->{'auth_strings'}) + && $task->{'auth_strings'} ne '' + ) { + my $key = credential_store_get_key( + $pa_config, + $dbh, + $task->{'auth_strings'} + ); + + # Inside an eval, here it shouln't fail unless bad configured. + $task->{'username'} = $key->{'username'}; + $task->{'password'} = $key->{'password'}; + + } + } + + my $recon = new PandoraFMS::Recon::Base( + communities => \@communities, + dbh => $dbh, + group_id => $task->{'id_group'}, + id_os => $task->{'id_os'}, + id_network_profile => $task->{'id_network_profile'}, + os_detection => $task->{'os_detect'}, + parent_detection => $task->{'parent_detection'}, + parent_recursion => $task->{'parent_recursion'}, + pa_config => $pa_config, + recon_ports => $task->{'recon_ports'}, + resolve_names => $task->{'resolve_names'}, + snmp_auth_user => $task->{'snmp_auth_user'}, + snmp_auth_pass => $task->{'snmp_auth_pass'}, + snmp_auth_method => $task->{'snmp_auth_method'}, + snmp_checks => $task->{'snmp_checks'}, + snmp_enabled => $task->{'snmp_enabled'}, + snmp_privacy_method => $task->{'snmp_privacy_method'}, + snmp_privacy_pass => $task->{'snmp_privacy_pass'}, + snmp_security_level => $task->{'snmp_security_level'}, + snmp_timeout => $task->{'snmp_timeout'}, + snmp_version => $task->{'snmp_version'}, + subnets => \@subnets, + task_id => $task->{'id_rt'}, + vlan_cache_enabled => $task->{'vlan_enabled'}, + wmi_enabled => $task->{'wmi_enabled'}, + auth_strings_array => \@auth_strings, + autoconfiguration_enabled => $task->{'autoconfiguration_enabled'}, + main_event_id => $main_event, + server_id => $server_id, + %{$pa_config}, + task_data => $task, + public_url => PandoraFMS::Config::pandora_get_tconfig_token($dbh, 'public_url', ''), + %cnf_extra + ); + + $recon->scan(); + + # Clean tmp file. + if (defined($cnf_extra{'creds_file'}) + && -f $cnf_extra{'creds_file'}) { + unlink($cnf_extra{'creds_file'}); + } + + + # Clean one shot tasks + if ($task->{'type'} eq DISCOVERY_DEPLOY_AGENTS) { + db_delete_limit($dbh, ' trecon_task ', ' id_rt = ? ', 1, $task->{'id_rt'}); + } + }; + if ($@) { + logger( + $pa_config, + 'Cannot execute Discovery task: ' . safe_output($task->{'name'}) . $@, + 10 + ); + update_recon_task ($dbh, $task_id, -1); + return; + } } ################################################################################ # Update recon task status. ################################################################################ sub update_recon_task ($$$) { - my ($dbh, $id_task, $status) = @_; - - db_do ($dbh, 'UPDATE trecon_task SET utimestamp = ?, status = ? WHERE id_rt = ?', time (), $status, $id_task); + my ($dbh, $id_task, $status) = @_; + + db_do ($dbh, 'UPDATE trecon_task SET utimestamp = ?, status = ? WHERE id_rt = ?', time (), $status, $id_task); } ################################################################################ # Executes recon scripts ################################################################################ sub exec_recon_script ($$$) { - my ($pa_config, $dbh, $task) = @_; - - # Get recon plugin data - my $script = get_db_single_row ($dbh, 'SELECT * FROM trecon_script WHERE id_recon_script = ?', $task->{'id_recon_script'}); - return -1 unless defined ($script); - - logger($pa_config, 'Executing recon script ' . safe_output($script->{'name'}), 10); - - my $command = safe_output($script->{'script'}); - - my $macros = safe_output($task->{'macros'}); + my ($pa_config, $dbh, $task) = @_; + + # Get recon plugin data + my $script = get_db_single_row ($dbh, 'SELECT * FROM trecon_script WHERE id_recon_script = ?', $task->{'id_recon_script'}); + return -1 unless defined ($script); + + logger($pa_config, 'Executing recon script ' . safe_output($script->{'name'}), 10); + + my $command = safe_output($script->{'script'}); + + my $macros = safe_output($task->{'macros'}); - # \r and \n should be escaped for decode_json(). - $macros =~ s/\n/\\n/g; - $macros =~ s/\r/\\r/g; - my $decoded_macros; - - if ($macros) { - eval { - $decoded_macros = decode_json(encode_utf8($macros)); - }; - } - - my $macros_parameters = ''; - - # Add module macros as parameter - if(ref($decoded_macros) eq "HASH") { - # Convert the hash to a sorted array - my @sorted_macros; - while (my ($i, $m) = each (%{$decoded_macros})) { - $sorted_macros[$i] = $m; - } - - # Remove the 0 position - shift @sorted_macros; - - foreach my $m (@sorted_macros) { - $macros_parameters = $macros_parameters . ' "' . $m->{"value"} . '"'; - } + # \r and \n should be escaped for decode_json(). + $macros =~ s/\n/\\n/g; + $macros =~ s/\r/\\r/g; + my $decoded_macros; + + if ($macros) { + eval { + $decoded_macros = decode_json(encode_utf8($macros)); + }; + } + + my $macros_parameters = ''; + + # Add module macros as parameter + if(ref($decoded_macros) eq "HASH") { + # Convert the hash to a sorted array + my @sorted_macros; + while (my ($i, $m) = each (%{$decoded_macros})) { + $sorted_macros[$i] = $m; } - my $ent_script = 0; - my $args = enterprise_hook('discovery_custom_recon_scripts',[$pa_config, $dbh, $task, $script]); - if (!$args) { - $args = "$task->{'id_rt'} $task->{'id_group'} $task->{'create_incident'} $macros_parameters"; - } else { - $ent_script = 1; - } - - if (-x $command) { - my $exec_output = `$command $args`; - logger($pa_config, "Execution output: \n". $exec_output, 10); - } else { - logger($pa_config, "Cannot execute recon task command $command.", 10); - } - - # Only update the timestamp in case something went wrong. The script should set the status. - db_do ($dbh, 'UPDATE trecon_task SET utimestamp = ? WHERE id_rt = ?', time (), $task->{'id_rt'}); + # Remove the 0 position + shift @sorted_macros; - if ($ent_script == 1) { - enterprise_hook('discovery_clean_custom_recon',[$pa_config, $dbh, $task, $script]); + foreach my $m (@sorted_macros) { + $macros_parameters = $macros_parameters . ' "' . $m->{"value"} . '"'; } - - logger($pa_config, 'Done executing recon script ' . safe_output($script->{'name'}), 10); - return 0; + } + + my $ent_script = 0; + my $args = enterprise_hook('discovery_custom_recon_scripts',[$pa_config, $dbh, $task, $script]); + if (!$args) { + $args = "$task->{'id_rt'} $task->{'id_group'} $task->{'create_incident'} $macros_parameters"; + } else { + $ent_script = 1; + } + + if (-x $command) { + my $exec_output = `$command $args`; + logger($pa_config, "Execution output: \n". $exec_output, 10); + } else { + logger($pa_config, "Cannot execute recon task command $command.", 10); + } + + # Only update the timestamp in case something went wrong. The script should set the status. + db_do ($dbh, 'UPDATE trecon_task SET utimestamp = ? WHERE id_rt = ?', time (), $task->{'id_rt'}); + + if ($ent_script == 1) { + enterprise_hook('discovery_clean_custom_recon',[$pa_config, $dbh, $task, $script]); + } + + logger($pa_config, 'Done executing recon script ' . safe_output($script->{'name'}), 10); + return 0; } ################################################################################ # Guess the OS using xprobe2 or nmap. ################################################################################ sub PandoraFMS::Recon::Base::guess_os($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - $DEVNULL = '/dev/null' if (!defined($DEVNULL)); - $DEVNULL = '/NUL' if ($^O =~ /win/i && !defined($DEVNULL)); + $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); - return OS_OTHER unless defined($device_type); - - return OS_ROUTER if ($device_type eq 'router'); - return OS_SWITCH if ($device_type eq 'switch'); - return OS_OTHER; - } - - # Use xprobe2 if available - if (-x $self->{'pa_config'}->{'xprobe2'}) { - my $return = `"$self->{pa_config}->{xprobe2}" $device 2>$DEVNULL`; - if ($? == 0) { - if($return =~ /Running OS:(.*)/) { - return pandora_get_os($self->{'dbh'}, $1); - } - } - } - - # Use nmap by default - if (-x $self->{'pa_config'}->{'nmap'}) { - my $return = `"$self->{pa_config}->{nmap}" -F -O $device 2>$DEVNULL`; - return OS_OTHER if ($? != 0); - - if ($return =~ /Aggressive OS guesses:\s*(.*)/) { - return pandora_get_os($self->{'dbh'}, $1); - } - } + # OS detection disabled. Use the device type. + if ($self->{'os_detection'} == 0) { + my $device_type = $self->get_device_type($device); + return OS_OTHER unless defined($device_type); + return OS_ROUTER if ($device_type eq 'router'); + return OS_SWITCH if ($device_type eq 'switch'); return OS_OTHER; + } + + # Use xprobe2 if available + if (-x $self->{'pa_config'}->{'xprobe2'}) { + my $return = `"$self->{pa_config}->{xprobe2}" $device 2>$DEVNULL`; + if ($? == 0) { + if($return =~ /Running OS:(.*)/) { + return pandora_get_os($self->{'dbh'}, $1); + } + } + } + + # Use nmap by default + if (-x $self->{'pa_config'}->{'nmap'}) { + my $return = `"$self->{pa_config}->{nmap}" -F -O $device 2>$DEVNULL`; + return OS_OTHER if ($? != 0); + + if ($return =~ /Aggressive OS guesses:\s*(.*)/) { + return pandora_get_os($self->{'dbh'}, $1); + } + } + + return OS_OTHER; } ################################################################################ # Returns the number of open ports from the given list. ################################################################################ sub PandoraFMS::Recon::Base::tcp_scan ($$) { - my ($self, $host) = @_; + my ($self, $host) = @_; - my $r = `"$self->{pa_config}->{nmap}" -p$self->{recon_ports} $host`; + 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; + # Same as ""| grep open | wc -l" but multi-OS; + my $open_ports = () = $r =~ /open/gm; - return $open_ports; + return $open_ports; } ################################################################################ # Create network profile modules for the given agent. ################################################################################ sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) { - my ($self, $agent_id, $device) = @_; + my ($self, $agent_id, $device) = @_; - # - # Plugin - # SNMP - # WMI - # ICMP - # + # + # Plugin + # SNMP + # WMI + # ICMP + # - return if empty($self->{'id_network_profile'}); + return if empty($self->{'id_network_profile'}); - my @templates = split /,/, $self->{'id_network_profile'}; + my @templates = split /,/, $self->{'id_network_profile'}; - # Get network components associated to the network profile. - my @np_components = get_db_rows($self->{'dbh'}, 'SELECT * FROM tnetwork_profile_component WHERE id_np = ?', $self->{'id_network_profile'}); - foreach my $np_component (@np_components) { + # Get network components associated to the network profile. + my @np_components = get_db_rows($self->{'dbh'}, 'SELECT * FROM tnetwork_profile_component WHERE id_np = ?', $self->{'id_network_profile'}); + foreach my $np_component (@np_components) { - # Get network component data - my $component = get_db_single_row($self->{'dbh'}, 'SELECT * FROM tnetwork_component WHERE id_nc = ?', $np_component->{'id_nc'}); - if (!defined ($component)) { - $self->call('message', "Network component ID " . $np_component->{'id_nc'} . " not found.", 5); - next; - } - - ## XXX Puede tener varios penes. - #next if (defined($template->{'pen'}) - # && get_enterprise_oid($device) != $template->{'pen'} ); - - # Use snmp_community from network task instead the component snmp_community - $component->{'snmp_community'} = safe_output($self->get_community($device)); - $component->{'tcp_send'} = $self->{'snmp_version'}; - $component->{'custom_string_1'} = $self->{'snmp_privacy_method'}; - $component->{'custom_string_2'} = $self->{'snmp_privacy_pass'}; - $component->{'custom_string_3'} = $self->{'snmp_security_level'}; - $component->{'plugin_parameter'} = $self->{'snmp_auth_method'}; - $component->{'plugin_user'} = $self->{'snmp_auth_user'}; - $component->{'plugin_pass'} = $self->{'snmp_auth_pass'}; - - pandora_create_module_from_network_component($self->{'pa_config'}, $component, $agent_id, $self->{'dbh'}); + # Get network component data + my $component = get_db_single_row($self->{'dbh'}, 'SELECT * FROM tnetwork_component WHERE id_nc = ?', $np_component->{'id_nc'}); + if (!defined ($component)) { + $self->call('message', "Network component ID " . $np_component->{'id_nc'} . " not found.", 5); + next; } + + ## XXX Puede tener varios penes. + #next if (defined($template->{'pen'}) + # && get_enterprise_oid($device) != $template->{'pen'} ); + + # Use snmp_community from network task instead the component snmp_community + $component->{'snmp_community'} = safe_output($self->get_community($device)); + $component->{'tcp_send'} = $self->{'snmp_version'}; + $component->{'custom_string_1'} = $self->{'snmp_privacy_method'}; + $component->{'custom_string_2'} = $self->{'snmp_privacy_pass'}; + $component->{'custom_string_3'} = $self->{'snmp_security_level'}; + $component->{'plugin_parameter'} = $self->{'snmp_auth_method'}; + $component->{'plugin_user'} = $self->{'snmp_auth_user'}; + $component->{'plugin_pass'} = $self->{'snmp_auth_pass'}; + + pandora_create_module_from_network_component($self->{'pa_config'}, $component, $agent_id, $self->{'dbh'}); + } } ################################################################################ # Create agents and modules reported by Recon::Base. ################################################################################ sub PandoraFMS::Recon::Base::report_scanned_agents($) { - my ($self) = @_; + my ($self) = @_; - if(defined($self->{'task_data'}{'direct_report'}) - && $self->{'task_data'}{'direct_report'} eq "2" - ) { - # Load cache. - my @rows = get_db_rows( - $self->{'dbh'}, - 'SELECT * FROM tdiscovery_tmp_agents WHERE `id_rt`=?', - $self->{'task_data'}{'id_rt'} + if(defined($self->{'task_data'}{'direct_report'}) + && $self->{'task_data'}{'direct_report'} == DISCOVERY_RESULTS + ) { + # Load cache. + my @rows = get_db_rows( + $self->{'dbh'}, + 'SELECT * FROM tdiscovery_tmp_agents WHERE `id_rt`=?', + $self->{'task_data'}{'id_rt'} + ); + + foreach my $row (@rows) { + my $name = safe_output($row->{'label'}); + my $data; + eval { + $data = decode_json(decode_base64($row->{'data'})); + }; + + # Store. + $self->{'agents_found'}{$name} = $data; + } + } + + foreach my $label (keys %{$self->{'agents_found'}}) { + if (!is_enabled($self->{'direct_report'})) { + # Store temporally. Wait user approval. + my $encoded; + eval { + local $SIG{__DIE__}; + $encoded = encode_base64(encode_json($self->{'agents_found'})); + }; + + my $id = get_db_value( + $self->{'dbh'}, + 'SELECT id FROM tdiscovery_tmp_agents WHERE id_rt = ? AND label = ?', + $self->{'task_data'}{'id_rt'}, + safe_input($label) + ); + + if (defined($id)) { + # Already defined. + $self->{'agents_found'}{$label}{'id'} = $id; + + db_do( + $self->{'dbh'}, + 'UPDATE tdiscovery_tmp_agents SET `data` = ? ' + .'WHERE `id_rt` = ? AND `label` = ?', + $encoded, + $self->{'task_data'}{'id_rt'}, + safe_input($label) ); + next; + } - foreach my $row (@rows) { - my $name = safe_output($row->{'label'}); - my $data; - eval { - $data = decode_json(decode_base64($row->{'data'})); - }; - - # Store. - $self->{'agents_found'}{$name} = $data; - } - } - - foreach my $label (keys %{$self->{'agents_found'}}) { - if (!is_enabled($self->{'direct_report'})) { - # Store temporally. Wait user approval. - my $encoded; - eval { - local $SIG{__DIE__}; - $encoded = encode_base64(encode_json($self->{'agents_found'})); - }; - - my $id = get_db_value( - $self->{'dbh'}, - 'SELECT id FROM tdiscovery_tmp_agents WHERE id_rt = ? AND label = ?', - $self->{'task_data'}{'id_rt'}, - safe_input($label) - ); - - if (defined($id)) { - # Already defined. - $self->{'agents_found'}{$label}{'id'} = $id; - - db_do( - $self->{'dbh'}, - 'UPDATE tdiscovery_tmp_agents SET `data` = ? ' - .'WHERE `id_rt` = ? AND `label` = ?', - $encoded, - $self->{'task_data'}{'id_rt'}, - safe_input($label) - ); - next; - } - - # Insert. - $self->{'agents_found'}{$label}{'id'} = db_insert( - $self->{'dbh'}, - 'id', - 'INSERT INTO tdiscovery_tmp_agents (`id_rt`,`label`,`data`,`created`) ' - .'VALUES (?, ?, ?, now())', - $self->{'task_data'}{'id_rt'}, - safe_input($label), - $encoded - ); - } else { - # Create agents. - } + # Insert. + $self->{'agents_found'}{$label}{'id'} = db_insert( + $self->{'dbh'}, + 'id', + 'INSERT INTO tdiscovery_tmp_agents (`id_rt`,`label`,`data`,`created`) ' + .'VALUES (?, ?, ?, now())', + $self->{'task_data'}{'id_rt'}, + safe_input($label), + $encoded + ); + } else { + # Create agents. } + } } ################################################################################ # Connect the given devices in the Pandora FMS database. ################################################################################ sub PandoraFMS::Recon::Base::connect_agents($$$$$) { - my ($self, $dev_1, $if_1, $dev_2, $if_2) = @_; + my ($self, $dev_1, $if_1, $dev_2, $if_2) = @_; - # Get the agent for the first device. - my $agent_1 = get_agent_from_addr($self->{'dbh'}, $dev_1); - if (!defined($agent_1)) { - $agent_1 = get_agent_from_name($self->{'dbh'}, $dev_1); - } - return unless defined($agent_1); + # Get the agent for the first device. + my $agent_1 = get_agent_from_addr($self->{'dbh'}, $dev_1); + if (!defined($agent_1)) { + $agent_1 = get_agent_from_name($self->{'dbh'}, $dev_1); + } + return unless defined($agent_1); - # Get the agent for the second device. - my $agent_2 = get_agent_from_addr($self->{'dbh'}, $dev_2); - if (!defined($agent_2)) { - $agent_2 = get_agent_from_name($self->{'dbh'}, $dev_2); - } - return unless defined($agent_2); + # Get the agent for the second device. + my $agent_2 = get_agent_from_addr($self->{'dbh'}, $dev_2); + if (!defined($agent_2)) { + $agent_2 = get_agent_from_name($self->{'dbh'}, $dev_2); + } + return unless defined($agent_2); - # Use ping modules by default. - $if_1 = 'Host Alive' if ($if_1 eq ''); - $if_2 = 'Host Alive' if ($if_2 eq ''); + # Use ping modules by default. + $if_1 = 'Host Alive' if ($if_1 eq ''); + $if_2 = 'Host Alive' if ($if_2 eq ''); - # Check whether the modules exists. - my $module_name_1 = $if_1 eq 'Host Alive' ? 'Host Alive' : "${if_1}_ifOperStatus"; - my $module_name_2 = $if_2 eq 'Host Alive' ? 'Host Alive' : "${if_2}_ifOperStatus"; - my $module_id_1 = get_agent_module_id($self->{'dbh'}, $module_name_1, $agent_1->{'id_agente'}); - if ($module_id_1 <= 0) { - $self->call('message', "ERROR: Module " . safe_output($module_name_1) . " does not exist for agent $dev_1.", 5); - return; - } - my $module_id_2 = get_agent_module_id($self->{'dbh'}, $module_name_2, $agent_2->{'id_agente'}); - if ($module_id_2 <= 0) { - $self->call('message', "ERROR: Module " . safe_output($module_name_2) . " does not exist for agent $dev_2.", 5); - return; - } + # Check whether the modules exists. + my $module_name_1 = $if_1 eq 'Host Alive' ? 'Host Alive' : "${if_1}_ifOperStatus"; + my $module_name_2 = $if_2 eq 'Host Alive' ? 'Host Alive' : "${if_2}_ifOperStatus"; + my $module_id_1 = get_agent_module_id($self->{'dbh'}, $module_name_1, $agent_1->{'id_agente'}); + if ($module_id_1 <= 0) { + $self->call('message', "ERROR: Module " . safe_output($module_name_1) . " does not exist for agent $dev_1.", 5); + return; + } + my $module_id_2 = get_agent_module_id($self->{'dbh'}, $module_name_2, $agent_2->{'id_agente'}); + if ($module_id_2 <= 0) { + $self->call('message', "ERROR: Module " . safe_output($module_name_2) . " does not exist for agent $dev_2.", 5); + return; + } - # Connect the modules if they are not already connected. - my $connection_id = get_db_value($self->{'dbh'}, 'SELECT id FROM tmodule_relationship WHERE (module_a = ? AND module_b = ? AND `type` = "direct") OR (module_b = ? AND module_a = ? AND `type` = "direct")', $module_id_1, $module_id_2, $module_id_1, $module_id_2); - if (! defined($connection_id)) { - db_do($self->{'dbh'}, 'INSERT INTO tmodule_relationship (`module_a`, `module_b`, `id_rt`) VALUES(?, ?, ?)', $module_id_1, $module_id_2, $self->{'task_id'}); - } + # Connect the modules if they are not already connected. + my $connection_id = get_db_value($self->{'dbh'}, 'SELECT id FROM tmodule_relationship WHERE (module_a = ? AND module_b = ? AND `type` = "direct") OR (module_b = ? AND module_a = ? AND `type` = "direct")', $module_id_1, $module_id_2, $module_id_1, $module_id_2); + if (! defined($connection_id)) { + db_do($self->{'dbh'}, 'INSERT INTO tmodule_relationship (`module_a`, `module_b`, `id_rt`) VALUES(?, ?, ?)', $module_id_1, $module_id_2, $self->{'task_id'}); + } } @@ -611,98 +614,98 @@ sub PandoraFMS::Recon::Base::connect_agents($$$$$) { # ] ################################################################################ sub PandoraFMS::Recon::Base::create_agents($$) { - my ($self, $data) = @_; + my ($self, $data) = @_; - my $pa_config = $self->{'pa_config'}; - my $dbh = $self->{'dbh'}; - my $server_id = $self->{'server_id'}; + my $pa_config = $self->{'pa_config'}; + my $dbh = $self->{'dbh'}; + my $server_id = $self->{'server_id'}; - return undef if (ref($data) ne "ARRAY"); + return undef if (ref($data) ne "ARRAY"); - foreach my $information (@{$data}) { - my $agent = $information->{'agent_data'}; - my $modules = $information->{'module_data'}; - my $force_processing = 0; + foreach my $information (@{$data}) { + my $agent = $information->{'agent_data'}; + my $modules = $information->{'module_data'}; + my $force_processing = 0; - # Search agent - my $current_agent = PandoraFMS::Core::locate_agent( - $pa_config, $dbh, $agent->{'agent_name'} - ); + # Search agent + my $current_agent = PandoraFMS::Core::locate_agent( + $pa_config, $dbh, $agent->{'agent_name'} + ); - my $parent_id; - if (defined($agent->{'parent_agent_name'})) { - $parent_id = PandoraFMS::Core::locate_agent( - $pa_config, $dbh, $agent->{'parent_agent_name'} - ); - if ($parent_id) { - $parent_id = $parent_id->{'id_agente'}; - } - } - - my $agent_id; - my $os_id = get_os_id($dbh, $agent->{'os'}); - - if ($os_id < 0) { - $os_id = get_os_id($dbh, 'Other'); - } - - if (!$current_agent) { - # Create agent. - $agent_id = pandora_create_agent( - $pa_config, $pa_config->{'servername'}, $agent->{'agent_name'}, - $agent->{'address'}, $agent->{'id_group'}, $parent_id, - $os_id, $agent->{'description'}, - $agent->{'interval'}, $dbh, $agent->{'timezone_offset'} - ); - - $current_agent = $parent_id = PandoraFMS::Core::locate_agent( - $pa_config, $dbh, $agent->{'agent_name'} - ); - - $force_processing = 1; - - } else { - $agent_id = $current_agent->{'id_agente'}; - } - - if (!defined($agent_id)) { - return undef; - } - - if (defined($agent->{'address'}) && $agent->{'address'} ne '') { - pandora_add_agent_address( - $pa_config, $agent_id, $agent->{'agent_name'}, - $agent->{'address'}, $dbh - ); - } - - # Update agent information - pandora_update_agent( - $pa_config, strftime("%Y-%m-%d %H:%M:%S", localtime()), $agent_id, - $agent->{'os_version'}, $agent->{'agent_version'}, - $agent->{'interval'}, $dbh, undef, $parent_id - ); - - # Add modules. - if (ref($modules) eq "ARRAY") { - foreach my $module (@{$modules}) { - next unless ref($module) eq 'HASH'; - # Translate data structure to simulate XML parser return. - my %data_translated = map { $_ => [ $module->{$_} ] } keys %{$module}; - - # Process modules. - PandoraFMS::DataServer::process_module_data ( - $pa_config, \%data_translated, - $server_id, $current_agent, - $module->{'name'}, $module->{'type'}, - $agent->{'interval'}, - strftime ("%Y/%m/%d %H:%M:%S", localtime()), - $dbh, $force_processing - ); - } - } + my $parent_id; + if (defined($agent->{'parent_agent_name'})) { + $parent_id = PandoraFMS::Core::locate_agent( + $pa_config, $dbh, $agent->{'parent_agent_name'} + ); + if ($parent_id) { + $parent_id = $parent_id->{'id_agente'}; + } } + my $agent_id; + my $os_id = get_os_id($dbh, $agent->{'os'}); + + if ($os_id < 0) { + $os_id = get_os_id($dbh, 'Other'); + } + + if (!$current_agent) { + # Create agent. + $agent_id = pandora_create_agent( + $pa_config, $pa_config->{'servername'}, $agent->{'agent_name'}, + $agent->{'address'}, $agent->{'id_group'}, $parent_id, + $os_id, $agent->{'description'}, + $agent->{'interval'}, $dbh, $agent->{'timezone_offset'} + ); + + $current_agent = $parent_id = PandoraFMS::Core::locate_agent( + $pa_config, $dbh, $agent->{'agent_name'} + ); + + $force_processing = 1; + + } else { + $agent_id = $current_agent->{'id_agente'}; + } + + if (!defined($agent_id)) { + return undef; + } + + if (defined($agent->{'address'}) && $agent->{'address'} ne '') { + pandora_add_agent_address( + $pa_config, $agent_id, $agent->{'agent_name'}, + $agent->{'address'}, $dbh + ); + } + + # Update agent information + pandora_update_agent( + $pa_config, strftime("%Y-%m-%d %H:%M:%S", localtime()), $agent_id, + $agent->{'os_version'}, $agent->{'agent_version'}, + $agent->{'interval'}, $dbh, undef, $parent_id + ); + + # Add modules. + if (ref($modules) eq "ARRAY") { + foreach my $module (@{$modules}) { + next unless ref($module) eq 'HASH'; + # Translate data structure to simulate XML parser return. + my %data_translated = map { $_ => [ $module->{$_} ] } keys %{$module}; + + # Process modules. + PandoraFMS::DataServer::process_module_data ( + $pa_config, \%data_translated, + $server_id, $current_agent, + $module->{'name'}, $module->{'type'}, + $agent->{'interval'}, + strftime ("%Y/%m/%d %H:%M:%S", localtime()), + $dbh, $force_processing + ); + } + } + } + } @@ -711,407 +714,407 @@ sub PandoraFMS::Recon::Base::create_agents($$) { # existing) agent, undef on error. ################################################################################ sub PandoraFMS::Recon::Base::create_agent($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - # Clean name. - $device = clean_blank($device); + # Clean name. + $device = clean_blank($device); - # Resolve hostnames. - my $host_name = (($self->{'resolve_names'} == 1) ? gethostbyaddr(inet_aton($device), AF_INET) : $device); - # Fallback to device IP if host name could not be resolved. - $host_name = $device if (!defined($host_name) || $host_name eq ''); - my $agent = locate_agent($self->{'pa_config'}, $self->{'dbh'}, $host_name); + # Resolve hostnames. + my $host_name = (($self->{'resolve_names'} == 1) ? gethostbyaddr(inet_aton($device), AF_INET) : $device); + # Fallback to device IP if host name could not be resolved. + $host_name = $device if (!defined($host_name) || $host_name eq ''); + my $agent = locate_agent($self->{'pa_config'}, $self->{'dbh'}, $host_name); - my ($agent_id, $agent_learning); - if (!defined($agent)) { - $host_name = $device unless defined ($host_name); + my ($agent_id, $agent_learning); + if (!defined($agent)) { + $host_name = $device unless defined ($host_name); - # Guess the OS. - my $id_os = $self->guess_os($device); + # Guess the OS. + my $id_os = $self->guess_os($device); - # Are we filtering hosts by OS? - return if ($self->{'id_os'} > 0 && $id_os != $self->{'id_os'}); + # Are we filtering hosts by OS? + return if ($self->{'id_os'} > 0 && $id_os != $self->{'id_os'}); - # Are we filtering hosts by TCP port? - return if ($self->{'recon_ports'} ne '' && $self->tcp_scan($device) == 0); - my $location = get_geoip_info($self->{'pa_config'}, $device); - $agent_id = pandora_create_agent( - $self->{'pa_config'}, $self->{'pa_config'}->{'servername'}, - $host_name, $device, $self->{'group_id'}, 0, $id_os, - '', 300, $self->{'dbh'}, undef, $location->{'longitude'}, - $location->{'latitude'} - ); - return undef unless defined ($agent_id) and ($agent_id > 0); + # Are we filtering hosts by TCP port? + return if ($self->{'recon_ports'} ne '' && $self->tcp_scan($device) == 0); + my $location = get_geoip_info($self->{'pa_config'}, $device); + $agent_id = pandora_create_agent( + $self->{'pa_config'}, $self->{'pa_config'}->{'servername'}, + $host_name, $device, $self->{'group_id'}, 0, $id_os, + '', 300, $self->{'dbh'}, undef, $location->{'longitude'}, + $location->{'latitude'} + ); + return undef unless defined ($agent_id) and ($agent_id > 0); - # Autoconfigure agent - if (defined($self->{'autoconfiguration_enabled'}) && $self->{'autoconfiguration_enabled'} == 1) { - my $agent_data = PandoraFMS::DB::get_db_single_row($self->{'dbh'}, 'SELECT * FROM tagente WHERE id_agente = ?', $agent_id); - # Update agent configuration once, after create agent. - enterprise_hook('autoconfigure_agent', [$self->{'pa_config'}, $host_name, $agent_id, $agent_data, $self->{'dbh'}, 1]); - } - - if (defined($self->{'main_event_id'})) { - my $addresses_str = join(',', safe_output($self->get_addresses($device))); - pandora_extended_event( - $self->{'pa_config'}, $self->{'dbh'}, $self->{'main_event_id'}, - "[Discovery] New " . safe_output($self->get_device_type($device)) . " found " . $host_name . " (" . $addresses_str . ") Agent $agent_id." - ); - - } - - $agent_learning = 1; - - # Create network profile modules for the agent - $self->create_network_profile_modules($agent_id, $device); + # Autoconfigure agent + if (defined($self->{'autoconfiguration_enabled'}) && $self->{'autoconfiguration_enabled'} == 1) { + my $agent_data = PandoraFMS::DB::get_db_single_row($self->{'dbh'}, 'SELECT * FROM tagente WHERE id_agente = ?', $agent_id); + # Update agent configuration once, after create agent. + enterprise_hook('autoconfigure_agent', [$self->{'pa_config'}, $host_name, $agent_id, $agent_data, $self->{'dbh'}, 1]); } - else { - $agent_id = $agent->{'id_agente'}; - $agent_learning = $agent->{'modo'}; - } - - # Do not create any modules if the agent is not in learning mode. - return unless ($agent_learning == 1); - - # Add found IP addresses to the agent. - foreach my $ip_addr ($self->get_addresses($device)) { - my $addr_id = get_addr_id($self->{'dbh'}, $ip_addr); - $addr_id = add_address($self->{'dbh'}, $ip_addr) unless ($addr_id > 0); - next unless ($addr_id > 0); - - # Assign the new address to the agent - my $agent_addr_id = get_agent_addr_id($self->{'dbh'}, $addr_id, $agent_id); - if ($agent_addr_id <= 0) { - db_do($self->{'dbh'}, 'INSERT INTO taddress_agent (`id_a`, `id_agent`) - VALUES (?, ?)', $addr_id, $agent_id); - } - } - - # Create a ping module. - my $module_id = get_agent_module_id($self->{'dbh'}, "ping", $agent_id); - if ($module_id <= 0) { - my %module = ('id_tipo_modulo' => 6, - 'id_modulo' => 2, - 'nombre' => "ping", - 'descripcion' => '', - 'id_agente' => $agent_id, - 'ip_target' => $device); - pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); - } - - # Add interfaces to the agent if it responds to SNMP. - return $agent_id unless ($self->is_snmp_discovered($device)); - my $community = $self->get_community($device); - - my @output = $self->snmp_get_value_array($device, $PandoraFMS::Recon::Base::IFINDEX); - foreach my $if_index (@output) { - next unless ($if_index =~ /^[0-9]+$/); - - # Check the status of the interface. - if ($self->{'all_ifaces'} == 0) { - my $if_status = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index"); - next unless $if_status == 1; - } - - # Fill the module description with the IP and MAC addresses. - my $mac = $self->get_if_mac($device, $if_index); - my $ip = $self->get_if_ip($device, $if_index); - my $if_desc = ($mac ne '' ? "MAC $mac " : '') . ($ip ne '' ? "IP $ip" : ''); - - # Get the name of the network interface. - my $if_name = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFNAME.$if_index"); - $if_name = "if$if_index" unless defined ($if_name); - $if_name =~ s/"//g; - $if_name = clean_blank($if_name); - - # Check whether the module already exists. - my $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifOperStatus', $agent_id); - - next if ($module_id > 0 && !$agent_learning); - # Encode problematic characters. - $if_desc = safe_input($if_desc); + if (defined($self->{'main_event_id'})) { + my $addresses_str = join(',', safe_output($self->get_addresses($device))); + pandora_extended_event( + $self->{'pa_config'}, $self->{'dbh'}, $self->{'main_event_id'}, + "[Discovery] New " . safe_output($self->get_device_type($device)) . " found " . $host_name . " (" . $addresses_str . ") Agent $agent_id." + ); - # Interface status module. - $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifOperStatus', $agent_id); - if ($module_id <= 0) { - my %module = ('id_tipo_modulo' => 18, - 'id_modulo' => 2, - 'nombre' => safe_input($if_name)."_ifOperStatus", - 'descripcion' => $if_desc, - 'id_agente' => $agent_id, - 'ip_target' => $device, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - 'snmp_community' => $community, - 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index" - ); - pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); - } else { - my %module = ( - 'descripcion' => $if_desc, - 'ip_target' => $device, - 'snmp_community' => $community, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - 'tcp_send' => $self->{'snmp_version'}, - ); - pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); - } + } + + $agent_learning = 1; - # Incoming traffic module. - my $if_hc_in_octets = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFHCINOCTECTS.$if_index"); - if (defined($if_hc_in_octets)) { - $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifHCInOctets', $agent_id); - if ($module_id <= 0) { - my %module = ('id_tipo_modulo' => 16, - 'id_modulo' => 2, - 'nombre' => safe_input($if_name)."_ifHCInOctets", - 'descripcion' => 'The total number of octets received on the interface, including framing characters. This object is a 64-bit version of ifInOctets.', - 'id_agente' => $agent_id, - 'ip_target' => $device, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - 'snmp_community' => $community, - 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCINOCTECTS.$if_index"); - pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); - } else { - my %module = ( - 'ip_target' => $device, - 'snmp_community' => $community, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - ); - pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); - } - } - # ifInOctets - elsif (defined($self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFINOCTECTS.$if_index"))) { - $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifInOctets', $agent_id); - if ($module_id <= 0) { - my %module = ('id_tipo_modulo' => 16, - 'id_modulo' => 2, - 'nombre' => safe_input($if_name)."_ifInOctets", - 'descripcion' => 'The total number of octets received on the interface, including framing characters.', - 'id_agente' => $agent_id, - 'ip_target' => $device, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - 'snmp_community' => $community, - 'snmp_oid' => "$PandoraFMS::Recon::Base::IFINOCTECTS.$if_index"); - pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); - } else { - my %module = ( - 'ip_target' => $device, - 'snmp_community' => $community, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - ); - pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); - } - } + # Create network profile modules for the agent + $self->create_network_profile_modules($agent_id, $device); + } + else { + $agent_id = $agent->{'id_agente'}; + $agent_learning = $agent->{'modo'}; + } - # Outgoing traffic module. - my $if_hc_out_octets = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFHCOUTOCTECTS.$if_index"); - if (defined($if_hc_out_octets)) { - $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifHCOutOctets', $agent_id); - if ($module_id <= 0) { - my %module = ('id_tipo_modulo' => 16, - 'id_modulo' => 2, - 'nombre' => safe_input($if_name)."_ifHCOutOctets", - 'descripcion' => 'The total number of octets received on the interface, including framing characters. This object is a 64-bit version of ifOutOctets.', - 'id_agente' => $agent_id, - 'ip_target' => $device, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - 'snmp_community' => $community, - 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCOUTOCTECTS.$if_index"); - pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); - } else { - my %module = ( - 'ip_target' => $device, - 'snmp_community' => $community, - 'tcp_send' => $self->{'snmp_version'}, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - ); - pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); - } - } - # ifOutOctets - elsif (defined($self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFOUTOCTECTS.$if_index"))) { - $module_id = get_agent_module_id($self->{'dbh'}, "${if_name}_ifOutOctets", $agent_id); - if ($module_id <= 0) { - my %module = ('id_tipo_modulo' => 16, - 'id_modulo' => 2, - 'nombre' => safe_input($if_name)."_ifOutOctets", - 'descripcion' => 'The total number of octets received on the interface, including framing characters.', - 'id_agente' => $agent_id, - 'ip_target' => $device, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - 'snmp_community' => $community, - 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOUTOCTECTS.$if_index"); - pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); - } else { - my %module = ( - 'ip_target' => $device, - 'snmp_community' => $community, - 'tcp_send' => $self->{'snmp_version'}, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - ); - pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); - } - } + # Do not create any modules if the agent is not in learning mode. + return unless ($agent_learning == 1); + + # Add found IP addresses to the agent. + foreach my $ip_addr ($self->get_addresses($device)) { + my $addr_id = get_addr_id($self->{'dbh'}, $ip_addr); + $addr_id = add_address($self->{'dbh'}, $ip_addr) unless ($addr_id > 0); + next unless ($addr_id > 0); + + # Assign the new address to the agent + my $agent_addr_id = get_agent_addr_id($self->{'dbh'}, $addr_id, $agent_id); + if ($agent_addr_id <= 0) { + db_do($self->{'dbh'}, 'INSERT INTO taddress_agent (`id_a`, `id_agent`) + VALUES (?, ?)', $addr_id, $agent_id); + } + } + + # Create a ping module. + my $module_id = get_agent_module_id($self->{'dbh'}, "ping", $agent_id); + if ($module_id <= 0) { + my %module = ('id_tipo_modulo' => 6, + 'id_modulo' => 2, + 'nombre' => "ping", + 'descripcion' => '', + 'id_agente' => $agent_id, + 'ip_target' => $device); + pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); + } + + # Add interfaces to the agent if it responds to SNMP. + return $agent_id unless ($self->is_snmp_discovered($device)); + my $community = $self->get_community($device); + + my @output = $self->snmp_get_value_array($device, $PandoraFMS::Recon::Base::IFINDEX); + foreach my $if_index (@output) { + next unless ($if_index =~ /^[0-9]+$/); + + # Check the status of the interface. + if ($self->{'all_ifaces'} == 0) { + my $if_status = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index"); + next unless $if_status == 1; } - return $agent_id; + # Fill the module description with the IP and MAC addresses. + my $mac = $self->get_if_mac($device, $if_index); + my $ip = $self->get_if_ip($device, $if_index); + my $if_desc = ($mac ne '' ? "MAC $mac " : '') . ($ip ne '' ? "IP $ip" : ''); + + # Get the name of the network interface. + my $if_name = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFNAME.$if_index"); + $if_name = "if$if_index" unless defined ($if_name); + $if_name =~ s/"//g; + $if_name = clean_blank($if_name); + + # Check whether the module already exists. + my $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifOperStatus', $agent_id); + + next if ($module_id > 0 && !$agent_learning); + + # Encode problematic characters. + $if_desc = safe_input($if_desc); + + # Interface status module. + $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifOperStatus', $agent_id); + if ($module_id <= 0) { + my %module = ('id_tipo_modulo' => 18, + 'id_modulo' => 2, + 'nombre' => safe_input($if_name)."_ifOperStatus", + 'descripcion' => $if_desc, + 'id_agente' => $agent_id, + 'ip_target' => $device, + 'tcp_send' => $self->{'snmp_version'}, + 'custom_string_1' => $self->{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'snmp_security_level'}, + 'plugin_parameter' => $self->{'snmp_auth_method'}, + 'plugin_user' => $self->{'snmp_auth_user'}, + 'plugin_pass' => $self->{'snmp_auth_pass'}, + 'snmp_community' => $community, + 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index" + ); + pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); + } else { + my %module = ( + 'descripcion' => $if_desc, + 'ip_target' => $device, + 'snmp_community' => $community, + 'tcp_send' => $self->{'snmp_version'}, + 'custom_string_1' => $self->{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'snmp_security_level'}, + 'plugin_parameter' => $self->{'snmp_auth_method'}, + 'plugin_user' => $self->{'snmp_auth_user'}, + 'plugin_pass' => $self->{'snmp_auth_pass'}, + 'tcp_send' => $self->{'snmp_version'}, + ); + pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); + } + + # Incoming traffic module. + my $if_hc_in_octets = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFHCINOCTECTS.$if_index"); + if (defined($if_hc_in_octets)) { + $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifHCInOctets', $agent_id); + if ($module_id <= 0) { + my %module = ('id_tipo_modulo' => 16, + 'id_modulo' => 2, + 'nombre' => safe_input($if_name)."_ifHCInOctets", + 'descripcion' => 'The total number of octets received on the interface, including framing characters. This object is a 64-bit version of ifInOctets.', + 'id_agente' => $agent_id, + 'ip_target' => $device, + 'tcp_send' => $self->{'snmp_version'}, + 'custom_string_1' => $self->{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'snmp_security_level'}, + 'plugin_parameter' => $self->{'snmp_auth_method'}, + 'plugin_user' => $self->{'snmp_auth_user'}, + 'plugin_pass' => $self->{'snmp_auth_pass'}, + 'snmp_community' => $community, + 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCINOCTECTS.$if_index"); + pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); + } else { + my %module = ( + 'ip_target' => $device, + 'snmp_community' => $community, + 'tcp_send' => $self->{'snmp_version'}, + 'custom_string_1' => $self->{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'snmp_security_level'}, + 'plugin_parameter' => $self->{'snmp_auth_method'}, + 'plugin_user' => $self->{'snmp_auth_user'}, + 'plugin_pass' => $self->{'snmp_auth_pass'}, + ); + pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); + } + } + # ifInOctets + elsif (defined($self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFINOCTECTS.$if_index"))) { + $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifInOctets', $agent_id); + if ($module_id <= 0) { + my %module = ('id_tipo_modulo' => 16, + 'id_modulo' => 2, + 'nombre' => safe_input($if_name)."_ifInOctets", + 'descripcion' => 'The total number of octets received on the interface, including framing characters.', + 'id_agente' => $agent_id, + 'ip_target' => $device, + 'tcp_send' => $self->{'snmp_version'}, + 'custom_string_1' => $self->{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'snmp_security_level'}, + 'plugin_parameter' => $self->{'snmp_auth_method'}, + 'plugin_user' => $self->{'snmp_auth_user'}, + 'plugin_pass' => $self->{'snmp_auth_pass'}, + 'snmp_community' => $community, + 'snmp_oid' => "$PandoraFMS::Recon::Base::IFINOCTECTS.$if_index"); + pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); + } else { + my %module = ( + 'ip_target' => $device, + 'snmp_community' => $community, + 'tcp_send' => $self->{'snmp_version'}, + 'custom_string_1' => $self->{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'snmp_security_level'}, + 'plugin_parameter' => $self->{'snmp_auth_method'}, + 'plugin_user' => $self->{'snmp_auth_user'}, + 'plugin_pass' => $self->{'snmp_auth_pass'}, + ); + pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); + } + } + + # Outgoing traffic module. + my $if_hc_out_octets = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFHCOUTOCTECTS.$if_index"); + if (defined($if_hc_out_octets)) { + $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifHCOutOctets', $agent_id); + if ($module_id <= 0) { + my %module = ('id_tipo_modulo' => 16, + 'id_modulo' => 2, + 'nombre' => safe_input($if_name)."_ifHCOutOctets", + 'descripcion' => 'The total number of octets received on the interface, including framing characters. This object is a 64-bit version of ifOutOctets.', + 'id_agente' => $agent_id, + 'ip_target' => $device, + 'tcp_send' => $self->{'snmp_version'}, + 'custom_string_1' => $self->{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'snmp_security_level'}, + 'plugin_parameter' => $self->{'snmp_auth_method'}, + 'plugin_user' => $self->{'snmp_auth_user'}, + 'plugin_pass' => $self->{'snmp_auth_pass'}, + 'snmp_community' => $community, + 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCOUTOCTECTS.$if_index"); + pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); + } else { + my %module = ( + 'ip_target' => $device, + 'snmp_community' => $community, + 'tcp_send' => $self->{'snmp_version'}, + 'tcp_send' => $self->{'snmp_version'}, + 'custom_string_1' => $self->{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'snmp_security_level'}, + 'plugin_parameter' => $self->{'snmp_auth_method'}, + 'plugin_user' => $self->{'snmp_auth_user'}, + 'plugin_pass' => $self->{'snmp_auth_pass'}, + ); + pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); + } + } + # ifOutOctets + elsif (defined($self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFOUTOCTECTS.$if_index"))) { + $module_id = get_agent_module_id($self->{'dbh'}, "${if_name}_ifOutOctets", $agent_id); + if ($module_id <= 0) { + my %module = ('id_tipo_modulo' => 16, + 'id_modulo' => 2, + 'nombre' => safe_input($if_name)."_ifOutOctets", + 'descripcion' => 'The total number of octets received on the interface, including framing characters.', + 'id_agente' => $agent_id, + 'ip_target' => $device, + 'tcp_send' => $self->{'snmp_version'}, + 'custom_string_1' => $self->{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'snmp_security_level'}, + 'plugin_parameter' => $self->{'snmp_auth_method'}, + 'plugin_user' => $self->{'snmp_auth_user'}, + 'plugin_pass' => $self->{'snmp_auth_pass'}, + 'snmp_community' => $community, + 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOUTOCTECTS.$if_index"); + pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); + } else { + my %module = ( + 'ip_target' => $device, + 'snmp_community' => $community, + 'tcp_send' => $self->{'snmp_version'}, + 'tcp_send' => $self->{'snmp_version'}, + 'custom_string_1' => $self->{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'snmp_security_level'}, + 'plugin_parameter' => $self->{'snmp_auth_method'}, + 'plugin_user' => $self->{'snmp_auth_user'}, + 'plugin_pass' => $self->{'snmp_auth_pass'}, + ); + pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); + } + } + } + + return $agent_id; } ################################################################################ # Delete already existing connections. ################################################################################ sub PandoraFMS::Recon::Base::delete_connections($) { - my ($self) = @_; + my ($self) = @_; - $self->call('message', "Deleting connections...", 10); - db_do($self->{'dbh'}, 'DELETE FROM tmodule_relationship WHERE id_rt=?', $self->{'task_id'}); + $self->call('message', "Deleting connections...", 10); + db_do($self->{'dbh'}, 'DELETE FROM tmodule_relationship WHERE id_rt=?', $self->{'task_id'}); } ################################################################################ # Print log messages. ################################################################################ sub PandoraFMS::Recon::Base::message($$$) { - my ($self, $message, $verbosity) = @_; + my ($self, $message, $verbosity) = @_; - logger($self->{'pa_config'}, "[Recon task " . $self->{'task_id'} . "] $message", $verbosity); + logger($self->{'pa_config'}, "[Recon task " . $self->{'task_id'} . "] $message", $verbosity); } ################################################################################ # Connect the given hosts to its parent. ################################################################################ sub PandoraFMS::Recon::Base::set_parent($$$) { - my ($self, $host, $parent) = @_; + my ($self, $host, $parent) = @_; - return unless ($self->{'parent_detection'} == 1); + return unless ($self->{'parent_detection'} == 1); - # Get the agent for the host. - my $agent = get_agent_from_addr($self->{'dbh'}, $host); - if (!defined($agent)) { - $agent = get_agent_from_name($self->{'dbh'}, $host); - } - return unless defined($agent); + # Get the agent for the host. + my $agent = get_agent_from_addr($self->{'dbh'}, $host); + if (!defined($agent)) { + $agent = get_agent_from_name($self->{'dbh'}, $host); + } + return unless defined($agent); - # Check if the parent agent exists. - my $agent_parent = get_agent_from_addr($self->{'dbh'}, $parent); - if (!defined($agent_parent)) { - $agent_parent = get_agent_from_name($self->{'dbh'}, $parent); - } - return unless (defined ($agent_parent)); + # Check if the parent agent exists. + my $agent_parent = get_agent_from_addr($self->{'dbh'}, $parent); + if (!defined($agent_parent)) { + $agent_parent = get_agent_from_name($self->{'dbh'}, $parent); + } + return unless (defined ($agent_parent)); - # Is the agent in learning mode? - return unless ($agent_parent->{'modo'} == 1); + # Is the agent in learning mode? + return unless ($agent_parent->{'modo'} == 1); - # Connect the host to its parent. - db_do($self->{'dbh'}, 'UPDATE tagente SET id_parent=? WHERE id_agente=?', $agent_parent->{'id_agente'}, $agent->{'id_agente'}); + # Connect the host to its parent. + db_do($self->{'dbh'}, 'UPDATE tagente SET id_parent=? WHERE id_agente=?', $agent_parent->{'id_agente'}, $agent->{'id_agente'}); } ################################################################################ # Create a WMI module for the given agent. ################################################################################ sub PandoraFMS::Recon::Base::wmi_module { - my ($self, $agent_id, $target, $wmi_query, $wmi_auth, $column, - $module_name, $module_description, $module_type, $unit) = @_; + my ($self, $agent_id, $target, $wmi_query, $wmi_auth, $column, + $module_name, $module_description, $module_type, $unit) = @_; - # Check whether the module already exists. - my $module_id = get_agent_module_id($self->{'dbh'}, $module_name, $agent_id); - return if ($module_id > 0); + # Check whether the module already exists. + my $module_id = get_agent_module_id($self->{'dbh'}, $module_name, $agent_id); + return if ($module_id > 0); - my ($user, $pass) = ($wmi_auth ne '') ? split('%', $wmi_auth) : (undef, undef); - my %module = ( - 'descripcion' => safe_input($module_description), - 'id_agente' => $agent_id, - 'id_modulo' => 6, - 'id_tipo_modulo' => get_module_id($self->{'dbh'}, $module_type), - 'ip_target' => $target, - 'nombre' => safe_input($module_name), - 'plugin_pass' => defined($pass) ? $pass : '', - 'plugin_user' => defined($user) ? $user : '', - 'snmp_oid' => $wmi_query, - 'tcp_port' => $column, - 'unit' => defined($unit) ? $unit : '' - ); - - pandora_create_module_from_hash($self->{'pa_config'}, \%module, $self->{'dbh'}); + my ($user, $pass) = ($wmi_auth ne '') ? split('%', $wmi_auth) : (undef, undef); + my %module = ( + 'descripcion' => safe_input($module_description), + 'id_agente' => $agent_id, + 'id_modulo' => 6, + 'id_tipo_modulo' => get_module_id($self->{'dbh'}, $module_type), + 'ip_target' => $target, + 'nombre' => safe_input($module_name), + 'plugin_pass' => defined($pass) ? $pass : '', + 'plugin_user' => defined($user) ? $user : '', + 'snmp_oid' => $wmi_query, + 'tcp_port' => $column, + 'unit' => defined($unit) ? $unit : '' + ); + + pandora_create_module_from_hash($self->{'pa_config'}, \%module, $self->{'dbh'}); } ################################################################################ # Update recon task status. ################################################################################ sub PandoraFMS::Recon::Base::update_progress ($$) { - my ($self, $progress) = @_; + my ($self, $progress) = @_; - my $stats = {}; - if (defined($self->{'summary'}) && $self->{'summary'} ne '') { - $stats->{'summary'} = $self->{'summary'}; - } - $stats->{'step'} = $self->{'step'}; - $stats->{'c_network_name'} = $self->{'c_network_name'}; - $stats->{'c_network_percent'} = $self->{'c_network_percent'}; + my $stats = {}; + if (defined($self->{'summary'}) && $self->{'summary'} ne '') { + $stats->{'summary'} = $self->{'summary'}; + } + $stats->{'step'} = $self->{'step'}; + $stats->{'c_network_name'} = $self->{'c_network_name'}; + $stats->{'c_network_percent'} = $self->{'c_network_percent'}; - # Store progress, last contact and overall status. - db_do ($self->{'dbh'}, 'UPDATE trecon_task SET utimestamp = ?, status = ?, summary = ? WHERE id_rt = ?', - time (), $progress, encode_json($stats), $self->{'task_id'}); + # Store progress, last contact and overall status. + db_do ($self->{'dbh'}, 'UPDATE trecon_task SET utimestamp = ?, status = ?, summary = ? WHERE id_rt = ?', + time (), $progress, encode_json($stats), $self->{'task_id'}); } 1; diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 279c84e337..49868448a7 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -18,24 +18,27 @@ use PandoraFMS::Recon::Util; # Constants. use constant { - STEP_SCANNING => 1, - STEP_AFT => 2, - STEP_TRACEROUTE => 3, - STEP_GATEWAY => 4, - STEP_STATISTICS => 1, - STEP_APP_SCAN => 2, - STEP_CUSTOM_QUERIES => 3, - DISCOVERY_HOSTDEVICES => 0, - DISCOVERY_HOSTDEVICES_CUSTOM => 1, - DISCOVERY_CLOUD_AWS => 2, - DISCOVERY_APP_VMWARE => 3, - DISCOVERY_APP_MYSQL => 4, - DISCOVERY_APP_ORACLE => 5, - DISCOVERY_CLOUD_AWS_EC2 => 6, - DISCOVERY_CLOUD_AWS_RDS => 7, - DISCOVERY_CLOUD_AZURE_COMPUTE => 8, - DISCOVERY_DEPLOY_AGENTS => 9, - DISCOVERY_APP_SAP => 10, + STEP_SCANNING => 1, + STEP_AFT => 2, + STEP_TRACEROUTE => 3, + STEP_GATEWAY => 4, + STEP_STATISTICS => 1, + STEP_APP_SCAN => 2, + STEP_CUSTOM_QUERIES => 3, + DISCOVERY_HOSTDEVICES => 0, + DISCOVERY_HOSTDEVICES_CUSTOM => 1, + DISCOVERY_CLOUD_AWS => 2, + DISCOVERY_APP_VMWARE => 3, + DISCOVERY_APP_MYSQL => 4, + DISCOVERY_APP_ORACLE => 5, + DISCOVERY_CLOUD_AWS_EC2 => 6, + DISCOVERY_CLOUD_AWS_RDS => 7, + DISCOVERY_CLOUD_AZURE_COMPUTE => 8, + DISCOVERY_DEPLOY_AGENTS => 9, + DISCOVERY_APP_SAP => 10, + DISCOVERY_SEARCH => 0, + DISCOVERY_STANDARD => 1, + DISCOVERY_RESULTS => 2, }; # $DEVNULL @@ -104,268 +107,268 @@ our @EXPORT = qw( # Create a new ReconTask object. ################################################################################ sub new { - my $class = shift; + my $class = shift; - my $self = { + my $self = { - # Known aliases (multiple IP addresses for the same host. - aliases => {}, + # Known aliases (multiple IP addresses for the same host. + aliases => {}, - # Keep our own ARP cache to connect hosts to switches/routers. - arp_cache => {}, + # Keep our own ARP cache to connect hosts to switches/routers. + arp_cache => {}, - # Found children. - children => {}, + # Found children. + children => {}, - # Working SNMP community for each device. - community_cache => {}, + # Working SNMP community for each device. + community_cache => {}, - # Cache of deviced discovered. - dicovered_cache => {}, + # Cache of deviced discovered. + dicovered_cache => {}, - # Connections between devices. - connections => {}, + # Connections between devices. + connections => {}, - # Devices by type. - hosts => [], - routers => [], - switches => [], + # Devices by type. + hosts => [], + routers => [], + switches => [], - # Found interfaces. - ifaces => {}, + # Found interfaces. + ifaces => {}, - # Found parents. - parents => {}, + # Found parents. + parents => {}, - # Route cache. - routes => [], - default_gw => undef, + # Route cache. + routes => [], + default_gw => undef, - # SNMP query cache. - snmp_cache => {}, + # SNMP query cache. + snmp_cache => {}, - # Globally enable/disable SNMP scans. - snmp_enabled => 1, + # Globally enable/disable SNMP scans. + snmp_enabled => 1, - # Globally enable/disable WMI scans. - wmi_enabled => 0, - auth_strings_array => [], - wmi_timeout => 3, - timeout_cmd => '', + # Globally enable/disable WMI scans. + wmi_enabled => 0, + auth_strings_array => [], + wmi_timeout => 3, + timeout_cmd => '', - # Switch to switch connections. Used to properly connect hosts - # that are connected to a switch wich is in turn connected to another switch, - # since the hosts will show up in the latter's switch AFT too. - switch_to_switch => {}, + # Switch to switch connections. Used to properly connect hosts + # that are connected to a switch wich is in turn connected to another switch, + # since the hosts will show up in the latter's switch AFT too. + switch_to_switch => {}, - # Visited devices (initially empty). - visited_devices => {}, + # Visited devices (initially empty). + visited_devices => {}, - # Per device VLAN cache. - vlan_cache => {}, - vlan_cache_enabled => 1, # User configuration. Globally disables the VLAN cache. - __vlan_cache_enabled__ => 0, # Internal state. Allows us to enable/disable the VLAN cache on a per SNMP query basis. + # Per device VLAN cache. + vlan_cache => {}, + vlan_cache_enabled => 1, # User configuration. Globally disables the VLAN cache. + __vlan_cache_enabled__ => 0, # Internal state. Allows us to enable/disable the VLAN cache on a per SNMP query basis. - # Configuration parameters. - all_ifaces => 0, - communities => [], - icmp_checks => 2, - icmp_timeout => 2, - id_os => 0, - id_network_profile => 0, - nmap => '/usr/bin/nmap', - parent_detection => 1, - parent_recursion => 5, - os_detection => 0, - recon_timing_template => 3, - recon_ports => '', - resolve_names => 0, - snmp_auth_user => '', - snmp_auth_pass => '', - snmp_auth_method => '', - snmp_checks => 2, - snmp_privacy_method => '', - snmp_privacy_pass => '', - snmp_security_level => '', - snmp_timeout => 2, - snmp_version => 1, - subnets => [], - autoconfiguration_enabled => 0, + # Configuration parameters. + all_ifaces => 0, + communities => [], + icmp_checks => 2, + icmp_timeout => 2, + id_os => 0, + id_network_profile => 0, + nmap => '/usr/bin/nmap', + parent_detection => 1, + parent_recursion => 5, + os_detection => 0, + recon_timing_template => 3, + recon_ports => '', + resolve_names => 0, + snmp_auth_user => '', + snmp_auth_pass => '', + snmp_auth_method => '', + snmp_checks => 2, + snmp_privacy_method => '', + snmp_privacy_pass => '', + snmp_security_level => '', + snmp_timeout => 2, + snmp_version => 1, + subnets => [], + autoconfiguration_enabled => 0, - # Store progress summary - Discovery progress view. - step => 0, - c_network_name => '', - c_network_percent => 0.0, - summary => { - SNMP => 0, - WMI => 0, - discovered => 0, - alive => 0, - not_alive => 0 - }, - @_, + # Store progress summary - Discovery progress view. + step => 0, + c_network_name => '', + c_network_percent => 0.0, + summary => { + SNMP => 0, + WMI => 0, + discovered => 0, + alive => 0, + not_alive => 0 + }, + @_, - }; + }; - # Perform some sanity checks. - die("No subnet was specified.") unless defined($self->{'subnets'}); + # Perform some sanity checks. + die("No subnet was specified.") unless defined($self->{'subnets'}); - $self = bless($self, $class); + $self = bless($self, $class); - # Check SNMP params id SNMP is enabled - if ($self->{'snmp_enabled'}) { + # Check SNMP params id SNMP is enabled + if ($self->{'snmp_enabled'}) { - # Check SNMP version - if ( $self->{'snmp_version'} ne '1' - && $self->{'snmp_version'} ne '2' - && $self->{'snmp_version'} ne '2c' - && $self->{'snmp_version'} ne '3') { - $self->{'snmp_enabled'} = 0; - $self->call('message', "SNMP version " . $self->{'snmp_version'} . " not supported (only 1, 2, 2c and 3).", 5); - } + # Check SNMP version + if ( $self->{'snmp_version'} ne '1' + && $self->{'snmp_version'} ne '2' + && $self->{'snmp_version'} ne '2c' + && $self->{'snmp_version'} ne '3') { + $self->{'snmp_enabled'} = 0; + $self->call('message', "SNMP version " . $self->{'snmp_version'} . " not supported (only 1, 2, 2c and 3).", 5); + } - # Check the version 3 parameters - if ($self->{'snmp_version'} eq '3') { + # Check the version 3 parameters + if ($self->{'snmp_version'} eq '3') { - # Fixed some vars - $self->{'communities'} = []; + # Fixed some vars + $self->{'communities'} = []; - # SNMP v3 checks - if ( $self->{'snmp_security_level'} ne 'noAuthNoPriv' - &&$self->{'snmp_security_level'} ne 'authNoPriv' - &&$self->{'snmp_security_level'} ne 'authPriv') { - $self->{'snmp_enabled'} = 0; - $self->call('message', "Invalid SNMP security level " . $self->{'snmp_security_level'} . ".", 5); - } - if ($self->{'snmp_privacy_method'} ne 'DES' && $self->{'snmp_privacy_method'} ne 'AES') { - $self->{'snmp_enabled'} = 0; - $self->call('message', "Invalid SNMP privacy method " . $self->{'snmp_privacy_method'} . ".", 5); - } - if ($self->{'snmp_auth_method'} ne 'MD5' && $self->{'snmp_auth_method'} ne 'SHA') { - $self->{'snmp_enabled'} = 0; - $self->call('message', "Invalid SNMP authentication method " . $self->{'snmp_auth_method'} . ".", 5); - } - } else { + # SNMP v3 checks + if ( $self->{'snmp_security_level'} ne 'noAuthNoPriv' + &&$self->{'snmp_security_level'} ne 'authNoPriv' + &&$self->{'snmp_security_level'} ne 'authPriv') { + $self->{'snmp_enabled'} = 0; + $self->call('message', "Invalid SNMP security level " . $self->{'snmp_security_level'} . ".", 5); + } + if ($self->{'snmp_privacy_method'} ne 'DES' && $self->{'snmp_privacy_method'} ne 'AES') { + $self->{'snmp_enabled'} = 0; + $self->call('message', "Invalid SNMP privacy method " . $self->{'snmp_privacy_method'} . ".", 5); + } + if ($self->{'snmp_auth_method'} ne 'MD5' && $self->{'snmp_auth_method'} ne 'SHA') { + $self->{'snmp_enabled'} = 0; + $self->call('message', "Invalid SNMP authentication method " . $self->{'snmp_auth_method'} . ".", 5); + } + } else { - # Fixed some vars - $self->{'snmp_auth_user'} = ''; - $self->{'snmp_auth_pass'} = ''; - $self->{'snmp_auth_method'} = ''; - $self->{'snmp_privacy_method'} = ''; - $self->{'snmp_privacy_pass'} = ''; - $self->{'snmp_security_level'} = ''; + # Fixed some vars + $self->{'snmp_auth_user'} = ''; + $self->{'snmp_auth_pass'} = ''; + $self->{'snmp_auth_method'} = ''; + $self->{'snmp_privacy_method'} = ''; + $self->{'snmp_privacy_pass'} = ''; + $self->{'snmp_security_level'} = ''; - # Disable SNMP scans if no community was given. - if (ref($self->{'communities'}) ne "ARRAY" || scalar(@{$self->{'communities'}}) == 0) { - $self->{'snmp_enabled'} = 0; - $self->call('message', "There is no SNMP community configured.", 5); + # Disable SNMP scans if no community was given. + if (ref($self->{'communities'}) ne "ARRAY" || scalar(@{$self->{'communities'}}) == 0) { + $self->{'snmp_enabled'} = 0; + $self->call('message', "There is no SNMP community configured.", 5); - } - } - } + } + } + } - # Prepare auth array. - # WMI could be launched with '-N' - no pass - argument. - if ($self->{'wmi_enabled'} == 1){ - if (defined($self->{'auth_strings_str'})) { - @{$self->{'auth_strings_array'}} = split(',', $self->{'auth_strings_str'}); - } + # Prepare auth array. + # WMI could be launched with '-N' - no pass - argument. + if ($self->{'wmi_enabled'} == 1){ + if (defined($self->{'auth_strings_str'})) { + @{$self->{'auth_strings_array'}} = split(',', $self->{'auth_strings_str'}); + } - # Timeout available only in linux environments. - if ($^O =~ /lin/i && defined($self->{'plugin_exec'}) && defined($self->{'wmi_timeout'})) { - $self->{'timeout_cmd'} = $self->{'plugin_exec'}.' '.$self->{'wmi_timeout'}.' '; - } - } + # Timeout available only in linux environments. + if ($^O =~ /lin/i && defined($self->{'plugin_exec'}) && defined($self->{'wmi_timeout'})) { + $self->{'timeout_cmd'} = $self->{'plugin_exec'}.' '.$self->{'wmi_timeout'}.' '; + } + } - # Remove all snmp related values if disabled - if (!$self->{'snmp_enabled'}) { - $self->{'communities'} = []; - $self->{'snmp_auth_user'} = ''; - $self->{'snmp_auth_pass'} = ''; - $self->{'snmp_auth_method'} = ''; - $self->{'snmp_privacy_method'} = ''; - $self->{'snmp_privacy_pass'} = ''; - $self->{'snmp_security_level'} = ''; - } + # Remove all snmp related values if disabled + if (!$self->{'snmp_enabled'}) { + $self->{'communities'} = []; + $self->{'snmp_auth_user'} = ''; + $self->{'snmp_auth_pass'} = ''; + $self->{'snmp_auth_method'} = ''; + $self->{'snmp_privacy_method'} = ''; + $self->{'snmp_privacy_pass'} = ''; + $self->{'snmp_security_level'} = ''; + } - return $self; + return $self; } ################################################################################ # Add an address to a device. ################################################################################ sub add_addresses($$$) { - my ($self, $device, $ip_address) = @_; + my ($self, $device, $ip_address) = @_; - $self->{'visited_devices'}->{$device}->{'addr'}->{$ip_address} = ''; + $self->{'visited_devices'}->{$device}->{'addr'}->{$ip_address} = ''; } ################################################################################ # Add a MAC/IP address to the ARP cache. ################################################################################ sub add_mac($$$) { - my ($self, $mac, $ip_addr) = @_; + my ($self, $mac, $ip_addr) = @_; - $mac = parse_mac($mac); - $self->{'arp_cache'}->{$mac} = $ip_addr; + $mac = parse_mac($mac); + $self->{'arp_cache'}->{$mac} = $ip_addr; } ################################################################################ # Add an interface/MAC to the interface cache. ################################################################################ sub add_iface($$$) { - my ($self, $iface, $mac) = @_; + my ($self, $iface, $mac) = @_; - $iface =~ s/"//g; - $self->{'ifaces'}->{$mac} = $iface; + $iface =~ s/"//g; + $self->{'ifaces'}->{$mac} = $iface; } ################################################################################ # Discover connectivity from address forwarding tables. ################################################################################ sub aft_connectivity($$) { - my ($self, $switch) = @_; - my (%mac_temp, @aft_temp); + my ($self, $switch) = @_; + my (%mac_temp, @aft_temp); - return unless ($self->is_snmp_discovered($switch)); + return unless ($self->is_snmp_discovered($switch)); - $self->enable_vlan_cache(); + $self->enable_vlan_cache(); - # Get the address forwarding table (AFT) of each switch. - my @aft; - foreach my $mac ($self->snmp_get_value_array($switch, $DOT1DTPFDBADDRESS)) { - push(@aft, parse_mac($mac)); - } + # Get the address forwarding table (AFT) of each switch. + my @aft; + foreach my $mac ($self->snmp_get_value_array($switch, $DOT1DTPFDBADDRESS)) { + push(@aft, parse_mac($mac)); + } - # Search for matching entries. - foreach my $aft_mac (@aft) { + # Search for matching entries. + foreach my $aft_mac (@aft) { - # Do we know who this is? - my $host = $self->get_ip_from_mac($aft_mac); - next unless defined($host) and $host ne ''; + # Do we know who this is? + my $host = $self->get_ip_from_mac($aft_mac); + next unless defined($host) and $host ne ''; - # Get the name of the host interface if available. - my $host_if_name = $self->get_iface($aft_mac); - $host_if_name = defined($host_if_name) ? $host_if_name : 'ping'; + # Get the name of the host interface if available. + my $host_if_name = $self->get_iface($aft_mac); + $host_if_name = defined($host_if_name) ? $host_if_name : 'ping'; - # Get the interface associated to the port were we found the MAC address. - my $switch_if_name = $self->get_if_from_aft($switch, $aft_mac); - next unless defined($switch_if_name) and ($switch_if_name ne ''); + # Get the interface associated to the port were we found the MAC address. + my $switch_if_name = $self->get_if_from_aft($switch, $aft_mac); + next unless defined($switch_if_name) and ($switch_if_name ne ''); - # Do not connect a host to a switch twice using the same interface. - # The switch is probably connected to another switch. - next if ($self->is_switch_connected($host, $host_if_name)); - $self->mark_switch_connected($host, $host_if_name); + # Do not connect a host to a switch twice using the same interface. + # The switch is probably connected to another switch. + next if ($self->is_switch_connected($host, $host_if_name)); + $self->mark_switch_connected($host, $host_if_name); - # The switch and the host are already connected. - next if ($self->are_connected($switch, $switch_if_name, $host, $host_if_name)); + # The switch and the host are already connected. + next if ($self->are_connected($switch, $switch_if_name, $host, $host_if_name)); - # Connect! - $self->mark_connected($switch, $switch_if_name, $host, $host_if_name); - $self->call('message', "Switch $switch (if $switch_if_name) is connected to host $host (if $host_if_name).", 5); - } + # Connect! + $self->mark_connected($switch, $switch_if_name, $host, $host_if_name); + $self->call('message', "Switch $switch (if $switch_if_name) is connected to host $host (if $host_if_name).", 5); + } - $self->disable_vlan_cache(); + $self->disable_vlan_cache(); } @@ -373,22 +376,22 @@ sub aft_connectivity($$) { # Return 1 if the given devices are connected to each other, 0 otherwise. ################################################################################ sub are_connected($$$$$) { - my ($self, $dev_1, $if_1, $dev_2, $if_2) = @_; + my ($self, $dev_1, $if_1, $dev_2, $if_2) = @_; - # Check for aliases! - $dev_1 = $self->{'aliases'}->{$dev_1} if defined($self->{'aliases'}->{$dev_1}); - $dev_2 = $self->{'aliases'}->{$dev_2} if defined($self->{'aliases'}->{$dev_2}); + # Check for aliases! + $dev_1 = $self->{'aliases'}->{$dev_1} if defined($self->{'aliases'}->{$dev_1}); + $dev_2 = $self->{'aliases'}->{$dev_2} if defined($self->{'aliases'}->{$dev_2}); - # Use ping modules when interfaces are unknown. - $if_1 = "ping" if $if_1 eq ''; - $if_2 = "ping" if $if_2 eq ''; + # Use ping modules when interfaces are unknown. + $if_1 = "ping" if $if_1 eq ''; + $if_2 = "ping" if $if_2 eq ''; - if ( defined($self->{'connections'}->{"${dev_1}\t${if_1}\t${dev_2}\t${if_2}"}) - ||defined($self->{'connections'}->{"${dev_2}\t${if_2}\t${dev_1}\t${if_1}"})) { - return 1; - } + if ( defined($self->{'connections'}->{"${dev_1}\t${if_1}\t${dev_2}\t${if_2}"}) + ||defined($self->{'connections'}->{"${dev_2}\t${if_2}\t${dev_1}\t${if_1}"})) { + return 1; + } - return 0; + return 0; } ################################################################################ @@ -396,19 +399,19 @@ sub are_connected($$$$$) { # Already discovered by scan_subnet. ################################################################################ sub icmp_discovery($$) { - my ($self, $addr) = @_; + my ($self, $addr) = @_; - $self->prepare_agent($addr); + $self->prepare_agent($addr); - $self->add_module($addr, 'icmp', - { - 'ip_target' => $addr, - 'name' => "Host Alive", - 'description' => '', - 'type' => 'generic_data', - 'id_modulo' => 2, - } - ); + $self->add_module($addr, 'icmp', + { + 'ip_target' => $addr, + 'name' => "Host Alive", + 'description' => '', + 'type' => 'generic_data', + 'id_modulo' => 2, + } + ); } @@ -416,46 +419,46 @@ sub icmp_discovery($$) { # Discover as much information as possible from the given device using SNMP. ################################################################################ sub snmp_discovery($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - # Have we already visited this device? - return if ($self->is_visited($device)); + # Have we already visited this device? + return if ($self->is_visited($device)); - # Mark the device as visited. - $self->mark_visited($device); + # Mark the device as visited. + $self->mark_visited($device); - # Are SNMP scans enabled? - if ($self->{'snmp_enabled'} == 1) { + # Are SNMP scans enabled? + if ($self->{'snmp_enabled'} == 1) { - # Try to find the MAC with an ARP request. - $self->get_mac_from_ip($device); + # Try to find the MAC with an ARP request. + $self->get_mac_from_ip($device); - # Check if the device responds to SNMP. - if ($self->snmp_responds($device)) { - $self->{'summary'}->{'SNMP'} += 1; + # Check if the device responds to SNMP. + if ($self->snmp_responds($device)) { + $self->{'summary'}->{'SNMP'} += 1; - # Fill the VLAN cache. - $self->find_vlans($device); + # Fill the VLAN cache. + $self->find_vlans($device); - # Guess the device type. - $self->guess_device_type($device); + # Guess the device type. + $self->guess_device_type($device); - # Find aliases for the device. - $self->find_aliases($device); + # Find aliases for the device. + $self->find_aliases($device); - # Find interfaces for the device. - $self->find_ifaces($device); + # Find interfaces for the device. + $self->find_ifaces($device); - # Check remote ARP caches. - $self->remote_arp($device); + # Check remote ARP caches. + $self->remote_arp($device); - # Get PEN. - $self->snmp_pen($device); - } - } + # Get PEN. + $self->snmp_pen($device); + } + } - # Create an agent for the device and add it to the list of known hosts. - $self->add_agent($device); + # Create an agent for the device and add it to the list of known hosts. + $self->add_agent($device); } @@ -463,252 +466,252 @@ sub snmp_discovery($$) { # Try to call the given function on the given object. ################################################################################ sub call { - my $self = shift; - my $func = shift; - my @params = @_; + my $self = shift; + my $func = shift; + my @params = @_; - if ($self->can($func)) { - $self->$func(@params); - } + if ($self->can($func)) { + $self->$func(@params); + } } ################################################################################ # Disable the VLAN cache. ################################################################################ sub disable_vlan_cache($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - $self->{'__vlan_cache_enabled__'} = 0; + $self->{'__vlan_cache_enabled__'} = 0; } ################################################################################ # Enable the VLAN cache. ################################################################################ sub enable_vlan_cache($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - return if ($self->{'vlan_cache_enabled'} == 0); - $self->{'__vlan_cache_enabled__'} = 1; + return if ($self->{'vlan_cache_enabled'} == 0); + $self->{'__vlan_cache_enabled__'} = 1; } ################################################################################ # Connect the given hosts to its gateway. ################################################################################ sub gateway_connectivity($$) { - my ($self, $host) = @_; + my ($self, $host) = @_; - my $gw = $self->get_gateway($host); - return unless defined($gw); + my $gw = $self->get_gateway($host); + return unless defined($gw); - # Check for aliases! - $host = $self->{'aliases'}->{$host} if defined($self->{'aliases'}->{$host}); - $gw = $self->{'aliases'}->{$gw} if defined($self->{'aliases'}->{$gw}); + # Check for aliases! + $host = $self->{'aliases'}->{$host} if defined($self->{'aliases'}->{$host}); + $gw = $self->{'aliases'}->{$gw} if defined($self->{'aliases'}->{$gw}); - # Same host, different IP addresses. - return if ($host eq $gw); + # Same host, different IP addresses. + return if ($host eq $gw); - $self->call('message', "Host $host is reached via gateway $gw.", 5); - $self->mark_connected($gw, '', $host, ''); + $self->call('message', "Host $host is reached via gateway $gw.", 5); + $self->mark_connected($gw, '', $host, ''); } ################################################################################ # Find IP address aliases for the given device. ################################################################################ sub find_aliases($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - # Get ARP cache. - my @ip_addresses = $self->snmp_get_value_array($device, $IPENTADDR); - foreach my $ip_address (@ip_addresses) { + # Get ARP cache. + my @ip_addresses = $self->snmp_get_value_array($device, $IPENTADDR); + foreach my $ip_address (@ip_addresses) { - # Skip broadcast and localhost addresses. - next if ($ip_address =~ m/\.255$|\.0$|127\.0\.0\.1$/); + # Skip broadcast and localhost addresses. + next if ($ip_address =~ m/\.255$|\.0$|127\.0\.0\.1$/); - # Sometimes we find the same IP address we had. - next if ($ip_address eq $device); + # Sometimes we find the same IP address we had. + next if ($ip_address eq $device); - $self->add_addresses($device, $ip_address); + $self->add_addresses($device, $ip_address); - # Try to find the MAC with an ARP request. - $self->get_mac_from_ip($ip_address); + # Try to find the MAC with an ARP request. + $self->get_mac_from_ip($ip_address); - $self->call('message', "Found address $ip_address for host $device.", 5); + $self->call('message', "Found address $ip_address for host $device.", 5); - # Is this address an alias itself? - $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device}); - next if ($ip_address eq $device); + # Is this address an alias itself? + $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device}); + next if ($ip_address eq $device); - # Link the two addresses. - $self->{'aliases'}->{$ip_address} = $device; - } + # Link the two addresses. + $self->{'aliases'}->{$ip_address} = $device; + } } ################################################################################ # Find all the interfaces for the given host. ################################################################################ sub find_ifaces($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - # Does it respond to SNMP? - return unless ($self->is_snmp_discovered($device)); + # Does it respond to SNMP? + return unless ($self->is_snmp_discovered($device)); - my @output = $self->snmp_get_value_array($device, $PandoraFMS::Recon::Base::IFINDEX); - foreach my $if_index (@output) { + my @output = $self->snmp_get_value_array($device, $PandoraFMS::Recon::Base::IFINDEX); + foreach my $if_index (@output) { - next unless ($if_index =~ /^[0-9]+$/); + next unless ($if_index =~ /^[0-9]+$/); - # Ignore virtual interfaces. - next if ($self->get_if_type($device, $if_index) eq '53'); + # Ignore virtual interfaces. + next if ($self->get_if_type($device, $if_index) eq '53'); - # Get the MAC. - my $mac = $self->get_if_mac($device, $if_index); - next unless (defined($mac) && $mac ne ''); + # Get the MAC. + my $mac = $self->get_if_mac($device, $if_index); + next unless (defined($mac) && $mac ne ''); - # Save it. - $self->add_mac($mac, $device); + # Save it. + $self->add_mac($mac, $device); - # Get the name of the network interface. - my $if_name = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFNAME.$if_index"); - next unless defined($if_name); + # Get the name of the network interface. + my $if_name = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFNAME.$if_index"); + next unless defined($if_name); - # Save it. - $self->add_iface($if_name, $mac); + # Save it. + $self->add_iface($if_name, $mac); - $self->call('message', "Found interface $if_name MAC $mac for host $device.", 5); - } + $self->call('message', "Found interface $if_name MAC $mac for host $device.", 5); + } } ################################################################################ # Find the device's VLANs and fill the VLAN cache. ################################################################################ sub find_vlans ($$) { - my ($self, $device) = @_; - my %vlan_hash; + my ($self, $device) = @_; + my %vlan_hash; - foreach my $vlan ($self->snmp_get_value_array($device, $VTPVLANIFINDEX)) { - next if $vlan eq '0'; - $vlan_hash{$vlan} = 1; - } - my @vlans = keys(%vlan_hash); + foreach my $vlan ($self->snmp_get_value_array($device, $VTPVLANIFINDEX)) { + next if $vlan eq '0'; + $vlan_hash{$vlan} = 1; + } + my @vlans = keys(%vlan_hash); - $self->{'vlan_cache'}->{$device} = []; - push(@{$self->{'vlan_cache'}->{$device}}, @vlans) if (scalar(@vlans) > 0); + $self->{'vlan_cache'}->{$device} = []; + push(@{$self->{'vlan_cache'}->{$device}}, @vlans) if (scalar(@vlans) > 0); } ################################################################################ # Return the addresses of the given device as an array. ################################################################################ sub get_addresses($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - if (defined($self->{'visited_devices'}->{$device})) { - return keys(%{$self->{'visited_devices'}->{$device}->{'addr'}}); - } + if (defined($self->{'visited_devices'}->{$device})) { + return keys(%{$self->{'visited_devices'}->{$device}->{'addr'}}); + } - # By default return the given address. - return ($device); + # By default return the given address. + return ($device); } ################################################################################ # Return a device structure from an IP address. ################################################################################ sub get_device($$) { - my ($self, $addr) = @_; + my ($self, $addr) = @_; - if (defined($self->{'visited_devices'}->{$addr})) { - return $self->{'visited_devices'}->{$addr}; - } + if (defined($self->{'visited_devices'}->{$addr})) { + return $self->{'visited_devices'}->{$addr}; + } - return undef; + return undef; } ################################################################################ # Get the SNMP community of the given device. Returns undef if no community was found. ################################################################################ sub get_community($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - return '' if ($self->{'snmp_version'} eq "3"); + return '' if ($self->{'snmp_version'} eq "3"); - if (defined($self->{'community_cache'}->{$device})) { - return $self->{'community_cache'}->{$device}; - } + if (defined($self->{'community_cache'}->{$device})) { + return $self->{'community_cache'}->{$device}; + } - return ''; + return ''; } ################################################################################ # Return the connection hash. ################################################################################ sub get_connections($) { - my ($self) = @_; + my ($self) = @_; - return $self->{'connections'}; + return $self->{'connections'}; } ################################################################################ # Return the parent relationship hash. ################################################################################ sub get_parents($) { - my ($self) = @_; + my ($self) = @_; - return $self->{'parents'}; + return $self->{'parents'}; } ################################################################################ # Get the type of the given device. ################################################################################ sub get_device_type($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - if (defined($self->{'visited_devices'}->{$device})) { - return $self->{'visited_devices'}->{$device}->{'type'}; - } + if (defined($self->{'visited_devices'}->{$device})) { + return $self->{'visited_devices'}->{$device}->{'type'}; + } - # Assume 'host' by default. - return 'host'; + # Assume 'host' by default. + return 'host'; } ################################################################################ # Return all known hosts that are not switches or routers. ################################################################################ sub get_hosts($) { - my ($self) = @_; + my ($self) = @_; - return $self->{'hosts'}; + return $self->{'hosts'}; } ################################################################################ # Add an interface/MAC to the interface cache. ################################################################################ sub get_iface($$) { - my ($self, $mac) = @_; + my ($self, $mac) = @_; - return undef unless defined($self->{'ifaces'}->{$mac}); + return undef unless defined($self->{'ifaces'}->{$mac}); - return $self->{'ifaces'}->{$mac}; + return $self->{'ifaces'}->{$mac}; } ################################################################################ # Get an interface name from an AFT entry. Returns undef on error. ################################################################################ sub get_if_from_aft($$$) { - my ($self, $switch, $mac) = @_; + my ($self, $switch, $mac) = @_; - # Get the port associated to the MAC. - my $port = $self->snmp_get_value($switch, "$DOT1DTPFDBPORT." . mac_to_dec($mac)); - return '' unless defined($port); + # Get the port associated to the MAC. + my $port = $self->snmp_get_value($switch, "$DOT1DTPFDBPORT." . mac_to_dec($mac)); + return '' unless defined($port); - # Get the interface index associated to the port. - my $if_index = $self->snmp_get_value($switch, "$DOT1DBASEPORTIFINDEX.$port"); - return '' unless defined($if_index); + # Get the interface index associated to the port. + my $if_index = $self->snmp_get_value($switch, "$DOT1DBASEPORTIFINDEX.$port"); + return '' unless defined($if_index); - # Get the interface name. - my $if_name = $self->snmp_get_value($switch, "$IFNAME.$if_index"); - return "if$if_index" unless defined($if_name); + # Get the interface name. + my $if_name = $self->snmp_get_value($switch, "$IFNAME.$if_index"); + return "if$if_index" unless defined($if_name); - $if_name =~ s/"//g; - return $if_name; + $if_name =~ s/"//g; + return $if_name; } @@ -716,214 +719,214 @@ sub get_if_from_aft($$$) { # Get an interface name from an IP address. ################################################################################ sub get_if_from_ip($$$) { - my ($self, $device, $ip_addr) = @_; + my ($self, $device, $ip_addr) = @_; - # Get the port associated to the IP address. - my $if_index = $self->snmp_get_value($device, "$IPROUTEIFINDEX.$ip_addr"); - return '' unless defined($if_index); + # Get the port associated to the IP address. + my $if_index = $self->snmp_get_value($device, "$IPROUTEIFINDEX.$ip_addr"); + return '' unless defined($if_index); - # Get the name of the interface associated to the port. - my $if_name = $self->snmp_get_value($device, "$IFNAME.$if_index"); - return '' unless defined($if_name); + # Get the name of the interface associated to the port. + my $if_name = $self->snmp_get_value($device, "$IFNAME.$if_index"); + return '' unless defined($if_name); - $if_name =~ s/"//g; - return $if_name; + $if_name =~ s/"//g; + return $if_name; } ################################################################################ # Get an interface name from a MAC address. ################################################################################ sub get_if_from_mac($$$) { - my ($self, $device, $mac) = @_; + my ($self, $device, $mac) = @_; - # Get the port associated to the IP address. - my @output = $self->snmp_get($device, $IFPHYSADDRESS); - foreach my $line (@output) { - chomp($line); - next unless $line =~ /^IFPHYSADDRESS.(\S+)\s+=\s+\S+:\s+(.*)$/; - my ($if_index, $if_mac) = ($1, $2); + # Get the port associated to the IP address. + my @output = $self->snmp_get($device, $IFPHYSADDRESS); + foreach my $line (@output) { + chomp($line); + next unless $line =~ /^IFPHYSADDRESS.(\S+)\s+=\s+\S+:\s+(.*)$/; + my ($if_index, $if_mac) = ($1, $2); - # Make sure the MAC addresses match. - next unless (mac_matches($mac, $if_mac) == 1); + # Make sure the MAC addresses match. + next unless (mac_matches($mac, $if_mac) == 1); - # Pupulate the ARP cache. - $self->add_mac($mac, $device); + # Pupulate the ARP cache. + $self->add_mac($mac, $device); - # Get the name of the interface associated to the port. - my $if_name = $self->snmp_get_value($device, "$IFNAME.$if_index"); - return '' unless defined($if_name); + # Get the name of the interface associated to the port. + my $if_name = $self->snmp_get_value($device, "$IFNAME.$if_index"); + return '' unless defined($if_name); - $if_name =~ s/"//g; - return $if_name; - } + $if_name =~ s/"//g; + return $if_name; + } - return ''; + return ''; } ################################################################################ # Get an interface name from a port number. Returns '' on error. ################################################################################ sub get_if_from_port($$$) { - my ($self, $switch, $port) = @_; + my ($self, $switch, $port) = @_; - # Get the interface index associated to the port. - my $if_index = $self->snmp_get_value($switch, "$DOT1DBASEPORTIFINDEX.$port"); - return '' unless defined($if_index); + # Get the interface index associated to the port. + my $if_index = $self->snmp_get_value($switch, "$DOT1DBASEPORTIFINDEX.$port"); + return '' unless defined($if_index); - # Get the interface name. - my $if_name = $self->snmp_get_value($switch, "$IFNAME.$if_index"); - return "if$if_index" unless defined($if_name); + # Get the interface name. + my $if_name = $self->snmp_get_value($switch, "$IFNAME.$if_index"); + return "if$if_index" unless defined($if_name); - $if_name =~ s/"//g; - return $if_name; + $if_name =~ s/"//g; + return $if_name; } ################################################################################ # Returns the IP address of the given interface (by index). ################################################################################ sub get_if_ip($$$) { - my ($self, $device, $if_index) = @_; + my ($self, $device, $if_index) = @_; - my @output = $self->snmp_get($device, $IPADENTIFINDEX); - foreach my $line (@output) { - chomp($line); - return $1 if ($line =~ m/^$IPADENTIFINDEX.(\S+)\s+=\s+\S+:\s+$if_index$/); - } + my @output = $self->snmp_get($device, $IPADENTIFINDEX); + foreach my $line (@output) { + chomp($line); + return $1 if ($line =~ m/^$IPADENTIFINDEX.(\S+)\s+=\s+\S+:\s+$if_index$/); + } - return ''; + return ''; } ################################################################################ # Returns the MAC address of the given interface (by index). ################################################################################ sub get_if_mac($$$) { - my ($self, $device, $if_index) = @_; + my ($self, $device, $if_index) = @_; - my $mac = $self->snmp_get_value($device, "$IFPHYSADDRESS.$if_index"); - return '' unless defined($mac); + my $mac = $self->snmp_get_value($device, "$IFPHYSADDRESS.$if_index"); + return '' unless defined($mac); - # Clean-up the MAC address. - $mac = parse_mac($mac); + # Clean-up the MAC address. + $mac = parse_mac($mac); - return $mac; + return $mac; } ################################################################################ # Returns the type of the given interface (by index). ################################################################################ sub get_if_type($$$) { - my ($self, $device, $if_index) = @_; + my ($self, $device, $if_index) = @_; - my $type = $self->snmp_get_value($device, "$IFTYPE.$if_index"); - return '' unless defined($type); + my $type = $self->snmp_get_value($device, "$IFTYPE.$if_index"); + return '' unless defined($type); - return $type; + return $type; } ################################################################################ # Get an IP address from the ARP cache given the MAC address. ################################################################################ sub get_ip_from_mac($$) { - my ($self, $mac_addr) = @_; + my ($self, $mac_addr) = @_; - if (defined($self->{'arp_cache'}->{$mac_addr})) { - return $self->{'arp_cache'}->{$mac_addr}; - } + if (defined($self->{'arp_cache'}->{$mac_addr})) { + return $self->{'arp_cache'}->{$mac_addr}; + } - return undef; + return undef; } ################################################################################ # Attemtps to find ################################################################################ sub get_mac_from_ip($$) { - my ($self, $host) = @_; - my $mac = undef; + my ($self, $host) = @_; + my $mac = undef; - eval { - $mac = `arping -c 1 $host 2>$DEVNULL`; - $mac = undef unless ($? == 0); - }; + eval { + $mac = `arping -c 1 $host 2>$DEVNULL`; + $mac = undef unless ($? == 0); + }; - return unless defined($mac); + return unless defined($mac); - ($mac) = $mac =~ /\[(.*?)\]/ if defined($mac); + ($mac) = $mac =~ /\[(.*?)\]/ if defined($mac); - # Clean-up the MAC address. - chomp($mac); - $mac = parse_mac($mac); - $self->add_mac($mac, $host); + # Clean-up the MAC address. + chomp($mac); + $mac = parse_mac($mac); + $self->add_mac($mac, $host); - $self->call('message', "Found MAC $mac for host $host in the local ARP cache.", 5); + $self->call('message', "Found MAC $mac for host $host in the local ARP cache.", 5); } ################################################################################ # Get a port number from an AFT entry. Returns undef on error. ################################################################################ sub get_port_from_aft($$$) { - my ($self, $switch, $mac) = @_; + my ($self, $switch, $mac) = @_; - # Get the port associated to the MAC. - my $port = $self->snmp_get_value($switch, "$DOT1DTPFDBPORT." . mac_to_dec($mac)); - return '' unless defined($port); + # Get the port associated to the MAC. + my $port = $self->snmp_get_value($switch, "$DOT1DTPFDBPORT." . mac_to_dec($mac)); + return '' unless defined($port); - return $port; + return $port; } ################################################################################ # Fill the route cache. ################################################################################ sub get_routes($) { - my ($self) = @_; + my ($self) = @_; - # Empty the current route cache. - $self->{'routes'} = []; + # Empty the current route cache. + $self->{'routes'} = []; - # Parse route's output. - my @output = `route -n 2>$DEVNULL`; - foreach my $line (@output) { - chomp($line); - if ($line =~ /^0\.0\.0\.0\s+(\d+\.\d+\.\d+\.\d+).*/) { - $self->{'default_gw'} = $1; - } elsif ($line =~ /^(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+).*/) { - push(@{$self->{'routes'}}, { dest => $1, gw => $2, mask => $3 }); - } - } + # Parse route's output. + my @output = `route -n 2>$DEVNULL`; + foreach my $line (@output) { + chomp($line); + if ($line =~ /^0\.0\.0\.0\s+(\d+\.\d+\.\d+\.\d+).*/) { + $self->{'default_gw'} = $1; + } elsif ($line =~ /^(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+).*/) { + push(@{$self->{'routes'}}, { dest => $1, gw => $2, mask => $3 }); + } + } - # Replace 0.0.0.0 with the default gateway's IP. - return unless defined($self->{'default_gw'}); - foreach my $route (@{$self->{'routes'}}) { - $route->{gw} = $self->{'default_gw'} if ($route->{'gw'} eq '0.0.0.0'); - } + # Replace 0.0.0.0 with the default gateway's IP. + return unless defined($self->{'default_gw'}); + foreach my $route (@{$self->{'routes'}}) { + $route->{gw} = $self->{'default_gw'} if ($route->{'gw'} eq '0.0.0.0'); + } } ################################################################################ # Get the gateway to reach the given host. ################################################################################ sub get_gateway($) { - my ($self, $host) = @_; + my ($self, $host) = @_; - # Look for a specific route to the given host. - foreach my $route (@{$self->{'routes'}}) { - if (subnet_matches($host, $route->{'dest'}, $route->{'mask'})) { - return $route->{'gw'}; - } - } + # Look for a specific route to the given host. + foreach my $route (@{$self->{'routes'}}) { + if (subnet_matches($host, $route->{'dest'}, $route->{'mask'})) { + return $route->{'gw'}; + } + } - # Return the default gateway. - return $self->{'default_gw'} if defined($self->{'default_gw'}); + # Return the default gateway. + return $self->{'default_gw'} if defined($self->{'default_gw'}); - # Ops! - return undef; + # Ops! + return undef; } ################################################################################ # Return a pointer to an array containing configured subnets. ################################################################################ sub get_subnets($) { - my ($self) = @_; + my ($self) = @_; - return $self->{'subnets'}; + return $self->{'subnets'}; } ################################################################################ @@ -932,150 +935,150 @@ sub get_subnets($) { # like get_hosts, get_switches, get_routers and get_all_devices. ################################################################################ sub get_visited_devices($) { - my ($self) = @_; + my ($self) = @_; - return $self->{'visited_devices'}; + return $self->{'visited_devices'}; } ################################################################################ # Returns an array of found VLAN IDs. ################################################################################ sub get_vlans($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - # Disabled in verison 3 - return () if ($self->{'snmp_version'} eq "3"); + # Disabled in verison 3 + return () if ($self->{'snmp_version'} eq "3"); - # Is the VLAN cache disabled? - return () unless ($self->{'__vlan_cache_enabled__'} == 1); + # Is the VLAN cache disabled? + return () unless ($self->{'__vlan_cache_enabled__'} == 1); - return () unless defined($self->{'vlan_cache'}->{$device}); + return () unless defined($self->{'vlan_cache'}->{$device}); - return @{$self->{'vlan_cache'}->{$device}}; + return @{$self->{'vlan_cache'}->{$device}}; } ################################################################################ # Guess the type of the given device. ################################################################################ sub guess_device_type($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - # Get the value of sysServices. - my $services = $self->snmp_get_value($device, "$SYSSERVICES.0"); - return unless defined($services); + # Get the value of sysServices. + my $services = $self->snmp_get_value($device, "$SYSSERVICES.0"); + return unless defined($services); - # Check the individual bits. - my @service_bits = split('', unpack('b8', pack('C', $services))); + # Check the individual bits. + my @service_bits = split('', unpack('b8', pack('C', $services))); - # Check for layer 2 connectivity support. - my $bridge_mib = $self->snmp_get_value($device, $DOT1DBASEBRIDGEADDRESS); + # Check for layer 2 connectivity support. + my $bridge_mib = $self->snmp_get_value($device, $DOT1DBASEBRIDGEADDRESS); - # L2? - my $device_type; - if ($service_bits[1] == 1) { + # L2? + my $device_type; + if ($service_bits[1] == 1) { - # L3? - if ($service_bits[2] == 1) { + # L3? + if ($service_bits[2] == 1) { - # Bridge MIB? - if (defined($bridge_mib)) { - $device_type = 'switch'; - } else { + # Bridge MIB? + if (defined($bridge_mib)) { + $device_type = 'switch'; + } else { - # L7? - if ($service_bits[6] == 1) { - $device_type = 'host'; - } else { - $device_type = 'router'; - } - } - }else { + # L7? + if ($service_bits[6] == 1) { + $device_type = 'host'; + } else { + $device_type = 'router'; + } + } + }else { - # Bridge MIB? - if (defined($bridge_mib)) { - $device_type = 'switch'; - } else { - $device_type = 'host'; - } - } - }else { + # Bridge MIB? + if (defined($bridge_mib)) { + $device_type = 'switch'; + } else { + $device_type = 'host'; + } + } + }else { - # L3? - if ($service_bits[2] == 1) { + # L3? + if ($service_bits[2] == 1) { - # L4? - if ($service_bits[3] == 1) { - $device_type = 'switch'; - } else { + # L4? + if ($service_bits[3] == 1) { + $device_type = 'switch'; + } else { - # L7? - if ($service_bits[6] == 1) { - $device_type = 'host'; - } else { - $device_type = 'router'; - } - } - }else { + # L7? + if ($service_bits[6] == 1) { + $device_type = 'host'; + } else { + $device_type = 'router'; + } + } + }else { - # Printer MIB? - my $printer_mib = $self->snmp_get_value($device, $PRTMARKERINDEX); - if (defined($printer_mib)) { - $device_type = 'printer'; - } else { - $device_type = 'host'; - } - } - } + # Printer MIB? + my $printer_mib = $self->snmp_get_value($device, $PRTMARKERINDEX); + if (defined($printer_mib)) { + $device_type = 'printer'; + } else { + $device_type = 'host'; + } + } + } - # Set the type of the device. - $self->set_device_type($device, $device_type); + # Set the type of the device. + $self->set_device_type($device, $device_type); } ################################################################################ # Return 1 if the given device has children. ################################################################################ sub has_children($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - # Check for aliases! - $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device}); + # Check for aliases! + $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device}); - return 1 if (defined($self->{'children'}->{$device})); + return 1 if (defined($self->{'children'}->{$device})); - return 0; + return 0; } ################################################################################ # Return 1 if the given device has a parent. ################################################################################ sub has_parent($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - # Check for aliases! - $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device}); + # Check for aliases! + $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device}); - return 1 if (defined($self->{'parents'}->{$device})); + return 1 if (defined($self->{'parents'}->{$device})); - return 0; + return 0; } ################################################################################ # Returns 1 if the device belongs to one of the scanned subnets. ################################################################################ sub in_subnet($$) { - my ($self, $device) = @_; - $device = ip_to_long($device); + my ($self, $device) = @_; + $device = ip_to_long($device); - # No subnets specified. - return 1 if (scalar(@{$self->{'subnets'}}) <= 0); + # No subnets specified. + return 1 if (scalar(@{$self->{'subnets'}}) <= 0); - foreach my $subnet (@{$self->{'subnets'}}) { - if (subnet_matches($device, $subnet)) { - return 1; - } - } + foreach my $subnet (@{$self->{'subnets'}}) { + if (subnet_matches($device, $subnet)) { + return 1; + } + } - return 0; + return 0; } ################################################################################ @@ -1083,30 +1086,30 @@ sub in_subnet($$) { # up in a switch/router's port. ################################################################################ sub is_switch_connected($$$) { - my ($self, $device, $iface) = @_; + my ($self, $device, $iface) = @_; - # Check for aliases! - $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device}); + # Check for aliases! + $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device}); - return 1 if defined($self->{'switch_to_switch'}->{"${device}\t${iface}"}); + return 1 if defined($self->{'switch_to_switch'}->{"${device}\t${iface}"}); - return 0; + return 0; } ################################################################################ # Returns 1 if the given device has already been visited, 0 otherwise. ################################################################################ sub is_visited($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - # Check for aliases! - $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device}); + # Check for aliases! + $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device}); - if (defined($self->{'visited_devices'}->{$device})) { - return 1; - } + if (defined($self->{'visited_devices'}->{$device})) { + return 1; + } - return 0; + return 0; } ################################################################################ @@ -1114,74 +1117,74 @@ sub is_visited($$) { # Returns 0 otherwise. ################################################################################ sub is_snmp_discovered($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - # Check if device is into discovered cache - return (defined($self->{'discovered_cache'}->{$device})) ? 1 : 0; + # Check if device is into discovered cache + return (defined($self->{'discovered_cache'}->{$device})) ? 1 : 0; } ################################################################################ # Mark the given devices as connected to each other on the given interfaces. ################################################################################ sub mark_connected($$;$$$) { - my ($self, $parent, $parent_if, $child, $child_if) = @_; + my ($self, $parent, $parent_if, $child, $child_if) = @_; - # Check for aliases! - $parent = $self->{'aliases'}->{$parent} if defined($self->{'aliases'}->{$parent}); - $child = $self->{'aliases'}->{$child} if defined($self->{'aliases'}->{$child}); + # Check for aliases! + $parent = $self->{'aliases'}->{$parent} if defined($self->{'aliases'}->{$parent}); + $child = $self->{'aliases'}->{$child} if defined($self->{'aliases'}->{$child}); - # Use ping modules when interfaces are unknown. - $parent_if = "Host Alive" if $parent_if eq ''; - $child_if = "Host Alive" if $child_if eq ''; + # Use ping modules when interfaces are unknown. + $parent_if = "Host Alive" if $parent_if eq ''; + $child_if = "Host Alive" if $child_if eq ''; - # Do not connect devices using ping modules. A parent-child relationship is enough. - if ($parent_if ne "Host Alive" || $child_if ne "Host Alive") { - $self->{'connections'}->{"${parent}\t${parent_if}\t${child}\t${child_if}"} = 1; - $self->call('connect_agents', $parent, $parent_if, $child, $child_if); - } + # Do not connect devices using ping modules. A parent-child relationship is enough. + if ($parent_if ne "Host Alive" || $child_if ne "Host Alive") { + $self->{'connections'}->{"${parent}\t${parent_if}\t${child}\t${child_if}"} = 1; + $self->call('connect_agents', $parent, $parent_if, $child, $child_if); + } - # Prevent parent-child loops. - if (!defined($self->{'parents'}->{$parent}) - ||$self->{'parents'}->{$parent} ne $child) { + # Prevent parent-child loops. + if (!defined($self->{'parents'}->{$parent}) + ||$self->{'parents'}->{$parent} ne $child) { - # A parent-child relationship is always created to help complete the map with - # layer 3 information. - $self->{'parents'}->{$child} = $parent; - $self->{'children'}->{$parent} = $child; - $self->call('set_parent', $child, $parent); - } + # A parent-child relationship is always created to help complete the map with + # layer 3 information. + $self->{'parents'}->{$child} = $parent; + $self->{'children'}->{$parent} = $child; + $self->call('set_parent', $child, $parent); + } } ################################################################################ # Mark the given switch as having a connection on the given interface. ################################################################################ sub mark_switch_connected($$$) { - my ($self, $device, $iface) = @_; + my ($self, $device, $iface) = @_; - # Check for aliases! - $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device}); - $self->{'switch_to_switch'}->{"${device}\t${iface}"} = 1; + # Check for aliases! + $device = $self->{'aliases'}->{$device} if defined($self->{'aliases'}->{$device}); + $self->{'switch_to_switch'}->{"${device}\t${iface}"} = 1; } ################################################################################ # Mark the given device as visited. ################################################################################ sub mark_visited($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - $self->{'visited_devices'}->{$device} = { - 'addr' => { $device => '' }, - 'type' => 'host' - }; + $self->{'visited_devices'}->{$device} = { + 'addr' => { $device => '' }, + 'type' => 'host' + }; } ################################################################################ # Mark the given device as snmp discovered. ################################################################################ sub mark_discovered($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - $self->{'discovered_cache'}->{$device} = 1; + $self->{'discovered_cache'}->{$device} = 1; } ################################################################################ @@ -1190,13 +1193,13 @@ sub mark_discovered($$) { # Updates the SNMP community cache on v1, v2 and v2c. ################################################################################ sub snmp_responds($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - return 1 if($self->is_snmp_discovered($device)); + return 1 if($self->is_snmp_discovered($device)); - return ($self->{'snmp_version'} eq "3") - ? $self->snmp_responds_v3($device) - : $self->snmp_responds_v122c($device); + return ($self->{'snmp_version'} eq "3") + ? $self->snmp_responds_v3($device) + : $self->snmp_responds_v122c($device); } ################################################################################ @@ -1204,23 +1207,23 @@ sub snmp_responds($$) { # found, 0 otherwise. Updates the SNMP community cache. ################################################################################ sub snmp_responds_v122c($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - foreach my $community (@{$self->{'communities'}}) { + foreach my $community (@{$self->{'communities'}}) { - # Clean blanks. - $community =~ s/\s+//g; + # Clean blanks. + $community =~ s/\s+//g; - my $command = $self->snmp_get_command($device, ".0", $community); - `$command`; - if ($? == 0) { - $self->set_community($device, $community); - $self->mark_discovered($device); - return 1; - } - } + my $command = $self->snmp_get_command($device, ".0", $community); + `$command`; + if ($? == 0) { + $self->set_community($device, $community); + $self->mark_discovered($device); + return 1; + } + } - return 0; + return 0; } @@ -1229,279 +1232,279 @@ sub snmp_responds_v122c($$) { # Returns 1 if successfull snmp contact, 0 otherwise. ################################################################################ sub snmp_responds_v3($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - my $command = $self->snmp_get_command($device, ".0"); - `$command`; + my $command = $self->snmp_get_command($device, ".0"); + `$command`; - if ($? == 0) { - $self->mark_discovered($device); - return 1; - } + if ($? == 0) { + $self->mark_discovered($device); + return 1; + } - return 0; + return 0; } ################################################################################ # Parse the local ARP cache. ################################################################################ sub local_arp($) { - my ($self) = @_; + my ($self) = @_; - 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); - } + 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); + } } ################################################################################ # Parse remote SNMP ARP caches. ################################################################################ sub remote_arp($$) { - my ($self, $device) = @_; + my ($self, $device) = @_; - # Try to learn more MAC addresses from the device's ARP cache. - my @output = $self->snmp_get($device, $IPNETTOMEDIAPHYSADDRESS); - foreach my $line (@output) { - next unless ($line =~ /^$IPNETTOMEDIAPHYSADDRESS\.\d+\.(\S+)\s+=\s+\S+:\s+(.*)$/); - my ($ip_addr, $mac_addr) = ($1, $2); + # Try to learn more MAC addresses from the device's ARP cache. + my @output = $self->snmp_get($device, $IPNETTOMEDIAPHYSADDRESS); + foreach my $line (@output) { + next unless ($line =~ /^$IPNETTOMEDIAPHYSADDRESS\.\d+\.(\S+)\s+=\s+\S+:\s+(.*)$/); + my ($ip_addr, $mac_addr) = ($1, $2); - # Skip broadcast, net and local addresses. - next if ($ip_addr =~ m/\.255$|\.0$|127\.0\.0\.1$/); + # Skip broadcast, net and local addresses. + next if ($ip_addr =~ m/\.255$|\.0$|127\.0\.0\.1$/); - $mac_addr = parse_mac($mac_addr); - $self->add_mac($mac_addr, $ip_addr); - $self->call('message', "Found MAC $mac_addr for host $ip_addr in the ARP cache of host $device.", 5); - } + $mac_addr = parse_mac($mac_addr); + $self->add_mac($mac_addr, $ip_addr); + $self->call('message', "Found MAC $mac_addr for host $ip_addr in the ARP cache of host $device.", 5); + } - # Look in atPhysAddress for MAC addresses too. - @output = $self->snmp_get($device, $ATPHYSADDRESS); - foreach my $line (@output) { - next unless ($line =~ m/^$ATPHYSADDRESS\.\d+\.\d+\.(\S+)\s+=\s+\S+:\s+(.*)$/); - my ($ip_addr, $mac_addr) = ($1, $2); + # Look in atPhysAddress for MAC addresses too. + @output = $self->snmp_get($device, $ATPHYSADDRESS); + foreach my $line (@output) { + next unless ($line =~ m/^$ATPHYSADDRESS\.\d+\.\d+\.(\S+)\s+=\s+\S+:\s+(.*)$/); + my ($ip_addr, $mac_addr) = ($1, $2); - # Skip broadcast, net and local addresses. - next if ($ip_addr =~ m/\.255$|\.0$|127\.0\.0\.1$/); + # Skip broadcast, net and local addresses. + next if ($ip_addr =~ m/\.255$|\.0$|127\.0\.0\.1$/); - $mac_addr = parse_mac($mac_addr); - $self->add_mac($mac_addr, $ip_addr); - $self->call('message', "Found MAC $mac_addr for host $ip_addr in the ARP cache (atPhysAddress) of host $device.", 5); - } + $mac_addr = parse_mac($mac_addr); + $self->add_mac($mac_addr, $ip_addr); + $self->call('message', "Found MAC $mac_addr for host $ip_addr in the ARP cache (atPhysAddress) of host $device.", 5); + } } ################################################################################ # Add agent to pool (will be registered at the end of the scan). ################################################################################ sub prepare_agent($$) { - my ($self, $addr) = @_; - $self->{'agents_found'} = {} if ref($self->{'agents_found'}) ne 'HASH'; + my ($self, $addr) = @_; + $self->{'agents_found'} = {} if ref($self->{'agents_found'}) ne 'HASH'; - # Already initialized. - return if ref($self->{'agents_found'}->{$addr}) eq 'HASH'; + # Already initialized. + return if ref($self->{'agents_found'}->{$addr}) eq 'HASH'; - $self->{'agents_found'}->{$addr} = { - 'agent' => { - 'nombre' => $addr, - 'direccion' => $addr, - 'alias' => $addr, - }, - 'pen' => $self->{'pen'}{$addr}, - 'modules' => [], - }; + $self->{'agents_found'}->{$addr} = { + 'agent' => { + 'nombre' => $addr, + 'direccion' => $addr, + 'alias' => $addr, + }, + 'pen' => $self->{'pen'}{$addr}, + 'modules' => [], + }; } ################################################################################ # Add agent to pool (will be registered at the end of the scan). ################################################################################ sub add_agent($$) { - my ($self, $addr) = @_; - - $self->prepare_agent($addr); + my ($self, $addr) = @_; + + $self->prepare_agent($addr); } ################################################################################ # Add module to agent (tmp pool) (will be registered at the end of the scan). ################################################################################ sub add_module($$$$) { - my ($self, $agent, $type, $data) = @_; + my ($self, $agent, $type, $data) = @_; - $self->prepare_agent($agent); + $self->prepare_agent($agent); - push @{$self->{'agents_found'}->{$agent}->{'modules'}}, $data; - + push @{$self->{'agents_found'}->{$agent}->{'modules'}}, $data; + } ################################################################################ # Test target address (methods). ################################################################################ sub test_capabilities($$) { - my ($self, $addr) = @_; + my ($self, $addr) = @_; - $self->icmp_discovery($addr); + $self->icmp_discovery($addr); - if (is_enabled($self->{'snmp_enabled'})) { - # SNMP discovery. - $self->snmp_discovery($addr); - } + if (is_enabled($self->{'snmp_enabled'})) { + # SNMP discovery. + $self->snmp_discovery($addr); + } - # WMI discovery. - if (is_enabled($self->{'wmi_enabled'})) { - # Add wmi scan if enabled. - $self->wmi_scan($addr); - } + # WMI discovery. + if (is_enabled($self->{'wmi_enabled'})) { + # Add wmi scan if enabled. + $self->wmi_scan($addr); + } } ################################################################################ # Scan the given subnet. ################################################################################ sub scan_subnet($) { - my ($self) = @_; - my $progress = 1; + my ($self) = @_; + my $progress = 1; - my @subnets = @{$self->get_subnets()}; - foreach my $subnet (@subnets) { - $self->{'c_network_percent'} = 0; - $self->{'c_network_name'} = $subnet; - $self->call('update_progress', ceil($progress)); + my @subnets = @{$self->get_subnets()}; + foreach my $subnet (@subnets) { + $self->{'c_network_percent'} = 0; + $self->{'c_network_name'} = $subnet; + $self->call('update_progress', ceil($progress)); - # Clean blanks. - $subnet =~ s/\s+//g; + # Clean blanks. + $subnet =~ s/\s+//g; - my $net_addr = new NetAddr::IP($subnet); - if (!defined($net_addr)) { - $self->call('message', "Invalid network: $subnet", 3); - next; - } + my $net_addr = new NetAddr::IP($subnet); + if (!defined($net_addr)) { + $self->call('message', "Invalid network: $subnet", 3); + next; + } - # Save the network and broadcast addresses. - my $network = $net_addr->network(); - my $broadcast = $net_addr->broadcast(); + # Save the network and broadcast addresses. + my $network = $net_addr->network(); + my $broadcast = $net_addr->broadcast(); - my @hosts = map { (split('/', $_))[0] } $net_addr->hostenum; - my $total_hosts = scalar(@hosts); - my %hosts_alive = (); + my @hosts = map { (split('/', $_))[0] } $net_addr->hostenum; + my $total_hosts = scalar(@hosts); + my %hosts_alive = (); - # By default 200, (20 * 10) - my $host_block_size = $self->{'block_size'}; + # By default 200, (20 * 10) + my $host_block_size = $self->{'block_size'}; - # The first 50% of the recon task approx. - my $step = 40.0 / scalar(@subnets) / (($total_hosts / $host_block_size)+1); - my $subnet_step = 50.0 / (($total_hosts / $host_block_size)+1); + # The first 50% of the recon task approx. + my $step = 40.0 / scalar(@subnets) / (($total_hosts / $host_block_size)+1); + my $subnet_step = 50.0 / (($total_hosts / $host_block_size)+1); - for (my $block_index=0; - $block_index < $total_hosts; - $block_index += $host_block_size - ) { - # Update the recon task - # Increase self summary.alive hosts. - $self->call('message', "Searching for hosts (".$block_index." / ".$total_hosts.")", 5); - my $to = $host_block_size + $block_index; - $to = $total_hosts if $to >= $total_hosts; + for (my $block_index=0; + $block_index < $total_hosts; + $block_index += $host_block_size + ) { + # Update the recon task + # Increase self summary.alive hosts. + $self->call('message', "Searching for hosts (".$block_index." / ".$total_hosts.")", 5); + my $to = $host_block_size + $block_index; + $to = $total_hosts if $to >= $total_hosts; - my $c_block_size = $to - $block_index; - my @block = pandora_block_ping( - { - 'fping' => $self->{'fping'}, - # XXX CAMBIAR POR 0.5 - 'networktimeout' => 0.01 # use fping defaults - }, - @hosts[$block_index .. $to - 1] - ); + my $c_block_size = $to - $block_index; + my @block = pandora_block_ping( + { + 'fping' => $self->{'fping'}, + # XXX CAMBIAR POR 0.5 + 'networktimeout' => 0.01 # use fping defaults + }, + @hosts[$block_index .. $to - 1] + ); - # check alive hosts in current block - %hosts_alive = ( - %hosts_alive, - map {chomp; $_ => 1} @block - ); + # check alive hosts in current block + %hosts_alive = ( + %hosts_alive, + map {chomp; $_ => 1} @block + ); - $self->{'summary'}->{'not_alive'} += $c_block_size - (scalar @block); - $self->{'summary'}->{'alive'} += scalar @block; + $self->{'summary'}->{'not_alive'} += $c_block_size - (scalar @block); + $self->{'summary'}->{'alive'} += scalar @block; - # Update progress. - $progress += $step; - $self->{'c_network_percent'} += $subnet_step; + # Update progress. + $progress += $step; + $self->{'c_network_percent'} += $subnet_step; - # Populate. - $self->call('update_progress', ceil($progress)); - } + # Populate. + $self->call('update_progress', ceil($progress)); + } - # Update progress. - $self->call('message', "Searching for hosts (".$total_hosts." / ".$total_hosts.")", 5); - $progress = ceil($progress); - $self->{'c_network_percent'} = 50; + # Update progress. + $self->call('message', "Searching for hosts (".$total_hosts." / ".$total_hosts.")", 5); + $progress = ceil($progress); + $self->{'c_network_percent'} = 50; - # Populate. - $self->call('update_progress', ceil($progress)); + # Populate. + $self->call('update_progress', ceil($progress)); - $total_hosts = scalar keys %hosts_alive; - $step = 40.0 / scalar(@subnets) / $total_hosts; - $subnet_step = 50.0 / $total_hosts; - foreach my $addr (keys %hosts_alive) { - # Increase self summary.alive hosts. - $self->call('message', "Scanning host: $addr", 5); + $total_hosts = scalar keys %hosts_alive; + $step = 40.0 / scalar(@subnets) / $total_hosts; + $subnet_step = 50.0 / $total_hosts; + foreach my $addr (keys %hosts_alive) { + # Increase self summary.alive hosts. + $self->call('message', "Scanning host: $addr", 5); - # Update progress. - $progress += $step; - $self->{'c_network_percent'} += $subnet_step; + # Update progress. + $progress += $step; + $self->{'c_network_percent'} += $subnet_step; - # Populate. - $self->call('update_progress', ceil($progress)); + # Populate. + $self->call('update_progress', ceil($progress)); - # Enable/ disable capabilities. - $self->test_capabilities($addr); - } - } + # Enable/ disable capabilities. + $self->test_capabilities($addr); + } + } } ################################################################################ # Perform a Cloud scan ################################################################################ sub cloud_scan($) { - my $self = shift; - my ($progress, $step); + my $self = shift; + my ($progress, $step); - my $type = ''; + my $type = ''; - if ( $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_EC2 - || $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) { - $type = 'Aws'; - } else { + if ( $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_EC2 + || $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) { + $type = 'Aws'; + } else { - # Unrecognized task type. - $self->call('message', 'Unrecognized task type', 1); - $self->call('update_progress', -1); - return; - } + # Unrecognized task type. + $self->call('message', 'Unrecognized task type', 1); + $self->call('update_progress', -1); + return; + } - # Initialize cloud object. - my $cloudObj = PandoraFMS::Recon::Util::enterprise_new( - 'PandoraFMS::Recon::Cloud::'.$type, - [ - task_data => $self->{'task_data'}, - aws_access_key_id => $self->{'aws_access_key_id'}, - aws_secret_access_key => $self->{'aws_secret_access_key'}, - cloud_util_path => $self->{'cloud_util_path'}, - creds_file => $self->{'creds_file'}, - parent => $self - ] + # Initialize cloud object. + my $cloudObj = PandoraFMS::Recon::Util::enterprise_new( + 'PandoraFMS::Recon::Cloud::'.$type, + [ + task_data => $self->{'task_data'}, + aws_access_key_id => $self->{'aws_access_key_id'}, + aws_secret_access_key => $self->{'aws_secret_access_key'}, + cloud_util_path => $self->{'cloud_util_path'}, + creds_file => $self->{'creds_file'}, + parent => $self + ] - ); + ); - if (!$cloudObj) { + if (!$cloudObj) { - # Failed to initialize, check Cloud credentials or anything. - $self->call('message', 'Unable to initialize PandoraFMS::Recon::Cloud::'.$type, 3); - } else { + # Failed to initialize, check Cloud credentials or anything. + $self->call('message', 'Unable to initialize PandoraFMS::Recon::Cloud::'.$type, 3); + } else { - # Let Cloud object manage scan. - $cloudObj->scan(); - } + # Let Cloud object manage scan. + $cloudObj->scan(); + } - # Update progress. - # Done! - $self->{'step'} = ''; - $self->call('update_progress', -1); + # Update progress. + # Done! + $self->{'step'} = ''; + $self->call('update_progress', -1); } @@ -1509,78 +1512,78 @@ sub cloud_scan($) { # Performs a database scan. ################################################################################ sub database_scan($$$) { - my ($self, $type, $obj, $global_percent, $targets) = @_; + my ($self, $type, $obj, $global_percent, $targets) = @_; - my @data; - my @modules; + my @data; + my @modules; - my $dbObjCfg = $obj->get_config(); + my $dbObjCfg = $obj->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'} = $obj->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'} = $obj->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, $obj->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, $obj->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, $obj->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, $obj->execute_custom_queries(); - if (defined($dbObjCfg->{'scan_databases'}) - && "$dbObjCfg->{'scan_databases'}" eq "1") { + if (defined($dbObjCfg->{'scan_databases'}) + && "$dbObjCfg->{'scan_databases'}" eq "1") { - # Skip database scan in Oracle tasks - next if defined($self->{'type'}) && $self->{'type'} == DISCOVERY_APP_ORACLE; + # Skip database scan in Oracle tasks + next if defined($self->{'type'}) && $self->{'type'} == DISCOVERY_APP_ORACLE; - my $__data = $obj->scan_databases(); + my $__data = $obj->scan_databases(); - if (ref($__data) eq "ARRAY") { - if (defined($dbObjCfg->{'agent_per_database'}) - && $dbObjCfg->{'agent_per_database'} == 1) { + if (ref($__data) eq "ARRAY") { + if (defined($dbObjCfg->{'agent_per_database'}) + && $dbObjCfg->{'agent_per_database'} == 1) { - # Agent per database detected. - push @data, @{$__data}; + # Agent per database detected. + push @data, @{$__data}; - } else { + } else { - # Merge modules into engine agent. - my @_modules = map { - map { $_ } - @{$_->{'module_data'}} - } @{$__data}; + # Merge modules into engine agent. + my @_modules = map { + map { $_ } + @{$_->{'module_data'}} + } @{$__data}; - push @modules, @_modules; - } - } - } + push @modules, @_modules; + } + } + } - return { - 'modules' => \@modules, - 'data' => \@data - }; + return { + 'modules' => \@modules, + 'data' => \@data + }; } @@ -1588,153 +1591,153 @@ sub database_scan($$$) { # Perform an Application scan. ################################################################################ sub app_scan($) { - my ($self) = @_; - my ($progress, $step); + my ($self) = @_; + my ($progress, $step); - my $type = ''; - my $db_scan = 0; + my $type = ''; + my $db_scan = 0; - # APP object initialization. - if ($self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL) { - $type = 'MySQL'; - } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE) { - $type = 'Oracle'; - } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) { - $type = 'SAP'; - } else { - # Unrecognized task type. - $self->call('message', 'Unrecognized task type', 1); - $self->call('update_progress', -1); - return; - } + # APP object initialization. + if ($self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL) { + $type = 'MySQL'; + } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE) { + $type = 'Oracle'; + } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) { + $type = 'SAP'; + } else { + # Unrecognized task type. + $self->call('message', 'Unrecognized task type', 1); + $self->call('update_progress', -1); + return; + } - my @targets = split /,/, $self->{'task_data'}->{'subnet'}; + my @targets = split /,/, $self->{'task_data'}->{'subnet'}; - my $global_step = 100 / (scalar @targets); - my $global_percent = 0; - my $i = 0; - foreach my $target (@targets) { - if ( !defined($target) - || $target eq '' - || $target =~ /^#/) { - # Ignore empty target or commented one. - next; - } + my $global_step = 100 / (scalar @targets); + my $global_percent = 0; + my $i = 0; + foreach my $target (@targets) { + if ( !defined($target) + || $target eq '' + || $target =~ /^#/) { + # Ignore empty target or commented one. + next; + } - my @data; - my @modules; + my @data; + my @modules; - $self->{'step'} = STEP_APP_SCAN; - $self->{'c_network_name'} = $target; - $self->{'c_network_percent'} = 0; + $self->{'step'} = STEP_APP_SCAN; + $self->{'c_network_name'} = $target; + $self->{'c_network_percent'} = 0; - # Send message - $self->call('message', 'Checking target ' . $target, 10); + # Send message + $self->call('message', 'Checking target ' . $target, 10); - # Force target acquirement. - $self->{'task_data'}->{'dbhost'} = $target; - $self->{'task_data'}->{'target_index'} = $i++; + # Force target acquirement. + $self->{'task_data'}->{'dbhost'} = $target; + $self->{'task_data'}->{'target_index'} = $i++; - # Update progress - $self->{'c_network_percent'} = 10; - $self->call('update_progress', $global_percent + (10 / (scalar @targets))); + # Update progress + $self->{'c_network_percent'} = 10; + $self->call('update_progress', $global_percent + (10 / (scalar @targets))); - # Connect to target. - my $obj = PandoraFMS::Recon::Util::enterprise_new( - 'PandoraFMS::Recon::Applications::'.$type, - { - %{$self->{'task_data'}}, - 'target' => $target, - 'pa_config' => $self->{'pa_config'}, - 'parent' => $self - }, - ); + # Connect to target. + my $obj = PandoraFMS::Recon::Util::enterprise_new( + 'PandoraFMS::Recon::Applications::'.$type, + { + %{$self->{'task_data'}}, + 'target' => $target, + 'pa_config' => $self->{'pa_config'}, + 'parent' => $self + }, + ); - if (defined($obj)) { + if (defined($obj)) { - # Verify if object is connected. If cannot connect to current target - # return with module. - if (!$obj->is_connected()) { - $self->call('message', 'Cannot connect to target ' . $target, 3); - $global_percent += $global_step; - $self->{'c_network_percent'} = 90; + # Verify if object is connected. If cannot connect to current target + # return with module. + if (!$obj->is_connected()) { + $self->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' - }; + # 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 { - # - # $results is always a hash with: - # @modules => 'global' modules. - # @data => { - # 'agent_data' => {} - # 'module_data' => [] - # } - my $results; + } else { + # + # $results is always a hash with: + # @modules => 'global' modules. + # @data => { + # 'agent_data' => {} + # 'module_data' => [] + # } + my $results; - # Scan connected obj. - if ( $self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL - || $self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE) { + # Scan connected obj. + if ( $self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL + || $self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE) { - # Database. - $results = $self->database_scan($type, $obj, $global_percent, \@targets); + # Database. + $results = $self->database_scan($type, $obj, $global_percent, \@targets); - } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) { + } elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) { - # SAP scan - $results = $obj->scan(); + # SAP scan + $results = $obj->scan(); - } + } - # Add results. - if (ref($results) eq 'HASH') { - if (defined($results->{'modules'})) { - push @modules, @{$results->{'modules'}}; - } + # Add results. + if (ref($results) eq 'HASH') { + if (defined($results->{'modules'})) { + push @modules, @{$results->{'modules'}}; + } - if (defined($results->{'data'})) { - push @data, @{$results->{'data'}}; - } - } - } + if (defined($results->{'data'})) { + push @data, @{$results->{'data'}}; + } + } + } - # Put engine agent at the beginning of the list. - my $version = $obj->get_version(); - unshift @data, { - 'agent_data' => { - 'agent_name' => $obj->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' => $obj->get_host(), - 'description' => '', - }, - 'module_data' => \@modules, - }; + # Put engine agent at the beginning of the list. + my $version = $obj->get_version(); + unshift @data, { + 'agent_data' => { + 'agent_name' => $obj->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' => $obj->get_host(), + 'description' => '', + }, + 'module_data' => \@modules, + }; - $self->call('create_agents', \@data); + $self->call('create_agents', \@data); - # Destroy item. - undef($obj); - } + # Destroy item. + undef($obj); + } - $global_percent += $global_step; - $self->{'c_network_percent'} = 100; - $self->call('update_progress', $global_percent); - } + $global_percent += $global_step; + $self->{'c_network_percent'} = 100; + $self->call('update_progress', $global_percent); + } - # Update progress. - # Done! - $self->{'step'} = ''; - $self->call('update_progress', -1); + # Update progress. + # Done! + $self->{'step'} = ''; + $self->call('update_progress', -1); } @@ -1743,35 +1746,35 @@ sub app_scan($) { # Perform a deployment scan. ################################################################################ sub deploy_scan($) { - my $self = shift; - my ($progress, $step); + my $self = shift; + my ($progress, $step); - my $type = ''; + my $type = ''; - # Initialize deployer object. - my $deployer = PandoraFMS::Recon::Util::enterprise_new( - 'PandoraFMS::Recon::Deployer', - [ - task_data => $self->{'task_data'}, - parent => $self - ] + # Initialize deployer object. + my $deployer = PandoraFMS::Recon::Util::enterprise_new( + 'PandoraFMS::Recon::Deployer', + [ + task_data => $self->{'task_data'}, + parent => $self + ] - ); + ); - if (!$deployer) { + if (!$deployer) { - # Failed to initialize, check Cloud credentials or anything. - $self->call('message', 'Unable to initialize PandoraFMS::Recon::Deployer', 3); - } else { + # Failed to initialize, check Cloud credentials or anything. + $self->call('message', 'Unable to initialize PandoraFMS::Recon::Deployer', 3); + } else { - # Let deployer object manage scan. - $deployer->scan(); - } + # Let deployer object manage scan. + $deployer->scan(); + } - # Update progress. - # Done! - $self->{'step'} = ''; - $self->call('update_progress', -1); + # Update progress. + # Done! + $self->{'step'} = ''; + $self->call('update_progress', -1); } @@ -1779,111 +1782,113 @@ sub deploy_scan($) { # Perform a network scan. ################################################################################ sub scan($) { - my ($self) = @_; - my ($progress, $step) = 1, 0; + my ($self) = @_; + my ($progress, $step) = 1, 0; - # 1% - $self->call('update_progress', 1); + # 1% + $self->call('update_progress', 1); - if (defined($self->{'task_data'})) { - if ( $self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL - || $self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE - || $self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) { - # Application scan. - $self->call('message', "Scanning application ...", 6); - return $self->app_scan(); - } + if (defined($self->{'task_data'})) { + if ( $self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL + || $self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE + || $self->{'task_data'}->{'type'} == DISCOVERY_APP_SAP) { + # Application scan. + $self->call('message', "Scanning application ...", 6); + return $self->app_scan(); + } - if ($self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) { + if ($self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) { - # Cloud scan. - return $self->cloud_scan(); - } + # Cloud scan. + return $self->cloud_scan(); + } - if($self->{'task_data'}->{'type'} == DISCOVERY_DEPLOY_AGENTS) { - return $self->deploy_scan(); - } - } + if($self->{'task_data'}->{'type'} == DISCOVERY_DEPLOY_AGENTS) { + return $self->deploy_scan(); + } + } + # XXX + print "Metodo: ".$self->{'task_data'}{'direct_report'}."\n"; + + if(defined($self->{'task_data'}{'direct_report'}) + && $self->{'task_data'}{'direct_report'} == DISCOVERY_RESULTS + ) { + # Use Cached results. + return $self->call('report_scanned_agents'); + } - if(defined($self->{'task_data'}{'direct_report'}) - && $self->{'task_data'}{'direct_report'} eq "2" - ) { - # Use Cached results. - return $self->call('report_scanned_agents'); - } + # Find devices. + $self->call('message', "[1/4] Scanning the network...", 3); + $self->{'step'} = STEP_SCANNING; + $self->call('update_progress', $progress); - # Find devices. - $self->call('message', "[1/4] Scanning the network...", 3); - $self->{'step'} = STEP_SCANNING; - $self->call('update_progress', $progress); + $self->scan_subnet(); + # Read the local ARP cache. + $self->local_arp(); - $self->scan_subnet(); - # Read the local ARP cache. - $self->local_arp(); + # Get a list of found hosts. + my @hosts = @{$self->get_hosts()}; + if (scalar(@hosts) > 0 && $self->{'parent_detection'} == 1) { - # Get a list of found hosts. - my @hosts = @{$self->get_hosts()}; - if (scalar(@hosts) > 0 && $self->{'parent_detection'} == 1) { + # Delete previous connections. + $self->call('delete_connections'); - # Delete previous connections. - $self->call('delete_connections'); + # Connectivity from address forwarding tables. + $self->call('message', "[2/4] Finding address forwarding table connectivity...", 3); + $self->{'step'} = STEP_AFT; + ($progress, $step) = (80, 8.0 / scalar(@hosts)); # From 50% to 70%. + for (my $i = 0; defined($hosts[$i]); $i++) { + $self->call('update_progress', $progress); + $progress += $step; + $self->aft_connectivity($hosts[$i]); + } - # Connectivity from address forwarding tables. - $self->call('message', "[2/4] Finding address forwarding table connectivity...", 3); - $self->{'step'} = STEP_AFT; - ($progress, $step) = (80, 8.0 / scalar(@hosts)); # From 50% to 70%. - for (my $i = 0; defined($hosts[$i]); $i++) { - $self->call('update_progress', $progress); - $progress += $step; - $self->aft_connectivity($hosts[$i]); - } + # Connect hosts that are still unconnected using traceroute. + $self->call('message', "[3/4] Finding traceroute connectivity.", 3); + $self->{'step'} = STEP_TRACEROUTE; + ($progress, $step) = (88, 8.0 / scalar(@hosts)); # From 70% to 90%. + foreach my $host (@hosts) { + $self->call('update_progress', $progress); + $progress += $step; + next if ($self->has_parent($host) || $self->has_children($host)); + $self->traceroute_connectivity($host); + } - # Connect hosts that are still unconnected using traceroute. - $self->call('message', "[3/4] Finding traceroute connectivity.", 3); - $self->{'step'} = STEP_TRACEROUTE; - ($progress, $step) = (88, 8.0 / scalar(@hosts)); # From 70% to 90%. - foreach my $host (@hosts) { - $self->call('update_progress', $progress); - $progress += $step; - next if ($self->has_parent($host) || $self->has_children($host)); - $self->traceroute_connectivity($host); - } + # Connect hosts that are still unconnected using known gateways. + $self->call('message', "[4/4] Finding host to gateway connectivity.", 3); + $self->{'step'} = STEP_GATEWAY; + ($progress, $step) = (94, 6.0 / scalar(@hosts)); # From 70% to 90%. + $self->get_routes(); # Update the route cache. + foreach my $host (@hosts) { + $self->call('update_progress', $progress); + $progress += $step; + next if ($self->has_parent($host)); + $self->gateway_connectivity($host); + } + } - # Connect hosts that are still unconnected using known gateways. - $self->call('message', "[4/4] Finding host to gateway connectivity.", 3); - $self->{'step'} = STEP_GATEWAY; - ($progress, $step) = (94, 6.0 / scalar(@hosts)); # From 70% to 90%. - $self->get_routes(); # Update the route cache. - foreach my $host (@hosts) { - $self->call('update_progress', $progress); - $progress += $step; - next if ($self->has_parent($host)); - $self->gateway_connectivity($host); - } - } + # Done! + $self->{'step'} = ''; + $self->call('update_progress', -1); - # Done! - $self->{'step'} = ''; - $self->call('update_progress', -1); + # Print debug information on found devices. + $self->call('message', "[Summary]", 3); + foreach my $host (@hosts) { + my $device = $self->get_device($host); + next unless defined($device); - # Print debug information on found devices. - $self->call('message', "[Summary]", 3); - foreach my $host (@hosts) { - my $device = $self->get_device($host); - next unless defined($device); + # Print device information. + my $dev_info = "Device: " . $device->{'type'} . " ("; + foreach my $ip_address ($self->get_addresses($host)) { + $dev_info .= "$ip_address,"; + } + chop($dev_info); + $dev_info .= ')'; + $self->call('message', $dev_info, 3); + } - # Print device information. - my $dev_info = "Device: " . $device->{'type'} . " ("; - foreach my $ip_address ($self->get_addresses($host)) { - $dev_info .= "$ip_address,"; - } - chop($dev_info); - $dev_info .= ')'; - $self->call('message', $dev_info, 3); - } - - # Send agent information to Database (Discovery) or XML (satellite.). - $self->call('report_scanned_agents', $self->{'agents_found'}); + # Send agent information to Database (Discovery) or XML (satellite.). + $self->call('report_scanned_agents', $self->{'agents_found'}); } @@ -1891,33 +1896,33 @@ sub scan($) { # Set an SNMP community for the given device. ################################################################################ sub set_community($$$) { - my ($self, $device, $community) = @_; + my ($self, $device, $community) = @_; - $self->{'community_cache'}->{$device} = $community; + $self->{'community_cache'}->{$device} = $community; } ################################################################################ # Set the type of the given device. ################################################################################ sub set_device_type($$$) { - my ($self, $device, $type) = @_; + my ($self, $device, $type) = @_; - $self->{'visited_devices'}->{$device}->{'type'} = $type; + $self->{'visited_devices'}->{$device}->{'type'} = $type; } ################################################################################ # Calculate ################################################################################ sub snmp_pen($$) { - my ($self, $addr) = @_; + my ($self, $addr) = @_; - $self->{'pen'} = {} if ref($self->{'pen'}) ne 'HASH'; + $self->{'pen'} = {} if ref($self->{'pen'}) ne 'HASH'; - $self->{'pen'}{$addr} = $self->snmp_get($addr, $PEN_OID); + $self->{'pen'}{$addr} = $self->snmp_get($addr, $PEN_OID); - if(defined($self->{'pen'}{$addr})) { - ($self->{'pen'}{$addr}) = $self->{'pen'}{$addr} =~ /\.\d+\.\d+\.\d+\.\d+\.\d+\.\d+\.(\d+?)\./ - } + if(defined($self->{'pen'}{$addr})) { + ($self->{'pen'}{$addr}) = $self->{'pen'}{$addr} =~ /\.\d+\.\d+\.\d+\.\d+\.\d+\.\d+\.(\d+?)\./ + } } @@ -1925,65 +1930,65 @@ sub snmp_pen($$) { # Performs an SNMP WALK and returns the response as an array. ################################################################################ sub snmp_get($$$) { - my ($self, $device, $oid) = @_; - my @output; + my ($self, $device, $oid) = @_; + my @output; - return () unless defined $self->is_snmp_discovered($device); - my $community = $self->get_community($device); + return () unless defined $self->is_snmp_discovered($device); + my $community = $self->get_community($device); - # Check the SNMP query cache first. - if (defined($self->{'snmp_cache'}->{"${device}_${oid}"})) { - return @{$self->{'snmp_cache'}->{"${device}_${oid}"}}; - } + # Check the SNMP query cache first. + if (defined($self->{'snmp_cache'}->{"${device}_${oid}"})) { + return @{$self->{'snmp_cache'}->{"${device}_${oid}"}}; + } - # Check VLANS. - my @vlans = $self->get_vlans($device); - if (scalar(@vlans) == 0) { - my $command = $self->snmp_get_command($device, $oid, $community); - @output = `$command`; - }else { + # Check VLANS. + my @vlans = $self->get_vlans($device); + if (scalar(@vlans) == 0) { + my $command = $self->snmp_get_command($device, $oid, $community); + @output = `$command`; + }else { - # Handle duplicate lines. - my %output_hash; - foreach my $vlan (@vlans) { - my $command = $self->snmp_get_command($device, $oid, $community, $vlan); - foreach my $line (`$command`) { - $output_hash{$line} = 1; - } - } - push(@output, keys(%output_hash)); - } + # Handle duplicate lines. + my %output_hash; + foreach my $vlan (@vlans) { + my $command = $self->snmp_get_command($device, $oid, $community, $vlan); + foreach my $line (`$command`) { + $output_hash{$line} = 1; + } + } + push(@output, keys(%output_hash)); + } - # Update the SNMP query cache. - $self->{'snmp_cache'}->{"${device}_${oid}"} = [@output]; + # Update the SNMP query cache. + $self->{'snmp_cache'}->{"${device}_${oid}"} = [@output]; - return @output; + return @output; } ################################################################################ # Get the snmpwalk command seing version 1, 2, 2c or 3. ################################################################################ sub snmp_get_command { - my ($self, $device, $oid, $community, $vlan) = @_; - $vlan = defined($vlan) ? "\@" . $vlan : ''; + my ($self, $device, $oid, $community, $vlan) = @_; + $vlan = defined($vlan) ? "\@" . $vlan : ''; - 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'} "; - } - $command .= " -l$self->{'snmp_security_level'} "; - if ($self->{'snmp_security_level'} ne "noAuthNoPriv") { - $command .= " -u$self->{'snmp_auth_user'} -a$self->{'snmp_auth_method'} -A$self->{'snmp_auth_pass'} "; - } - if ($self->{'snmp_security_level'} eq "authPriv") { - $command .= " -x$self->{'snmp_privacy_method'} -X$self->{'snmp_privacy_pass'} "; - } - } else { - $command .= " -c$community$vlan "; - } + 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'} "; + } + $command .= " -l$self->{'snmp_security_level'} "; + if ($self->{'snmp_security_level'} ne "noAuthNoPriv") { + $command .= " -u$self->{'snmp_auth_user'} -a$self->{'snmp_auth_method'} -A$self->{'snmp_auth_pass'} "; + } + if ($self->{'snmp_security_level'} eq "authPriv") { + $command .= " -x$self->{'snmp_privacy_method'} -X$self->{'snmp_privacy_pass'} "; + } + } else { + $command .= " -c$community$vlan "; + } - return "$command $device $oid 2>$DEVNULL"; + return "$command $device $oid 2>$DEVNULL"; } @@ -1992,86 +1997,86 @@ sub snmp_get_command { # on error. ################################################################################ sub snmp_get_value($$$) { - my ($self, $device, $oid) = @_; + my ($self, $device, $oid) = @_; - my @output = $self->snmp_get($device, $oid); - foreach my $line (@output) { - chomp($line); - return $1 if ($line =~ /^$oid\s+=\s+\S+:\s+(.*)$/); - } + my @output = $self->snmp_get($device, $oid); + foreach my $line (@output) { + chomp($line); + return $1 if ($line =~ /^$oid\s+=\s+\S+:\s+(.*)$/); + } - return undef; + return undef; } ################################################################################ # Performs an SNMP WALK and returns an array of values. ################################################################################ sub snmp_get_value_array($$$) { - my ($self, $device, $oid) = @_; - my @values; + my ($self, $device, $oid) = @_; + my @values; - my @output = $self->snmp_get($device, $oid); - foreach my $line (@output) { - chomp($line); - push(@values, $1) if ($line =~ /^$oid\S*\s+=\s+\S+:\s+(.*)$/); - } + my @output = $self->snmp_get($device, $oid); + foreach my $line (@output) { + chomp($line); + push(@values, $1) if ($line =~ /^$oid\S*\s+=\s+\S+:\s+(.*)$/); + } - return @values; + return @values; } ################################################################################ # Performs an SNMP WALK and returns a hash of values. ################################################################################ sub snmp_get_value_hash($$$) { - my ($self, $device, $oid) = @_; - my %values; + my ($self, $device, $oid) = @_; + my %values; - my @output = $self->snmp_get_value_array($device, $oid); - foreach my $line (@output) { - $values{$line} = ''; - } + my @output = $self->snmp_get_value_array($device, $oid); + foreach my $line (@output) { + $values{$line} = ''; + } - return %values; + return %values; } ################################################################################ # Connect the given host to its parent using traceroute. ################################################################################ sub traceroute_connectivity($$) { - my ($self, $host) = @_; + my ($self, $host) = @_; - # Perform a traceroute. - my $nmap_args = '-nsP -PE --traceroute --max-retries '.$self->{'icmp_checks'}.' --host-timeout '.$self->{'icmp_timeout'}.'s -T'.$self->{'recon_timing_template'}; - my $np = PandoraFMS::Recon::NmapParser->new(); - eval {$np->parsescan($self->{'nmap'}, $nmap_args, ($host));}; - return if ($@); + # Perform a traceroute. + my $nmap_args = '-nsP -PE --traceroute --max-retries '.$self->{'icmp_checks'}.' --host-timeout '.$self->{'icmp_timeout'}.'s -T'.$self->{'recon_timing_template'}; + my $np = PandoraFMS::Recon::NmapParser->new(); + eval {$np->parsescan($self->{'nmap'}, $nmap_args, ($host));}; + return if ($@); - # Get hops to the host. - my ($h) = $np->all_hosts(); - return unless defined($h); - my @hops = $h->all_trace_hops(); + # Get hops to the host. + my ($h) = $np->all_hosts(); + return unless defined($h); + my @hops = $h->all_trace_hops(); - # Skip the target host. - pop(@hops); + # Skip the target host. + pop(@hops); - # Reverse the host order (closest hosts first). - @hops = reverse(@hops); + # Reverse the host order (closest hosts first). + @hops = reverse(@hops); - # Look for parents. - my $device = $host; - for (my $i = 0; $i < $self->{'parent_recursion'}; $i++) { - next unless defined($hops[$i]); - my $parent = $hops[$i]->ipaddr(); + # Look for parents. + my $device = $host; + for (my $i = 0; $i < $self->{'parent_recursion'}; $i++) { + next unless defined($hops[$i]); + my $parent = $hops[$i]->ipaddr(); - # Create an agent for the parent. - $self->add_agent($parent); + # Create an agent for the parent. + $self->add_agent($parent); - $self->call('message', "Host $device is one hop away from host $parent.", 5); - $self->mark_connected($parent, '', $device, ''); + $self->call('message', "Host $device is one hop away from host $parent.", 5); + $self->mark_connected($parent, '', $device, ''); - # Move on to the next hop. - $device = $parent; - } + # Move on to the next hop. + $device = $parent; + } } ################################################################################ @@ -2079,94 +2084,94 @@ sub traceroute_connectivity($$) { # undef if it does not respond to WMI. ################################################################################ sub responds_to_wmi { - my ($self, $target) = @_; + my ($self, $target) = @_; - foreach my $auth (@{$self->{'auth_strings_array'}}) { - my @output; - if ($auth ne '') { - @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -U $auth //$target "SELECT * FROM Win32_ComputerSystem" 2>&1`; - } else { - @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -N //$target "SELECT * FROM Win32_ComputerSystem" 2>&1`; - } + foreach my $auth (@{$self->{'auth_strings_array'}}) { + my @output; + if ($auth ne '') { + @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -U $auth //$target "SELECT * FROM Win32_ComputerSystem" 2>&1`; + } else { + @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -N //$target "SELECT * FROM Win32_ComputerSystem" 2>&1`; + } - foreach my $line (@output) { - chomp($line); - return $auth if ($line =~ m/^CLASS: Win32_ComputerSystem$/); - } - } + foreach my $line (@output) { + chomp($line); + return $auth if ($line =~ m/^CLASS: Win32_ComputerSystem$/); + } + } - return undef; + return undef; } ################################################################################ # Add wmi modules to the given host. ################################################################################ sub wmi_scan { - my ($self, $target) = @_; + my ($self, $target) = @_; - $self->call('message', "[".$target."] Checking WMI.", 5); + $self->call('message', "[".$target."] Checking WMI.", 5); - my $auth = $self->responds_to_wmi($target); - return unless defined($auth); + my $auth = $self->responds_to_wmi($target); + return unless defined($auth); - $self->{'summary'}->{'WMI'} += 1; + $self->{'summary'}->{'WMI'} += 1; - $self->call('message', "[".$target."] WMI available.", 10); + $self->call('message', "[".$target."] WMI available.", 10); - # Register agent. - $self->add_agent($target); + # Register agent. + $self->add_agent($target); - # Add modules. - # CPU. - my @cpus = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceId FROM Win32_Processor', 0); - foreach my $cpu (@cpus) { - $self->add_module($target, 'wmi', - { - 'target' => $target, - 'query' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId='$cpu'", - 'auth' => $auth, - 'column' => 1, - 'name' => "CPU Load $cpu", - 'description' => "Load for $cpu (%)", - 'type' => 'generic_data', - 'unit' => '%', - } - ); - } + # Add modules. + # CPU. + my @cpus = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceId FROM Win32_Processor', 0); + foreach my $cpu (@cpus) { + $self->add_module($target, 'wmi', + { + 'target' => $target, + 'query' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId='$cpu'", + 'auth' => $auth, + 'column' => 1, + 'name' => "CPU Load $cpu", + 'description' => "Load for $cpu (%)", + 'type' => 'generic_data', + 'unit' => '%', + } + ); + } - # Memory. - my $mem = $self->wmi_get_value($target, $auth, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0); - if (defined($mem)) { - $self->add_module($target, 'wmi', - { - 'target' => $target, - 'query' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem", - 'auth' => $auth, - 'column' => 0, - 'name' => 'FreeMemory', - 'description' => 'Free memory', - 'type' => 'generic_data', - 'unit' => 'KB', - } - ); - } + # Memory. + my $mem = $self->wmi_get_value($target, $auth, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0); + if (defined($mem)) { + $self->add_module($target, 'wmi', + { + 'target' => $target, + 'query' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem", + 'auth' => $auth, + 'column' => 0, + 'name' => 'FreeMemory', + 'description' => 'Free memory', + 'type' => 'generic_data', + 'unit' => 'KB', + } + ); + } - # Disk. - my @units = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceID FROM Win32_LogicalDisk', 0); - foreach my $unit (@units) { - $self->add_module($target, 'wmi', - { - 'target' => $target, - 'query' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'", - 'auth' => $auth, - 'column' => 1, - 'name' => "FreeDisk $unit", - 'description' => 'Available disk space in kilobytes', - 'type' => 'generic_data', - 'unit' => 'KB', - } - ); - } + # Disk. + my @units = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceID FROM Win32_LogicalDisk', 0); + foreach my $unit (@units) { + $self->add_module($target, 'wmi', + { + 'target' => $target, + 'query' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'", + 'auth' => $auth, + 'column' => 1, + 'name' => "FreeDisk $unit", + 'description' => 'Available disk space in kilobytes', + 'type' => 'generic_data', + 'unit' => 'KB', + } + ); + } } @@ -2178,19 +2183,19 @@ sub wmi_scan { # Performs a wmi get requests and returns the response as an array. ################################################################################ sub wmi_get { - my ($self, $target, $auth, $query) = @_; + my ($self, $target, $auth, $query) = @_; - my @output; - if (defined($auth) && $auth ne '') { - @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -U $auth //$target "$query" 2>&1`; - }else { - @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -N //$target "$query" 2>&1`; - } + my @output; + if (defined($auth) && $auth ne '') { + @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -U $auth //$target "$query" 2>&1`; + }else { + @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -N //$target "$query" 2>&1`; + } - # Something went wrong. - return () if ($? != 0); + # Something went wrong. + return () if ($? != 0); - return @output; + return @output; } ################################################################################ @@ -2198,18 +2203,18 @@ sub wmi_get { # Returns undef on error. ################################################################################ sub wmi_get_value { - my ($self, $target, $auth, $query, $column) = @_; - my @result; + my ($self, $target, $auth, $query, $column) = @_; + my @result; - my @output = $self->wmi_get($target, $auth, $query); - return undef unless defined($output[2]); + my @output = $self->wmi_get($target, $auth, $query); + return undef unless defined($output[2]); - my $line = $output[2]; - chomp($line); - my @columns = split(/\|/, $line); - return undef unless defined($columns[$column]); + my $line = $output[2]; + chomp($line); + my @columns = split(/\|/, $line); + return undef unless defined($columns[$column]); - return $columns[$column]; + return $columns[$column]; } ################################################################################ @@ -2217,19 +2222,19 @@ sub wmi_get_value { # in an array. ################################################################################ sub wmi_get_value_array { - my ($self, $target, $auth, $query, $column) = @_; - my @result; + my ($self, $target, $auth, $query, $column) = @_; + my @result; - my @output = $self->wmi_get($target, $auth, $query); - foreach (my $i = 2; defined($output[$i]); $i++) { - my $line = $output[$i]; - chomp($line); - my @columns = split(/\|/, $line); - next unless defined($columns[$column]); - push(@result, $columns[$column]); - } + my @output = $self->wmi_get($target, $auth, $query); + foreach (my $i = 2; defined($output[$i]); $i++) { + my $line = $output[$i]; + chomp($line); + my @columns = split(/\|/, $line); + next unless defined($columns[$column]); + push(@result, $columns[$column]); + } - return @result; + return @result; } ################################################################################ From f58276ddbbd65a0a837df464ade6cd49cdb39fb0 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Wed, 18 Mar 2020 19:31:58 +0100 Subject: [PATCH 011/111] Templates --- pandora_console/extras/mr/37.sql | 2 +- .../pandoradb_migrate_6.0_to_7.0.mysql.sql | 2 +- .../wizards/DiscoveryTaskList.class.php | 228 +++++++++------- pandora_console/include/class/HTML.class.php | 1 + pandora_console/pandoradb.sql | 2 +- pandora_server/lib/PandoraFMS/Core.pm | 2 +- .../lib/PandoraFMS/DiscoveryServer.pm | 253 +++++++++++++++--- pandora_server/lib/PandoraFMS/Recon/Base.pm | 45 ++-- 8 files changed, 379 insertions(+), 156 deletions(-) diff --git a/pandora_console/extras/mr/37.sql b/pandora_console/extras/mr/37.sql index 50b4c04306..118114755a 100644 --- a/pandora_console/extras/mr/37.sql +++ b/pandora_console/extras/mr/37.sql @@ -10,7 +10,7 @@ CREATE TABLE `tdiscovery_tmp_agents` ( `label` varchar(600) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `data` text, `review_date` datetime DEFAULT NULL, - `created` int(1) unsigned NOT NULL DEFAULT '0', + `created` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `id_rt` (`id_rt`), INDEX `label` (`label`), diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index de53643ec9..d591d50fd1 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -1672,7 +1672,7 @@ CREATE TABLE `tdiscovery_tmp_agents` ( `label` varchar(600) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `data` text, `review_date` datetime DEFAULT NULL, - `created` int(1) unsigned NOT NULL DEFAULT '0', + `created` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `id_rt` (`id_rt`), INDEX `label` (`label`), diff --git a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php index 2134da1f37..fc3851cf5b 100644 --- a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php +++ b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php @@ -289,7 +289,7 @@ class DiscoveryTaskList extends HTML [ 'utimestamp' => 0, 'status' => 1, - 'direct_report' => DISCOVERY_RESULTS, + 'direct_report' => $direct_report, ], ['id_rt' => $id] ); @@ -526,14 +526,22 @@ class DiscoveryTaskList extends HTML if ($task['direct_report'] == 1) { if ($task['status'] <= 0) { $data[5] = __('Done'); + } else if ($task['utimestamp'] == 0 + && empty($task['summary']) + ) { + $data[5] = __('Not started'); } else { $data[5] = __('Pending'); } } else { - if ($task['status'] <= 0) { + if ($task['status'] <= 0 && $task['utimestamp'] > 0) { $data[5] = ''; $data[5] .= __('Review'); $data[5] .= ''; + } else if ($task['utimestamp'] == 0 + && empty($task['summary']) + ) { + $data[5] = __('Not started'); } else { $data[5] = __('Searching'); } @@ -1121,68 +1129,83 @@ class DiscoveryTaskList extends HTML return; } - $task_data = db_get_row('tdiscovery_tmp_agents', 'id_rt', $id_task); + $task_data = db_get_all_rows_filter( + 'tdiscovery_tmp_agents', + ['id_rt' => $id_task] + ); $task = db_get_row('trecon_task', 'id_rt', $id_task); + $simple_data = []; if (is_array($task_data)) { - $data = json_decode(base64_decode($task_data['data']), true); - $simple_data = array_reduce( - $data, - function ($carry, $item) { - $id = $item['agent']['nombre']; + foreach ($task_data as $agent) { + $data = json_decode(base64_decode($agent['data']), true); - $tmp = [ - 'id' => $id, - 'name' => $item['agent']['nombre'], - 'checked' => $item['checked'], - ]; + if (is_array($data) === false) { + continue; + } - if (empty($item['agent']['agent_id'])) { - $agent_id = agents_get_agent_id($id, true); - if ($agent_id > 0) { - $tmp['disabled'] = 1; - $tmp['checked'] = 1; - $tmp['agent_id'] = $agent_id; - } - } + $id = $data['agent']['nombre']; - $carry[] = $tmp; - $childs = array_reduce( - $item['modules'], - function ($c, $i) use ($id, $agent_id) { - $tmp = [ - 'name' => $i['name'], - 'id' => $id.'-'.$i['name'], - 'pid' => $id, - 'checked' => $i['checked'], - ]; + // Partial. + $tmp = [ + 'id' => $id, + 'name' => $id, + 'checked' => $data['agent']['checked'], + ]; + + $agent_id = $data['agent']['agent_id']; + if (empty($agent_id)) { + $agent_id = agents_get_agent_id($id, true); + } + + if ($agent_id > 0) { + $tmp['disabled'] = 1; + $tmp['checked'] = 1; + $tmp['agent_id'] = $agent_id; + } + + // Store. + $simple_data[] = $tmp; + + if (is_array($data['modules'])) { + $simple_data = array_merge( + $simple_data, + array_reduce( + $data['modules'], + function ($carry, $item) use ($id, $agent_id) { + if ($item['name'] == 'Host Alive') { + return $carry; + } + + $tmp = [ + 'name' => $item['name'], + 'id' => $id.'-'.$item['name'], + 'pid' => $id, + 'checked' => $item['checked'], + ]; + + $agentmodule_id = $item['agentmodule_id']; + if (empty($agentmodule_id)) { + $agentmodule_id = modules_get_agentmodule_id( + io_safe_input($item['name']), + $agent_id + ); + } - if (empty($i['agentmodule_id'])) { - $agentmodule_id = modules_get_agentmodule_id( - io_safe_input($i['name']), - $agent_id - ); if ($agentmodule_id > 0) { $tmp['disabled'] = 1; $tmp['checked'] = 1; $tmp['module_id'] = $agentmodule_id; } - } - $c[] = $tmp; - return $c; - }, - [] + $carry[] = $tmp; + return $carry; + }, + [] + ) ); - $carry = array_merge( - $carry, - $childs - ); - - return $carry; - }, - [] - ); + } + } echo '
      '; echo $this->progressTaskSummary($task); @@ -1225,10 +1248,9 @@ class DiscoveryTaskList extends HTML return; } + $ids = []; $selection = io_safe_output(get_parameter('tree-data-tree', '')); - if (empty($selection)) { - $ids = []; - } else { + if (empty($selection) === false) { $selection = json_decode($selection, true); $ids = array_reduce( $selection, @@ -1239,57 +1261,73 @@ class DiscoveryTaskList extends HTML ); } - $task_data = db_get_row('tdiscovery_tmp_agents', 'id', $id_task); - - if (is_array($task_data)) { - $data = json_decode(base64_decode($task_data['data']), true); - } + $task_data = db_get_all_rows_filter( + 'tdiscovery_tmp_agents', + ['id_rt' => $id_task] + ); $summary = []; - if (is_array($data)) { - foreach ($data as $agent_name => $row) { - if (in_array($agent_name, $ids)) { - $data[$agent_name]['checked'] = 1; - if ($data[$agent_name]['checked'] != 1) { - $summary[] = '
    • '.$agent_name.'
    • '; - } - } else { - if ($data[$agent_name]['checked'] == 1) { - $summary[] = '
    • '.__('Removed').' '.$agent_name.'
    • '; + if (is_array($ids)) { + foreach ($task_data as $row) { + $data = json_decode(base64_decode($row['data']), true); + + if (is_array($data)) { + // Analize each agent. + $agent_name = $data['agent']['nombre']; + if (in_array($agent_name, $ids)) { + if ($data['agent']['checked'] != 1) { + $summary[] = '
    • '.$agent_name.'
    • '; + } + + $data['agent']['checked'] = 1; + } else { + if ($data['agent']['checked'] == 1) { + $summary[] = '
    • '.__('Removed').' '.$agent_name.'
    • '; + } + + $data['agent']['checked'] = 0; } - $data[$agent_name]['checked'] = 0; - } + // Modules. + if (is_array($data['modules'])) { + $n_modules = count($data['modules']); + for ($i = 0; $i < $n_modules; $i++) { + $module_name = $data['modules'][$i]['name']; + if (in_array($agent_name.'-'.$module_name, $ids)) { + if ($data['modules'][$i]['checked'] != 1) { + $summary[] = '
    • '.$agent_name.' - '.$module_name.'
    • '; + } - if (is_array($row['modules'])) { - $n_modules = count($row['modules']); - for ($i = 0; $i < $n_modules; $i++) { - $module_name = $row['modules'][$i]['name']; - if (in_array($agent_name.'-'.$module_name, $ids)) { - $data[$agent_name]['modules'][$i]['checked'] = 1; - if ($row['modules'][$i]['checked'] != 1) { - $summary[] = '
    • '.$agent_name.' - '.$module_name.'
    • '; - } - } else { - if ($row['modules'][$i]['checked'] == 1) { - $summary[] = '
    • '.__('Removed').' '.$agent_name.' - '.$module_name.'
    • '; - } + $data['modules'][$i]['checked'] = 1; + } else { + if ($data['modules'][$i]['checked'] == 1) { + $summary[] = '
    • '.__('Removed').' '.$agent_name.' - '.$module_name.'
    • '; + } - $data[$agent_name]['modules'][$i]['checked'] = 0; + $data['modules'][$i]['checked'] = 0; + } } } + + // Update data. + db_process_sql_update( + 'tdiscovery_tmp_agents', + [ + 'data' => base64_encode(json_encode($data)), + 'review_date' => date('Y-m-d H:i:s'), + ], + [ + 'id_rt' => $id_task, + 'label' => $agent_name, + ] + ); } } + } - // Update targets. - db_process_sql_update( - 'tdiscovery_tmp_agents', - [ - 'data' => base64_encode(json_encode($data)), - ], - ['id_rt' => $id_task] - ); - + if (empty($summary)) { + $out .= __('No changes'); + } else { // Schedule execution. db_process_sql_update( 'trecon_task', @@ -1300,11 +1338,7 @@ class DiscoveryTaskList extends HTML ], ['id_rt' => $id_task] ); - } - if (empty($summary)) { - $out .= __('No changes'); - } else { $out .= __('Summary'); $out .= '
        '; $out .= join('', $summary); diff --git a/pandora_console/include/class/HTML.class.php b/pandora_console/include/class/HTML.class.php index 6394951af8..55c87199c0 100644 --- a/pandora_console/include/class/HTML.class.php +++ b/pandora_console/include/class/HTML.class.php @@ -1081,6 +1081,7 @@ var simTree_'.$target.'; \'\' ); + $("#tree-data-'.$target.'").val(JSON.stringify(simTree_'.$target.'.sels)); }); '; diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 360e3f8a3b..8c4d52ae45 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -819,7 +819,7 @@ CREATE TABLE `tdiscovery_tmp_agents` ( `label` varchar(600) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `data` text, `review_date` datetime DEFAULT NULL, - `created` int(1) unsigned NOT NULL DEFAULT '0', + `created` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `id_rt` (`id_rt`), INDEX `label` (`label`), diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index 6abacb2429..6fe43036ff 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -3266,7 +3266,7 @@ sub pandora_create_agent ($$$$$$$$$$;$$$$$$$$$$) { $agent_mode = 1 unless defined($agent_mode); $alias = $agent_name unless defined($alias); - $description = "Created by $server_name" unless ($description ne ''); + $description = "Created by $server_name" unless (defined($description) && $description ne ''); my ($columns, $values) = db_insert_get_values ({ 'nombre' => safe_input($agent_name), 'direccion' => $address, 'comentarios' => $description, diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index b9ccafbf2a..5ee472b3c1 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -61,6 +61,8 @@ use constant { STEP_AFT => 2, STEP_TRACEROUTE => 3, STEP_GATEWAY => 4, + STEP_MONITORING => 5, + STEP_APPLY => 6, STEP_STATISTICS => 1, STEP_APP_SCAN => 2, STEP_CUSTOM_QUERIES => 3, @@ -452,6 +454,14 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) { # ICMP # + use Data::Dumper; + $Data::Dumper::Sortkeys = 1; + + print Dumper($device); + print Dumper($self->{'task_data'}); + + die(); + return if empty($self->{'id_network_profile'}); my @templates = split /,/, $self->{'id_network_profile'}; @@ -481,7 +491,12 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) { $component->{'plugin_user'} = $self->{'snmp_auth_user'}; $component->{'plugin_pass'} = $self->{'snmp_auth_pass'}; - pandora_create_module_from_network_component($self->{'pa_config'}, $component, $agent_id, $self->{'dbh'}); + pandora_create_module_from_network_component( + $self->{'pa_config'}, + $component, + $agent_id, + $self->{'dbh'} + ); } } @@ -491,8 +506,19 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) { sub PandoraFMS::Recon::Base::report_scanned_agents($) { my ($self) = @_; + my $force_creation = 0; + + if (defined($self->{'task_data'}{'direct_report'}) + && $self->{'task_data'}{'direct_report'} == DISCOVERY_STANDARD + ) { + $force_creation = 1; + } + + # + # Creation + # if(defined($self->{'task_data'}{'direct_report'}) - && $self->{'task_data'}{'direct_report'} == DISCOVERY_RESULTS + && $self->{'task_data'}{'direct_report'} == DISCOVERY_RESULTS ) { # Load cache. my @rows = get_db_rows( @@ -501,63 +527,214 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { $self->{'task_data'}{'id_rt'} ); + my @agents; + + my $progress = 0; + my $step = 100.00 / scalar @rows; foreach my $row (@rows) { + $progress += $step; + $self->call('update_progress', $progress); + my $name = safe_output($row->{'label'}); my $data; eval { + local $SIG{__DIE__}; $data = decode_json(decode_base64($row->{'data'})); }; + if ($@) { + $self->call('message', "ERROR JSON: $@", 3); + } - # Store. - $self->{'agents_found'}{$name} = $data; - } - } + # Register target agent if enabled. + if (is_enabled($data->{'agent'}{'checked'}) + || $force_creation + ) { + my $parent_id; + my $os_id = $self->guess_os($data->{'agent'}{'direccion'}); - foreach my $label (keys %{$self->{'agents_found'}}) { - if (!is_enabled($self->{'direct_report'})) { - # Store temporally. Wait user approval. - my $encoded; - eval { - local $SIG{__DIE__}; - $encoded = encode_base64(encode_json($self->{'agents_found'})); - }; + $self->call('message', "Agent accepted: ".$data->{'agent'}{'nombre'}, 5); - my $id = get_db_value( - $self->{'dbh'}, - 'SELECT id FROM tdiscovery_tmp_agents WHERE id_rt = ? AND label = ?', - $self->{'task_data'}{'id_rt'}, - safe_input($label) - ); - - if (defined($id)) { - # Already defined. - $self->{'agents_found'}{$label}{'id'} = $id; + # Agent creation. + my $agent_id = $data->{'agent'}{'agent_id'}; + my $agent_learning = 1; + if (!defined($agent_id) || $agent_id == 0) { + $agent_id = pandora_create_agent( + $self->{'pa_config'}, $self->{'servername'}, $data->{'agent'}{'nombre'}, + $data->{'agent'}{'direccion'}, $self->{'task_data'}{'group_id'}, $parent_id, + $os_id, $data->{'agent'}->{'description'}, + $data->{'agent'}{'interval'}, $self->{'dbh'}, + $data->{'agent'}{'timezone_offset'} + ); + + $data->{'agent'}{'agent_id'} = $agent_id; + $agent_learning = 1; + } else { + $agent_learning = get_db_value( + $self->{'dbh'}, + 'SELECT modo FROM tagente WHERE id_agente = ?', + $agent_id + ); + + } + $self->call('message', "Agent id: ".$data->{'agent'}{'agent_id'}, 5); + + # Create selected modules. + if(ref($data->{'modules'}) eq "ARRAY") { + for (my $i=0; $i < scalar @{$data->{'modules'}}; $i++) { + my $module = $data->{'modules'}[$i]; + + # Do not create any modules if the agent is not in learning mode. + next unless ($agent_learning == 1); + + # Host alive is always being created. + if ($module->{'name'} ne 'Host Alive') { + next unless (is_enabled($module->{'checked'}) || $force_creation); + } + + $self->call('message', "[$agent_id] Module: ".$module->{'name'}, 5); + + my $agentmodule_id = $module->{'agentmodule_id'}; + if (!defined($agentmodule_id) || $agentmodule_id == 0) { + # Create module. + $agentmodule_id = pandora_create_module_from_hash( + $self->{'pa_config'}, + { + 'id_tipo_modulo' => get_module_id($self->{'dbh'}, $module->{'type'}), + 'id_modulo' => $module->{'id_modulo'}, + 'nombre' => safe_input($module->{'name'}), + 'descripcion' => '', + 'id_agente' => $agent_id, + 'ip_target' => $data->{'agent'}{'direccion'} + }, + $self->{'dbh'} + ); + + # Store. + $data->{'modules'}[$i]{'agentmodule_id'} = $agentmodule_id; + + $self->call( + 'message', + "[$agent_id] Module: ".$module->{'name'}." ID: $agentmodule_id", + 5 + ); + } + } + } + + my $encoded; + eval { + local $SIG{__DIE__}; + $encoded = encode_base64( + encode_json($data) + ); + }; + + # Update. db_do( $self->{'dbh'}, 'UPDATE tdiscovery_tmp_agents SET `data` = ? ' .'WHERE `id_rt` = ? AND `label` = ?', $encoded, $self->{'task_data'}{'id_rt'}, - safe_input($label) + $name ); - next; + } - # Insert. - $self->{'agents_found'}{$label}{'id'} = db_insert( - $self->{'dbh'}, - 'id', - 'INSERT INTO tdiscovery_tmp_agents (`id_rt`,`label`,`data`,`created`) ' - .'VALUES (?, ?, ?, now())', - $self->{'task_data'}{'id_rt'}, - safe_input($label), - $encoded - ); - } else { - # Create agents. } + + # Data creation finished. + return; } + + + # + # Cleanup previous results. + # + db_do( + $self->{'dbh'}, + 'DELETE FROM tdiscovery_tmp_agents ' + .'WHERE `id_rt` = ?', + $self->{'task_data'}{'id_rt'} + ); + + # + # Store and review. + # + + my @hosts = keys %{$self->{'agents_found'}}; + $self->{'step'} = STEP_APPLY; + my ($progress, $step) = (90, 10.0 / scalar(@hosts)); # From 90% to 100%. + foreach my $label (keys %{$self->{'agents_found'}}) { + $self->call('update_progress', $progress); + $progress += $step; + # Store temporally. Wait user approval. + my $encoded; + eval { + local $SIG{__DIE__}; + $encoded = encode_base64( + encode_json($self->{'agents_found'}->{$label}) + ); + }; + + my $id = get_db_value( + $self->{'dbh'}, + 'SELECT id FROM tdiscovery_tmp_agents WHERE id_rt = ? AND label = ?', + $self->{'task_data'}{'id_rt'}, + safe_input($label) + ); + + if (defined($id)) { + # Already defined. + $self->{'agents_found'}{$label}{'id'} = $id; + + db_do( + $self->{'dbh'}, + 'UPDATE tdiscovery_tmp_agents SET `data` = ? ' + .'WHERE `id_rt` = ? AND `label` = ?', + $encoded, + $self->{'task_data'}{'id_rt'}, + safe_input($label) + ); + next; + } + + # Insert. + $self->{'agents_found'}{$label}{'id'} = db_insert( + $self->{'dbh'}, + 'id', + 'INSERT INTO tdiscovery_tmp_agents (`id_rt`,`label`,`data`,`created`) ' + .'VALUES (?, ?, ?, now())', + $self->{'task_data'}{'id_rt'}, + safe_input($label), + $encoded + ); + } +} + +################################################################################ +# Apply monitoring templates selected to detected agents. +################################################################################ +sub PandoraFMS::Recon::Base::apply_monitoring($) { + my ($self) = @_; + + my @hosts = keys %{$self->{'agents_found'}}; + + $self->{'step'} = STEP_MONITORING; + # From 80% to 90%. + my ($progress, $step) = (80, 10.0 / scalar(@hosts)); + + use Data::Dumper; + print Dumper($self->{'task_data'}); + + foreach my $label (keys %{$self->{'agents_found'}}) { + $self->call('update_progress', $progress); + $progress += $step; + print ">> $label\n"; + + } + } ################################################################################ diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 49868448a7..6ac2545794 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -22,6 +22,8 @@ use constant { STEP_AFT => 2, STEP_TRACEROUTE => 3, STEP_GATEWAY => 4, + STEP_MONITORING => 5, + STEP_APPLY => 6, STEP_STATISTICS => 1, STEP_APP_SCAN => 2, STEP_CUSTOM_QUERIES => 3, @@ -408,7 +410,7 @@ sub icmp_discovery($$) { 'ip_target' => $addr, 'name' => "Host Alive", 'description' => '', - 'type' => 'generic_data', + 'type' => 'remote_icmp_proc', 'id_modulo' => 2, } ); @@ -1389,7 +1391,7 @@ sub scan_subnet($) { my $host_block_size = $self->{'block_size'}; # The first 50% of the recon task approx. - my $step = 40.0 / scalar(@subnets) / (($total_hosts / $host_block_size)+1); + my $step = 25.0 / scalar(@subnets) / (($total_hosts / $host_block_size)+1); my $subnet_step = 50.0 / (($total_hosts / $host_block_size)+1); for (my $block_index=0; @@ -1438,7 +1440,7 @@ sub scan_subnet($) { $self->call('update_progress', ceil($progress)); $total_hosts = scalar keys %hosts_alive; - $step = 40.0 / scalar(@subnets) / $total_hosts; + $step = 25.0 / scalar(@subnets) / $total_hosts; $subnet_step = 50.0 / $total_hosts; foreach my $addr (keys %hosts_alive) { # Increase self summary.alive hosts. @@ -1807,18 +1809,21 @@ sub scan($) { return $self->deploy_scan(); } } - # XXX - print "Metodo: ".$self->{'task_data'}{'direct_report'}."\n"; - + if(defined($self->{'task_data'}{'direct_report'}) && $self->{'task_data'}{'direct_report'} == DISCOVERY_RESULTS ) { # Use Cached results. - return $self->call('report_scanned_agents'); + $self->call('report_scanned_agents'); + + # Done! + $self->{'step'} = ''; + $self->call('update_progress', -1); + return; } # Find devices. - $self->call('message', "[1/4] Scanning the network...", 3); + $self->call('message', "[1/6] Scanning the network...", 3); $self->{'step'} = STEP_SCANNING; $self->call('update_progress', $progress); @@ -1834,9 +1839,9 @@ sub scan($) { $self->call('delete_connections'); # Connectivity from address forwarding tables. - $self->call('message', "[2/4] Finding address forwarding table connectivity...", 3); + $self->call('message', "[2/6] Finding address forwarding table connectivity...", 3); $self->{'step'} = STEP_AFT; - ($progress, $step) = (80, 8.0 / scalar(@hosts)); # From 50% to 70%. + ($progress, $step) = (50, 10.0 / scalar(@hosts)); # From 50% to 60%. for (my $i = 0; defined($hosts[$i]); $i++) { $self->call('update_progress', $progress); $progress += $step; @@ -1844,9 +1849,9 @@ sub scan($) { } # Connect hosts that are still unconnected using traceroute. - $self->call('message', "[3/4] Finding traceroute connectivity.", 3); + $self->call('message', "[3/6] Finding traceroute connectivity.", 3); $self->{'step'} = STEP_TRACEROUTE; - ($progress, $step) = (88, 8.0 / scalar(@hosts)); # From 70% to 90%. + ($progress, $step) = (60, 10.0 / scalar(@hosts)); # From 60% to 70%. foreach my $host (@hosts) { $self->call('update_progress', $progress); $progress += $step; @@ -1855,9 +1860,9 @@ sub scan($) { } # Connect hosts that are still unconnected using known gateways. - $self->call('message', "[4/4] Finding host to gateway connectivity.", 3); + $self->call('message', "[4/6] Finding host to gateway connectivity.", 3); $self->{'step'} = STEP_GATEWAY; - ($progress, $step) = (94, 6.0 / scalar(@hosts)); # From 70% to 90%. + ($progress, $step) = (70, 10.0 / scalar(@hosts)); # From 70% to 80%. $self->get_routes(); # Update the route cache. foreach my $host (@hosts) { $self->call('update_progress', $progress); @@ -1867,9 +1872,9 @@ sub scan($) { } } - # Done! - $self->{'step'} = ''; - $self->call('update_progress', -1); + # Apply monitoring templates + $self->call('message', "[5/6] Applying monitoring.", 3); + $self->call('apply_monitoring', $self); # Print debug information on found devices. $self->call('message', "[Summary]", 3); @@ -1887,9 +1892,15 @@ sub scan($) { $self->call('message', $dev_info, 3); } + # Apply monitoring templates + $self->call('message', "[6/6] Process results.", 3); # Send agent information to Database (Discovery) or XML (satellite.). $self->call('report_scanned_agents', $self->{'agents_found'}); + # Done! + $self->{'step'} = ''; + $self->call('update_progress', -1); + } ################################################################################ From c9813afc9b2f4f4b88954ade1a836795f220c48f Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Thu, 19 Mar 2020 12:13:56 +0100 Subject: [PATCH 012/111] DB changes --- pandora_console/extras/mr/37.sql | 3 +++ .../extras/pandoradb_migrate_6.0_to_7.0.mysql.sql | 5 +++++ pandora_console/pandoradb.sql | 1 + 3 files changed, 9 insertions(+) diff --git a/pandora_console/extras/mr/37.sql b/pandora_console/extras/mr/37.sql index 50b4c04306..87a3e6a5ac 100644 --- a/pandora_console/extras/mr/37.sql +++ b/pandora_console/extras/mr/37.sql @@ -3,6 +3,7 @@ START TRANSACTION; ALTER TABLE trecon_task MODIFY COLUMN `id_network_profile` TEXT; ALTER TABLE `trecon_task` CHANGE COLUMN `create_incident` `direct_report` TINYINT(1) UNSIGNED DEFAULT 0; UPDATE `trecon_task` SET `direct_report` = 1; +ALTER TABLE `tnetwork_profile` ADD COLUMN `pen` TEXT; CREATE TABLE `tdiscovery_tmp_agents` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, @@ -32,4 +33,6 @@ CREATE TABLE `tdiscovery_tmp_connections` ( REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +ALTE + COMMIT; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index de53643ec9..945b4e6d38 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -1472,6 +1472,11 @@ ALTER TABLE tnetwork_component ADD COLUMN `dynamic_two_tailed` tinyint(1) unsign ALTER TABLE `tnetwork_component` ADD COLUMN `ff_type` tinyint(1) unsigned default '0'; ALTER TABLE `tnetwork_component` MODIFY COLUMN `ff_type` tinyint(1) unsigned NULL DEFAULT '0'; +-- ---------------------------------------------------------------------- +-- Table `tnetwork_profile` +-- ---------------------------------------------------------------------- +ALTER TABLE `tnetwork_profile` ADD COLUMN `pen` TEXT; + -- --------------------------------------------------------------------- -- Table `tagente` -- --------------------------------------------------------------------- diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 360e3f8a3b..941381a04b 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -942,6 +942,7 @@ CREATE TABLE IF NOT EXISTS `tnetwork_profile` ( `id_np` int(10) unsigned NOT NULL auto_increment, `name` varchar(100) NOT NULL default '', `description` varchar(250) default '', + `pen` text default '', PRIMARY KEY (`id_np`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; From 99cb286274e55343def5b94136617e40c3920bef Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Thu, 19 Mar 2020 14:11:09 +0100 Subject: [PATCH 013/111] Pre-check modules (SNMP, TCP, ICMP) Discovery --- pandora_server/lib/PandoraFMS/Core.pm | 2 + .../lib/PandoraFMS/DiscoveryServer.pm | 260 ++++++++++++++---- pandora_server/lib/PandoraFMS/Recon/Base.pm | 32 ++- pandora_server/lib/PandoraFMS/Tools.pm | 18 ++ 4 files changed, 242 insertions(+), 70 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index 6fe43036ff..99ddf48796 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -3067,6 +3067,8 @@ sub pandora_create_module_from_network_component ($$$$) { pandora_create_module_tags ($pa_config, $dbh, $module_id, $component_tags); logger($pa_config, 'Creating module ' . safe_output ($component->{'nombre'}) . " (ID $module_id) for agent $addr from network component.", 10); + + return $module_id; } ########################################################################## diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index 5ee472b3c1..b5785a5c6a 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -441,11 +441,133 @@ sub PandoraFMS::Recon::Base::tcp_scan ($$) { return $open_ports; } +################################################################################ +# Verifies if a module will be normal. +################################################################################ +sub PandoraFMS::Recon::Base::test_module($$) { + my ($self, $addr, $module) = @_; + + # Default values. + my $test = { + %{$module}, + 'ip_target' => $addr, + }; + + if (is_enabled($module->{'__module_component'})) { + # Component. Translate some fields. + $test->{'id_tipo_modulo'} = $module->{'type'}; + } else { + # Module. + $test->{'id_tipo_modulo'} = $module->{'id_modulo'}; + } + + my $value; + + # 1. Try to retrieve value. + if ($test->{'id_tipo_modulo'} >= 15 && $test->{'id_tipo_modulo'} <= 18) { + # SNMP + $value = $self->call( + 'snmp_get', + $test->{'ip_target'}, + $test->{'snmp_oid'} + ); + } elsif ($test->{'id_tipo_modulo'} == 6) { + # ICMP - alive - already tested. + $value = 1; + + } elsif ($test->{'id_tipo_modulo'} == 7) { + # ICMP - latency + $value = pandora_ping_latency( + $self->{'pa_config'}, + $test->{'ip_target'}, + $test->{'max_timeout'}, + $test->{'max_retries'}, + ); + + } elsif (($test->{'id_tipo_modulo'} >= 1 && $test->{'id_tipo_modulo'} <= 5) + || ($test->{'id_tipo_modulo'} >= 21 && $test->{'id_tipo_modulo'} <= 23) + && is_enabled($test->{'id_plugin'}) + ) { + # Generic, plugins. (21-23 ASYNC) + # XXX TODO: Test plugins. + return 1; + + } elsif ($test->{'id_tipo_modulo'} >= 34 && $test->{'id_tipo_modulo'} <= 37) { + # Remote command. + # XXX TODO: Test remote commands. + return 1; + } elsif ($test->{'id_tipo_modulo'} >= 8 && $test->{'id_tipo_modulo'} <= 11) { + # TCP + + return 0 unless is_numeric($test->{'tcp_port'}) + && $test->{'tcp_port'} > 0 + && $test->{'tcp_port'} <= 65535; + + my $result; + + PandoraFMS::NetworkServer::pandora_query_tcp( + $self->{'pa_config'}, + $test->{'tcp_port'}, + $test->{'ip_target'}, + \$result, + \$value, + $test->{'tcp_send'}, + $test->{'tcp_rcv'}, + $test->{'id_tipo_modulo'}, + $test->{'max_timeout'}, + $test->{'max_retries'}, + '', + ); + + # Result 0 is OK, 1 failed + return 0 unless defined($result) && $result == 0; + return 0 unless defined($value); + + } + + # Invalid data (empty or not defined) + return 0 if is_empty($value); + + # 2. Check if value matches type definition and fits thresholds. + if (is_in_array([1,2,4,5,6,7,8,9,11,15,16,18,21,22,25,30,31,32,34,35,37],$test->{'id_tipo_modulo'})) { + # Numeric. + return 0 unless is_numeric($value); + + if (!is_enabled($test->{'critical_inverse'})) { + return 0 if $value >= $test->{'min_critical'} && $value <= $test->{'max_critical'}; + } else { + return 0 if $value < $test->{'min_critical'} && $value > $test->{'max_critical'}; + } + + if (is_in_array([2,6,9,18,21,31,35], $test->{'id_tipo_modulo'})) { + # Boolean. + if (!is_enabled($test->{'critical_inverse'})) { + return 0 if $value == 0; + } else { + return 0 if $value != 0; + } + } + + } else { + # String. + if (!is_enabled($test->{'critical_inverse'})) { + return 0 if !is_empty($test->{'str_critical'}) && $value =~ /$test->{'str_critical'}/; + } else { + return 0 if !is_empty($test->{'str_critical'}) && $value !~ /$test->{'str_critical'}/; + } + + } + + # Success. + return 1; + +} + ################################################################################ # Create network profile modules for the given agent. ################################################################################ -sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) { - my ($self, $agent_id, $device) = @_; +sub PandoraFMS::Recon::Base::create_network_profile_modules($$) { + my ($self, $device) = @_; # # Plugin @@ -454,50 +576,61 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) { # ICMP # - use Data::Dumper; - $Data::Dumper::Sortkeys = 1; - - print Dumper($device); - print Dumper($self->{'task_data'}); - - die(); - - return if empty($self->{'id_network_profile'}); + return if is_empty($self->{'id_network_profile'}); my @templates = split /,/, $self->{'id_network_profile'}; - # Get network components associated to the network profile. - my @np_components = get_db_rows($self->{'dbh'}, 'SELECT * FROM tnetwork_profile_component WHERE id_np = ?', $self->{'id_network_profile'}); - foreach my $np_component (@np_components) { + my $data = $self->{'agents_found'}{$device}; - # Get network component data - my $component = get_db_single_row($self->{'dbh'}, 'SELECT * FROM tnetwork_component WHERE id_nc = ?', $np_component->{'id_nc'}); - if (!defined ($component)) { - $self->call('message', "Network component ID " . $np_component->{'id_nc'} . " not found.", 5); - next; + foreach my $t_id (@templates) { + # 1. Retrieve template info. + my $template = get_db_single_row( + $self->{'dbh'}, + 'SELECT * FROM `tnetwork_profile` WHERE `id_np` = ?', + $t_id + ); + + # 2. Verify Private Enterprise Number matches (PEN) + if (defined($template->{'pen'})) { + my @penes = split(',', $template->{'pen'}); + + next unless (is_in_array(\@penes, $data->{'pen'})); } - ## XXX Puede tener varios penes. - #next if (defined($template->{'pen'}) - # && get_enterprise_oid($device) != $template->{'pen'} ); - - # Use snmp_community from network task instead the component snmp_community - $component->{'snmp_community'} = safe_output($self->get_community($device)); - $component->{'tcp_send'} = $self->{'snmp_version'}; - $component->{'custom_string_1'} = $self->{'snmp_privacy_method'}; - $component->{'custom_string_2'} = $self->{'snmp_privacy_pass'}; - $component->{'custom_string_3'} = $self->{'snmp_security_level'}; - $component->{'plugin_parameter'} = $self->{'snmp_auth_method'}; - $component->{'plugin_user'} = $self->{'snmp_auth_user'}; - $component->{'plugin_pass'} = $self->{'snmp_auth_pass'}; - - pandora_create_module_from_network_component( - $self->{'pa_config'}, - $component, - $agent_id, - $self->{'dbh'} + # 2. retrieve module list from target template. + my @np_components = get_db_rows( + $self->{'dbh'}, + 'SELECT * FROM tnetwork_profile_component WHERE id_np = ?', + $t_id ); + + foreach my $np_component (@np_components) { + # 2. Test each possible module. + my $component = get_db_single_row( + $self->{'dbh'}, + 'SELECT * FROM tnetwork_component WHERE id_nc = ?', + $np_component->{'id_nc'} + ); + + $component->{'name'} = safe_output($component->{'name'}); + if ($component->{'type'} >= 15 && $component->{'type'} <= 18) { + $component->{'snmp_community'} = safe_output($self->get_community($device)); + $component->{'tcp_send'} = $self->{'snmp_version'}; + $component->{'custom_string_1'} = $self->{'snmp_privacy_method'}; + $component->{'custom_string_2'} = $self->{'snmp_privacy_pass'}; + $component->{'custom_string_3'} = $self->{'snmp_security_level'}; + $component->{'plugin_parameter'} = $self->{'snmp_auth_method'}; + $component->{'plugin_user'} = $self->{'snmp_auth_user'}; + $component->{'plugin_pass'} = $self->{'snmp_auth_pass'}; + } + + $component->{'__module_component'} = 1; + + # 3. Try to register module into monitoring list. + $self->call('add_module', $device, $component); + } } + } ################################################################################ @@ -580,9 +713,9 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { $self->call('message', "Agent id: ".$data->{'agent'}{'agent_id'}, 5); # Create selected modules. - if(ref($data->{'modules'}) eq "ARRAY") { - for (my $i=0; $i < scalar @{$data->{'modules'}}; $i++) { - my $module = $data->{'modules'}[$i]; + if(ref($data->{'modules'}) eq "HASH") { + foreach my $i (keys %{$data->{'modules'}}) { + my $module = $data->{'modules'}{$i}; # Do not create any modules if the agent is not in learning mode. next unless ($agent_learning == 1); @@ -596,22 +729,33 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { my $agentmodule_id = $module->{'agentmodule_id'}; if (!defined($agentmodule_id) || $agentmodule_id == 0) { - # Create module. - $agentmodule_id = pandora_create_module_from_hash( - $self->{'pa_config'}, - { - 'id_tipo_modulo' => get_module_id($self->{'dbh'}, $module->{'type'}), - 'id_modulo' => $module->{'id_modulo'}, - 'nombre' => safe_input($module->{'name'}), - 'descripcion' => '', - 'id_agente' => $agent_id, - 'ip_target' => $data->{'agent'}{'direccion'} - }, - $self->{'dbh'} - ); + + if (is_enabled($module->{'__module_component'})) { + # Module from network component. + $agentmodule_id = pandora_create_module_from_network_component( + $self->{'pa_config'}, + $module, + $agent_id, + $self->{'dbh'} + ); + } else { + # Create module - Direct. + $agentmodule_id = pandora_create_module_from_hash( + $self->{'pa_config'}, + { + 'id_tipo_modulo' => get_module_id($self->{'dbh'}, $module->{'type'}), + 'id_modulo' => $module->{'id_modulo'}, + 'nombre' => safe_input($module->{'name'}), + 'descripcion' => '', + 'id_agente' => $agent_id, + 'ip_target' => $data->{'agent'}{'direccion'} + }, + $self->{'dbh'} + ); + } # Store. - $data->{'modules'}[$i]{'agentmodule_id'} = $agentmodule_id; + $data->{'modules'}{$i}{'agentmodule_id'} = $agentmodule_id; $self->call( 'message', @@ -725,13 +869,11 @@ sub PandoraFMS::Recon::Base::apply_monitoring($) { # From 80% to 90%. my ($progress, $step) = (80, 10.0 / scalar(@hosts)); - use Data::Dumper; - print Dumper($self->{'task_data'}); - foreach my $label (keys %{$self->{'agents_found'}}) { $self->call('update_progress', $progress); $progress += $step; - print ">> $label\n"; + $self->call('message', "Checking modules for $label", 5); + $self->call('create_network_profile_modules', $label); } diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 6ac2545794..ec437249f0 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -384,9 +384,9 @@ sub are_connected($$$$$) { $dev_1 = $self->{'aliases'}->{$dev_1} if defined($self->{'aliases'}->{$dev_1}); $dev_2 = $self->{'aliases'}->{$dev_2} if defined($self->{'aliases'}->{$dev_2}); - # Use ping modules when interfaces are unknown. - $if_1 = "ping" if $if_1 eq ''; - $if_2 = "ping" if $if_2 eq ''; + # Use Host Alive modules when interfaces are unknown. + $if_1 = "Host Alive" if $if_1 eq ''; + $if_2 = "Host Alive" if $if_2 eq ''; if ( defined($self->{'connections'}->{"${dev_1}\t${if_1}\t${dev_2}\t${if_2}"}) ||defined($self->{'connections'}->{"${dev_2}\t${if_2}\t${dev_1}\t${if_1}"})) { @@ -405,7 +405,7 @@ sub icmp_discovery($$) { $self->prepare_agent($addr); - $self->add_module($addr, 'icmp', + $self->add_module($addr, { 'ip_target' => $addr, 'name' => "Host Alive", @@ -1328,12 +1328,22 @@ sub add_agent($$) { ################################################################################ # Add module to agent (tmp pool) (will be registered at the end of the scan). ################################################################################ -sub add_module($$$$) { - my ($self, $agent, $type, $data) = @_; +sub add_module($$$) { + my ($self, $agent, $data) = @_; $self->prepare_agent($agent); - push @{$self->{'agents_found'}->{$agent}->{'modules'}}, $data; + $self->{'agents_found'}->{$agent}->{'modules'} = {} + unless ref($self->{'agents_found'}->{$agent}->{'modules'}) eq 'HASH'; + + # Test module. Is it well defined? + return unless ref($data) eq 'HASH' && defined($data->{'name'}) + && $data->{'name'} ne ''; + + # Test module. Is it success? + return unless $self->call('test_module', $agent, $data); + + $self->{'agents_found'}->{$agent}->{'modules'}{$data->{'name'}} = $data; } @@ -1409,7 +1419,7 @@ sub scan_subnet($) { { 'fping' => $self->{'fping'}, # XXX CAMBIAR POR 0.5 - 'networktimeout' => 0.01 # use fping defaults + 'networktimeout' => 0.5 # use fping defaults }, @hosts[$block_index .. $to - 1] ); @@ -2136,7 +2146,7 @@ sub wmi_scan { # CPU. my @cpus = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceId FROM Win32_Processor', 0); foreach my $cpu (@cpus) { - $self->add_module($target, 'wmi', + $self->add_module($target, { 'target' => $target, 'query' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId='$cpu'", @@ -2153,7 +2163,7 @@ sub wmi_scan { # Memory. my $mem = $self->wmi_get_value($target, $auth, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0); if (defined($mem)) { - $self->add_module($target, 'wmi', + $self->add_module($target, { 'target' => $target, 'query' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem", @@ -2170,7 +2180,7 @@ sub wmi_scan { # Disk. my @units = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceID FROM Win32_LogicalDisk', 0); foreach my $unit (@units) { - $self->add_module($target, 'wmi', + $self->add_module($target, { 'target' => $target, 'query' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'", diff --git a/pandora_server/lib/PandoraFMS/Tools.pm b/pandora_server/lib/PandoraFMS/Tools.pm index a478ca6d67..92c6a06cd5 100755 --- a/pandora_server/lib/PandoraFMS/Tools.pm +++ b/pandora_server/lib/PandoraFMS/Tools.pm @@ -113,6 +113,7 @@ our @EXPORT = qw( is_metaconsole is_offline is_empty + is_in_array to_number clean_blank credential_store_get_key @@ -659,6 +660,23 @@ sub is_empty { return 0; } +################################################################################ +# Check if a value is in an array +################################################################################ +sub is_in_array { + my ($array, $value) = @_; + + if (is_empty($value)) { + return 0; + } + + my %params = map { $_ => 1 } @{$array}; + if (exists($params{$value})) { + return 1; + } + return 0; +} + ################################################################################ # SUB md5check (param_1, param_2) # Verify MD5 file .checksum From 32c6e7f30c6cdb65901a7299d1cd632db3209056 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Thu, 19 Mar 2020 14:26:01 +0100 Subject: [PATCH 014/111] Minor fixes --- pandora_console/include/functions_ui.php | 24 ++++++++++--------- .../lib/PandoraFMS/DiscoveryServer.pm | 1 + 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index 33f6e85ca6..b210bbfa50 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -2873,10 +2873,12 @@ function ui_progress( $text = $progress.'%'; } + $id = uniqid(); + ui_require_css_file('progress'); - $output .= ''; - $output .= ''; + $output .= ''; $output .= ''; if ($ajax !== false && is_array($ajax)) { @@ -2900,8 +2902,8 @@ function ui_progress( success: function(data) { try { val = JSON.parse(data); - $(".progress_main").attr("data-label", val + " %"); - $(".progress").width(val+"%"); + $("#'.$id.'").attr("data-label", val + " %"); + $("#'.$id.'_progress").width(val+"%"); } catch (e) { console.error(e); } @@ -2914,8 +2916,8 @@ function ui_progress( $output .= ' \ No newline at end of file diff --git a/pandora_console/include/class/ManageBlock.class.php b/pandora_console/include/class/ManageBlock.class.php index 97534f8f0d..2eda9d9f56 100644 --- a/pandora_console/include/class/ManageBlock.class.php +++ b/pandora_console/include/class/ManageBlock.class.php @@ -63,6 +63,27 @@ class ManageBlock extends HTML */ private $id_np; + /** + * Name of Block Template + * + * @var [type] + */ + private $name; + + /** + * Description of Block Template + * + * @var [type] + */ + private $description; + + /** + * Private Enterprise Numbers of Block Templates + * + * @var [type] + */ + private $pen; + /** * Constructor @@ -90,14 +111,15 @@ class ManageBlock extends HTML exit; } - $this->id_np = get_parameter('id_np', -1); - - $this->offset = get_parameter('offset', 0); - - $this->ajaxController = $ajax_controller; - - // Set baseUrl for use it in several locations in this class - $this->baseUrl = ui_get_full_url('index.php?sec=gmodules&sec2=godmode/modules/manage_block_templates'); + // Set baseUrl for use it in several locations in this class. + $this->baseUrl = ui_get_full_url('index.php?sec=gmodules&sec2=godmode/modules/manage_block_templates'); + // Capture all parameters before start. + $this->id_np = get_parameter('id_np', -1); + $this->name = get_parameter('name', ''); + $this->description = get_parameter('description', ''); + $this->pen = get_parameter('pen', ''); + $this->offset = get_parameter('offset', 0); + $this->ajaxController = $ajax_controller; return $this; } @@ -162,6 +184,34 @@ class ManageBlock extends HTML } + /** + * Undocumented function + * + * @return void + */ + private function manageData() + { + // if ($) + $name = get_parameter('name', ''); + $description = get_parameter('description', ''); + $pen = get_parameter('pen', ''); + hd($name); + hd($description); + hd($pen); + } + + + private function setNetworkProfile() + { + if ($this->id_np !== 0) { + $output = db_get_row('tnetwork_profile', 'id_np', $this->id_np); + $this->name = $output['name']; + $this->description = $output['description']; + $this->pen = $output['pen']; + } + } + + /** * Create the table with the list of Blocks Templates * @@ -288,44 +338,32 @@ class ManageBlock extends HTML /** * Prints Form for template management - * - * @param integer $id_np */ - public function moduleTemplateForm(int $id_np=0) + public function moduleTemplateForm() { - $output = []; - $createNewBlock = ($id_np === 0) ? true : false; + $createNewBlock = ($this->id_np === 0) ? true : false; if ($createNewBlock) { // Assignation for submit button. $formButtonClass = 'sub wand'; $formButtonName = 'crtbutton'; $formButtonLabel = __('Create'); - // Set of empty values. - $description = ''; - $name = ''; - $pen = ''; } else { // Assignation for submit button. $formButtonClass = 'sub upd'; $formButtonName = 'updbutton'; $formButtonLabel = __('Update'); - // Profile exists. - $row = db_get_row('tnetwork_profile', 'id_np', $id_np); - // Fill the inputs with the obtained data. - $description = $row['description']; - $name = $row['name']; - $pen = ''; + // Profile exists. Set the attributes with the info. + $this->setNetworkProfile(); } // Main form. $form = [ - 'action' => $this->baseUrl, - 'id' => 'module_block_form', - 'onsubmit' => 'return false;', - 'method' => 'POST', - 'class' => 'databox filters', - 'extra' => '', + 'action' => $this->baseUrl, + 'id' => 'module_block_form', + 'method' => 'POST', + 'class' => 'databox filters', + 'extra' => '', ]; // Inputs. @@ -338,7 +376,7 @@ class ManageBlock extends HTML 'name' => 'name', 'input_class' => 'flex-row', 'type' => 'text', - 'value' => $name, + 'value' => $this->name, 'return' => true, ], ]; @@ -350,7 +388,7 @@ class ManageBlock extends HTML 'name' => 'description', 'input_class' => 'flex-row', 'type' => 'textarea', - 'value' => $description, + 'value' => $this->description, 'return' => true, ], ]; @@ -362,7 +400,7 @@ class ManageBlock extends HTML 'name' => 'pen', 'input_class' => 'flex-row', 'type' => 'text', - 'value' => $pen, + 'value' => $this->pen, 'return' => true, ], ]; @@ -371,26 +409,22 @@ class ManageBlock extends HTML 'arguments' => [ 'name' => $formButtonName, 'label' => $formButtonLabel, - 'type' => 'button', + 'type' => 'submit', 'attributes' => 'class="'.$formButtonClass.'"', 'return' => true, ], ]; - $inputs[] = [ - 'arguments' => [ - 'name' => 'buttonGoBack', - 'label' => __('Go back'), - 'type' => 'button', - 'attributes' => 'class="sub cancel"', - 'return' => true, - ], - ]; + ui_require_jquery_file('tag-editor'); + ui_require_css_file('jquery.tag-editor'); + + $js = '$(\'#text-pen\').tagEditor();'; $this->printFormAsList( [ 'form' => $form, 'inputs' => $inputs, + 'js' => $js, true ] ); @@ -402,83 +436,108 @@ class ManageBlock extends HTML FROM tnetwork_profile_component AS npc, tnetwork_component AS nc INNER JOIN tnetwork_component_group AS ncg ON ncg.id_sg = nc.id_group WHERE npc.id_nc = nc.id_nc AND npc.id_np = %d', - $id_np + $this->id_np ); $moduleBlocks = db_get_all_rows_sql($sql); - $blockTables = []; - // Build the information of the blocks - foreach ($moduleBlocks as $block) { - if (key_exists($block['group'], $blockTables) === false) { - $blockTables[$block['group']] = [ - 'name' => $block['group_name'], - 'data' => [], - ]; - } else { - $blockTables[$block['group']]['data'][] = [ - 'component_id' => $block['component_id'], - 'name' => $block['name'], - 'type' => $block['type'], - 'description' => $block['description'], - ]; - } - } - - if (count($blockTables) === 0) { - ui_print_info_message(__('No module blocks for this profile')); - } else { - foreach ($blockTables as $id_group => $blockTable) { - $blockData = $blockTable['data']; - $blockTitle = $blockTable['name']; - $blockTitle .= '
        '.html_print_checkbox_switch_extended('block_id_'.$id_group, 1, 0, false, '', '', true).'
        '; - - $table = new StdClasS(); - $table->class = 'databox data'; - $table->width = '75%'; - $table->styleTable = 'margin: 2em auto 0;border: 1px solid #ddd;background: white;'; - $table->rowid = []; - $table->data = []; - - $table->cellpadding = 0; - $table->cellspacing = 0; - $table->width = '100%'; - $table->class = 'info_table'; - - $table->head = []; - $table->head[0] = __('Module Name'); - $table->head[1] = __('Type'); - $table->head[2] = __('Description'); - $table->head[3] = ''.__('Add').''; - - $table->size = []; - $table->size[0] = '20%'; - $table->size[2] = '65%'; - $table->size[3] = '15%'; - - $table->align = []; - $table->align[3] = 'right'; - - $table->style = []; - $table->style[3] = 'padding-right:2em'; - - $table->data = []; - - foreach ($blockData as $module) { - $data[0] = $module['name']; - $data[1] = ui_print_moduletype_icon($module['type'], true); - $data[2] = mb_strimwidth(io_safe_output($module['description']), 0, 150, '...'); - $data[3] = html_print_checkbox_switch_extended('active_'.$module['component_id'], 1, 0, false, '', '', true); - - array_push($table->data, $data); + if ($moduleBlocks) { + $blockTables = []; + // Build the information of the blocks + foreach ($moduleBlocks as $block) { + if (key_exists($block['group'], $blockTables) === false) { + $blockTables[$block['group']] = [ + 'name' => $block['group_name'], + 'data' => [], + ]; + } else { + $blockTables[$block['group']]['data'][] = [ + 'component_id' => $block['component_id'], + 'name' => $block['name'], + 'type' => $block['type'], + 'description' => $block['description'], + ]; } - - $content = html_print_table($table, true); - - $output[] = ui_toggle($content, $blockTitle, '', '', false); } + + if (count($blockTables) === 0) { + ui_print_info_message(__('No module blocks for this profile')); + } else { + foreach ($blockTables as $id_group => $blockTable) { + $blockData = $blockTable['data']; + $blockTitle = $blockTable['name']; + $blockTitle .= '
        '.html_print_checkbox_switch_extended('block_id_'.$id_group, 1, 0, false, '', '', true).'
        '; + + $table = new StdClasS(); + $table->class = 'databox data'; + $table->width = '75%'; + $table->styleTable = 'margin: 2em auto 0;border: 1px solid #ddd;background: white;'; + $table->rowid = []; + $table->data = []; + + $table->cellpadding = 0; + $table->cellspacing = 0; + $table->width = '100%'; + $table->class = 'info_table'; + + $table->head = []; + $table->head[0] = __('Module Name'); + $table->head[1] = __('Type'); + $table->head[2] = __('Description'); + $table->head[3] = ''.__('Add').''; + + $table->size = []; + $table->size[0] = '20%'; + $table->size[2] = '65%'; + $table->size[3] = '15%'; + + $table->align = []; + $table->align[3] = 'right'; + + $table->style = []; + $table->style[3] = 'padding-right:2em'; + + $table->data = []; + + foreach ($blockData as $module) { + $data[0] = $module['name']; + $data[1] = ui_print_moduletype_icon($module['type'], true); + $data[2] = mb_strimwidth(io_safe_output($module['description']), 0, 150, '...'); + $data[3] = html_print_checkbox_switch_extended('switch_'.$id_group.'_'.$module['component_id'], 1, 0, false, 'switchBlockControl(event)', '', true); + // $data[3] .= html_print_input_hidden(); + array_push($table->data, $data); + } + + $content = html_print_table($table, true); + + ui_toggle($content, $blockTitle, '', '', false); + } + } + } else { + ui_print_info_message(__('No module blocks for this profile')); } } + $javascript = " + + "; + + echo $javascript; + + $this->printGoBackButton($this->baseUrl); } From 28cdbf140964f0416d73a9e7ea94f93d979594ca Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 23 Mar 2020 15:15:44 +0100 Subject: [PATCH 019/111] Added rawInputs for forms construtor --- pandora_console/include/class/HTML.class.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pandora_console/include/class/HTML.class.php b/pandora_console/include/class/HTML.class.php index 55c87199c0..41231c6c17 100644 --- a/pandora_console/include/class/HTML.class.php +++ b/pandora_console/include/class/HTML.class.php @@ -926,6 +926,7 @@ class HTML { $form = $data['form']; $inputs = $data['inputs']; + $rawInputs = $data['rawInputs']; $js = $data['js']; $rawjs = $data['js_block']; $cb_function = $data['cb_function']; @@ -962,6 +963,11 @@ class HTML $output .= '
      '; $output .= '
      '; + // There is possible add raw inputs for this form. + if (empty($rawInputs) === false) { + $output .= $rawInputs; + } + $output .= '
        '.$output_submit.'
      '; $output .= ''; $output .= ''; From c18d3397302b11f6d61d32205e8dc65f196f3e56 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 23 Mar 2020 15:16:54 +0100 Subject: [PATCH 020/111] WIP: Backup upload --- .../modules/manage_block_templates.php | 11 +++-- .../include/class/ManageBlock.class.php | 40 +++++++++++++------ 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/pandora_console/godmode/modules/manage_block_templates.php b/pandora_console/godmode/modules/manage_block_templates.php index c9f55c14c2..3a93d975b0 100644 --- a/pandora_console/godmode/modules/manage_block_templates.php +++ b/pandora_console/godmode/modules/manage_block_templates.php @@ -73,10 +73,13 @@ if (is_ajax()) { $manageBlock->run(); // Get the id_np. $id_np = $manageBlock->getIdNp(); + $saveData = $manageBlock->getSaveData(); - // Show the proper window. - if ($id_np === -1) { - // List all Module Block. + if ($saveData === true) { + // Save the data sent + $manageBlock->saveData(); + } else if ($id_np === -1) { + // List all Module Blocks. $manageBlock->moduleBlockList(); } else { // Create new o update Template. @@ -88,7 +91,7 @@ if (is_ajax()) { - - - -
      - -
      - - - -'; - echo " $label "; - echo ''; - if (!extension_loaded($ext)) { - echo ""; - return 1; - } else { - echo ""; - return 0; - } - - echo ''; -} - -function check_include($ext, $label) -{ - echo ''; - echo " $label "; - echo ''; - if (!include $ext) { - echo ""; - return 1; - } else { - echo ""; - return 0; - } - - echo ''; -} - - -function check_exists($file, $label) -{ - echo ''; - echo " $label "; - echo ''; - if (!file_exists($file)) { - echo " "; - return 1; - } else { - echo " "; - return 0; - } - - echo ''; -} - - -function check_generic($ok, $label) -{ - echo ""; - if ($ok == 0) { - echo " "; - echo ''; - echo " $label "; - echo ''; - echo ''; - return 1; - } else { - echo " "; - echo ''; - echo " $label "; - echo ''; - echo ''; - return 0; - } -} - - -function check_writable($fullpath, $label) -{ - echo ""; - if (file_exists($fullpath)) { - if (is_writable($fullpath)) { - echo " "; - echo ''; - echo " $label "; - echo ''; - echo ''; - return 0; - } else { - echo " "; - echo ''; - echo " $label "; - echo ''; - echo ''; - return 1; - } - } else { - echo " "; - echo ''; - echo " $label "; - echo ''; - echo ''; - return 1; - } -} - - -function check_variable($var, $value, $label, $mode) -{ - echo ''; - echo " $label "; - echo ''; - if ($mode == 1) { - if ($var >= $value) { - echo " "; - return 0; - } else { - echo " "; - return 1; - } - } else if ($var == $value) { - echo " "; - return 0; - } else { - echo " "; - return 1; - } - - echo ''; -} - - -function parse_mysql_dump($url) -{ - if (file_exists($url)) { - $file_content = file($url); - $query = ''; - foreach ($file_content as $sql_line) { - if (trim($sql_line) != '' && strpos($sql_line, '-- ') === false) { - $query .= $sql_line; - if (preg_match("/;[\040]*\$/", $sql_line)) { - if (!$result = mysql_query($query)) { - echo mysql_error(); - // Uncomment for debug - echo "
      $query
      "; - return 0; - } - - $query = ''; - } - } - } - - return 1; - } else { - return 0; - } -} - - -function parse_mysqli_dump($connection, $url) -{ - if (file_exists($url)) { - $file_content = file($url); - $query = ''; - foreach ($file_content as $sql_line) { - if (trim($sql_line) != '' && strpos($sql_line, '-- ') === false) { - $query .= $sql_line; - if (preg_match("/;[\040]*\$/", $sql_line)) { - if (!$result = mysqli_query($connection, $query)) { - echo mysqli_error(); - // Uncomment for debug - echo "
      $query
      "; - return 0; - } - - $query = ''; - } - } - } - - return 1; - } else { - return 0; - } -} - - -function random_name($size) -{ - $temp = ''; - for ($a = 0; $a < $size; $a++) { - $temp = $temp.chr(rand(122, 97)); - } - - return $temp; -} - - -function print_logo_status($step, $step_total) -{ - global $banner; - - $header = " -
      -
      -
      - $banner -
      -
      "; - $header .= " -
      - Install step $step of $step_total -
      "; - - return $header; -} - - -// -// This function adjusts path settings in pandora db for FreeBSD. -// -// All packages and configuration files except operating system's base files -// are installed under /usr/local in FreeBSD. So, path settings in pandora db -// for some programs should be changed from the Linux default. -// -function adjust_paths_for_freebsd($engine, $connection=false) -{ - $adjust_sql = [ - "update trecon_script set script = REPLACE(script,'/usr/share','/usr/local/share');", - "update tconfig set value = REPLACE(value,'/usr/bin','/usr/local/bin') where token='netflow_daemon' OR token='netflow_nfdump' OR token='netflow_nfexpire';", - "update talert_commands set command = REPLACE(command,'/usr/bin','/usr/local/bin');", - "update talert_commands set command = REPLACE(command,'/usr/share', '/usr/local/share');", - "update tplugin set execute = REPLACE(execute,'/usr/share','/usr/local/share');", - "update tevent_response set target = REPLACE(target,'/usr/share','/usr/local/share');", - "insert into tconfig (token, value) VALUES ('graphviz_bin_dir', '/usr/local/bin');", - ]; - - for ($i = 0; $i < count($adjust_sql); $i++) { - switch ($engine) { - case 'mysql': - $result = mysql_query($adjust_sql[$i]); - break; - - case 'mysqli': - $result = mysqli_query($connection, $adjust_sql[$i]); - break; - - case 'oracle': - // Delete the last semicolon from current query - $query = substr($adjust_sql[$i], 0, (strlen($adjust_sql[$i]) - 1)); - $sql = oci_parse($connection, $query); - $result = oci_execute($sql); - break; - - case 'pgsql': - pg_send_query($connection, $adjust_sql[$i]); - $result = pg_get_result($connection); - break; - } - - if (!$result) { - return 0; - } - } - - return 1; -} - - -function install_step1() -{ - global $banner; - - echo " -
      -
      - ".print_logo_status(1, 6)." -
      -

      Welcome to Pandora FMS installation Wizard

      -

      This wizard helps you to quick install Pandora FMS console and main database in your system.

      -

      In four steps, this installer will check all dependencies and will create your configuration, ready to use.

      -

      For more information, please refer to documentation.
      - Pandora FMS Development Team

      - "; - if (file_exists('include/config.php')) { - echo "
      Warning: You already have a config.php file. - Configuration and database would be overwritten if you continued.
      "; - } - - echo '
      '; - echo ''; - $writable = check_writable('include', 'Checking if ./include is writable'); - if (file_exists('include/config.php')) { - $writable += check_writable('include/config.php', 'Checking if include/config.php is writable'); - } - - echo '
      '; - - echo "
      Warning: This installer will overwrite and destroy - your existing Pandora FMS configuration and Database. Before continue, - please be sure that you have no valuable Pandora FMS data in your Database.
      -
      "; - - echo "
      Upgrade: - If you want to upgrade from Pandora FMS 4.x to 5.0 version, please use the migration tool inside /extras directory in this setup. -
      "; - - echo '
      '; - - if ($writable == 0) { - echo "
      "; - echo ""; - echo '
      '; - } else { - echo "
      ERROR:You need to setup permissions to be able to write in ./include directory
      "; - } - - echo '
      '; - - echo "
      "; - echo " -
      -
      - Pandora FMS is an OpenSource Software project registered at - SourceForge -
      -
      "; -} - - -function install_step1_licence() -{ - echo " -
      -
      - ".print_logo_status(2, 6)." -
      -

      GPL2 Licence terms agreement

      -

      Pandora FMS is an OpenSource software project licensed under the GPL2 licence. Pandora FMS includes, as well, another software also licensed under LGPL and BSD licenses. Before continue, you must accept the licence terms.. -

      For more information, please refer to our website at http://pandorafms.org and contact us if you have any kind of question about the usage of Pandora FMS

      -

      If you dont accept the licence terms, please, close your browser and delete Pandora FMS files.

      - "; - - if (!file_exists('COPYING')) { - echo "
      Licence file 'COPYING' is not present in your distribution. This means you have some 'partial' Pandora FMS distribution. We cannot continue without accepting the licence file."; - echo '
      '; - } else { - echo "
      "; - echo "'; - echo '

      '; - echo "

      "; - } - - echo '
      '; - - echo "
      -
      -
      - Pandora FMS is an OpenSource Software project registered at - SourceForge -
      -
      "; -} - - -function install_step2() -{ - echo " -
      -
      - ".print_logo_status(3, 6)." -
      "; - echo '

      Checking software dependencies

      '; - echo ''; - $res = 0; - $res += check_variable(phpversion(), '7.0', 'PHP version >= 7.0', 1); - $res += check_extension('gd', 'PHP GD extension'); - $res += check_extension('ldap', 'PHP LDAP extension'); - $res += check_extension('snmp', 'PHP SNMP extension'); - $res += check_extension('session', 'PHP session extension'); - $res += check_extension('gettext', 'PHP gettext extension'); - $res += check_extension('mbstring', 'PHP Multibyte String'); - $res += check_extension('zip', 'PHP Zip'); - $res += check_extension('zlib', 'PHP Zlib extension'); - $res += check_extension('json', 'PHP json extension'); - $res += check_extension('curl', 'CURL (Client URL Library)'); - $res += check_extension('filter', 'PHP filter extension'); - $res += check_extension('calendar', 'PHP calendar extension'); - if (PHP_OS == 'FreeBSD') { - $res += check_exists('/usr/local/bin/twopi', 'Graphviz Binary'); - } else if (PHP_OS == 'NetBSD') { - $res += check_exists('/usr/pkg/bin/twopi', 'Graphviz Binary'); - } else if (substr(PHP_OS, 0, 3) == 'WIN') { - $res += check_exists("..\\..\\..\\Graphviz\\bin\\twopi.exe", 'Graphviz Binary'); - } else { - $res += check_exists('/usr/bin/twopi', 'Graphviz Binary'); - } - - echo ''; - check_extension('mysqli', 'PHP MySQL(mysqli) extension'); - echo '
      '; - echo "DB Engines"; - echo ''; - echo '
      '; - - if ($res > 0) { - echo " -
      You have some incomplete - dependencies. Please correct them or this installer - will not be able to finish your installation. -
      -
      - Remember, if you install any PHP module to comply - with these dependences, you need to restart - your HTTP/Apache server after it to use the new - modules. -
      -
      - Ignore it. -
      "; - } else { - echo "
      "; - echo " - "; - echo '
      '; - } - - echo '
      '; - echo "
      "; - echo " -
      -
      -
      -
      - Pandora FMS is an OpenSource Software project registered at - SourceForge -
      -
      "; -} - - -function install_step3() -{ - $options = ''; - if (extension_loaded('mysql')) { - $options .= ""; - } - - if (extension_loaded('mysqli')) { - $options .= ""; - } - - $error = false; - if (empty($options)) { - $error = true; - } - - echo " -
      -
      - ".print_logo_status(4, 6)." -
      -

      Environment and database setup

      -

      - This wizard will create your Pandora FMS database, - and populate it with all the data needed to run for the first time. -

      -

      - You need a privileged user to create database schema, this is usually root user. - Information about root user will not be used or stored anymore. -

      -

      - You can also deploy the scheme into an existing Database. - In this case you need a privileged Database user and password of that instance. -

      -

      - Now, please, complete all details to configure your database and environment setup. -

      -
      - Warning: This installer will overwrite and destroy your existing - Pandora FMS configuration and Database. Before continue, - please be sure that you have no valuable Pandora FMS data in your Database. -

      -
      "; - - if (extension_loaded('oci8')) { - echo "
      For Oracle installation an existing Database with a privileged user is needed.
      "; - } - - if (!$error) { - echo ""; - } - - echo ""; - echo '"; - - // the field dbgrant is only shown when the DB host is different from 127.0.0.1 or localhost - echo " - - "; - - echo " "; - - echo ""; - echo '
      '; - echo 'DB Engine
      '; - - if ($error) { - echo " -
      - Warning: You haven't a any DB engine with PHP. Please check the previous step to DB engine dependencies. -
      "; - } else { - echo "'; - - echo '
      '; - echo ' Installation in
      '; - echo "'; - } - - echo "
      DB User with privileges
      - - -
      DB Password for this user
      - - -
      DB Hostname
      - - -
      DB Name (pandora by default)
      - - -
      Drop Database if exists
      - -
      Full path to HTTP publication directory
      - For example /var/www/pandora_console/ -
      - - -
      '; - echo "URL path to Pandora FMS Console
      - For example '/pandora_console' -
      - -
      - "; - - if (!$error) { - echo "
      "; - echo " - "; - echo '
      '; - ?> - - '; - - echo ''; - - echo "
      "; - echo "
      -
      - Pandora FMS is an OpenSource Software project registered at - SourceForge -
      -
      "; -} - - -function install_step4() -{ - $pandora_config = 'include/config.php'; - - if ((! isset($_POST['user'])) || (! isset($_POST['dbname'])) || (! isset($_POST['host'])) - || (! isset($_POST['pass'])) || (!isset($_POST['engine'])) || (! isset($_POST['db_action'])) - ) { - $dbpassword = ''; - $dbuser = ''; - $dbhost = ''; - $dbname = ''; - $engine = ''; - $dbaction = ''; - $dbgrant = ''; - } else { - $engine = $_POST['engine']; - $dbpassword = $_POST['pass']; - $dbuser = $_POST['user']; - $dbhost = $_POST['host']; - $dbaction = $_POST['db_action']; - if (isset($_POST['dbgrant']) && $_POST['dbgrant'] != '') { - $dbgrant = $_POST['dbgrant']; - } else { - $dbgrant = $_SERVER['SERVER_ADDR']; - } - - if (isset($_POST['drop'])) { - $dbdrop = $_POST['drop']; - } else { - $dbdrop = 0; - } - - $dbname = $_POST['dbname']; - if (isset($_POST['url'])) { - $url = $_POST['url']; - } else { - $url = 'http://localhost'; - } - - if (isset($_POST['path'])) { - $path = $_POST['path']; - $path = str_replace('\\', '/', $path); - // Windows compatibility - } else { - $path = '/var/www'; - } - } - - $everything_ok = 0; - $step1 = 0; - $step2 = 0; - $step3 = 0; - $step4 = 0; - $step5 = 0; - $step6 = 0; - $step7 = 0; - - echo " -
      -
      - ".print_logo_status(5, 6)." -
      -

      Creating database and default configuration file

      - "; - switch ($engine) { - case 'mysql': - if (! mysql_connect($dbhost, $dbuser, $dbpassword)) { - check_generic(0, 'Connection with Database'); - } else { - check_generic(1, 'Connection with Database'); - - // Drop database if needed and don't want to install over an existing DB - if ($dbdrop == 1) { - mysql_query("DROP DATABASE IF EXISTS `$dbname`"); - } - - // Create schema - if ($dbaction == 'db_new' || $dbdrop == 1) { - $step1 = mysql_query("CREATE DATABASE `$dbname`"); - check_generic($step1, "Creating database '$dbname'"); - } else { - $step1 = 1; - } - - if ($step1 == 1) { - $step2 = mysql_select_db($dbname); - check_generic($step2, "Opening database '$dbname'"); - - $step3 = parse_mysql_dump('pandoradb.sql'); - check_generic($step3, 'Creating schema'); - - $step4 = parse_mysql_dump('pandoradb_data.sql'); - check_generic($step4, 'Populating database'); - if (PHP_OS == 'FreeBSD') { - $step_freebsd = adjust_paths_for_freebsd($engine); - check_generic($step_freebsd, 'Adjusting paths in database for FreeBSD'); - } - - $random_password = random_name(8); - $host = $dbhost; - // set default granted origin to the origin of the queries - if (($dbhost != 'localhost') && ($dbhost != '127.0.0.1')) { - $host = $dbgrant; - // if the granted origin is different from local machine, set the valid origin - } - - $step5 = mysql_query( - "GRANT ALL PRIVILEGES ON `$dbname`.* to pandora@$host - IDENTIFIED BY '".$random_password."'" - ); - mysql_query('FLUSH PRIVILEGES'); - check_generic($step5, "Established privileges for user pandora. A new random password has been generated: $random_password
      Please write it down, you will need to setup your Pandora FMS server, editing the /etc/pandora/pandora_server.conf file
      "); - - $step6 = is_writable('include'); - check_generic($step6, "Write permissions to save config file in './include'"); - - $cfgin = fopen('include/config.inc.php', 'r'); - $cfgout = fopen($pandora_config, 'w'); - $config_contents = fread($cfgin, filesize('include/config.inc.php')); - $dbtype = 'mysql'; - $config_new = ''; - $step7 = fputs($cfgout, $config_new); - $step7 = ($step7 + fputs($cfgout, $config_contents)); - if ($step7 > 0) { - $step7 = 1; - } - - fclose($cfgin); - fclose($cfgout); - chmod($pandora_config, 0600); - check_generic($step7, "Created new config file at '".$pandora_config."'"); - } - } - - if (($step7 + $step6 + $step5 + $step4 + $step3 + $step2 + $step1) == 7) { - $everything_ok = 1; - } - break; - - case 'mysqli': - $connection = mysqli_connect($dbhost, $dbuser, $dbpassword); - if (mysqli_connect_error() > 0) { - check_generic(0, 'Connection with Database'); - } else { - check_generic(1, 'Connection with Database'); - - // Drop database if needed and don't want to install over an existing DB - if ($dbdrop == 1) { - mysqli_query($connection, "DROP DATABASE IF EXISTS `$dbname`"); - } - - // Create schema - if ($dbaction == 'db_new' || $dbdrop == 1) { - $step1 = mysqli_query($connection, "CREATE DATABASE `$dbname`"); - check_generic($step1, "Creating database '$dbname'"); - } else { - $step1 = 1; - } - - if ($step1 == 1) { - $step2 = mysqli_select_db($connection, $dbname); - check_generic($step2, "Opening database '$dbname'"); - - $step3 = parse_mysqli_dump($connection, 'pandoradb.sql'); - check_generic($step3, 'Creating schema'); - - $step4 = parse_mysqli_dump($connection, 'pandoradb_data.sql'); - check_generic($step4, 'Populating database'); - if (PHP_OS == 'FreeBSD') { - $step_freebsd = adjust_paths_for_freebsd($engine, $connection); - check_generic($step_freebsd, 'Adjusting paths in database for FreeBSD'); - } - - $random_password = random_name(8); - $host = $dbhost; - // set default granted origin to the origin of the queries - if (($dbhost != 'localhost') && ($dbhost != '127.0.0.1')) { - $host = $dbgrant; - // if the granted origin is different from local machine, set the valid origin - } - - $step5 = mysqli_query( - $connection, - "GRANT ALL PRIVILEGES ON `$dbname`.* to pandora@$host - IDENTIFIED BY '".$random_password."'" - ); - mysqli_query($connection, 'FLUSH PRIVILEGES'); - check_generic($step5, "Established privileges for user pandora. A new random password has been generated: $random_password
      Please write it down, you will need to setup your Pandora FMS server, editing the /etc/pandora/pandora_server.conf file
      "); - - $step6 = is_writable('include'); - check_generic($step6, "Write permissions to save config file in './include'"); - - $cfgin = fopen('include/config.inc.php', 'r'); - $cfgout = fopen($pandora_config, 'w'); - $config_contents = fread($cfgin, filesize('include/config.inc.php')); - $dbtype = 'mysql'; - $config_new = ''; - $step7 = fputs($cfgout, $config_new); - $step7 = ($step7 + fputs($cfgout, $config_contents)); - if ($step7 > 0) { - $step7 = 1; - } - - fclose($cfgin); - fclose($cfgout); - chmod($pandora_config, 0600); - check_generic($step7, "Created new config file at '".$pandora_config."'"); - } - } - - if (($step7 + $step6 + $step5 + $step4 + $step3 + $step2 + $step1) == 7) { - $everything_ok = 1; - } - break; - } - - echo '
      '; - - if ($everything_ok == 1) { - echo "
      "; - echo " - "; - echo '
      '; - } else { - $info = "
      There were some problems. - Installation was not completed. -

      Please correct failures before trying again. - All database "; - if ($engine == 'oracle') { - $info .= 'objects '; - } else { - $info .= 'schemes '; - } - - $info .= 'created in this step have been dropped.

      -
      '; - echo $info; - - switch ($engine) { - case 'mysql': - if (mysql_error() != '') { - echo "
      ERROR: ".mysql_error().'.
      '; - } - - if ($step1 == 1) { - mysql_query("DROP DATABASE $dbname"); - } - break; - - case 'mysqli': - if (mysqli_error($connection) != '') { - echo "
      ERROR: ".mysqli_error($connection).'.
      '; - } - - if ($step1 == 1) { - mysqli_query($connection, "DROP DATABASE $dbname"); - } - break; - } - - echo '
      '; - } - - echo '
      '; - echo "
      "; - echo " -
      -
      - Pandora FMS is an Open Source Software project registered at - SourceForge -
      -
      "; -} - - -function install_step5() -{ - echo " -
      -
      - ".print_logo_status(6, 6)." -
      -

      Installation complete

      -

      For security, you now must manually delete this installer - ('install.php') file before trying to access to your Pandora FMS console. -

      You should also install Pandora FMS Servers before trying to monitor anything; - please read documentation on how to install it.

      -

      Default user is 'admin' with password 'pandora', - please change it both as soon as possible.

      -

      Don't forget to check http://pandorafms.com - for updates. -

      Select if you want to rename 'install.php'.

      -
      - - -
      -


      . -

      -
      "; - - echo "
      -
      - Pandora FMS is an OpenSource Software project registered at - SourceForge -
      -
      "; -} diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index d40787c74a..2d446e007d 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -771,7 +771,7 @@ CREATE TABLE IF NOT EXISTS `trecon_task` ( `description` varchar(250) NOT NULL default '', `subnet` text NOT NULL, `id_network_profile` text, - `direct_report` tinyint(1) unsigned NOT NULL default 0, + `review_mode` tinyint(1) unsigned NOT NULL default 0, `id_group` int(10) unsigned NOT NULL default 1, `utimestamp` bigint(20) unsigned NOT NULL default 0, `status` tinyint(4) NOT NULL default 0, @@ -803,6 +803,7 @@ CREATE TABLE IF NOT EXISTS `trecon_task` ( `snmp_security_level` varchar(25) NOT NULL default '', `wmi_enabled` tinyint(1) unsigned DEFAULT 0, `auth_strings` text, + `auto_monitor` TINYINT(1) UNSIGNED DEFAULT 1, `autoconfiguration_enabled` tinyint(1) unsigned default 0, `summary` text, `type` int NOT NULL default 0, @@ -827,18 +828,13 @@ CREATE TABLE `tdiscovery_tmp_agents` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `tdiscovery_tmp_connections` ( - `id_rt` int(10) unsigned NOT NULL, - `id1` int(10) unsigned NOT NULL AUTO_INCREMENT, - `id2` int(10) unsigned NOT NULL, - `if1` text, - `if2` text, - PRIMARY KEY (`id1`,`id2`), - CONSTRAINT `tdtc_trt` FOREIGN KEY (`id_rt`) - REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `tdtc_tdta1` FOREIGN KEY (`id1`) - REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `tdtc_tdta2` FOREIGN KEY (`id2`) - REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id_rt` int(10) unsigned NOT NULL, + `dev_1` text, + `dev_2` text, + `if_1` text, + `if_2` text, + PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------------------------------------------------- @@ -945,6 +941,16 @@ CREATE TABLE IF NOT EXISTS `tnetwork_profile` ( PRIMARY KEY (`id_np`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- ---------------------------------------------------------------------- +-- Table `tpen` +-- ---------------------------------------------------------------------- +CREATE TABLE `tpen` ( + `id_np` int(10) unsigned NOT NULL, + `pen` int(10) unsigned NOT NULL, + PRIMARY KEY (`id_np`,`pen`), + CONSTRAINT `fk_np_id` FOREIGN KEY (`id_np`) REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + -- ---------------------------------------------------------------------- -- Table `tnetwork_profile_component` -- ---------------------------------------------------------------------- diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index 99ddf48796..ca2eae5157 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -3076,7 +3076,7 @@ sub pandora_create_module_from_network_component ($$$$) { ########################################################################## sub pandora_create_module_from_hash ($$$) { my ($pa_config, $parameters, $dbh) = @_; - + logger($pa_config, "Creating module '$parameters->{'nombre'}' for agent ID $parameters->{'id_agente'}.", 10); @@ -3107,8 +3107,12 @@ sub pandora_create_module_from_hash ($$$) { } # Encrypt SNMP v3 passwords. - if ($parameters->{'id_tipo_modulo'} >= 15 && $parameters->{'id_tipo_modulo'} <= 18 && - $parameters->{'tcp_send'} eq '3') { + if (defined($parameters->{'tcp_send'}) + && $parameters->{'tcp_send'} eq '3' + && defined($parameters->{'id_tipo_modulo'}) + && $parameters->{'id_tipo_modulo'} >= 15 + && $parameters->{'id_tipo_modulo'} <= 18 + ) { $parameters->{'custom_string_2'} = pandora_input_password($pa_config, $parameters->{'custom_string_2'}); } @@ -3116,7 +3120,11 @@ sub pandora_create_module_from_hash ($$$) { 'tagente_modulo', $parameters); my $status = 4; - if (defined ($parameters->{'id_tipo_modulo'}) && ($parameters->{'id_tipo_modulo'} == 21 || $parameters->{'id_tipo_modulo'} == 22 || $parameters->{'id_tipo_modulo'} == 23)) { + if (defined ($parameters->{'id_tipo_modulo'}) + && ($parameters->{'id_tipo_modulo'} == 21 + || $parameters->{'id_tipo_modulo'} == 22 + || $parameters->{'id_tipo_modulo'} == 23) + ) { $status = 0; } diff --git a/pandora_server/lib/PandoraFMS/DB.pm b/pandora_server/lib/PandoraFMS/DB.pm index b190c763da..d712a45ea6 100644 --- a/pandora_server/lib/PandoraFMS/DB.pm +++ b/pandora_server/lib/PandoraFMS/DB.pm @@ -81,6 +81,8 @@ our @EXPORT = qw( get_module_id get_module_name get_nc_profile_name + get_pen_templates + get_nc_profile_advanced get_os_id get_os_name get_plugin_id @@ -657,6 +659,39 @@ sub get_nc_profile_name ($$) { return get_db_value ($dbh, "SELECT * FROM tnetwork_profile WHERE id_np = ?", $nc_id); } +########################################################################## +## Return all network component's profile ids matching given PEN. +########################################################################## +sub get_pen_templates($$) { + my ($dbh, $pen) = @_; + + my @results = get_db_rows( + $dbh, + 'SELECT t.`id_np` + FROM `tnetwork_profile` t + INNER JOIN `tpen` p ON p.`id_np` = t.`id_np` + WHERE p.`pen` = ?', + $pen + ); + + return @results; +} + +########################################################################## +## Return a network component's profile data and pen list, given its ID. +########################################################################## +sub get_nc_profile_advanced($$) { + my ($dbh, $id_nc) = @_; + return get_db_single_row( + $dbh, + 'SELECT t.*,GROUP_CONCAT(p.pen) AS "pen" + FROM `tnetwork_profile` t LEFT JOIN `tpen` p ON t.id_np = p.id_np + WHERE t.`id_np` = ? + GROUP BY t.`id_np`', + $id_nc + ); +} + ########################################################################## ## Return user profile ID given the user id, group id and profile id. ########################################################################## diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index c16d93f42f..68db6f0467 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -74,7 +74,7 @@ use constant { DISCOVERY_CLOUD_AZURE_COMPUTE => 8, DISCOVERY_DEPLOY_AGENTS => 9, DISCOVERY_APP_SAP => 10, - DISCOVERY_SEARCH => 0, + DISCOVERY_REVIEW => 0, DISCOVERY_STANDARD => 1, DISCOVERY_RESULTS => 2, }; @@ -469,7 +469,7 @@ sub PandoraFMS::Recon::Base::test_module($$) { if ($test->{'id_tipo_modulo'} >= 15 && $test->{'id_tipo_modulo'} <= 18) { # SNMP $value = $self->call( - 'snmp_get', + 'snmp_get_value', $test->{'ip_target'}, $test->{'snmp_oid'} ); @@ -565,32 +565,194 @@ sub PandoraFMS::Recon::Base::test_module($$) { } +################################################################################ +# Create interface modules for the given agent (if needed). +################################################################################ +sub PandoraFMS::Recon::Base::create_interface_modules($$) { + my ($self, $device) = @_; + + # Add interfaces to the agent if it responds to SNMP. + return unless ($self->is_snmp_discovered($device)); + my $community = $self->get_community($device); + + my @output = $self->snmp_get_value_array($device, $PandoraFMS::Recon::Base::IFINDEX); + foreach my $if_index (@output) { + next unless ($if_index =~ /^[0-9]+$/); + + # Check the status of the interface. + my $if_status = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index"); + next unless $if_status == 1; + + # Fill the module description with the IP and MAC addresses. + my $mac = $self->get_if_mac($device, $if_index); + my $ip = $self->get_if_ip($device, $if_index); + my $if_desc = ($mac ne '' ? "MAC $mac " : '') . ($ip ne '' ? "IP $ip" : ''); + + # Get the name of the network interface. + my $if_name = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFNAME.$if_index"); + $if_name = "if$if_index" unless defined ($if_name); + $if_name =~ s/"//g; + $if_name = clean_blank($if_name); + + # Interface status module. + $self->call( + 'add_module', + $device, + { + 'id_tipo_modulo' => 18, + 'id_modulo' => 2, + 'name' => $if_name."_ifOperStatus", + 'descripcion' => safe_input( + $if_desc + ), + 'ip_target' => $device, + 'tcp_send' => $self->{'task_data'}{'snmp_version'}, + 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'}, + 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'}, + 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'}, + 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'}, + 'snmp_community' => $community, + 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index" + } + ); + + # Incoming traffic module. + my $if_hc_in_octets = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFHCINOCTECTS.$if_index"); + if (defined($if_hc_in_octets)) { + # Use HC counters. + # ifHCInOctets + $self->call( + 'add_module', + $device, + { + 'id_tipo_modulo' => 16, + 'id_modulo' => 2, + 'name' => $if_name."_ifHCInOctets", + 'descripcion' => safe_input( + 'The total number of octets received on the interface, including framing characters. This object is a 64-bit version of ifInOctets.' + ), + 'ip_target' => $device, + 'tcp_send' => $self->{'task_data'}{'snmp_version'}, + 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'}, + 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'}, + 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'}, + 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'}, + 'snmp_community' => $community, + 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCINOCTECTS.$if_index" + } + ); + } else { + # Use 32b counters. + # ifInOctets + $self->call( + 'add_module', + $device, + { + 'id_tipo_modulo' => 16, + 'id_modulo' => 2, + 'name' => $if_name."_ifInOctets", + 'descripcion' => safe_input( + 'The total number of octets received on the interface, including framing characters.' + ), + 'ip_target' => $device, + 'tcp_send' => $self->{'task_data'}{'snmp_version'}, + 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'}, + 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'}, + 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'}, + 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'}, + 'snmp_community' => $community, + 'snmp_oid' => "$PandoraFMS::Recon::Base::IFINOCTECTS.$if_index" + } + ); + } + + # Outgoing traffic module. + my $if_hc_out_octets = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFHCOUTOCTECTS.$if_index"); + if (defined($if_hc_out_octets)) { + # Use HC counters. + # ifHCOutOctets + $self->call( + 'add_module', + $device, + { + 'id_tipo_modulo' => 16, + 'id_modulo' => 2, + 'name' => $if_name."_ifHCOutOctets", + 'descripcion' => safe_input( + 'The total number of octets received on the interface, including framing characters. This object is a 64-bit version of ifOutOctets.' + ), + 'ip_target' => $device, + 'tcp_send' => $self->{'task_data'}{'snmp_version'}, + 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'}, + 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'}, + 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'}, + 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'}, + 'snmp_community' => $community, + 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCOUTOCTECTS.$if_index" + } + ); + } else { + # Use 32b counters. + # ifOutOctets + $self->call( + 'add_module', + $device, + { + 'id_tipo_modulo' => 16, + 'id_modulo' => 2, + 'name' => $if_name."_ifOutOctets", + 'descripcion' => safe_input( + 'The total number of octets received on the interface, including framing characters.' + ), + 'ip_target' => $device, + 'tcp_send' => $self->{'task_data'}{'snmp_version'}, + 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'}, + 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'}, + 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'}, + 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'}, + 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'}, + 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'}, + 'snmp_community' => $community, + 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOUTOCTECTS.$if_index" + } + ); + } + } + +} + ################################################################################ # Create network profile modules for the given agent. ################################################################################ sub PandoraFMS::Recon::Base::create_network_profile_modules($$) { my ($self, $device) = @_; - # - # Plugin - # SNMP - # WMI - # ICMP - # + my @template_ids = (); - return if is_empty($self->{'id_network_profile'}); + if (is_enabled($self->{'task_data'}{'auto_monitor'})) { + # Apply PEN monitoring template (HW). + push @template_ids, get_pen_templates($self->{'dbh'}, $self->get_pen($device)); + } else { + # Return if no specific templates are selected. + return if is_empty($self->{'id_network_profile'}); + } - my @templates = split /,/, $self->{'id_network_profile'}; + push @template_ids, split /,/, $self->{'id_network_profile'} + unless is_empty($self->{'id_network_profile'}); my $data = $self->{'agents_found'}{$device}; - foreach my $t_id (@templates) { + foreach my $t_id (@template_ids) { # 1. Retrieve template info. - my $template = get_db_single_row( - $self->{'dbh'}, - 'SELECT * FROM `tnetwork_profile` WHERE `id_np` = ?', - $t_id - ); + my $template = get_nc_profile_advanced($self->{'dbh'}, $t_id); # 2. Verify Private Enterprise Number matches (PEN) if (defined($template->{'pen'})) { @@ -599,7 +761,7 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$) { next unless (is_in_array(\@penes, $data->{'pen'})); } - # 2. retrieve module list from target template. + # 3. Retrieve module list from target template. my @np_components = get_db_rows( $self->{'dbh'}, 'SELECT * FROM tnetwork_profile_component WHERE id_np = ?', @@ -607,7 +769,7 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$) { ); foreach my $np_component (@np_components) { - # 2. Test each possible module. + # 4. Register each module (candidate). 'add_module' will test them. my $component = get_db_single_row( $self->{'dbh'}, 'SELECT * FROM tnetwork_component WHERE id_nc = ?', @@ -643,8 +805,8 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { my $force_creation = 0; - if (defined($self->{'task_data'}{'direct_report'}) - && $self->{'task_data'}{'direct_report'} == DISCOVERY_STANDARD + if (defined($self->{'task_data'}{'review_mode'}) + && $self->{'task_data'}{'review_mode'} == DISCOVERY_STANDARD ) { $force_creation = 1; } @@ -652,8 +814,8 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { # # Creation # - if(defined($self->{'task_data'}{'direct_report'}) - && $self->{'task_data'}{'direct_report'} == DISCOVERY_RESULTS + if(defined($self->{'task_data'}{'review_mode'}) + && $self->{'task_data'}{'review_mode'} == DISCOVERY_RESULTS ) { # Load cache. my @rows = get_db_rows( @@ -754,6 +916,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { $data->{'agent'}{'agent_id'} = $agent_id; } + $data->{'agent'}{'modo'} = $agent_learning; $self->call('message', "Agent id: ".$data->{'agent'}{'agent_id'}, 5); # Create selected modules. @@ -817,18 +980,24 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { $module->{'__module_component'} = 1; } else { # Create module - Direct. + my $name = $module->{'name'}; + delete $module->{'name'}; $agentmodule_id = pandora_create_module_from_hash( $self->{'pa_config'}, { + %{$module}, 'id_tipo_modulo' => $id_tipo_modulo, 'id_modulo' => $module->{'id_modulo'}, - 'nombre' => safe_input($module->{'name'}), + 'nombre' => safe_input($name), 'descripcion' => safe_input($description), 'id_agente' => $agent_id, 'ip_target' => $data->{'agent'}{'direccion'} }, $self->{'dbh'} ); + + $module->{'name'} = $name; + } # Restore. @@ -854,6 +1023,8 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { ); }; + push @agents, $data->{'agent'}; + # Update. db_do( $self->{'dbh'}, @@ -868,6 +1039,49 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { } + # Update parent relationships. + foreach my $agent (@agents) { + # Avoid processing if does not exist. + next unless (defined($agent->{'agent_id'})); + + # Avoid processing undefined parents. + next unless defined($agent->{'parent'}); + + # Get parent id. + my $parent = get_agent_from_addr($self->{'dbh'}, $agent->{'parent'}); + if (!defined($parent)) { + $parent = get_agent_from_name($self->{'dbh'}, $agent->{'parent'}); + } + next unless defined($parent); + + # Is the agent in learning mode? + next unless ($agent->{'modo'} == 1); + + # Connect the host to its parent. + db_do($self->{'dbh'}, + 'UPDATE tagente SET id_parent=? WHERE id_agente=?', + $parent->{'id_agente'}, $agent->{'agent_id'} + ); + } + + # Connect agents. + my @connections = get_db_rows( + $self->{'dbh'}, + 'SELECT * FROM tdiscovery_tmp_connections WHERE id_rt = ?', + $self->{'task_data'}{'id_rt'} + ); + + foreach my $cn (@connections) { + $self->call('connect_agents', + $cn->{'dev_1'}, + $cn->{'if_1'}, + $cn->{'dev_2'}, + $cn->{'if_2'}, + # Force creation if direct. + $force_creation + ); + } + # Data creation finished. return; } @@ -876,6 +1090,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { # # Cleanup previous results. # + $self->call('message', "Cleanup previous results", 6); db_do( $self->{'dbh'}, 'DELETE FROM tdiscovery_tmp_agents ' @@ -887,6 +1102,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { # Store and review. # + $self->call('message', "Storing results", 6); my @hosts = keys %{$self->{'agents_found'}}; $self->{'step'} = STEP_PROCESSING; my ($progress, $step) = (90, 10.0 / scalar(@hosts)); # From 90% to 100%. @@ -935,6 +1151,8 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { $encoded ); } + + $self->call('message', "Completed", 5); } ################################################################################ @@ -948,22 +1166,54 @@ sub PandoraFMS::Recon::Base::apply_monitoring($) { $self->{'step'} = STEP_MONITORING; # From 80% to 90%. my ($progress, $step) = (80, 10.0 / scalar(@hosts)); + my ($partial, $sub_step) = (0, 100 / scalar(@hosts)); foreach my $label (keys %{$self->{'agents_found'}}) { + $self->{'c_network_percent'} = $partial; + $self->{'c_network_name'} = $label; $self->call('update_progress', $progress); $progress += $step; + $partial += $sub_step; $self->call('message', "Checking modules for $label", 5); + + # Monitorization selected. $self->call('create_network_profile_modules', $label); + # Monitorization - interfaces + $self->call('create_interface_modules', $label); + } + $self->{'c_network_percent'} = 100; + $self->call('update_progress', $progress); } ################################################################################ # Connect the given devices in the Pandora FMS database. ################################################################################ -sub PandoraFMS::Recon::Base::connect_agents($$$$$) { - my ($self, $dev_1, $if_1, $dev_2, $if_2) = @_; +sub PandoraFMS::Recon::Base::connect_agents($$$$$;$) { + my ($self, $dev_1, $if_1, $dev_2, $if_2, $force) = @_; + + if($self->{'task_data'}{'review_mode'} == DISCOVERY_REVIEW + || is_enabled($force) + ) { + # Store in tdiscovery_tmp_connections; + + db_process_insert( + $self->{'dbh'}, + 'id', + 'tdiscovery_tmp_connections', + { + 'id_rt' => $self->{'task_data'}{'id_rt'}, + 'dev_1' => $dev_1, + 'if_1' => $if_1, + 'dev_2' => $dev_2, + 'if_2' => $if_2, + } + ); + + return; + } # Get the agent for the first device. my $agent_1 = get_agent_from_addr($self->{'dbh'}, $dev_1); @@ -1209,7 +1459,7 @@ sub PandoraFMS::Recon::Base::create_agent($$) { next unless ($if_index =~ /^[0-9]+$/); # Check the status of the interface. - if ($self->{'all_ifaces'} == 0) { + if (!is_enabled($self->{'all_ifaces'})) { my $if_status = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index"); next unless $if_status == 1; } @@ -1447,25 +1697,11 @@ sub PandoraFMS::Recon::Base::set_parent($$$) { return unless ($self->{'parent_detection'} == 1); - # Get the agent for the host. - my $agent = get_agent_from_addr($self->{'dbh'}, $host); - if (!defined($agent)) { - $agent = get_agent_from_name($self->{'dbh'}, $host); - } - return unless defined($agent); + # Do not edit 'not scaned' agents. + return if is_empty($self->{'agents_found'}{$host}{'agent'}); - # Check if the parent agent exists. - my $agent_parent = get_agent_from_addr($self->{'dbh'}, $parent); - if (!defined($agent_parent)) { - $agent_parent = get_agent_from_name($self->{'dbh'}, $parent); - } - return unless (defined ($agent_parent)); + $self->{'agents_found'}{$host}{'parent'} = $parent; - # Is the agent in learning mode? - return unless ($agent_parent->{'modo'} == 1); - - # Connect the host to its parent. - db_do($self->{'dbh'}, 'UPDATE tagente SET id_parent=? WHERE id_agente=?', $agent_parent->{'id_agente'}, $agent->{'id_agente'}); } ################################################################################ diff --git a/pandora_server/lib/PandoraFMS/NetworkServer.pm b/pandora_server/lib/PandoraFMS/NetworkServer.pm index 755a05bf8c..0bca799815 100644 --- a/pandora_server/lib/PandoraFMS/NetworkServer.pm +++ b/pandora_server/lib/PandoraFMS/NetworkServer.pm @@ -384,6 +384,7 @@ sub pandora_query_snmp ($$$$) { my $output; # Command output # If not defined, always snmp v1 (standard) + $snmp_version = '1' unless defined($snmp_version); if ($snmp_version ne '1' && $snmp_version ne '2' && $snmp_version ne '2c' && $snmp_version ne '3') { $snmp_version = '1'; @@ -591,7 +592,7 @@ sub exec_network_module ($$$$) { my %data = ("data" => $module_data); pandora_process_module ($pa_config, \%data, '', $module, '', $timestamp, $utimestamp, $server_id, $dbh); - if ($agent_os_version eq ''){ + if (!defined($agent_os_version) || $agent_os_version eq ''){ $agent_os_version = $pa_config->{'servername'}.'_Net'; } diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 450db59933..8d2db93fb2 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -19,6 +19,7 @@ use PandoraFMS::Recon::Util; # Constants. use constant { STEP_SCANNING => 1, + STEP_CAPABILITIES => 7, STEP_AFT => 2, STEP_TRACEROUTE => 3, STEP_GATEWAY => 4, @@ -38,7 +39,7 @@ use constant { DISCOVERY_CLOUD_AZURE_COMPUTE => 8, DISCOVERY_DEPLOY_AGENTS => 9, DISCOVERY_APP_SAP => 10, - DISCOVERY_SEARCH => 0, + DISCOVERY_REVIEW => 0, DISCOVERY_STANDARD => 1, DISCOVERY_RESULTS => 2, }; @@ -351,7 +352,7 @@ sub aft_connectivity($$) { # Get the name of the host interface if available. my $host_if_name = $self->get_iface($aft_mac); - $host_if_name = defined($host_if_name) ? $host_if_name : 'ping'; + $host_if_name = defined($host_if_name) ? $host_if_name : 'Host Alive'; # Get the interface associated to the port were we found the MAC address. my $switch_if_name = $self->get_if_from_aft($switch, $aft_mac); @@ -459,6 +460,9 @@ sub snmp_discovery($$) { } } + # Create an agent for the device and add it to the list of known hosts. + push(@{$self->{'hosts'}}, $device); + # Create an agent for the device and add it to the list of known hosts. $self->add_agent($device); @@ -651,6 +655,17 @@ sub get_connections($) { return $self->{'connections'}; } +################################################################################ +# Return the PEN associated to target host. +################################################################################ +sub get_pen($$) { + my ($self, $host) = @_; + + return undef unless ref($self->{'pen'}) eq 'HASH'; + + return $self->{'pen'}->{$host}; +} + ################################################################################ # Return the parent relationship hash. ################################################################################ @@ -1341,7 +1356,8 @@ sub add_module($$$) { && $data->{'name'} ne ''; # Test module. Is it success? - return unless $self->call('test_module', $agent, $data); + my $rs = $self->call('test_module', $agent, $data); + return unless is_enabled($rs); $self->{'agents_found'}->{$agent}->{'modules'}{$data->{'name'}} = $data; @@ -1418,7 +1434,6 @@ sub scan_subnet($) { my @block = pandora_block_ping( { 'fping' => $self->{'fping'}, - # XXX CAMBIAR POR 0.5 'networktimeout' => 0.5 # use fping defaults }, @hosts[$block_index .. $to - 1] @@ -1452,9 +1467,12 @@ sub scan_subnet($) { $total_hosts = scalar keys %hosts_alive; $step = 25.0 / scalar(@subnets) / $total_hosts; $subnet_step = 50.0 / $total_hosts; + + $self->{'step'} = STEP_CAPABILITIES; foreach my $addr (keys %hosts_alive) { # Increase self summary.alive hosts. $self->call('message', "Scanning host: $addr", 5); + $self->{'c_network_name'} = $addr; # Update progress. $progress += $step; @@ -1820,10 +1838,11 @@ sub scan($) { } } - if(defined($self->{'task_data'}{'direct_report'}) - && $self->{'task_data'}{'direct_report'} == DISCOVERY_RESULTS + if(defined($self->{'task_data'}{'review_mode'}) + && $self->{'task_data'}{'review_mode'} == DISCOVERY_RESULTS ) { # Use Cached results. + $self->{'step'} = STEP_PROCESSING; $self->call('report_scanned_agents'); # Done! @@ -1834,6 +1853,7 @@ sub scan($) { # Find devices. $self->call('message', "[1/6] Scanning the network...", 3); + $self->{'c_network_name'} = ''; $self->{'step'} = STEP_SCANNING; $self->call('update_progress', $progress); @@ -1850,6 +1870,7 @@ sub scan($) { # Connectivity from address forwarding tables. $self->call('message', "[2/6] Finding address forwarding table connectivity...", 3); + $self->{'c_network_name'} = ''; $self->{'step'} = STEP_AFT; ($progress, $step) = (50, 10.0 / scalar(@hosts)); # From 50% to 60%. for (my $i = 0; defined($hosts[$i]); $i++) { @@ -1860,6 +1881,7 @@ sub scan($) { # Connect hosts that are still unconnected using traceroute. $self->call('message', "[3/6] Finding traceroute connectivity.", 3); + $self->{'c_network_name'} = ''; $self->{'step'} = STEP_TRACEROUTE; ($progress, $step) = (60, 10.0 / scalar(@hosts)); # From 60% to 70%. foreach my $host (@hosts) { @@ -1871,6 +1893,7 @@ sub scan($) { # Connect hosts that are still unconnected using known gateways. $self->call('message', "[4/6] Finding host to gateway connectivity.", 3); + $self->{'c_network_name'} = ''; $self->{'step'} = STEP_GATEWAY; ($progress, $step) = (70, 10.0 / scalar(@hosts)); # From 70% to 80%. $self->get_routes(); # Update the route cache. @@ -1941,7 +1964,7 @@ sub snmp_pen($$) { $self->{'pen'} = {} if ref($self->{'pen'}) ne 'HASH'; - $self->{'pen'}{$addr} = $self->snmp_get($addr, $PEN_OID); + $self->{'pen'}{$addr} = $self->snmp_get_value($addr, $PEN_OID); if(defined($self->{'pen'}{$addr})) { ($self->{'pen'}{$addr}) = $self->{'pen'}{$addr} =~ /\.\d+\.\d+\.\d+\.\d+\.\d+\.\d+\.(\d+?)\./ From 8d8474e67e8e4240c8efda50c5cdf1203e4bc359 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Wed, 25 Mar 2020 18:13:12 +0100 Subject: [PATCH 027/111] minor fix --- pandora_server/lib/PandoraFMS/DiscoveryServer.pm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index 68db6f0467..b9ddda908e 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -860,8 +860,9 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { $checked = scalar @map; } - $checked = $data->{'agent'}{'checked'} - if $checked < $data->{'agent'}{'checked'}; + $checked = $data->{'agent'}{'checked'} if + is_enabled($data->{'agent'}{'checked'}) + && $checked < $data->{'agent'}{'checked'}; # Register target agent if enabled. if (is_enabled($checked) From 86cbecc9a0632a870af0e0fd564ebeaaf2517a19 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Thu, 26 Mar 2020 09:04:10 +0100 Subject: [PATCH 028/111] WIP: PEN form near to clear --- pandora_console/godmode/menu.php | 22 +-- .../modules/private_enterprise_numbers.php | 137 ++++++++++++++++++ .../include/ajax/wizardSetup.ajax.php | 131 +++++++++++++++++ .../include/class/ConfigPEN.class.php | 83 +++++++---- 4 files changed, 337 insertions(+), 36 deletions(-) create mode 100644 pandora_console/godmode/modules/private_enterprise_numbers.php create mode 100644 pandora_console/include/ajax/wizardSetup.ajax.php diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index 8720225fec..9291a12336 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -140,18 +140,18 @@ if (check_acl($config['id_user'], 0, 'PM')) { $sub['godmode/modules/manage_network_components']['text'] = __('Remote components'); $sub['godmode/modules/manage_network_components']['id'] = 'Network components'; enterprise_hook('components_submenu'); - $sub['godmode/modules/configuration_wizard_setup']['text'] = __('Wizard Setup'); - $sub['godmode/modules/configuration_wizard_setup']['id'] = 'Wizard Setup'; - $sub['godmode/modules/configuration_wizard_setup']['type'] = 'direct'; - $sub['godmode/modules/configuration_wizard_setup']['subtype'] = 'nolink'; + $sub['configuration_wizard_setup']['text'] = __('Wizard Setup'); + $sub['configuration_wizard_setup']['id'] = 'Wizard Setup'; + $sub['configuration_wizard_setup']['type'] = 'direct'; + $sub['configuration_wizard_setup']['subtype'] = 'nolink'; $sub2 = []; - $sub2['private_enterprise_numbers']['text'] = __('Private Enterprise Numbers'); - $sub2['private_enterprise_numbers']['id'] = 'Private Enterprise Numbers'; - $sub2['SNMP_modules']['text'] = __('SNMP Modules'); - $sub2['SNMP_modules']['id'] = 'SNMP Modules'; - $sub2['WMI_modules']['text'] = __('WMI Modules'); - $sub2['WMI_modules']['id'] = 'WMI Modules'; - $sub['godmode/modules/configuration_wizard_setup']['sub2'] = $sub2; + $sub2['godmode/modules/private_enterprise_numbers']['text'] = __('Private Enterprise Numbers'); + $sub2['godmode/modules/private_enterprise_numbers']['id'] = 'Private Enterprise Numbers'; + $sub2['godmode/modules/SNMP_modules']['text'] = __('SNMP Modules'); + $sub2['godmode/modules/SNMP_modules']['id'] = 'SNMP Modules'; + $sub2['godmode/modules/WMI_modules']['text'] = __('WMI Modules'); + $sub2['godmode/modules/WMI_modules']['id'] = 'WMI Modules'; + $sub['configuration_wizard_setup']['sub2'] = $sub2; $sub['godmode/modules/manage_block_templates']['text'] = __('Module blocks'); $sub['godmode/modules/manage_block_templates']['id'] = 'Module blocks'; $sub['godmode/modules/manage_network_templates']['text'] = __('Module templates (legacy)'); diff --git a/pandora_console/godmode/modules/private_enterprise_numbers.php b/pandora_console/godmode/modules/private_enterprise_numbers.php new file mode 100644 index 0000000000..71cc7b1dc4 --- /dev/null +++ b/pandora_console/godmode/modules/private_enterprise_numbers.php @@ -0,0 +1,137 @@ +run(); +} catch (Exception $ex) { + ui_print_error_message(__('Something went wrong. Please, take a look in the Pandora FMS log')); + echo '[PEN Configuration]'.$ex->getMessage(); +} +?> + diff --git a/pandora_console/include/ajax/wizardSetup.ajax.php b/pandora_console/include/ajax/wizardSetup.ajax.php new file mode 100644 index 0000000000..c8c296d922 --- /dev/null +++ b/pandora_console/include/ajax/wizardSetup.ajax.php @@ -0,0 +1,131 @@ + $pen_id_np, + 'pen' => $pen_number, + 'manufacturer' => $pen_manufacturer, + 'description' => $pen_description, + ] + ); + if ($work === false) { + $output = ui_print_error_message(__('Error inserting new PEN')); + } else { + $output = $configPEN->createMainTable(); + } + } else { + $output = ui_print_error_message(sprintf(__('The PEN %s exists already'), $pen_number)); + } + break; + + // Update one record. + case 'update': + if ($actual_pen['pen'] != $pen_number + || $actual_pen['manufacturer'] != $pen_manufacturer + || $actual_pen['description'] != $pen_description + ) { + $work = db_process_sql_update( + 'tpen', + [ + 'pen' => $pen_number, + 'manufacturer' => $pen_manufacturer, + 'description' => $pen_description, + ], + ['pen' => $pen_number] + ); + + if ($work === false) { + $output = ui_print_error_message(__('Error updating data')); + } else { + $output = ui_print_success_message(__('PEN updated in DB')); + } + } else { + $output = ui_print_error_message(__('No changes applied')); + } + break; + + // Delete one record. + case 'delete': + if ($actual_pen != false) { + db_process_sql_delete( + 'tpen', + ['pen' => $pen_number] + ); + $output = $configPEN->createMainTable(); + } else { + $output = ui_print_error_message(__('Something goes wrong. Please, retry')); + } + break; + + default: + // Nothing to do. + break; +} + +// Return data. +return $output; diff --git a/pandora_console/include/class/ConfigPEN.class.php b/pandora_console/include/class/ConfigPEN.class.php index e88aab56d9..bf3c799e0f 100644 --- a/pandora_console/include/class/ConfigPEN.class.php +++ b/pandora_console/include/class/ConfigPEN.class.php @@ -36,9 +36,9 @@ class ConfigPEN extends HTML { /** - * Undocumented variable + * URL Base * - * @var [type] + * @var string */ private $baseUrl; @@ -58,15 +58,16 @@ class ConfigPEN extends HTML 'ACL Violation', 'Trying to access event viewer' ); - - if (is_ajax()) { + /* + if (is_ajax()) { echo json_encode(['error' => 'noaccess']); - } - + } + */ include 'general/noaccess.php'; exit; } + $this->offset = ''; $this->baseUrl = 'index.php?sec=configuration_wizard_setup&sec2=godmode/modules/private_enterprise_numbers'; } @@ -117,36 +118,47 @@ class ConfigPEN extends HTML $this->printHeader(true) ); - $this->createMainTable(); + // Definition for AJAX. + html_print_input_hidden( + 'ajax_file', + ui_get_full_url('ajax.php', false, false, false) + ); + // Allow message area. + html_print_div(['id' => 'message_show_area']); + // Prints the main table. + html_print_div( + [ + 'id' => 'main_table_area', + 'content' => $this->createMainTable(), + ] + ); } /** - * Undocumented function + * Create the main table with the PENs info * - * @return void + * @return string Return entire the table */ - private function createMainTable() + public function createMainTable() { global $config; // Get the count of PENs. $countPENs = db_get_value( 'count(*)', - 'tnetwork_profile' + 'tpen' ); // Get all the data. $resultPENs = db_get_all_rows_filter( - 'tnetwork_profile', + 'tpen', [ 'order' => 'id_np', 'limit' => $config['block_size'], ] ); - hd($resultPENs); - ui_pagination($countPENs, false, $this->offset); // Create the table with Module Block list. $table = new StdClasS(); @@ -181,15 +193,15 @@ class ConfigPEN extends HTML foreach ($resultPENs as $row) { $data = []; - $data[0] = html_print_checkbox_extended('delete_multiple[]', $row['id_np'], false, false, '', 'class="check_delete"', true); - $data[1] = ''.$row['id_np'].''; - $data[2] = ''.$row['name'].''; - $data[3] = ''.ui_print_truncate_text(io_safe_output($row['description']), 'description', true, true, true, '[…]').''; - $table->cellclass[][3] = 'action_buttons'; + $data[0] = html_print_checkbox_extended('delete_multiple[]', $row['pen'], false, false, '', 'class="check_delete"', true); + $data[1] = ''.$row['pen'].''; + $data[2] = ''.$row['manufacturer'].''; + $data[3] = ''.ui_print_truncate_text(io_safe_output($row['description']), 'description', true, true, true, '[…]').''; + $table->cellclass[][4] = 'action_buttons'; $data[4] = html_print_input_image( - 'edit_pen_'.$row['id_np'].'_', + 'edit_pen_', 'images/edit.png', - $row['id_np'], + $row['pen'], 'max-width: 27px;', true, [ @@ -198,22 +210,43 @@ class ConfigPEN extends HTML ] ); $data[4] .= html_print_input_image( - 'delete_pen_'.$row['id_np'].'_', + 'delete_pen_', 'images/cross.png', - $row['id_np'], + $row['pen'], '', true, [ 'title' => 'Delete PEN', - 'onclick' => 'if (!confirm(\''.__('Are you sure?').'\')) return false;', + 'onclick' => 'if (confirm(\''.__('Are you sure?').'\')) deletePEN(event);', ] ); array_push($table->data, $data); } - html_print_table($table); + // Last line for adding new PENs. + $data = []; + $data[0] = ''; + $data[1] = html_print_input_text('pen_number', '', '', 10, 255, true); + $data[2] = html_print_input_text('pen_manufacturer', '', '', 30, 255, true); + $data[3] = html_print_input_text('pen_description', '', '', 80, 255, true); + $table->cellclass[][4] = 'action_buttons'; + $data[4] = html_print_input_image( + 'add_new_pen', + 'images/add_mc.png', + '', + 'margin: 0 auto; display: block;', + true, + [ + 'title' => 'Add new PEN', + 'onclick' => 'javascript:addNewPEN()', + ] + ); + // Add last line. + array_push($table->data, $data); + // Return the entire table. + return html_print_table($table, true); } From 2c8655b1a3f4375f401289fcf410b584b522713f Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Thu, 26 Mar 2020 09:09:54 +0100 Subject: [PATCH 029/111] restored install.php --- pandora_console/install.php | 1127 +++++++++++++++++++++++++++++++++++ 1 file changed, 1127 insertions(+) create mode 100644 pandora_console/install.php diff --git a/pandora_console/install.php b/pandora_console/install.php new file mode 100644 index 0000000000..db1ed51f29 --- /dev/null +++ b/pandora_console/install.php @@ -0,0 +1,1127 @@ + + + + + Pandora FMS - Installation Wizard + + + + + + + + + + + + + + + +
      + +
      + + + +'; + echo " $label "; + echo ''; + if (!extension_loaded($ext)) { + echo ""; + return 1; + } else { + echo ""; + return 0; + } + + echo ''; +} + +function check_include($ext, $label) +{ + echo ''; + echo " $label "; + echo ''; + if (!include $ext) { + echo ""; + return 1; + } else { + echo ""; + return 0; + } + + echo ''; +} + + +function check_exists($file, $label) +{ + echo ''; + echo " $label "; + echo ''; + if (!file_exists($file)) { + echo " "; + return 1; + } else { + echo " "; + return 0; + } + + echo ''; +} + + +function check_generic($ok, $label) +{ + echo ""; + if ($ok == 0) { + echo " "; + echo ''; + echo " $label "; + echo ''; + echo ''; + return 1; + } else { + echo " "; + echo ''; + echo " $label "; + echo ''; + echo ''; + return 0; + } +} + + +function check_writable($fullpath, $label) +{ + echo ""; + if (file_exists($fullpath)) { + if (is_writable($fullpath)) { + echo " "; + echo ''; + echo " $label "; + echo ''; + echo ''; + return 0; + } else { + echo " "; + echo ''; + echo " $label "; + echo ''; + echo ''; + return 1; + } + } else { + echo " "; + echo ''; + echo " $label "; + echo ''; + echo ''; + return 1; + } +} + + +function check_variable($var, $value, $label, $mode) +{ + echo ''; + echo " $label "; + echo ''; + if ($mode == 1) { + if ($var >= $value) { + echo " "; + return 0; + } else { + echo " "; + return 1; + } + } else if ($var == $value) { + echo " "; + return 0; + } else { + echo " "; + return 1; + } + + echo ''; +} + + +function parse_mysql_dump($url) +{ + if (file_exists($url)) { + $file_content = file($url); + $query = ''; + foreach ($file_content as $sql_line) { + if (trim($sql_line) != '' && strpos($sql_line, '-- ') === false) { + $query .= $sql_line; + if (preg_match("/;[\040]*\$/", $sql_line)) { + if (!$result = mysql_query($query)) { + echo mysql_error(); + // Uncomment for debug + echo "
      $query
      "; + return 0; + } + + $query = ''; + } + } + } + + return 1; + } else { + return 0; + } +} + + +function parse_mysqli_dump($connection, $url) +{ + if (file_exists($url)) { + $file_content = file($url); + $query = ''; + foreach ($file_content as $sql_line) { + if (trim($sql_line) != '' && strpos($sql_line, '-- ') === false) { + $query .= $sql_line; + if (preg_match("/;[\040]*\$/", $sql_line)) { + if (!$result = mysqli_query($connection, $query)) { + echo mysqli_error(); + // Uncomment for debug + echo "
      $query
      "; + return 0; + } + + $query = ''; + } + } + } + + return 1; + } else { + return 0; + } +} + + +function random_name($size) +{ + $temp = ''; + for ($a = 0; $a < $size; $a++) { + $temp = $temp.chr(rand(122, 97)); + } + + return $temp; +} + + +function print_logo_status($step, $step_total) +{ + global $banner; + + $header = " +
      +
      +
      + $banner +
      +
      "; + $header .= " +
      + Install step $step of $step_total +
      "; + + return $header; +} + + +// +// This function adjusts path settings in pandora db for FreeBSD. +// +// All packages and configuration files except operating system's base files +// are installed under /usr/local in FreeBSD. So, path settings in pandora db +// for some programs should be changed from the Linux default. +// +function adjust_paths_for_freebsd($engine, $connection=false) +{ + $adjust_sql = [ + "update trecon_script set script = REPLACE(script,'/usr/share','/usr/local/share');", + "update tconfig set value = REPLACE(value,'/usr/bin','/usr/local/bin') where token='netflow_daemon' OR token='netflow_nfdump' OR token='netflow_nfexpire';", + "update talert_commands set command = REPLACE(command,'/usr/bin','/usr/local/bin');", + "update talert_commands set command = REPLACE(command,'/usr/share', '/usr/local/share');", + "update tplugin set execute = REPLACE(execute,'/usr/share','/usr/local/share');", + "update tevent_response set target = REPLACE(target,'/usr/share','/usr/local/share');", + "insert into tconfig (token, value) VALUES ('graphviz_bin_dir', '/usr/local/bin');", + ]; + + for ($i = 0; $i < count($adjust_sql); $i++) { + switch ($engine) { + case 'mysql': + $result = mysql_query($adjust_sql[$i]); + break; + + case 'mysqli': + $result = mysqli_query($connection, $adjust_sql[$i]); + break; + + case 'oracle': + // Delete the last semicolon from current query + $query = substr($adjust_sql[$i], 0, (strlen($adjust_sql[$i]) - 1)); + $sql = oci_parse($connection, $query); + $result = oci_execute($sql); + break; + + case 'pgsql': + pg_send_query($connection, $adjust_sql[$i]); + $result = pg_get_result($connection); + break; + } + + if (!$result) { + return 0; + } + } + + return 1; +} + + +function install_step1() +{ + global $banner; + + echo " +
      +
      + ".print_logo_status(1, 6)." +
      +

      Welcome to Pandora FMS installation Wizard

      +

      This wizard helps you to quick install Pandora FMS console and main database in your system.

      +

      In four steps, this installer will check all dependencies and will create your configuration, ready to use.

      +

      For more information, please refer to documentation.
      + Pandora FMS Development Team

      + "; + if (file_exists('include/config.php')) { + echo "
      Warning: You already have a config.php file. + Configuration and database would be overwritten if you continued.
      "; + } + + echo '
      '; + echo ''; + $writable = check_writable('include', 'Checking if ./include is writable'); + if (file_exists('include/config.php')) { + $writable += check_writable('include/config.php', 'Checking if include/config.php is writable'); + } + + echo '
      '; + + echo "
      Warning: This installer will overwrite and destroy + your existing Pandora FMS configuration and Database. Before continue, + please be sure that you have no valuable Pandora FMS data in your Database.
      +
      "; + + echo "
      Upgrade: + If you want to upgrade from Pandora FMS 4.x to 5.0 version, please use the migration tool inside /extras directory in this setup. +
      "; + + echo '
      '; + + if ($writable == 0) { + echo "
      "; + echo ""; + echo '
      '; + } else { + echo "
      ERROR:You need to setup permissions to be able to write in ./include directory
      "; + } + + echo '
      '; + + echo "
      "; + echo " +
      +
      + Pandora FMS is an OpenSource Software project registered at + SourceForge +
      +
      "; +} + + +function install_step1_licence() +{ + echo " +
      +
      + ".print_logo_status(2, 6)." +
      +

      GPL2 Licence terms agreement

      +

      Pandora FMS is an OpenSource software project licensed under the GPL2 licence. Pandora FMS includes, as well, another software also licensed under LGPL and BSD licenses. Before continue, you must accept the licence terms.. +

      For more information, please refer to our website at http://pandorafms.org and contact us if you have any kind of question about the usage of Pandora FMS

      +

      If you dont accept the licence terms, please, close your browser and delete Pandora FMS files.

      + "; + + if (!file_exists('COPYING')) { + echo "
      Licence file 'COPYING' is not present in your distribution. This means you have some 'partial' Pandora FMS distribution. We cannot continue without accepting the licence file."; + echo '
      '; + } else { + echo "
      "; + echo "'; + echo '

      '; + echo "

      "; + } + + echo '
      '; + + echo "
      +
      +
      + Pandora FMS is an OpenSource Software project registered at + SourceForge +
      +
      "; +} + + +function install_step2() +{ + echo " +
      +
      + ".print_logo_status(3, 6)." +
      "; + echo '

      Checking software dependencies

      '; + echo ''; + $res = 0; + $res += check_variable(phpversion(), '7.0', 'PHP version >= 7.0', 1); + $res += check_extension('gd', 'PHP GD extension'); + $res += check_extension('ldap', 'PHP LDAP extension'); + $res += check_extension('snmp', 'PHP SNMP extension'); + $res += check_extension('session', 'PHP session extension'); + $res += check_extension('gettext', 'PHP gettext extension'); + $res += check_extension('mbstring', 'PHP Multibyte String'); + $res += check_extension('zip', 'PHP Zip'); + $res += check_extension('zlib', 'PHP Zlib extension'); + $res += check_extension('json', 'PHP json extension'); + $res += check_extension('curl', 'CURL (Client URL Library)'); + $res += check_extension('filter', 'PHP filter extension'); + $res += check_extension('calendar', 'PHP calendar extension'); + if (PHP_OS == 'FreeBSD') { + $res += check_exists('/usr/local/bin/twopi', 'Graphviz Binary'); + } else if (PHP_OS == 'NetBSD') { + $res += check_exists('/usr/pkg/bin/twopi', 'Graphviz Binary'); + } else if (substr(PHP_OS, 0, 3) == 'WIN') { + $res += check_exists("..\\..\\..\\Graphviz\\bin\\twopi.exe", 'Graphviz Binary'); + } else { + $res += check_exists('/usr/bin/twopi', 'Graphviz Binary'); + } + + echo ''; + check_extension('mysqli', 'PHP MySQL(mysqli) extension'); + echo '
      '; + echo "DB Engines"; + echo ''; + echo '
      '; + + if ($res > 0) { + echo " +
      You have some incomplete + dependencies. Please correct them or this installer + will not be able to finish your installation. +
      +
      + Remember, if you install any PHP module to comply + with these dependences, you need to restart + your HTTP/Apache server after it to use the new + modules. +
      +
      + Ignore it. +
      "; + } else { + echo "
      "; + echo " + "; + echo '
      '; + } + + echo '
      '; + echo "
      "; + echo " +
      +
      +
      +
      + Pandora FMS is an OpenSource Software project registered at + SourceForge +
      +
      "; +} + + +function install_step3() +{ + $options = ''; + if (extension_loaded('mysql')) { + $options .= ""; + } + + if (extension_loaded('mysqli')) { + $options .= ""; + } + + $error = false; + if (empty($options)) { + $error = true; + } + + echo " +
      +
      + ".print_logo_status(4, 6)." +
      +

      Environment and database setup

      +

      + This wizard will create your Pandora FMS database, + and populate it with all the data needed to run for the first time. +

      +

      + You need a privileged user to create database schema, this is usually root user. + Information about root user will not be used or stored anymore. +

      +

      + You can also deploy the scheme into an existing Database. + In this case you need a privileged Database user and password of that instance. +

      +

      + Now, please, complete all details to configure your database and environment setup. +

      +
      + Warning: This installer will overwrite and destroy your existing + Pandora FMS configuration and Database. Before continue, + please be sure that you have no valuable Pandora FMS data in your Database. +

      +
      "; + + if (extension_loaded('oci8')) { + echo "
      For Oracle installation an existing Database with a privileged user is needed.
      "; + } + + if (!$error) { + echo ""; + } + + echo ""; + echo '"; + + // the field dbgrant is only shown when the DB host is different from 127.0.0.1 or localhost + echo " + + "; + + echo " "; + + echo ""; + echo '
      '; + echo 'DB Engine
      '; + + if ($error) { + echo " +
      + Warning: You haven't a any DB engine with PHP. Please check the previous step to DB engine dependencies. +
      "; + } else { + echo "'; + + echo '
      '; + echo ' Installation in
      '; + echo "'; + } + + echo "
      DB User with privileges
      + + +
      DB Password for this user
      + + +
      DB Hostname
      + + +
      DB Name (pandora by default)
      + + +
      Drop Database if exists
      + +
      Full path to HTTP publication directory
      + For example /var/www/pandora_console/ +
      + + +
      '; + echo "URL path to Pandora FMS Console
      + For example '/pandora_console' +
      + +
      + "; + + if (!$error) { + echo "
      "; + echo " + "; + echo '
      '; + ?> + + '; + + echo ''; + + echo "
      "; + echo "
      +
      + Pandora FMS is an OpenSource Software project registered at + SourceForge +
      +
      "; +} + + +function install_step4() +{ + $pandora_config = 'include/config.php'; + + if ((! isset($_POST['user'])) || (! isset($_POST['dbname'])) || (! isset($_POST['host'])) + || (! isset($_POST['pass'])) || (!isset($_POST['engine'])) || (! isset($_POST['db_action'])) + ) { + $dbpassword = ''; + $dbuser = ''; + $dbhost = ''; + $dbname = ''; + $engine = ''; + $dbaction = ''; + $dbgrant = ''; + } else { + $engine = $_POST['engine']; + $dbpassword = $_POST['pass']; + $dbuser = $_POST['user']; + $dbhost = $_POST['host']; + $dbaction = $_POST['db_action']; + if (isset($_POST['dbgrant']) && $_POST['dbgrant'] != '') { + $dbgrant = $_POST['dbgrant']; + } else { + $dbgrant = $_SERVER['SERVER_ADDR']; + } + + if (isset($_POST['drop'])) { + $dbdrop = $_POST['drop']; + } else { + $dbdrop = 0; + } + + $dbname = $_POST['dbname']; + if (isset($_POST['url'])) { + $url = $_POST['url']; + } else { + $url = 'http://localhost'; + } + + if (isset($_POST['path'])) { + $path = $_POST['path']; + $path = str_replace('\\', '/', $path); + // Windows compatibility + } else { + $path = '/var/www'; + } + } + + $everything_ok = 0; + $step1 = 0; + $step2 = 0; + $step3 = 0; + $step4 = 0; + $step5 = 0; + $step6 = 0; + $step7 = 0; + + echo " +
      +
      + ".print_logo_status(5, 6)." +
      +

      Creating database and default configuration file

      + "; + switch ($engine) { + case 'mysql': + if (! mysql_connect($dbhost, $dbuser, $dbpassword)) { + check_generic(0, 'Connection with Database'); + } else { + check_generic(1, 'Connection with Database'); + + // Drop database if needed and don't want to install over an existing DB + if ($dbdrop == 1) { + mysql_query("DROP DATABASE IF EXISTS `$dbname`"); + } + + // Create schema + if ($dbaction == 'db_new' || $dbdrop == 1) { + $step1 = mysql_query("CREATE DATABASE `$dbname`"); + check_generic($step1, "Creating database '$dbname'"); + } else { + $step1 = 1; + } + + if ($step1 == 1) { + $step2 = mysql_select_db($dbname); + check_generic($step2, "Opening database '$dbname'"); + + $step3 = parse_mysql_dump('pandoradb.sql'); + check_generic($step3, 'Creating schema'); + + $step4 = parse_mysql_dump('pandoradb_data.sql'); + check_generic($step4, 'Populating database'); + if (PHP_OS == 'FreeBSD') { + $step_freebsd = adjust_paths_for_freebsd($engine); + check_generic($step_freebsd, 'Adjusting paths in database for FreeBSD'); + } + + $random_password = random_name(8); + $host = $dbhost; + // set default granted origin to the origin of the queries + if (($dbhost != 'localhost') && ($dbhost != '127.0.0.1')) { + $host = $dbgrant; + // if the granted origin is different from local machine, set the valid origin + } + + $step5 = mysql_query( + "GRANT ALL PRIVILEGES ON `$dbname`.* to pandora@$host + IDENTIFIED BY '".$random_password."'" + ); + mysql_query('FLUSH PRIVILEGES'); + check_generic($step5, "Established privileges for user pandora. A new random password has been generated: $random_password
      Please write it down, you will need to setup your Pandora FMS server, editing the /etc/pandora/pandora_server.conf file
      "); + + $step6 = is_writable('include'); + check_generic($step6, "Write permissions to save config file in './include'"); + + $cfgin = fopen('include/config.inc.php', 'r'); + $cfgout = fopen($pandora_config, 'w'); + $config_contents = fread($cfgin, filesize('include/config.inc.php')); + $dbtype = 'mysql'; + $config_new = ''; + $step7 = fputs($cfgout, $config_new); + $step7 = ($step7 + fputs($cfgout, $config_contents)); + if ($step7 > 0) { + $step7 = 1; + } + + fclose($cfgin); + fclose($cfgout); + chmod($pandora_config, 0600); + check_generic($step7, "Created new config file at '".$pandora_config."'"); + } + } + + if (($step7 + $step6 + $step5 + $step4 + $step3 + $step2 + $step1) == 7) { + $everything_ok = 1; + } + break; + + case 'mysqli': + $connection = mysqli_connect($dbhost, $dbuser, $dbpassword); + if (mysqli_connect_error() > 0) { + check_generic(0, 'Connection with Database'); + } else { + check_generic(1, 'Connection with Database'); + + // Drop database if needed and don't want to install over an existing DB + if ($dbdrop == 1) { + mysqli_query($connection, "DROP DATABASE IF EXISTS `$dbname`"); + } + + // Create schema + if ($dbaction == 'db_new' || $dbdrop == 1) { + $step1 = mysqli_query($connection, "CREATE DATABASE `$dbname`"); + check_generic($step1, "Creating database '$dbname'"); + } else { + $step1 = 1; + } + + if ($step1 == 1) { + $step2 = mysqli_select_db($connection, $dbname); + check_generic($step2, "Opening database '$dbname'"); + + $step3 = parse_mysqli_dump($connection, 'pandoradb.sql'); + check_generic($step3, 'Creating schema'); + + $step4 = parse_mysqli_dump($connection, 'pandoradb_data.sql'); + check_generic($step4, 'Populating database'); + if (PHP_OS == 'FreeBSD') { + $step_freebsd = adjust_paths_for_freebsd($engine, $connection); + check_generic($step_freebsd, 'Adjusting paths in database for FreeBSD'); + } + + $random_password = random_name(8); + $host = $dbhost; + // set default granted origin to the origin of the queries + if (($dbhost != 'localhost') && ($dbhost != '127.0.0.1')) { + $host = $dbgrant; + // if the granted origin is different from local machine, set the valid origin + } + + $step5 = mysqli_query( + $connection, + "GRANT ALL PRIVILEGES ON `$dbname`.* to pandora@$host + IDENTIFIED BY '".$random_password."'" + ); + mysqli_query($connection, 'FLUSH PRIVILEGES'); + check_generic($step5, "Established privileges for user pandora. A new random password has been generated: $random_password
      Please write it down, you will need to setup your Pandora FMS server, editing the /etc/pandora/pandora_server.conf file
      "); + + $step6 = is_writable('include'); + check_generic($step6, "Write permissions to save config file in './include'"); + + $cfgin = fopen('include/config.inc.php', 'r'); + $cfgout = fopen($pandora_config, 'w'); + $config_contents = fread($cfgin, filesize('include/config.inc.php')); + $dbtype = 'mysql'; + $config_new = ''; + $step7 = fputs($cfgout, $config_new); + $step7 = ($step7 + fputs($cfgout, $config_contents)); + if ($step7 > 0) { + $step7 = 1; + } + + fclose($cfgin); + fclose($cfgout); + chmod($pandora_config, 0600); + check_generic($step7, "Created new config file at '".$pandora_config."'"); + } + } + + if (($step7 + $step6 + $step5 + $step4 + $step3 + $step2 + $step1) == 7) { + $everything_ok = 1; + } + break; + } + + echo '
      '; + + if ($everything_ok == 1) { + echo "
      "; + echo " + "; + echo '
      '; + } else { + $info = "
      There were some problems. + Installation was not completed. +

      Please correct failures before trying again. + All database "; + if ($engine == 'oracle') { + $info .= 'objects '; + } else { + $info .= 'schemes '; + } + + $info .= 'created in this step have been dropped.

      +
      '; + echo $info; + + switch ($engine) { + case 'mysql': + if (mysql_error() != '') { + echo "
      ERROR: ".mysql_error().'.
      '; + } + + if ($step1 == 1) { + mysql_query("DROP DATABASE $dbname"); + } + break; + + case 'mysqli': + if (mysqli_error($connection) != '') { + echo "
      ERROR: ".mysqli_error($connection).'.
      '; + } + + if ($step1 == 1) { + mysqli_query($connection, "DROP DATABASE $dbname"); + } + break; + } + + echo '
      '; + } + + echo '
      '; + echo "
      "; + echo " +
      +
      + Pandora FMS is an Open Source Software project registered at + SourceForge +
      +
      "; +} + + +function install_step5() +{ + echo " +
      +
      + ".print_logo_status(6, 6)." +
      +

      Installation complete

      +

      For security, you now must manually delete this installer + ('install.php') file before trying to access to your Pandora FMS console. +

      You should also install Pandora FMS Servers before trying to monitor anything; + please read documentation on how to install it.

      +

      Default user is 'admin' with password 'pandora', + please change it both as soon as possible.

      +

      Don't forget to check http://pandorafms.com + for updates. +

      Select if you want to rename 'install.php'.

      +
      + + +
      +


      . +

      +
      "; + + echo "
      +
      + Pandora FMS is an OpenSource Software project registered at + SourceForge +
      +
      "; +} From d40035a716d40846bfb475866878bda1ee0b094a Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Thu, 26 Mar 2020 09:10:08 +0100 Subject: [PATCH 030/111] restoration --- pandora_console/include/config_process.php | 2 +- pandora_console/include/functions_config.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pandora_console/include/config_process.php b/pandora_console/include/config_process.php index 93c06455fd..b854d66b75 100644 --- a/pandora_console/include/config_process.php +++ b/pandora_console/include/config_process.php @@ -209,7 +209,7 @@ if (!isset($config['inventory_changes_blacklist'])) { if (!isset($config['url_update_manager'])) { config_update_value( 'url_update_manager', - 'https://taldarim.artica.lan/pandoraupdate7/server.php' + 'https://licensing.artica.es/pandoraupdate7/server.php' ); } diff --git a/pandora_console/include/functions_config.php b/pandora_console/include/functions_config.php index 08931feaf8..96f266fc1e 100644 --- a/pandora_console/include/functions_config.php +++ b/pandora_console/include/functions_config.php @@ -3087,10 +3087,10 @@ function get_um_url() $url = $config['url_update_manager']; $url = substr($url, 0, (strlen($url) - strpos(strrev($url), '/'))); } else { - $url = 'https://taldarim.artica.lan/pandoraupdate7/'; + $url = 'https://licensing.artica.es/pandoraupdate7/'; config_update_value( 'url_update_manager', - 'https://taldarim.artica.lan/pandoraupdate7/server.php' + 'https://licensing.artica.es/pandoraupdate7/server.php' ); } From 2b21266a389305b214eb89af827116dbe69c5e5d Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Thu, 26 Mar 2020 12:17:28 +0100 Subject: [PATCH 031/111] WIP: At this point, PEN form is operative and functional --- .../modules/private_enterprise_numbers.php | 52 +++++++++---------- .../include/ajax/wizardSetup.ajax.php | 40 +++++++++----- .../include/class/ConfigPEN.class.php | 12 +++-- 3 files changed, 59 insertions(+), 45 deletions(-) diff --git a/pandora_console/godmode/modules/private_enterprise_numbers.php b/pandora_console/godmode/modules/private_enterprise_numbers.php index 71cc7b1dc4..6c660fee4a 100644 --- a/pandora_console/godmode/modules/private_enterprise_numbers.php +++ b/pandora_console/godmode/modules/private_enterprise_numbers.php @@ -45,11 +45,6 @@ try { diff --git a/pandora_console/include/ajax/wizardSetup.ajax.php b/pandora_console/include/ajax/wizardSetup.ajax.php index c8c296d922..072da2b606 100644 --- a/pandora_console/include/ajax/wizardSetup.ajax.php +++ b/pandora_console/include/ajax/wizardSetup.ajax.php @@ -53,10 +53,10 @@ $pen_id_np = get_parameter('pen_id'); $pen_number = get_parameter('pen_number'); $pen_manufacturer = get_parameter('pen_manufacturer'); $pen_description = get_parameter('pen_description'); - // Set the variables needed here. -$configPEN = new ConfigPEN(); -$output = ''; +$configPEN = new ConfigPEN(); +$message = ''; +$output = ''; // Let's do something. // First, get the current data. $actual_pen = db_get_row('tpen', 'pen', $pen_number); @@ -74,12 +74,12 @@ switch ($action) { ] ); if ($work === false) { - $output = ui_print_error_message(__('Error inserting new PEN')); + $message = ui_print_error_message(__('Error inserting new PEN'), '', true); } else { - $output = $configPEN->createMainTable(); + $message = ui_print_success_message(__('PEN added in DB'), '', true); } } else { - $output = ui_print_error_message(sprintf(__('The PEN %s exists already'), $pen_number)); + $message = ui_print_error_message(sprintf(__('The PEN %s exists already'), $pen_number)); } break; @@ -100,12 +100,12 @@ switch ($action) { ); if ($work === false) { - $output = ui_print_error_message(__('Error updating data')); + $message = ui_print_error_message(__('Error updating data')); } else { - $output = ui_print_success_message(__('PEN updated in DB')); + $message = ui_print_success_message(__('PEN updated in DB')); } } else { - $output = ui_print_error_message(__('No changes applied')); + $message = ui_print_error_message(__('No changes applied')); } break; @@ -116,9 +116,10 @@ switch ($action) { 'tpen', ['pen' => $pen_number] ); - $output = $configPEN->createMainTable(); + + $message = ui_print_success_message(__('PEN deleted in DB'), '', true); } else { - $output = ui_print_error_message(__('Something goes wrong. Please, retry')); + $message = ui_print_error_message(__('Something goes wrong. Please, retry'), '', true); } break; @@ -127,5 +128,20 @@ switch ($action) { break; } +// Make the data for return +$output = html_print_div( + [ + 'id' => 'ajax_message_show', + 'content' => $message, + ] +); + +$output .= html_print_div( + [ + 'id' => 'ajax_main_table', + 'content' => $configPEN->createMainTable(), + ] +); // Return data. -return $output; +echo $output; +// return $output; diff --git a/pandora_console/include/class/ConfigPEN.class.php b/pandora_console/include/class/ConfigPEN.class.php index bf3c799e0f..6dc0853624 100644 --- a/pandora_console/include/class/ConfigPEN.class.php +++ b/pandora_console/include/class/ConfigPEN.class.php @@ -159,7 +159,7 @@ class ConfigPEN extends HTML ] ); - ui_pagination($countPENs, false, $this->offset); + $output = ui_pagination($countPENs, false, $this->offset, 0, true); // Create the table with Module Block list. $table = new StdClasS(); $table->class = 'databox data'; @@ -206,7 +206,7 @@ class ConfigPEN extends HTML true, [ 'title' => 'Edit', - 'onclick' => 'javascript:modifyPENLine(event)', + 'onclick' => 'modifyPENLine(event)', ] ); $data[4] .= html_print_input_image( @@ -217,7 +217,7 @@ class ConfigPEN extends HTML true, [ 'title' => 'Delete PEN', - 'onclick' => 'if (confirm(\''.__('Are you sure?').'\')) deletePEN(event);', + 'onclick' => 'if (confirm(\''.sprintf(__('Are you sure to remove the PEN: %s?'), $row['pen']).'\')) deletePEN(event);', ] ); @@ -239,14 +239,16 @@ class ConfigPEN extends HTML true, [ 'title' => 'Add new PEN', - 'onclick' => 'javascript:addNewPEN()', + 'onclick' => 'addNewPEN()', ] ); // Add last line. array_push($table->data, $data); // Return the entire table. - return html_print_table($table, true); + $output .= html_print_table($table, true); + // $output = 'mis huevos morenos'; + return $output; } From 3eadde8a870f767af816858a032dc0edf1b6ff6c Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Thu, 26 Mar 2020 13:44:08 +0100 Subject: [PATCH 032/111] WMI review Discovery --- .../lib/PandoraFMS/DiscoveryServer.pm | 436 +++++------------- pandora_server/lib/PandoraFMS/Recon/Base.pm | 227 +++++---- 2 files changed, 250 insertions(+), 413 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index b9ddda908e..3214e011e9 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -531,16 +531,14 @@ sub PandoraFMS::Recon::Base::test_module($$) { return 0 if is_empty($value); # 2. Check if value matches type definition and fits thresholds. - if (is_in_array([1,2,4,5,6,7,8,9,11,15,16,18,21,22,25,30,31,32,34,35,37],$test->{'id_tipo_modulo'})) { + if (is_in_array( + [1,2,4,5,6,7,8,9,11,15,16,18,21,22,25,30,31,32,34,35,37], + $test->{'id_tipo_modulo'} + ) + ) { # Numeric. return 0 unless is_numeric($value); - if (!is_enabled($test->{'critical_inverse'})) { - return 0 if $value >= $test->{'min_critical'} && $value <= $test->{'max_critical'}; - } else { - return 0 if $value < $test->{'min_critical'} && $value > $test->{'max_critical'}; - } - if (is_in_array([2,6,9,18,21,31,35], $test->{'id_tipo_modulo'})) { # Boolean. if (!is_enabled($test->{'critical_inverse'})) { @@ -550,6 +548,27 @@ sub PandoraFMS::Recon::Base::test_module($$) { } } + my $thresholds_defined = 0; + + if ((!defined($test->{'min_critical'}) || $test->{'min_critical'} == 0) + && (!defined($test->{'max_critical'}) || $test->{'max_critical'} == 0) + ) { + # In Default 0,0 do not test.or not defined + $thresholds_defined = 0; + } else { + # min or max are diferent from 0 + $thresholds_defined = 1; + } + + if ($thresholds_defined > 0) { + # Check thresholds. + if (!is_enabled($test->{'critical_inverse'})) { + return 0 if $value >= $test->{'min_critical'} && $value <= $test->{'max_critical'}; + } else { + return 0 if $value < $test->{'min_critical'} && $value > $test->{'max_critical'}; + } + } + } else { # String. if (!is_enabled($test->{'critical_inverse'})) { @@ -729,6 +748,80 @@ sub PandoraFMS::Recon::Base::create_interface_modules($$) { } +################################################################################ +# Add wmi modules to the given host. +################################################################################ +sub PandoraFMS::Recon::Base::create_wmi_modules { + my ($self, $target) = @_; + + # Add modules to the agent if it responds to WMI. + return unless ($self->wmi_responds($target)); + + my $auth = $self->wmi_credentials($target); + + # Register agent. + $self->add_agent($target); + + # Add modules. + # CPU. + my @cpus = $self->wmi_get_value_array($target, 'SELECT DeviceId FROM Win32_Processor', 0); + foreach my $cpu (@cpus) { + $self->add_module( + $target, + { + 'target' => $target, + 'query' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId='$cpu'", + 'auth' => $auth, + 'column' => 1, + 'name' => "CPU Load $cpu", + 'description' => safe_input("Load for $cpu (%)"), + 'id_tipo_modulo' => 1, + 'id_modulo' => 6, + 'unit' => '%', + } + ); + } + + # Memory. + my $mem = $self->wmi_get_value($target, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0); + if (defined($mem)) { + $self->add_module( + $target, + { + 'target' => $target, + 'query' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem", + 'auth' => $auth, + 'column' => 0, + 'name' => 'FreeMemory', + 'description' => safe_input('Free memory'), + 'id_tipo_modulo' => 1, + 'id_modulo' => 6, + 'unit' => 'KB', + } + ); + } + + # Disk. + my @units = $self->wmi_get_value_array($target, 'SELECT DeviceID FROM Win32_LogicalDisk', 0); + foreach my $unit (@units) { + $self->add_module( + $target, + { + 'target' => $target, + 'query' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'", + 'auth' => $auth, + 'column' => 1, + 'name' => "FreeDisk $unit", + 'description' => safe_input('Available disk space in kilobytes'), + 'id_tipo_modulo' => 1, + 'id_modulo' => 6, + 'unit' => 'KB', + } + ); + } + +} + ################################################################################ # Create network profile modules for the given agent. ################################################################################ @@ -797,6 +890,19 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$) { } +################################################################################ +# Retrieve a key from credential store. +################################################################################ +sub PandoraFMS::Recon::Base::get_credentials { + my ($self, $key_index) = @_; + + return credential_store_get_key( + $self->{'pa_config'}, + $self->{'dbh'}, + $key_index + ); +} + ################################################################################ # Create agents and modules reported by Recon::Base. ################################################################################ @@ -1183,6 +1289,9 @@ sub PandoraFMS::Recon::Base::apply_monitoring($) { # Monitorization - interfaces $self->call('create_interface_modules', $label); + # Monitorization - WMI modules. + $self->call('create_wmi_modules', $label); + } $self->{'c_network_percent'} = 100; @@ -1358,319 +1467,6 @@ sub PandoraFMS::Recon::Base::create_agents($$) { } - -################################################################################ -# Create an agent for the given device. Returns the ID of the new (or -# existing) agent, undef on error. -################################################################################ -sub PandoraFMS::Recon::Base::create_agent($$) { - my ($self, $device) = @_; - - # Clean name. - $device = clean_blank($device); - - # Resolve hostnames. - my $host_name = (($self->{'resolve_names'} == 1) ? gethostbyaddr(inet_aton($device), AF_INET) : $device); - # Fallback to device IP if host name could not be resolved. - $host_name = $device if (!defined($host_name) || $host_name eq ''); - my $agent = locate_agent($self->{'pa_config'}, $self->{'dbh'}, $host_name); - - my ($agent_id, $agent_learning); - if (!defined($agent)) { - $host_name = $device unless defined ($host_name); - - # Guess the OS. - my $id_os = $self->guess_os($device); - - # Are we filtering hosts by OS? - return if ($self->{'id_os'} > 0 && $id_os != $self->{'id_os'}); - - # Are we filtering hosts by TCP port? - return if ($self->{'recon_ports'} ne '' && $self->tcp_scan($device) == 0); - my $location = get_geoip_info($self->{'pa_config'}, $device); - $agent_id = pandora_create_agent( - $self->{'pa_config'}, $self->{'pa_config'}->{'servername'}, - $host_name, $device, $self->{'group_id'}, 0, $id_os, - '', 300, $self->{'dbh'}, undef, $location->{'longitude'}, - $location->{'latitude'} - ); - return undef unless defined ($agent_id) and ($agent_id > 0); - - # Autoconfigure agent - if (defined($self->{'autoconfiguration_enabled'}) && $self->{'autoconfiguration_enabled'} == 1) { - my $agent_data = PandoraFMS::DB::get_db_single_row($self->{'dbh'}, 'SELECT * FROM tagente WHERE id_agente = ?', $agent_id); - # Update agent configuration once, after create agent. - enterprise_hook('autoconfigure_agent', [$self->{'pa_config'}, $host_name, $agent_id, $agent_data, $self->{'dbh'}, 1]); - } - - if (defined($self->{'main_event_id'})) { - my $addresses_str = join(',', safe_output($self->get_addresses($device))); - pandora_extended_event( - $self->{'pa_config'}, $self->{'dbh'}, $self->{'main_event_id'}, - "[Discovery] New " . safe_output($self->get_device_type($device)) . " found " . $host_name . " (" . $addresses_str . ") Agent $agent_id." - ); - - } - - $agent_learning = 1; - - # Create network profile modules for the agent - $self->create_network_profile_modules($agent_id, $device); - } - else { - $agent_id = $agent->{'id_agente'}; - $agent_learning = $agent->{'modo'}; - } - - # Do not create any modules if the agent is not in learning mode. - return unless ($agent_learning == 1); - - # Add found IP addresses to the agent. - foreach my $ip_addr ($self->get_addresses($device)) { - my $addr_id = get_addr_id($self->{'dbh'}, $ip_addr); - $addr_id = add_address($self->{'dbh'}, $ip_addr) unless ($addr_id > 0); - next unless ($addr_id > 0); - - # Assign the new address to the agent - my $agent_addr_id = get_agent_addr_id($self->{'dbh'}, $addr_id, $agent_id); - if ($agent_addr_id <= 0) { - db_do($self->{'dbh'}, 'INSERT INTO taddress_agent (`id_a`, `id_agent`) - VALUES (?, ?)', $addr_id, $agent_id); - } - } - - # Create a ping module. - my $module_id = get_agent_module_id($self->{'dbh'}, "ping", $agent_id); - if ($module_id <= 0) { - my %module = ('id_tipo_modulo' => 6, - 'id_modulo' => 2, - 'nombre' => "ping", - 'descripcion' => '', - 'id_agente' => $agent_id, - 'ip_target' => $device); - pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); - } - - # Add interfaces to the agent if it responds to SNMP. - return $agent_id unless ($self->is_snmp_discovered($device)); - my $community = $self->get_community($device); - - my @output = $self->snmp_get_value_array($device, $PandoraFMS::Recon::Base::IFINDEX); - foreach my $if_index (@output) { - next unless ($if_index =~ /^[0-9]+$/); - - # Check the status of the interface. - if (!is_enabled($self->{'all_ifaces'})) { - my $if_status = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index"); - next unless $if_status == 1; - } - - # Fill the module description with the IP and MAC addresses. - my $mac = $self->get_if_mac($device, $if_index); - my $ip = $self->get_if_ip($device, $if_index); - my $if_desc = ($mac ne '' ? "MAC $mac " : '') . ($ip ne '' ? "IP $ip" : ''); - - # Get the name of the network interface. - my $if_name = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFNAME.$if_index"); - $if_name = "if$if_index" unless defined ($if_name); - $if_name =~ s/"//g; - $if_name = clean_blank($if_name); - - # Check whether the module already exists. - my $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifOperStatus', $agent_id); - - next if ($module_id > 0 && !$agent_learning); - - # Encode problematic characters. - $if_desc = safe_input($if_desc); - - # Interface status module. - $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifOperStatus', $agent_id); - if ($module_id <= 0) { - my %module = ('id_tipo_modulo' => 18, - 'id_modulo' => 2, - 'nombre' => safe_input($if_name)."_ifOperStatus", - 'descripcion' => $if_desc, - 'id_agente' => $agent_id, - 'ip_target' => $device, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - 'snmp_community' => $community, - 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index" - ); - pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); - } else { - my %module = ( - 'descripcion' => $if_desc, - 'ip_target' => $device, - 'snmp_community' => $community, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - 'tcp_send' => $self->{'snmp_version'}, - ); - pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); - } - - # Incoming traffic module. - my $if_hc_in_octets = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFHCINOCTECTS.$if_index"); - if (defined($if_hc_in_octets)) { - $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifHCInOctets', $agent_id); - if ($module_id <= 0) { - my %module = ('id_tipo_modulo' => 16, - 'id_modulo' => 2, - 'nombre' => safe_input($if_name)."_ifHCInOctets", - 'descripcion' => 'The total number of octets received on the interface, including framing characters. This object is a 64-bit version of ifInOctets.', - 'id_agente' => $agent_id, - 'ip_target' => $device, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - 'snmp_community' => $community, - 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCINOCTECTS.$if_index"); - pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); - } else { - my %module = ( - 'ip_target' => $device, - 'snmp_community' => $community, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - ); - pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); - } - } - # ifInOctets - elsif (defined($self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFINOCTECTS.$if_index"))) { - $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifInOctets', $agent_id); - if ($module_id <= 0) { - my %module = ('id_tipo_modulo' => 16, - 'id_modulo' => 2, - 'nombre' => safe_input($if_name)."_ifInOctets", - 'descripcion' => 'The total number of octets received on the interface, including framing characters.', - 'id_agente' => $agent_id, - 'ip_target' => $device, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - 'snmp_community' => $community, - 'snmp_oid' => "$PandoraFMS::Recon::Base::IFINOCTECTS.$if_index"); - pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); - } else { - my %module = ( - 'ip_target' => $device, - 'snmp_community' => $community, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - ); - pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); - } - } - - # Outgoing traffic module. - my $if_hc_out_octets = $self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFHCOUTOCTECTS.$if_index"); - if (defined($if_hc_out_octets)) { - $module_id = get_agent_module_id($self->{'dbh'}, $if_name.'_ifHCOutOctets', $agent_id); - if ($module_id <= 0) { - my %module = ('id_tipo_modulo' => 16, - 'id_modulo' => 2, - 'nombre' => safe_input($if_name)."_ifHCOutOctets", - 'descripcion' => 'The total number of octets received on the interface, including framing characters. This object is a 64-bit version of ifOutOctets.', - 'id_agente' => $agent_id, - 'ip_target' => $device, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - 'snmp_community' => $community, - 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCOUTOCTECTS.$if_index"); - pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); - } else { - my %module = ( - 'ip_target' => $device, - 'snmp_community' => $community, - 'tcp_send' => $self->{'snmp_version'}, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - ); - pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); - } - } - # ifOutOctets - elsif (defined($self->snmp_get_value($device, "$PandoraFMS::Recon::Base::IFOUTOCTECTS.$if_index"))) { - $module_id = get_agent_module_id($self->{'dbh'}, "${if_name}_ifOutOctets", $agent_id); - if ($module_id <= 0) { - my %module = ('id_tipo_modulo' => 16, - 'id_modulo' => 2, - 'nombre' => safe_input($if_name)."_ifOutOctets", - 'descripcion' => 'The total number of octets received on the interface, including framing characters.', - 'id_agente' => $agent_id, - 'ip_target' => $device, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - 'snmp_community' => $community, - 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOUTOCTECTS.$if_index"); - pandora_create_module_from_hash ($self->{'pa_config'}, \%module, $self->{'dbh'}); - } else { - my %module = ( - 'ip_target' => $device, - 'snmp_community' => $community, - 'tcp_send' => $self->{'snmp_version'}, - 'tcp_send' => $self->{'snmp_version'}, - 'custom_string_1' => $self->{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'snmp_security_level'}, - 'plugin_parameter' => $self->{'snmp_auth_method'}, - 'plugin_user' => $self->{'snmp_auth_user'}, - 'plugin_pass' => $self->{'snmp_auth_pass'}, - ); - pandora_update_module_from_hash ($self->{'pa_config'}, \%module, 'id_agente_modulo', $module_id, $self->{'dbh'}); - } - } - } - - return $agent_id; -} - ################################################################################ # Delete already existing connections. ################################################################################ diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 8d2db93fb2..3ae1182b0e 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -42,6 +42,10 @@ use constant { DISCOVERY_REVIEW => 0, DISCOVERY_STANDARD => 1, DISCOVERY_RESULTS => 2, + WMI_UNREACHABLE => 1, + WMI_BAD_PASSWORD => 2, + WMI_GENERIC_ERROR => 3, + WMI_OK => 0, }; # $DEVNULL @@ -398,13 +402,17 @@ sub are_connected($$$$$) { } ################################################################################ -# Initialize tmp pool for device. -# Already discovered by scan_subnet. +# Initialize tmp pool for addr. +# Already discovered by scan_subnet. Registration only. ################################################################################ sub icmp_discovery($$) { my ($self, $addr) = @_; - $self->prepare_agent($addr); + # Create an agent for the device and add it to the list of known hosts. + push(@{$self->{'hosts'}}, $addr); + + # Create an agent for the device and add it to the list of known hosts. + $self->add_agent($addr); $self->add_module($addr, { @@ -459,13 +467,6 @@ sub snmp_discovery($$) { $self->snmp_pen($device); } } - - # Create an agent for the device and add it to the list of known hosts. - push(@{$self->{'hosts'}}, $device); - - # Create an agent for the device and add it to the list of known hosts. - $self->add_agent($device); - } ################################################################################ @@ -1379,7 +1380,7 @@ sub test_capabilities($$) { # WMI discovery. if (is_enabled($self->{'wmi_enabled'})) { # Add wmi scan if enabled. - $self->wmi_scan($addr); + $self->wmi_discovery($addr); } } @@ -2129,20 +2130,58 @@ sub traceroute_connectivity($$) { # Returns the credentials with which the host responds to WMI queries or # undef if it does not respond to WMI. ################################################################################ -sub responds_to_wmi { +sub wmi_credentials { + my ($self, $target) = @_; + return $self->{'wmi_auth'}{$target}; +} + +################################################################################ +# Calculate WMI credentials for target, 1 if calculated, undef if cannot +# connect to target. Credentials could be empty (-N) +################################################################################ +sub wmi_credentials_calculation { my ($self, $target) = @_; - foreach my $auth (@{$self->{'auth_strings_array'}}) { - my @output; - if ($auth ne '') { - @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -U $auth //$target "SELECT * FROM Win32_ComputerSystem" 2>&1`; - } else { - @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -N //$target "SELECT * FROM Win32_ComputerSystem" 2>&1`; + # Test empty credentials. + my @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -N //$target "SELECT * FROM Win32_ComputerSystem" 2>&1`; + my $rs = $self->wmi_output_check($?, @output); + + if ($rs == WMI_OK) { + $self->{'wmi_auth'}{$target} = ''; + return 1; + } + + if ($rs == WMI_UNREACHABLE) { + # Target does not respond. + $self->{'wmi'}{$target} = 0; + return undef; + } + + # Test all credentials selected. + foreach my $key_index (@{$self->{'auth_strings_array'}}) { + my $cred = $self->call('get_credentials', $key_index); + next if ref($cred) ne 'HASH'; + + my $auth = $cred->{'username'}.'%'.$cred->{'password'}; + next if $auth eq '%'; + + @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -U $auth //$target "SELECT * FROM Win32_ComputerSystem" 2>&1`; + + my $rs = $self->wmi_output_check($?, @output); + + if ($rs == WMI_OK) { + $self->{'wmi_auth'}{$target} = $auth; + $self->{'wmi'}{$target} = 1; + $self->{'summary'}->{'WMI'} += 1; + $self->call('message', "[".$target."] WMI available.", 10); + return 1; } - foreach my $line (@output) { - chomp($line); - return $auth if ($line =~ m/^CLASS: Win32_ComputerSystem$/); + if ($rs == WMI_UNREACHABLE) { + # Target does not respond. + $self->call('message', "[".$target."] WMI unreachable.", 10); + $self->{'wmi'}{$target} = 0; + return undef; } } @@ -2150,74 +2189,16 @@ sub responds_to_wmi { } ################################################################################ -# Add wmi modules to the given host. +# Tests wmi capability for addr. ################################################################################ -sub wmi_scan { - my ($self, $target) = @_; +sub wmi_discovery { + my ($self, $addr) = @_; - $self->call('message', "[".$target."] Checking WMI.", 5); + # Initialization. + $self->{'wmi'} = {} unless ref($self->{'wmi'}) eq 'HASH'; - my $auth = $self->responds_to_wmi($target); - return unless defined($auth); - - $self->{'summary'}->{'WMI'} += 1; - - $self->call('message', "[".$target."] WMI available.", 10); - - # Register agent. - $self->add_agent($target); - - # Add modules. - # CPU. - my @cpus = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceId FROM Win32_Processor', 0); - foreach my $cpu (@cpus) { - $self->add_module($target, - { - 'target' => $target, - 'query' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId='$cpu'", - 'auth' => $auth, - 'column' => 1, - 'name' => "CPU Load $cpu", - 'description' => "Load for $cpu (%)", - 'type' => 'generic_data', - 'unit' => '%', - } - ); - } - - # Memory. - my $mem = $self->wmi_get_value($target, $auth, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0); - if (defined($mem)) { - $self->add_module($target, - { - 'target' => $target, - 'query' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem", - 'auth' => $auth, - 'column' => 0, - 'name' => 'FreeMemory', - 'description' => 'Free memory', - 'type' => 'generic_data', - 'unit' => 'KB', - } - ); - } - - # Disk. - my @units = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceID FROM Win32_LogicalDisk', 0); - foreach my $unit (@units) { - $self->add_module($target, - { - 'target' => $target, - 'query' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'", - 'auth' => $auth, - 'column' => 1, - 'name' => "FreeDisk $unit", - 'description' => 'Available disk space in kilobytes', - 'type' => 'generic_data', - 'unit' => 'KB', - } - ); - } + # Calculate credentials. + $self->wmi_credentials_calculation($addr); } @@ -2225,10 +2206,52 @@ sub wmi_scan { # Extra: WMI imported methods. DO NOT EXPORT TO AVOID DOUBLE DEF. ################################################################################ +################################################################################ +# Validate wmi output. (err code and messages). +################################################################################ +sub wmi_output_check { + my ($self, $rc, @output) = @_; + if ($? != 0) { + # Something went wrong. + if (defined($output[-1]) && $output[-1] =~ /NTSTATUS: (.*)/) { + my $err = $1; + $self->{'last_wmi_error'} = $err; + + if ($err =~ /NT_STATUS_IO_TIMEOUT/ + || $err =~ /NT_STATUS_CONNECTION_REFUSED/ + ) { + # Fail. + return WMI_UNREACHABLE; + } + + if ($err =~ /NT_STATUS_ACCESS_DENIED/) { + return WMI_BAD_PASSWORD; + } + } + + # Fail. + return WMI_GENERIC_ERROR; + } + + # Ok. + return WMI_OK; +} + ################################################################################ # Performs a wmi get requests and returns the response as an array. ################################################################################ sub wmi_get { + my ($self, $target, $query) = @_; + + return () unless $self->wmi_responds($target); + + return $self->wmi_get_command($target, $self->{'wmi_auth'}{$target}, $query); +} + +################################################################################ +# Performs a wmi get requests and returns the response as an array. +################################################################################ +sub wmi_get_command { my ($self, $target, $auth, $query) = @_; my @output; @@ -2238,10 +2261,28 @@ sub wmi_get { @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -N //$target "$query" 2>&1`; } - # Something went wrong. - return () if ($? != 0); + my $rs = $self->wmi_output_check($?, @output); - return @output; + if ($rs == WMI_OK) { + return @output; + } + + $self->call( + 'message', + "[".$target."] WMI error: ".$self->{'last_wmi_error'}, + 10 + ); + + return (); +} + +################################################################################ +# Checks if target is reachable using wmi. +################################################################################ +sub wmi_responds { + my ($self, $target) = @_; + return 1 if is_enabled($self->{'wmi'}{$target}); + return 0; } ################################################################################ @@ -2249,10 +2290,10 @@ sub wmi_get { # Returns undef on error. ################################################################################ sub wmi_get_value { - my ($self, $target, $auth, $query, $column) = @_; + my ($self, $target, $query, $column) = @_; my @result; - my @output = $self->wmi_get($target, $auth, $query); + my @output = $self->wmi_get($target, $query); return undef unless defined($output[2]); my $line = $output[2]; @@ -2268,10 +2309,10 @@ sub wmi_get_value { # in an array. ################################################################################ sub wmi_get_value_array { - my ($self, $target, $auth, $query, $column) = @_; + my ($self, $target, $query, $column) = @_; my @result; - my @output = $self->wmi_get($target, $auth, $query); + my @output = $self->wmi_get($target, $query); foreach (my $i = 2; defined($output[$i]); $i++) { my $line = $output[$i]; chomp($line); From e923c9f5e01fecb10d0766064950d75d44421088 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Thu, 26 Mar 2020 14:33:56 +0100 Subject: [PATCH 033/111] minor fixes --- .../lib/PandoraFMS/DiscoveryServer.pm | 71 ++++++------------- pandora_server/lib/PandoraFMS/Recon/Base.pm | 11 +++ 2 files changed, 33 insertions(+), 49 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index 3214e011e9..bdfe445f15 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -757,10 +757,8 @@ sub PandoraFMS::Recon::Base::create_wmi_modules { # Add modules to the agent if it responds to WMI. return unless ($self->wmi_responds($target)); - my $auth = $self->wmi_credentials($target); - - # Register agent. - $self->add_agent($target); + my $key = $self->wmi_credentials_key($target); + my $creds = $self->call('get_credentials', $key); # Add modules. # CPU. @@ -769,12 +767,13 @@ sub PandoraFMS::Recon::Base::create_wmi_modules { $self->add_module( $target, { - 'target' => $target, - 'query' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId='$cpu'", - 'auth' => $auth, - 'column' => 1, + 'ip_target' => $target, + 'snmp_oid' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId=\'$cpu\'", + 'plugin_user' => $creds->{'username'}, + 'plugin_pass' => $creds->{'password'}, + 'tcp_port' => 1, 'name' => "CPU Load $cpu", - 'description' => safe_input("Load for $cpu (%)"), + 'descripcion' => safe_input("Load for $cpu (%)"), 'id_tipo_modulo' => 1, 'id_modulo' => 6, 'unit' => '%', @@ -788,12 +787,13 @@ sub PandoraFMS::Recon::Base::create_wmi_modules { $self->add_module( $target, { - 'target' => $target, - 'query' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem", - 'auth' => $auth, - 'column' => 0, + 'ip_target' => $target, + 'snmp_oid' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem", + 'plugin_user' => $creds->{'username'}, + 'plugin_pass' => $creds->{'password'}, + 'tcp_port' => 0, 'name' => 'FreeMemory', - 'description' => safe_input('Free memory'), + 'descripcion' => safe_input('Free memory'), 'id_tipo_modulo' => 1, 'id_modulo' => 6, 'unit' => 'KB', @@ -807,12 +807,13 @@ sub PandoraFMS::Recon::Base::create_wmi_modules { $self->add_module( $target, { - 'target' => $target, - 'query' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'", - 'auth' => $auth, - 'column' => 1, + 'ip_target' => $target, + 'snmp_oid' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'", + 'plugin_user' => $creds->{'username'}, + 'plugin_pass' => $creds->{'password'}, + 'tcp_port' => 1, 'name' => "FreeDisk $unit", - 'description' => safe_input('Available disk space in kilobytes'), + 'descripcion' => safe_input('Available disk space in kilobytes'), 'id_tipo_modulo' => 1, 'id_modulo' => 6, 'unit' => 'KB', @@ -1089,6 +1090,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { # Create module - Direct. my $name = $module->{'name'}; delete $module->{'name'}; + delete $module->{'description'}; $agentmodule_id = pandora_create_module_from_hash( $self->{'pa_config'}, { @@ -1104,7 +1106,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { ); $module->{'name'} = $name; - + $module->{'description'} = safe_output($description); } # Restore. @@ -1501,35 +1503,6 @@ sub PandoraFMS::Recon::Base::set_parent($$$) { } -################################################################################ -# Create a WMI module for the given agent. -################################################################################ -sub PandoraFMS::Recon::Base::wmi_module { - my ($self, $agent_id, $target, $wmi_query, $wmi_auth, $column, - $module_name, $module_description, $module_type, $unit) = @_; - - # Check whether the module already exists. - my $module_id = get_agent_module_id($self->{'dbh'}, $module_name, $agent_id); - return if ($module_id > 0); - - my ($user, $pass) = ($wmi_auth ne '') ? split('%', $wmi_auth) : (undef, undef); - my %module = ( - 'descripcion' => safe_input($module_description), - 'id_agente' => $agent_id, - 'id_modulo' => 6, - 'id_tipo_modulo' => get_module_id($self->{'dbh'}, $module_type), - 'ip_target' => $target, - 'nombre' => safe_input($module_name), - 'plugin_pass' => defined($pass) ? $pass : '', - 'plugin_user' => defined($user) ? $user : '', - 'snmp_oid' => $wmi_query, - 'tcp_port' => $column, - 'unit' => defined($unit) ? $unit : '' - ); - - pandora_create_module_from_hash($self->{'pa_config'}, \%module, $self->{'dbh'}); -} - ################################################################################ # Update recon task status. ################################################################################ diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 3ae1182b0e..9bf4e8e536 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -2135,6 +2135,15 @@ sub wmi_credentials { return $self->{'wmi_auth'}{$target}; } +################################################################################ +# Returns the credentials KEY with which the host responds to WMI queries or +# undef if it does not respond to WMI. +################################################################################ +sub wmi_credentials_key { + my ($self, $target) = @_; + return $self->{'wmi_auth_key'}{$target}; +} + ################################################################################ # Calculate WMI credentials for target, 1 if calculated, undef if cannot # connect to target. Credentials could be empty (-N) @@ -2148,6 +2157,7 @@ sub wmi_credentials_calculation { if ($rs == WMI_OK) { $self->{'wmi_auth'}{$target} = ''; + $self->{'wmi_auth_key'}{$target} = ''; return 1; } @@ -2171,6 +2181,7 @@ sub wmi_credentials_calculation { if ($rs == WMI_OK) { $self->{'wmi_auth'}{$target} = $auth; + $self->{'wmi_auth_key'}{$target} = $key_index; $self->{'wmi'}{$target} = 1; $self->{'summary'}->{'WMI'} += 1; $self->call('message', "[".$target."] WMI available.", 10); From 161c1eb643c9f32962c1df922c268567c13ca3a1 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Thu, 26 Mar 2020 14:41:54 +0100 Subject: [PATCH 034/111] WIP: Minor fixes --- .../modules/private_enterprise_numbers.php | 10 ++------ .../include/ajax/wizardSetup.ajax.php | 24 ++++--------------- .../include/class/ConfigPEN.class.php | 10 +++----- 3 files changed, 9 insertions(+), 35 deletions(-) diff --git a/pandora_console/godmode/modules/private_enterprise_numbers.php b/pandora_console/godmode/modules/private_enterprise_numbers.php index 6c660fee4a..286142628a 100644 --- a/pandora_console/godmode/modules/private_enterprise_numbers.php +++ b/pandora_console/godmode/modules/private_enterprise_numbers.php @@ -12,12 +12,6 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Load global vars -// TESTING - ini_set('display_errors', 1); - ini_set('display_startup_errors', 1); - error_reporting(E_ALL); - -// END global $config; check_login(); @@ -25,7 +19,7 @@ check_login(); if (! check_acl($config['id_user'], 0, 'PM')) { db_pandora_audit( 'ACL Violation', - 'Trying to access Network Profile Management' + 'Trying to access Wizard Setup' ); include 'general/noaccess.php'; return; @@ -61,7 +55,7 @@ try { $('#main_table_area').html(d); }, error: function(d) { - alert('Failed trying update database! -> '+String(data)); // True, must change the message + alert('Failed trying update database -> '+String(data)); // True, must change the message } }); diff --git a/pandora_console/include/ajax/wizardSetup.ajax.php b/pandora_console/include/ajax/wizardSetup.ajax.php index 072da2b606..dd7dc3ed9d 100644 --- a/pandora_console/include/ajax/wizardSetup.ajax.php +++ b/pandora_console/include/ajax/wizardSetup.ajax.php @@ -35,13 +35,10 @@ require_once 'include/functions_io.php'; require_once 'include/functions.php'; require_once $config['homedir'].'/include/class/ConfigPEN.class.php'; // Security. -if (! check_acl($config['id_user'], 0, 'PM') - && ! check_acl($config['id_user'], 0, 'EW') - && ! check_acl($config['id_user'], 0, 'EM') -) { +if (! check_acl($config['id_user'], 0, 'PM')) { db_pandora_audit( 'ACL Violation', - 'Trying to access to Wizard Setup' + 'Trying to access to Wizard Setup Ajax' ); include 'general/noaccess.php'; return; @@ -128,20 +125,7 @@ switch ($action) { break; } -// Make the data for return -$output = html_print_div( - [ - 'id' => 'ajax_message_show', - 'content' => $message, - ] -); - -$output .= html_print_div( - [ - 'id' => 'ajax_main_table', - 'content' => $configPEN->createMainTable(), - ] -); +// Create the response data. +$output = $message.$configPEN->createMainTable(); // Return data. echo $output; -// return $output; diff --git a/pandora_console/include/class/ConfigPEN.class.php b/pandora_console/include/class/ConfigPEN.class.php index 6dc0853624..c254a0fe60 100644 --- a/pandora_console/include/class/ConfigPEN.class.php +++ b/pandora_console/include/class/ConfigPEN.class.php @@ -53,16 +53,12 @@ class ConfigPEN extends HTML // Check access. check_login(); - if (! check_acl($config['id_user'], 0, 'AR')) { + if (! check_acl($config['id_user'], 0, 'PM')) { db_pandora_audit( 'ACL Violation', - 'Trying to access event viewer' + 'Trying to access PEN Definition feature' ); - /* - if (is_ajax()) { - echo json_encode(['error' => 'noaccess']); - } - */ + include 'general/noaccess.php'; exit; } From 75de601f5738f21496d6d56e72877d1cf8956f65 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Fri, 27 Mar 2020 08:51:17 +0100 Subject: [PATCH 035/111] Forms modified for be able add raw inputs --- pandora_console/godmode/menu.php | 8 ++++---- pandora_console/include/class/HTML.class.php | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index 9291a12336..6b4938d4a5 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -147,10 +147,10 @@ if (check_acl($config['id_user'], 0, 'PM')) { $sub2 = []; $sub2['godmode/modules/private_enterprise_numbers']['text'] = __('Private Enterprise Numbers'); $sub2['godmode/modules/private_enterprise_numbers']['id'] = 'Private Enterprise Numbers'; - $sub2['godmode/modules/SNMP_modules']['text'] = __('SNMP Modules'); - $sub2['godmode/modules/SNMP_modules']['id'] = 'SNMP Modules'; - $sub2['godmode/modules/WMI_modules']['text'] = __('WMI Modules'); - $sub2['godmode/modules/WMI_modules']['id'] = 'WMI Modules'; + $sub2['godmode/modules/manage_snmp_modules']['text'] = __('SNMP Modules'); + $sub2['godmode/modules/manage_snmp_modules']['id'] = 'SNMP Modules'; + $sub2['godmode/modules/manage_wmi_modules']['text'] = __('WMI Modules'); + $sub2['godmode/modules/manage_wmi_modules']['id'] = 'WMI Modules'; $sub['configuration_wizard_setup']['sub2'] = $sub2; $sub['godmode/modules/manage_block_templates']['text'] = __('Module blocks'); $sub['godmode/modules/manage_block_templates']['id'] = 'Module blocks'; diff --git a/pandora_console/include/class/HTML.class.php b/pandora_console/include/class/HTML.class.php index 41231c6c17..9ebf241377 100644 --- a/pandora_console/include/class/HTML.class.php +++ b/pandora_console/include/class/HTML.class.php @@ -746,6 +746,7 @@ class HTML ) { $form = $data['form']; $inputs = $data['inputs']; + $rawInputs = $data['rawInputs']; $js = $data['js']; $rawjs = $data['js_block']; $cb_function = $data['cb_function']; @@ -788,6 +789,11 @@ class HTML $output .= ''; + // There is possible add raw inputs for this form. + if (empty($rawInputs) === false) { + $output .= $rawInputs; + } + if ($print_white_box === true) { $output .= '
      '; } @@ -821,7 +827,7 @@ class HTML $form = $data['form']; $rows = $data['rows']; - + $rawInputs = $data['rawInputs']; $js = $data['js']; $rawjs = $data['js_block']; $cb_function = $data['cb_function']; @@ -896,6 +902,11 @@ class HTML } } + // There is possible add raw inputs for this form. + if (empty($rawInputs) === false) { + $output .= $rawInputs; + } + $output .= '
      '; $output .= '
        '.$output_submit.'
      '; @@ -962,12 +973,13 @@ class HTML } $output .= ''; - $output .= ''; // There is possible add raw inputs for this form. if (empty($rawInputs) === false) { $output .= $rawInputs; } + $output .= ''; + $output .= '
        '.$output_submit.'
      '; $output .= ''; $output .= ''; From 3a74e25068de591e061b82f071049d3df91faaf6 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Fri, 27 Mar 2020 11:41:56 +0100 Subject: [PATCH 036/111] PEN management --- pandora_console/extras/mr/37.sql | 8 +- .../pandoradb_migrate_6.0_to_7.0.mysql.sql | 8 +- .../modules/private_enterprise_numbers.php | 171 ++--- .../include/class/ConfigPEN.class.php | 702 +++++++++++++++--- .../include/class/CredentialStore.class.php | 2 + pandora_console/include/functions_html.php | 18 - pandora_console/include/functions_ui.php | 7 +- .../include/javascript/pandora_ui.js | 15 + pandora_console/include/styles/pen.css | 38 + pandora_console/pandoradb.sql | 18 +- 10 files changed, 735 insertions(+), 252 deletions(-) create mode 100644 pandora_console/include/styles/pen.css diff --git a/pandora_console/extras/mr/37.sql b/pandora_console/extras/mr/37.sql index cc35df6ab0..a3aef948b8 100644 --- a/pandora_console/extras/mr/37.sql +++ b/pandora_console/extras/mr/37.sql @@ -36,11 +36,11 @@ CREATE TABLE `tdiscovery_tmp_connections` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `tpen` ( - `id_np` int(10) unsigned NOT NULL, `pen` int(10) unsigned NOT NULL, - `manufacturer` TEXT NOT NULL, - `description` TEXT NULL, - PRIMARY KEY (`id_np`,`pen`), + `manufacturer` TEXT, + `description` TEXT, + `id_np` int(10) unsigned, + PRIMARY KEY (`pen`), CONSTRAINT `fk_np_id` FOREIGN KEY (`id_np`) REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index 86eecd0ae7..4de9b6a1f3 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -1480,11 +1480,11 @@ ALTER TABLE `tnetwork_component` MODIFY COLUMN `ff_type` tinyint(1) unsigned NUL -- Table `tpen` -- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tpen` ( - `id_np` int(10) unsigned NOT NULL, `pen` int(10) unsigned NOT NULL, - `manufacturer` TEXT NOT NULL, - `description` TEXT NULL, - PRIMARY KEY (`id_np`,`pen`), + `manufacturer` TEXT, + `description` TEXT, + `id_np` int(10) unsigned, + PRIMARY KEY (`pen`), CONSTRAINT `fk_np_id` FOREIGN KEY (`id_np`) REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/pandora_console/godmode/modules/private_enterprise_numbers.php b/pandora_console/godmode/modules/private_enterprise_numbers.php index 286142628a..ca6add6640 100644 --- a/pandora_console/godmode/modules/private_enterprise_numbers.php +++ b/pandora_console/godmode/modules/private_enterprise_numbers.php @@ -1,127 +1,68 @@ run(); -} catch (Exception $ex) { - ui_print_error_message(__('Something went wrong. Please, take a look in the Pandora FMS log')); - echo '[PEN Configuration]'.$ex->getMessage(); + // User access and validation is being processed on class constructor. + $obj = new ConfigPEN($ajaxPage); +} catch (Exception $e) { + if (is_ajax()) { + echo json_encode(['error' => '[ConfigPEN]'.$e->getMessage() ]); + exit; + } else { + echo '[ConfigPEN]'.$e->getMessage(); + } + + // Stop this execution, but continue 'globally'. + return; } -?> - + // Stop any execution. + exit; +} else { + // Run. + $obj->run(); +} diff --git a/pandora_console/include/class/ConfigPEN.class.php b/pandora_console/include/class/ConfigPEN.class.php index c254a0fe60..4a051d170c 100644 --- a/pandora_console/include/class/ConfigPEN.class.php +++ b/pandora_console/include/class/ConfigPEN.class.php @@ -35,6 +35,13 @@ require_once $config['homedir'].'/include/class/HTML.class.php'; class ConfigPEN extends HTML { + /** + * Url of controller. + * + * @var string + */ + public $ajaxController; + /** * URL Base * @@ -44,9 +51,11 @@ class ConfigPEN extends HTML /** - * Constructor + * Contructor. + * + * @param string $ajax_page Target ajax page. */ - public function __construct() + public function __construct($ajax_page) { global $config; @@ -63,8 +72,228 @@ class ConfigPEN extends HTML exit; } + $this->ajaxController = $ajax_page; $this->offset = ''; - $this->baseUrl = 'index.php?sec=configuration_wizard_setup&sec2=godmode/modules/private_enterprise_numbers'; + $this->baseUrl = ui_get_full_url( + 'index.php?sec=configuration_wizard_setup&sec2=godmode/modules/private_enterprise_numbers' + ); + + } + + + /** + * Returns an array with all the credentials matching filter and ACL. + * + * @param array $fields Fields array or 'count' keyword to retrieve count. + * @param array $filter Filters to be applied. + * @param integer $offset Offset (pagination). + * @param integer $limit Limit (pagination). + * @param string $order Sort order. + * @param string $sort_field Sort field. + * + * @return array With all results or false if error. + * @throws Exception On error. + */ + public static function getAll( + $fields, + $filter=null, + $offset=null, + $limit=null, + $order=null, + $sort_field=null + ) { + $sql_filters = []; + $order_by = ''; + $pagination = ''; + + $count = false; + if (!is_array($fields) && $fields == 'count') { + $fields = ['*']; + $count = true; + } else if (!is_array($fields)) { + error_log('[configPEN.getAll] Fields must be an array or "count".'); + throw new Exception('[configPEN.getAll] Fields must be an array or "count".'); + } + + if (is_array($filter)) { + if (!empty($filter['free_search'])) { + $sql_filters[] = vsprintf( + ' AND (lower(`manufacturer`) like lower("%%%s%%") + OR pen = "%s") ', + array_fill(0, 2, $filter['free_search']) + ); + } + + if (!empty($filter['pen'])) { + $sql_filters[] = sprintf( + ' AND `pen` = %d', + $filter['pen'] + ); + } + } + + if (isset($order)) { + $dir = 'asc'; + if ($order == 'desc') { + $dir = 'desc'; + }; + + if (in_array( + $sort_field, + [ + 'pen', + 'manufacturer', + 'description', + ] + ) + ) { + $order_by = sprintf( + 'ORDER BY `%s` %s', + $sort_field, + $dir + ); + } + } + + if (isset($limit) && $limit > 0 + && isset($offset) && $offset >= 0 + ) { + $pagination = sprintf( + ' LIMIT %d OFFSET %d ', + $limit, + $offset + ); + } + + $sql = sprintf( + 'SELECT %s + FROM `tpen` + WHERE 1=1 + %s + %s + %s', + join(',', $fields), + join(' ', $sql_filters), + $order_by, + $pagination + ); + + if ($count) { + $sql = sprintf('SELECT count(*) as n FROM ( %s ) tt', $sql); + + return db_get_value_sql($sql); + } + + return db_get_all_rows_sql($sql); + } + + + /** + * AJAX: Return JSON content for datatable. + * + * @return void + */ + function draw() + { + global $config; + + // Datatables offset, limit and order. + $filter = get_parameter('filter', []); + $start = get_parameter('start', 0); + $length = get_parameter('length', $config['block_size']); + $order = get_datatable_order(true); + try { + ob_start(); + + $fields = ['*']; + + // Retrieve data. + $data = $this->getAll( + // Fields. + $fields, + // Filter. + $filter, + // Offset. + $start, + // Limit. + $length, + // Order. + $order['direction'], + // Sort field. + $order['field'] + ); + + // Retrieve counter. + $count = $this->getAll( + 'count', + $filter + ); + + if ($data) { + $data = array_reduce( + $data, + function ($carry, $item) { + // Transforms array of arrays $data into an array + // of objects, making a post-process of certain fields. + $tmp = (object) $item; + + $tmp->description = io_safe_output($tmp->description); + $tmp->manufacturer = io_safe_output($tmp->manufacturer); + + $tmp->options = ''; + + $tmp->options = ''; + $tmp->options .= html_print_image( + 'images/eye.png', + true, + ['title' => __('Show')] + ); + $tmp->options .= ''; + $tmp->options .= ''; + $tmp->options .= html_print_image( + 'images/cross.png', + true, + ['title' => __('Delete')] + ); + $tmp->options .= ''; + + $carry[] = $tmp; + return $carry; + } + ); + } + + // Datatables format: RecordsTotal && recordsfiltered. + echo json_encode( + [ + 'data' => $data, + 'recordsTotal' => $count, + 'recordsFiltered' => $count, + ] + ); + // Capture output. + $response = ob_get_clean(); + } catch (Exception $e) { + echo json_encode(['error' => $e->getMessage()]); + exit; + } + + // If not valid, show error with issue. + json_decode($response); + if (json_last_error() == JSON_ERROR_NONE) { + // If valid dump. + echo $response; + } else { + echo json_encode( + ['error' => $response] + ); + } + + exit; } @@ -79,6 +308,7 @@ class ConfigPEN extends HTML // Require specific CSS and JS. ui_require_css_file('wizard'); ui_require_css_file('discovery'); + ui_require_css_file('pen'); // Header section. // Breadcrums. @@ -120,6 +350,12 @@ class ConfigPEN extends HTML ui_get_full_url('ajax.php', false, false, false) ); + // Ajax page (hidden). + html_print_input_hidden( + 'ajax_page', + $this->ajaxController + ); + // Allow message area. html_print_div(['id' => 'message_show_area']); // Prints the main table. @@ -132,6 +368,175 @@ class ConfigPEN extends HTML } + /** + * Load modal information for PEN management. + * + * Ajax. Direct HTML. + * + * @return void + */ + public function loadModal() + { + $values = []; + $id = (int) get_parameter('pen', 0); + if ($id > 0) { + $values = $this->getAll( + // Fields. + ['*'], + // Filter. + ['pen' => $id] + ); + if (is_array($values)) { + $values = $values[0]; + } + } + + $form = [ + 'action' => '#', + 'id' => 'modal_form', + 'onsubmit' => 'return false;', + 'class' => '', + ]; + + $inputs = []; + + $inputs[] = [ + 'label' => __('PEN'), + 'class' => 'flex-row', + 'id' => 'div-pen', + 'arguments' => [ + 'name' => 'pen', + 'type' => 'number', + 'value' => $values['pen'], + 'required' => true, + 'return' => true, + 'size' => 50, + ], + ]; + + $inputs[] = [ + 'label' => __('Manufacturer'), + 'class' => 'flex-row', + 'arguments' => [ + 'name' => 'manufacturer', + 'id' => 'manufacturer', + 'type' => 'text', + 'required' => true, + 'value' => io_safe_output($values['manufacturer']), + 'return' => true, + ], + ]; + + $inputs[] = [ + 'label' => __('Description'), + 'class' => 'flex-row', + 'arguments' => [ + 'name' => 'description', + 'id' => 'description', + 'type' => 'textarea', + 'value' => io_safe_output($values['description']), + 'return' => true, + 'rows' => 50, + 'columns' => 30, + ], + ]; + + echo '
      '; + echo parent::printForm( + [ + 'form' => $form, + 'inputs' => $inputs, + ], + true + ); + echo '
      '; + } + + + /** + * Delete a manufacturer register from db. + * + * @return void + */ + public function delete() + { + $pen = get_parameter('pen', 0); + + if (empty($pen)) { + echo json_encode(['error' => __('PEN is required')]); + } else { + if (db_process_sql_delete('tpen', ['pen' => $pen]) !== false) { + echo json_encode(['result' => __('Successfully deleted')]); + } else { + global $config; + echo json_encode(['error' => $config['dbconnection']->error]); + } + } + + } + + + /** + * Add a manufacturer to private enterprise numbers. + * + * @return void + */ + public function add() + { + $pen = get_parameter('pen', 0); + $manufacturer = get_parameter('manufacturer', ''); + $description = get_parameter('description', ''); + + if (empty($pen)) { + $error = __('PEN is required.'); + } + + if (empty($manufacturer)) { + $error = __('Manufacturer is required'); + } + + if (!empty($error)) { + echo json_encode( + ['error' => $error] + ); + } + + // Add if not exists. + $current = $this->getAll(['pen'], ['pen' => $pen]); + + if ($current === false) { + // New. + $rs = db_process_sql_insert( + 'tpen', + [ + 'pen' => $pen, + 'manufacturer' => io_safe_input($manufacturer), + 'description' => io_safe_input($description), + ] + ); + $str = __('created'); + } else { + // Update. + $rs = db_process_sql_update( + 'tpen', + [ + 'manufacturer' => io_safe_input($manufacturer), + 'description' => io_safe_input($description), + ], + ['pen' => $pen] + ); + $str = __('updated'); + } + + if ($rs === false) { + global $config; + echo json_encode(['error' => $config['dbconnection']->error]); + } else { + echo json_encode(['result' => __('Succesfully %s', $str)]); + } + } + + /** * Create the main table with the PENs info * @@ -140,110 +545,217 @@ class ConfigPEN extends HTML public function createMainTable() { global $config; - // Get the count of PENs. - $countPENs = db_get_value( - 'count(*)', - 'tpen' - ); - // Get all the data. - $resultPENs = db_get_all_rows_filter( - 'tpen', - [ - 'order' => 'id_np', - 'limit' => $config['block_size'], - ] - ); + $output = ''; - $output = ui_pagination($countPENs, false, $this->offset, 0, true); - // Create the table with Module Block list. - $table = new StdClasS(); - $table->class = 'databox data'; - $table->width = '75%'; - $table->styleTable = 'margin: 2em auto 0;border: 1px solid #ddd;background: white;'; - $table->rowid = []; - $table->data = []; + // Datatables list. + try { + $columns = [ + 'pen', + 'manufacturer', + 'description', + 'options', + ]; - $table->cellpadding = 0; - $table->cellspacing = 0; - $table->width = '100%'; - $table->class = 'info_table'; - - $table->head = []; - $table->head[0] = html_print_checkbox('all_delete', 0, false, true, false); - $table->head[1] = __('PEN'); - $table->head[2] = __('Manufacturer ID'); - $table->head[3] = __('Description'); - $table->head[4] = ''.__('Action').''; - - $table->size = []; - $table->size[0] = '20px'; - $table->size[1] = '10%'; - $table->size[2] = '25%'; - $table->size[4] = '70px'; - - $table->align = []; - $table->align[3] = 'left'; - - $table->data = []; - - foreach ($resultPENs as $row) { - $data = []; - $data[0] = html_print_checkbox_extended('delete_multiple[]', $row['pen'], false, false, '', 'class="check_delete"', true); - $data[1] = ''.$row['pen'].''; - $data[2] = ''.$row['manufacturer'].''; - $data[3] = ''.ui_print_truncate_text(io_safe_output($row['description']), 'description', true, true, true, '[…]').''; - $table->cellclass[][4] = 'action_buttons'; - $data[4] = html_print_input_image( - 'edit_pen_', - 'images/edit.png', - $row['pen'], - 'max-width: 27px;', - true, + $column_names = [ + __('PEN'), + __('Manufacturer'), + __('Description'), [ - 'title' => 'Edit', - 'onclick' => 'modifyPENLine(event)', + 'text' => __('Options'), + 'class' => 'action_buttons', + ], + ]; + + $this->tableId = 'keystore'; + // Load datatables user interface. + $output .= ui_print_datatable( + [ + 'id' => $this->tableId, + 'return' => true, + 'class' => 'info_table', + 'style' => 'width: 100%', + 'columns' => $columns, + 'column_names' => $column_names, + 'ajax_url' => $this->ajaxController, + 'ajax_data' => ['method' => 'draw'], + 'no_sortable_columns' => [-1], + 'order' => [ + 'field' => 'pen', + 'direction' => 'asc', + ], + 'search_button_class' => 'sub filter float-right', + 'form' => [ + 'inputs' => [ + [ + 'label' => __('Free search'), + 'type' => 'text', + 'class' => 'mw250px', + 'id' => 'free_search', + 'name' => 'free_search', + ], + ], + ], ] ); - $data[4] .= html_print_input_image( - 'delete_pen_', - 'images/cross.png', - $row['pen'], - '', - true, - [ - 'title' => 'Delete PEN', - 'onclick' => 'if (confirm(\''.sprintf(__('Are you sure to remove the PEN: %s?'), $row['pen']).'\')) deletePEN(event);', - ] - ); - - array_push($table->data, $data); + } catch (Exception $e) { + echo $e->getMessage(); } - // Last line for adding new PENs. - $data = []; - $data[0] = ''; - $data[1] = html_print_input_text('pen_number', '', '', 10, 255, true); - $data[2] = html_print_input_text('pen_manufacturer', '', '', 30, 255, true); - $data[3] = html_print_input_text('pen_description', '', '', 80, 255, true); - $table->cellclass[][4] = 'action_buttons'; - $data[4] = html_print_input_image( - 'add_new_pen', - 'images/add_mc.png', - '', - 'margin: 0 auto; display: block;', - true, + // Auxiliar div. + $output .= ''; + $output .= ''; + $output .= ''; + + // Create button. + $output .= parent::printInput( [ - 'title' => 'Add new PEN', - 'onclick' => 'addNewPEN()', + 'type' => 'submit', + 'name' => 'create', + 'label' => __('Register manufacturer'), + 'attributes' => 'class="sub next"', + 'return' => true, ] ); - // Add last line. - array_push($table->data, $data); - // Return the entire table. - $output .= html_print_table($table, true); - // $output = 'mis huevos morenos'; + ob_start(); + ?> + + label:not(.p-switch) { + width: auto; +} + +form.top-action-buttons ul.wizard { + display: flex; + flex-direction: row; +} + +ul.wizard li { + margin-right: 1em; +} + +form.modal ul.wizard li { + display: flex; + flex-direction: row; + width: 90%; + margin: 0 auto; + justify-items: center; +} + +form.modal ul.wizard li * { + flex: 1; +} + +ul.wizard li.flex-indep { + flex: 1; + margin: 0; +} + +div#div-form { + padding: 0 2em; +} + +div#div-form textarea { + width: 100%; + margin-top: 1em; +} diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index e0b064e0f2..1c88e65d43 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -944,16 +944,6 @@ CREATE TABLE IF NOT EXISTS `tnetwork_profile` ( PRIMARY KEY (`id_np`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; --- ---------------------------------------------------------------------- --- Table `tpen` --- ---------------------------------------------------------------------- -CREATE TABLE `tpen` ( - `id_np` int(10) unsigned NOT NULL, - `pen` int(10) unsigned NOT NULL, - PRIMARY KEY (`id_np`,`pen`), - CONSTRAINT `fk_np_id` FOREIGN KEY (`id_np`) REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -- ---------------------------------------------------------------------- -- Table `tnetwork_profile_component` -- ---------------------------------------------------------------------- @@ -967,11 +957,11 @@ CREATE TABLE IF NOT EXISTS `tnetwork_profile_component` ( -- Table `tpen` -- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tpen` ( - `id_np` int(10) unsigned NOT NULL, `pen` int(10) unsigned NOT NULL, - `manufacturer` TEXT NOT NULL, - `description` TEXT NULL, - PRIMARY KEY (`id_np`,`pen`), + `manufacturer` TEXT, + `description` TEXT, + `id_np` int(10) unsigned, + PRIMARY KEY (`pen`), CONSTRAINT `fk_np_id` FOREIGN KEY (`id_np`) REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; From 6a14ddea738cf6246b5c2a70fcca947ce41c8796 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Fri, 27 Mar 2020 11:50:41 +0100 Subject: [PATCH 037/111] minor fix --- .../include/class/ConfigPEN.class.php | 49 +++++++++++++++---- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/pandora_console/include/class/ConfigPEN.class.php b/pandora_console/include/class/ConfigPEN.class.php index 4a051d170c..5f2fb6ae37 100644 --- a/pandora_console/include/class/ConfigPEN.class.php +++ b/pandora_console/include/class/ConfigPEN.class.php @@ -400,18 +400,24 @@ class ConfigPEN extends HTML $inputs = []; + $arguments = [ + 'name' => 'pen', + 'type' => 'number', + 'value' => $values['pen'], + 'required' => true, + 'return' => true, + 'size' => 50, + ]; + + if ((bool) $values['pen']) { + $arguments['disabled'] = true; + } + $inputs[] = [ 'label' => __('PEN'), 'class' => 'flex-row', 'id' => 'div-pen', - 'arguments' => [ - 'name' => 'pen', - 'type' => 'number', - 'value' => $values['pen'], - 'required' => true, - 'return' => true, - 'size' => 50, - ], + 'arguments' => $arguments, ]; $inputs[] = [ @@ -477,7 +483,7 @@ class ConfigPEN extends HTML /** - * Add a manufacturer to private enterprise numbers. + * Add or update a manufacturer to private enterprise numbers. * * @return void */ @@ -486,6 +492,7 @@ class ConfigPEN extends HTML $pen = get_parameter('pen', 0); $manufacturer = get_parameter('manufacturer', ''); $description = get_parameter('description', ''); + $is_new = (bool) get_parameter('is_new', false); if (empty($pen)) { $error = __('PEN is required.'); @@ -506,6 +513,15 @@ class ConfigPEN extends HTML if ($current === false) { // New. + if ($is_new === false) { + echo json_encode( + [ + 'error' => __('This PEN definition does not exist'), + ] + ); + exit; + } + $rs = db_process_sql_insert( 'tpen', [ @@ -517,6 +533,15 @@ class ConfigPEN extends HTML $str = __('created'); } else { // Update. + if ($is_new === true) { + echo json_encode( + [ + 'error' => __('This PEN definition already exists'), + ] + ); + exit; + } + $rs = db_process_sql_update( 'tpen', [ @@ -656,9 +681,11 @@ function showForm(id) { var btn_ok_text = ""; var btn_cancel_text = ""; var title = ""; + var is_new = 1; if (id) { btn_ok_text = ""; title = " " + id; + is_new = 0; } load_modal({ target: $("#modal"), @@ -675,6 +702,10 @@ function showForm(id) { { name: "pen", value: id + }, + { + name: 'is_new', + value: is_new } ], onshow: { From 1be120b1dcecfd5ce6a0f7c6867341b07beca657 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Fri, 27 Mar 2020 12:18:09 +0100 Subject: [PATCH 038/111] Solved issue with display style --- pandora_console/include/functions_snmp_browser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/include/functions_snmp_browser.php b/pandora_console/include/functions_snmp_browser.php index 48e45d0e36..224a4ecc3f 100644 --- a/pandora_console/include/functions_snmp_browser.php +++ b/pandora_console/include/functions_snmp_browser.php @@ -783,7 +783,7 @@ function snmp_browser_print_container($return=false, $width='100%', $height='60% $table2->cellstyle[0][2] = 'text-align:center;'; // This extra div that can be handled by jquery's dialog. - $output = '
      '; + $output = '
      '; $output .= '
      '; $output .= '
      '; $output .= html_print_table($table, true); From 4e019fe1935900ff49d9f65618383307d659edc3 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Fri, 27 Mar 2020 13:47:49 +0100 Subject: [PATCH 039/111] Modified name for Network component to Remote component --- pandora_console/godmode/modules/manage_network_components.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/godmode/modules/manage_network_components.php b/pandora_console/godmode/modules/manage_network_components.php index afd7c09189..baa626f1ec 100644 --- a/pandora_console/godmode/modules/manage_network_components.php +++ b/pandora_console/godmode/modules/manage_network_components.php @@ -66,7 +66,7 @@ if (defined('METACONSOLE')) { } ui_print_page_header( - __('Module management').' » '.__('Network component management'), + __('Module management').' » '.__('Remote component management'), '', false, $help_header, From e883312038d54965ffadf7ea4b5a5519a3833be4 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 30 Mar 2020 08:22:07 +0200 Subject: [PATCH 040/111] Modified menu --- pandora_console/godmode/menu.php | 38 ++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index 6b4938d4a5..fe42097b26 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -137,25 +137,31 @@ if (!empty($sub)) { $sub = []; if (check_acl($config['id_user'], 0, 'PM')) { - $sub['godmode/modules/manage_network_components']['text'] = __('Remote components'); - $sub['godmode/modules/manage_network_components']['id'] = 'Network components'; - enterprise_hook('components_submenu'); - $sub['configuration_wizard_setup']['text'] = __('Wizard Setup'); - $sub['configuration_wizard_setup']['id'] = 'Wizard Setup'; - $sub['configuration_wizard_setup']['type'] = 'direct'; - $sub['configuration_wizard_setup']['subtype'] = 'nolink'; + // enterprise_hook('components_submenu'); + $sub['templates']['text'] = __('Templates'); + $sub['templates']['id'] = 'Templates'; + $sub['templates']['type'] = 'direct'; + $sub['templates']['subtype'] = 'nolink'; $sub2 = []; + $sub2['godmode/modules/manage_block_templates']['text'] = __('Module templates'); + $sub2['godmode/modules/manage_block_templates']['id'] = 'Module templates'; $sub2['godmode/modules/private_enterprise_numbers']['text'] = __('Private Enterprise Numbers'); $sub2['godmode/modules/private_enterprise_numbers']['id'] = 'Private Enterprise Numbers'; - $sub2['godmode/modules/manage_snmp_modules']['text'] = __('SNMP Modules'); - $sub2['godmode/modules/manage_snmp_modules']['id'] = 'SNMP Modules'; - $sub2['godmode/modules/manage_wmi_modules']['text'] = __('WMI Modules'); - $sub2['godmode/modules/manage_wmi_modules']['id'] = 'WMI Modules'; - $sub['configuration_wizard_setup']['sub2'] = $sub2; - $sub['godmode/modules/manage_block_templates']['text'] = __('Module blocks'); - $sub['godmode/modules/manage_block_templates']['id'] = 'Module blocks'; - $sub['godmode/modules/manage_network_templates']['text'] = __('Module templates (legacy)'); - $sub['godmode/modules/manage_network_templates']['id'] = 'Module templates'; + $sub2['enterprise/godmode/modules/local_components']['text'] = __('Local components'); + $sub2['enterprise/godmode/modules/local_components']['id'] = 'Local components'; + $sub2['godmode/modules/manage_network_components']['text'] = __('Remote components'); + $sub2['godmode/modules/manage_network_components']['id'] = 'Network components'; + $sub['templates']['sub2'] = $sub2; + /* + $sub2['godmode/modules/manage_snmp_modules']['text'] = __('SNMP Modules'); + $sub2['godmode/modules/manage_snmp_modules']['id'] = 'SNMP Modules'; + $sub2['godmode/modules/manage_wmi_modules']['text'] = __('WMI Modules'); + $sub2['godmode/modules/manage_wmi_modules']['id'] = 'WMI Modules'; + $sub['godmode/modules/manage_block_templates']['text'] = __('Module blocks'); + $sub['godmode/modules/manage_block_templates']['id'] = 'Module blocks'; + */ + + enterprise_hook('inventory_submenu'); enterprise_hook('autoconfiguration_menu'); enterprise_hook('agent_repository_menu'); From a7c783242d99b15716466e9665e94065a1f8b583 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 30 Mar 2020 12:51:52 +0200 Subject: [PATCH 041/111] Remaining stuff --- pandora_console/godmode/servers/discovery.php | 2 + .../wizards/DiscoveryTaskList.class.php | 32 ++- pandora_server/lib/PandoraFMS/Core.pm | 53 ++++- .../lib/PandoraFMS/DiscoveryServer.pm | 213 ++++++++++++------ 4 files changed, 230 insertions(+), 70 deletions(-) diff --git a/pandora_console/godmode/servers/discovery.php b/pandora_console/godmode/servers/discovery.php index 39f07aa025..3dd8e258ee 100755 --- a/pandora_console/godmode/servers/discovery.php +++ b/pandora_console/godmode/servers/discovery.php @@ -1,5 +1,7 @@ '; echo __('deselect all'); echo ''; + echo ''; + echo ''; echo '
      '; echo '
      '; @@ -1279,12 +1285,18 @@ class DiscoveryTaskList extends HTML } $ids = []; + $n_agents = 0; $selection = io_safe_output(get_parameter('tree-data-tree', '')); if (empty($selection) === false) { $selection = json_decode($selection, true); $ids = array_reduce( $selection, - function ($carry, $item) { + function ($carry, $item) use (&$n_agents) { + if (explode('-', $item['id'])[1] === null) { + // String is agent-module. + $n_agents++; + } + $carry[] = $item['id']; return $carry; } @@ -1296,6 +1308,24 @@ class DiscoveryTaskList extends HTML ['id_rt' => $id_task] ); + // License precheck. + $license = enterprise_hook('license_get_info'); + + if (is_array($license) === true + && $n_agents > ($license['limit'] - $license['count']) + ) { + $limit = ($license['limit'] - $license['count']); + echo json_encode( + [ + 'error' => __( + 'Your selection exceeds the agents available on your license. Limit %d', + $limit + ), + ] + ); + return; + } + $summary = []; if (is_array($ids)) { foreach ($task_data as $row) { diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index 9d2f4c18ac..b387de5283 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -270,7 +270,9 @@ our @EXPORT = qw( pandora_delete_custom_graph pandora_edit_custom_graph notification_set_targets - ); + notification_get_users + notification_get_groups +); # Some global variables our @DayNames = qw(sunday monday tuesday wednesday thursday friday saturday); @@ -6254,6 +6256,55 @@ sub notification_set_targets { return 1; } +########################################################################## + +=head2 C<< notification_get_users (I<$dbh>, I<$source>) >> +Get targets for given sources +=cut + +########################################################################## +sub notification_get_users { + my ($dbh, $source) = @_; + + my @results = get_db_rows( + $dbh, + 'SELECT id_user + FROM tnotification_source_user nsu + INNER JOIN tnotification_source ns ON nsu.id_source=ns.id + WHERE ns.description = ? + ', + safe_input($source) + ); + + @results = map { $_->{'id_user'} } @results; + return @results; +} + +########################################################################## + +=head2 C<< notification_get_groups (I<$dbh>, I<$source>) >> +Get targets for given sources +=cut + +########################################################################## +sub notification_get_groups { + my ($dbh, $source) = @_; + + my @results = get_db_rows( + $dbh, + 'SELECT id_group + FROM tnotification_source_group nsg + INNER JOIN tnotification_source ns ON nsg.id_source=ns.id + WHERE ns.description = ? + ', + safe_input($source) + ); + + @results = map { $_->{'id_group'} } @results; + return @results; +} + + # End of function declaration # End of defined Code diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index bdfe445f15..9be368749d 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -58,8 +58,8 @@ use constant { STEP_AFT => 2, STEP_TRACEROUTE => 3, STEP_GATEWAY => 4, - STEP_MONITORING => 5, - STEP_PROCESSING => 6, + STEP_MONITORING => 5, + STEP_PROCESSING => 6, STEP_STATISTICS => 1, STEP_APP_SCAN => 2, STEP_CUSTOM_QUERIES => 3, @@ -206,17 +206,26 @@ sub data_consumer ($$) { @auth_strings = split(/,/, safe_output($task->{'auth_strings'})); } - my $main_event = pandora_event($pa_config, "[Discovery] Execution summary",$task->{'id_group'}, 0, 0, 0, 0, 'system', 0, $dbh); + my $main_event = pandora_event($pa_config, + "[Discovery] Execution summary", + $task->{'id_group'}, 0, 0, 0, 0, 'system', 0, $dbh + ); my %cnf_extra; - my $r = enterprise_hook('discovery_generate_extra_cnf',[$pa_config, $dbh, $task, \%cnf_extra]); + my $r = enterprise_hook( + 'discovery_generate_extra_cnf', + [ + $pa_config, + $dbh, $task, + \%cnf_extra + ] + ); if (defined($r) && $r eq 'ERR') { # Could not generate extra cnf, skip this task. return; } - if ($task->{'type'} == DISCOVERY_APP_SAP) { # SAP TASK, retrieve license. $task->{'sap_license'} = pandora_get_config_value( @@ -752,74 +761,74 @@ sub PandoraFMS::Recon::Base::create_interface_modules($$) { # Add wmi modules to the given host. ################################################################################ sub PandoraFMS::Recon::Base::create_wmi_modules { - my ($self, $target) = @_; + my ($self, $target) = @_; # Add modules to the agent if it responds to WMI. return unless ($self->wmi_responds($target)); - my $key = $self->wmi_credentials_key($target); + my $key = $self->wmi_credentials_key($target); my $creds = $self->call('get_credentials', $key); - # Add modules. - # CPU. - my @cpus = $self->wmi_get_value_array($target, 'SELECT DeviceId FROM Win32_Processor', 0); - foreach my $cpu (@cpus) { - $self->add_module( - $target, - { - 'ip_target' => $target, - 'snmp_oid' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId=\'$cpu\'", - 'plugin_user' => $creds->{'username'}, + # Add modules. + # CPU. + my @cpus = $self->wmi_get_value_array($target, 'SELECT DeviceId FROM Win32_Processor', 0); + foreach my $cpu (@cpus) { + $self->add_module( + $target, + { + 'ip_target' => $target, + 'snmp_oid' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId=\'$cpu\'", + 'plugin_user' => $creds->{'username'}, 'plugin_pass' => $creds->{'password'}, - 'tcp_port' => 1, - 'name' => "CPU Load $cpu", - 'descripcion' => safe_input("Load for $cpu (%)"), - 'id_tipo_modulo' => 1, + 'tcp_port' => 1, + 'name' => "CPU Load $cpu", + 'descripcion' => safe_input("Load for $cpu (%)"), + 'id_tipo_modulo' => 1, 'id_modulo' => 6, - 'unit' => '%', - } - ); - } + 'unit' => '%', + } + ); + } - # Memory. - my $mem = $self->wmi_get_value($target, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0); - if (defined($mem)) { - $self->add_module( - $target, - { - 'ip_target' => $target, - 'snmp_oid' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem", - 'plugin_user' => $creds->{'username'}, - 'plugin_pass' => $creds->{'password'}, - 'tcp_port' => 0, - 'name' => 'FreeMemory', - 'descripcion' => safe_input('Free memory'), - 'id_tipo_modulo' => 1, + # Memory. + my $mem = $self->wmi_get_value($target, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0); + if (defined($mem)) { + $self->add_module( + $target, + { + 'ip_target' => $target, + 'snmp_oid' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem", + 'plugin_user' => $creds->{'username'}, + 'plugin_pass' => $creds->{'password'}, + 'tcp_port' => 0, + 'name' => 'FreeMemory', + 'descripcion' => safe_input('Free memory'), + 'id_tipo_modulo' => 1, 'id_modulo' => 6, - 'unit' => 'KB', - } - ); - } + 'unit' => 'KB', + } + ); + } - # Disk. - my @units = $self->wmi_get_value_array($target, 'SELECT DeviceID FROM Win32_LogicalDisk', 0); - foreach my $unit (@units) { - $self->add_module( - $target, - { - 'ip_target' => $target, - 'snmp_oid' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'", - 'plugin_user' => $creds->{'username'}, - 'plugin_pass' => $creds->{'password'}, - 'tcp_port' => 1, - 'name' => "FreeDisk $unit", - 'descripcion' => safe_input('Available disk space in kilobytes'), - 'id_tipo_modulo' => 1, + # Disk. + my @units = $self->wmi_get_value_array($target, 'SELECT DeviceID FROM Win32_LogicalDisk', 0); + foreach my $unit (@units) { + $self->add_module( + $target, + { + 'ip_target' => $target, + 'snmp_oid' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'", + 'plugin_user' => $creds->{'username'}, + 'plugin_pass' => $creds->{'password'}, + 'tcp_port' => 1, + 'name' => "FreeDisk $unit", + 'descripcion' => safe_input('Available disk space in kilobytes'), + 'id_tipo_modulo' => 1, 'id_modulo' => 6, - 'unit' => 'KB', - } - ); - } + 'unit' => 'KB', + } + ); + } } @@ -978,7 +987,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { my $parent_id; my $os_id = $self->guess_os($data->{'agent'}{'direccion'}); - $self->call('message', "Agent accepted: ".$data->{'agent'}{'nombre'}, 5); + $self->call('message', "Agent accepted: ".$data->{'agent'}{'nombre'}, 5); # Agent creation. my $agent_id = $data->{'agent'}{'agent_id'}; @@ -1003,6 +1012,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { ); if (!defined($agent_id) || $agent_id <= 0) { + # Agent creation. $agent_id = pandora_create_agent( $self->{'pa_config'}, $self->{'servername'}, $data->{'agent'}{'nombre'}, $data->{'agent'}{'direccion'}, $self->{'task_data'}{'group_id'}, $parent_id, @@ -1011,6 +1021,42 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { $data->{'agent'}{'timezone_offset'} ); + # Agent autoconfiguration. + if (is_enabled($self->{'autoconfiguration_enabled'})) { + my $agent_data = PandoraFMS::DB::get_db_single_row( + $self->{'dbh'}, + 'SELECT * FROM tagente WHERE id_agente = ?', + $agent_id + ); + + # Update agent configuration once, after create agent. + enterprise_hook( + 'autoconfigure_agent', + [ + $self->{'pa_config'}, + $data->{'agent'}{'direccion'}, + $agent_id, + $agent_data, + $self->{'dbh'}, + 1 + ] + ); + } + + if (defined($self->{'main_event_id'})) { + my $addresses_str = join( + ',', + safe_output($self->get_addresses($data->{'agent'}{'nombre'})) + ); + pandora_extended_event( + $self->{'pa_config'}, $self->{'dbh'}, + $self->{'main_event_id'},"[Discovery] New " + . safe_output($self->get_device_type($data->{'agent'}{'nombre'})) + . " found " . $$data->{'agent'}{'nombre'} . " (" . $addresses_str + . ") Agent $agent_id." + ); + } + $agent_learning = 1; } else { # Read from effective agent_id. @@ -1061,7 +1107,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { # Delete unwanted fields. delete $module->{'agentmodule_id'}; - delete $module->{'checked'}; + delete $module->{'checked'}; my $id_tipo_modulo = $module->{'id_tipo_modulo'}; $id_tipo_modulo = get_module_id($self->{'dbh'}, $module->{'type'}) @@ -1105,7 +1151,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { $self->{'dbh'} ); - $module->{'name'} = $name; + $module->{'name'} = $name; $module->{'description'} = safe_output($description); } @@ -1213,8 +1259,8 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { $self->call('message', "Storing results", 6); my @hosts = keys %{$self->{'agents_found'}}; - $self->{'step'} = STEP_PROCESSING; - my ($progress, $step) = (90, 10.0 / scalar(@hosts)); # From 90% to 100%. + $self->{'step'} = STEP_PROCESSING; + my ($progress, $step) = (90, 10.0 / scalar(@hosts)); # From 90% to 100%. foreach my $label (keys %{$self->{'agents_found'}}) { $self->call('update_progress', $progress); $progress += $step; @@ -1261,6 +1307,37 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { ); } + # Notify. + my $notification = {}; + $notification->{'subject'} = safe_input('Review pending'); + $notification->{'mensaje'} = safe_input( + 'Discovery task (host&devices) \''.safe_output($self->{'task_data'}{'name'}) + .'\' has been completed. Please review the results.' + ); + $notification->{'id_source'} = get_db_value( + $self->{'dbh'}, + 'SELECT id FROM tnotification_source WHERE description = ?', + safe_input('System status') + ); + + # Create message + my $notification_id = db_process_insert( + $self->{'dbh'}, + 'id_mensaje', + 'tmensajes', + $notification + ); + + if (is_enabled($notification_id)) { + my @users = notification_get_users($self->{'dbh'}, 'System status'); + my @groups = notification_get_groups($self->{'dbh'}, 'System status'); + + notification_set_targets( + $self->{'pa_config'}, $self->{'dbh'}, + $notification_id, \@users, \@groups + ); + } + $self->call('message', "Completed", 5); } @@ -1272,9 +1349,9 @@ sub PandoraFMS::Recon::Base::apply_monitoring($) { my @hosts = keys %{$self->{'agents_found'}}; - $self->{'step'} = STEP_MONITORING; + $self->{'step'} = STEP_MONITORING; # From 80% to 90%. - my ($progress, $step) = (80, 10.0 / scalar(@hosts)); + my ($progress, $step) = (80, 10.0 / scalar(@hosts)); my ($partial, $sub_step) = (0, 100 / scalar(@hosts)); foreach my $label (keys %{$self->{'agents_found'}}) { From 86dfcd162bc7a0f8db6479f93d7dd72827e93c6a Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 30 Mar 2020 14:28:10 +0200 Subject: [PATCH 042/111] Update --- .../lib/PandoraFMS/DiscoveryServer.pm | 106 +++++++++--------- pandora_server/lib/PandoraFMS/Recon/Base.pm | 15 ++- 2 files changed, 66 insertions(+), 55 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index 9be368749d..26a5566ac0 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -916,23 +916,21 @@ sub PandoraFMS::Recon::Base::get_credentials { ################################################################################ # Create agents and modules reported by Recon::Base. ################################################################################ -sub PandoraFMS::Recon::Base::report_scanned_agents($) { - my ($self) = @_; +sub PandoraFMS::Recon::Base::report_scanned_agents($;$) { + my ($self,$force) = @_; - my $force_creation = 0; - - if (defined($self->{'task_data'}{'review_mode'}) - && $self->{'task_data'}{'review_mode'} == DISCOVERY_STANDARD - ) { - $force_creation = 1; - } + my $force_creation = $force; + $force_creation = 0 unless (is_enabled($force)); # # Creation # - if(defined($self->{'task_data'}{'review_mode'}) - && $self->{'task_data'}{'review_mode'} == DISCOVERY_RESULTS + + if($force_creation == 1 + || (defined($self->{'task_data'}{'review_mode'}) + && $self->{'task_data'}{'review_mode'} == DISCOVERY_RESULTS) ) { + # Load cache. my @rows = get_db_rows( $self->{'dbh'}, @@ -1008,7 +1006,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { $agent_id = get_db_value( $self->{'dbh'}, 'SELECT id_agente FROM tagente WHERE nombre = ?', - safe_input($data->{'agent'}->{'name'}) + safe_input($data->{'agent'}{'nombre'}) ); if (!defined($agent_id) || $agent_id <= 0) { @@ -1046,13 +1044,14 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { if (defined($self->{'main_event_id'})) { my $addresses_str = join( ',', - safe_output($self->get_addresses($data->{'agent'}{'nombre'})) + $self->get_addresses(safe_output($data->{'agent'}{'nombre'})) ); + pandora_extended_event( $self->{'pa_config'}, $self->{'dbh'}, $self->{'main_event_id'},"[Discovery] New " - . safe_output($self->get_device_type($data->{'agent'}{'nombre'})) - . " found " . $$data->{'agent'}{'nombre'} . " (" . $addresses_str + . $self->get_device_type(safe_output($data->{'agent'}{'nombre'})) + . " found " . $data->{'agent'}{'nombre'} . " (" . $addresses_str . ") Agent $agent_id." ); } @@ -1090,17 +1089,13 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { $self->call('message', "[$agent_id] Module: ".$module->{'name'}, 5); - my $agentmodule_id = $module->{'agentmodule_id'}; - - if (defined($agentmodule_id) && $agentmodule_id > 0) { - $agentmodule_id = get_db_value( - $self->{'dbh'}, - 'SELECT id_agente_modulo FROM tagente_modulo - WHERE id_agente_modulo = ? AND nombre = ?', - $agentmodule_id, - safe_input($module->{'name'}) - ); - } + my $agentmodule_id = get_db_value( + $self->{'dbh'}, + 'SELECT id_agente_modulo FROM tagente_modulo + WHERE id_agente = ? AND nombre = ?', + $agent_id, + safe_input($module->{'name'}) + ); if (!is_enabled($agentmodule_id)) { # Create. @@ -1307,35 +1302,40 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($) { ); } - # Notify. - my $notification = {}; - $notification->{'subject'} = safe_input('Review pending'); - $notification->{'mensaje'} = safe_input( - 'Discovery task (host&devices) \''.safe_output($self->{'task_data'}{'name'}) - .'\' has been completed. Please review the results.' - ); - $notification->{'id_source'} = get_db_value( - $self->{'dbh'}, - 'SELECT id FROM tnotification_source WHERE description = ?', - safe_input('System status') - ); - # Create message - my $notification_id = db_process_insert( - $self->{'dbh'}, - 'id_mensaje', - 'tmensajes', - $notification - ); - - if (is_enabled($notification_id)) { - my @users = notification_get_users($self->{'dbh'}, 'System status'); - my @groups = notification_get_groups($self->{'dbh'}, 'System status'); - - notification_set_targets( - $self->{'pa_config'}, $self->{'dbh'}, - $notification_id, \@users, \@groups + if(defined($self->{'task_data'}{'review_mode'}) + && $self->{'task_data'}{'review_mode'} == DISCOVERY_REVIEW + ) { + # Notify. + my $notification = {}; + $notification->{'subject'} = safe_input('Review pending'); + $notification->{'mensaje'} = safe_input( + 'Discovery task (host&devices) \''.safe_output($self->{'task_data'}{'name'}) + .'\' has been completed. Please review the results.' ); + $notification->{'id_source'} = get_db_value( + $self->{'dbh'}, + 'SELECT id FROM tnotification_source WHERE description = ?', + safe_input('System status') + ); + + # Create message + my $notification_id = db_process_insert( + $self->{'dbh'}, + 'id_mensaje', + 'tmensajes', + $notification + ); + + if (is_enabled($notification_id)) { + my @users = notification_get_users($self->{'dbh'}, 'System status'); + my @groups = notification_get_groups($self->{'dbh'}, 'System status'); + + notification_set_targets( + $self->{'pa_config'}, $self->{'dbh'}, + $notification_id, \@users, \@groups + ); + } } $self->call('message', "Completed", 5); diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 9bf4e8e536..81e7d5993f 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -683,7 +683,11 @@ sub get_device_type($$) { my ($self, $device) = @_; if (defined($self->{'visited_devices'}->{$device})) { - return $self->{'visited_devices'}->{$device}->{'type'}; + if (defined($self->{'visited_devices'}->{$device}->{'type'})) { + return $self->{'visited_devices'}->{$device}->{'type'}; + } else { + $self->{'visited_devices'}->{$device}->{'type'} = 'host'; + } } # Assume 'host' by default. @@ -1931,7 +1935,14 @@ sub scan($) { $self->call('message', "[6/6] Processing results.", 3); $self->{'step'} = STEP_PROCESSING; # Send agent information to Database (Discovery) or XML (satellite.). - $self->call('report_scanned_agents', $self->{'agents_found'}); + $self->call('report_scanned_agents'); + + if(defined($self->{'task_data'}{'review_mode'}) + && $self->{'task_data'}{'review_mode'} == DISCOVERY_STANDARD + ) { + # Send agent information to Database (Discovery) or XML (satellite.). + $self->call('report_scanned_agents', 1); + } # Done! $self->{'step'} = ''; From c556bf3ba8678112bc79bd12420bd0e547154d0a Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 30 Mar 2020 15:03:22 +0200 Subject: [PATCH 043/111] License validation --- .../godmode/wizards/HostDevices.class.php | 39 +++++++++++++++++-- .../lib/PandoraFMS/DiscoveryServer.pm | 6 ++- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php index 727010cb8d..26333fbd49 100755 --- a/pandora_console/godmode/wizards/HostDevices.class.php +++ b/pandora_console/godmode/wizards/HostDevices.class.php @@ -946,6 +946,36 @@ class HostDevices extends Wizard ], ]; + // License precheck. + $license = enterprise_hook('license_get_info'); + $n_agents = 0; + foreach (explode(',', $this->task['subnet']) as $net) { + $mask = explode('/', $net, 2)[1]; + if (empty($mask) === true) { + $n_agents++; + } else { + $n_agents += pow(2, (32 - $mask)); + } + } + + $limited = false; + if (is_array($license) === true + && $n_agents > ($license['limit'] - $license['count']) + ) { + $limit = ($license['limit'] - $license['count']); + $limited = true; + } + + if ($limited === true) { + ui_print_warning_message( + __( + 'Configured networks could generate %d agents, your license only allows %d, \'review results\' is mandatory.', + $n_agents, + $limit + ) + ); + } + $form['inputs'][] = [ 'label' => __('Review results').ui_print_help_tip( __( @@ -954,10 +984,11 @@ class HostDevices extends Wizard true ), 'arguments' => [ - 'name' => 'review_results', - 'type' => 'switch', - 'return' => true, - 'value' => ($this->task['review_mode'] == DISCOVERY_STANDARD) ? 0 : 1, + 'name' => 'review_results', + 'type' => 'switch', + 'return' => true, + 'value' => ($this->task['review_mode'] == DISCOVERY_STANDARD) ? ($limited ? 1 : 0) : 1, + 'disabled' => $limited, ], ]; diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index 26a5566ac0..2c3d9f1c9f 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -1308,11 +1308,15 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($;$) { ) { # Notify. my $notification = {}; - $notification->{'subject'} = safe_input('Review pending'); + $notification->{'subject'} = safe_input('Discovery task '); + $notification->{'subject'} .= $self->{'task_data'}{'name'}; + $notification->{'subject'} .= safe_input(' review pending'); + $notification->{'mensaje'} = safe_input( 'Discovery task (host&devices) \''.safe_output($self->{'task_data'}{'name'}) .'\' has been completed. Please review the results.' ); + $notification->{'id_source'} = get_db_value( $self->{'dbh'}, 'SELECT id FROM tnotification_source WHERE description = ?', From 6ea901e7eeb4210447df54adedcc77759d60bbd6 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 30 Mar 2020 15:07:05 +0200 Subject: [PATCH 044/111] Limitations --- pandora_console/godmode/wizards/HostDevices.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php index 26333fbd49..43825c31e5 100755 --- a/pandora_console/godmode/wizards/HostDevices.class.php +++ b/pandora_console/godmode/wizards/HostDevices.class.php @@ -951,7 +951,7 @@ class HostDevices extends Wizard $n_agents = 0; foreach (explode(',', $this->task['subnet']) as $net) { $mask = explode('/', $net, 2)[1]; - if (empty($mask) === true) { + if (empty($mask)) { $n_agents++; } else { $n_agents += pow(2, (32 - $mask)); @@ -987,7 +987,7 @@ class HostDevices extends Wizard 'name' => 'review_results', 'type' => 'switch', 'return' => true, - 'value' => ($this->task['review_mode'] == DISCOVERY_STANDARD) ? ($limited ? 1 : 0) : 1, + 'value' => ($this->task['review_mode'] == DISCOVERY_STANDARD) ? (($limited) ? 1 : 0) : 1, 'disabled' => $limited, ], ]; From d09c5f355b208a0b004120f85568a06db822128e Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 30 Mar 2020 17:00:48 +0200 Subject: [PATCH 045/111] WIP: Fixes and refactor --- pandora_console/godmode/menu.php | 6 +- ...plates.php => manage_module_templates.php} | 31 +- .../modules/manage_network_templates.php | 9 +- ...ck.class.php => ModuleTemplates.class.php} | 383 ++++++++++++++++-- 4 files changed, 377 insertions(+), 52 deletions(-) rename pandora_console/godmode/modules/{manage_block_templates.php => manage_module_templates.php} (79%) rename pandora_console/include/class/{ManageBlock.class.php => ModuleTemplates.class.php} (57%) diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index fe42097b26..85b2864c05 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -143,8 +143,10 @@ if (check_acl($config['id_user'], 0, 'PM')) { $sub['templates']['type'] = 'direct'; $sub['templates']['subtype'] = 'nolink'; $sub2 = []; - $sub2['godmode/modules/manage_block_templates']['text'] = __('Module templates'); - $sub2['godmode/modules/manage_block_templates']['id'] = 'Module templates'; + $sub2['godmode/modules/manage_network_templates']['text'] = __('Module templates (legacy)'); + $sub2['godmode/modules/manage_network_templates']['id'] = 'Module templates'; + $sub2['godmode/modules/manage_module_templates']['text'] = __('Module templates'); + $sub2['godmode/modules/manage_module_templates']['id'] = 'Module templates'; $sub2['godmode/modules/private_enterprise_numbers']['text'] = __('Private Enterprise Numbers'); $sub2['godmode/modules/private_enterprise_numbers']['id'] = 'Private Enterprise Numbers'; $sub2['enterprise/godmode/modules/local_components']['text'] = __('Local components'); diff --git a/pandora_console/godmode/modules/manage_block_templates.php b/pandora_console/godmode/modules/manage_module_templates.php similarity index 79% rename from pandora_console/godmode/modules/manage_block_templates.php rename to pandora_console/godmode/modules/manage_module_templates.php index 3a93d975b0..1dba12e625 100644 --- a/pandora_console/godmode/modules/manage_block_templates.php +++ b/pandora_console/godmode/modules/manage_module_templates.php @@ -13,13 +13,13 @@ // GNU General Public License for more details. // Load global vars // TESTING - /* - ini_set('display_errors', 1); + + /* ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); */ // END global $config; - +hd($_POST); check_login(); if (! check_acl($config['id_user'], 0, 'PM')) { @@ -32,14 +32,14 @@ if (! check_acl($config['id_user'], 0, 'PM')) { } -require_once $config['homedir'].'/include/class/ManageBlock.class.php'; -$ajaxPage = ENTERPRISE_DIR.'/godmode/agentes/ManageBlock'; +require_once $config['homedir'].'/include/class/ModuleTemplates.class.php'; +$ajaxPage = ENTERPRISE_DIR.'/godmode/agentes/ModuleTemplates'; // Control call flow. try { // User access and validation is being processed on class constructor. - $manageBlock = new ManageBlock(''); + $moduleTemplates = new ModuleTemplates(''); } catch (Exception $e) { - echo '[ManageBlock]'.$e->getMessage(); + echo '[ModuleTemplates]'.$e->getMessage(); /* if (is_ajax()) { echo json_encode(['error' => '[MiFuncionalidad]'.$e->getMessage() ]); @@ -69,21 +69,18 @@ if (is_ajax()) { // Stop any execution. exit; } else { + //hd($_POST); // Run. - $manageBlock->run(); + $moduleTemplates->run(); // Get the id_np. - $id_np = $manageBlock->getIdNp(); - $saveData = $manageBlock->getSaveData(); - - if ($saveData === true) { - // Save the data sent - $manageBlock->saveData(); - } else if ($id_np === -1) { + $id_np = $moduleTemplates->getIdNp(); + $moduleTemplates->processData(); + if ($id_np === -1) { // List all Module Blocks. - $manageBlock->moduleBlockList(); + $moduleTemplates->moduleBlockList(); } else { // Create new o update Template. - $manageBlock->moduleTemplateForm(); + $moduleTemplates->moduleTemplateForm(); } } diff --git a/pandora_console/godmode/modules/manage_network_templates.php b/pandora_console/godmode/modules/manage_network_templates.php index 16b52aa2d0..2050fb916c 100644 --- a/pandora_console/godmode/modules/manage_network_templates.php +++ b/pandora_console/godmode/modules/manage_network_templates.php @@ -45,14 +45,15 @@ ui_print_page_header( true, 'modulemodal' ); - -ui_print_info_message( +/* + // At this moment, this message is not necessary + ui_print_info_message( __( 'This section is maintained only for legacy use. Please, keep in mind use %s for manage template blocks.', 'Module Blocks' ) -); - + ); +*/ require_once 'include/functions_network_profiles.php'; $delete_profile = (bool) get_parameter('delete_profile'); diff --git a/pandora_console/include/class/ManageBlock.class.php b/pandora_console/include/class/ModuleTemplates.class.php similarity index 57% rename from pandora_console/include/class/ManageBlock.class.php rename to pandora_console/include/class/ModuleTemplates.class.php index 64731c9949..36381c8ff3 100644 --- a/pandora_console/include/class/ManageBlock.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -30,9 +30,9 @@ global $config; require_once $config['homedir'].'/include/class/HTML.class.php'; /** - * Class ManageBlock + * Class ModuleTemplates */ -class ManageBlock extends HTML +class ModuleTemplates extends HTML { /** @@ -84,6 +84,20 @@ class ManageBlock extends HTML */ private $pen; + /** + * Group for adding modules + * + * @var string + */ + private $ncGroup; + + /** + * Filter for adding modules + * + * @var string + */ + private $ncFilter; + /** * Constructor @@ -112,7 +126,7 @@ class ManageBlock extends HTML } // Set baseUrl for use it in several locations in this class. - $this->baseUrl = ui_get_full_url('index.php?sec=gmodules&sec2=godmode/modules/manage_block_templates'); + $this->baseUrl = ui_get_full_url('index.php?sec=gmodules&sec2=godmode/modules/manage_module_templates'); // Capture all parameters before start. $this->id_np = get_parameter('id_np', -1); $this->name = get_parameter('name', ''); @@ -120,7 +134,8 @@ class ManageBlock extends HTML $this->pen = get_parameter('pen', ''); $this->offset = get_parameter('offset', 0); $this->ajaxController = $ajax_controller; - $this->saveData = (bool) get_parameter('save', 0); + $this->ncGroup = get_parameter('ncgroup', -1); + $this->ncFilter = get_parameter('ncfilter', ''); return $this; } @@ -147,9 +162,14 @@ class ManageBlock extends HTML 'label' => __('Configuration'), 'selected' => false, ], + [ + 'link' => '', + 'label' => __('Templates'), + 'selected' => false, + ], [ 'link' => $this->baseUrl, - 'label' => __('Module Blocks'), + 'label' => __('Module template management'), 'selected' => true, ], ], @@ -157,7 +177,7 @@ class ManageBlock extends HTML ); ui_print_page_header( - __('Manage module blocks'), + __('Module template management'), '', false, '', @@ -185,13 +205,94 @@ class ManageBlock extends HTML /** - * Get the value of if we want save the changes + * Undocumented function * - * @return boolean True if must save the changes + * @return void */ - public function getSaveData() + public function processData() { - return $this->saveData; + // This data is sent always + $name = get_parameter('name', ''); + $description = get_parameter('description', ''); + $pensList = get_parameter('pen', ''); + $action = get_parameter('submit_button', ''); + + // Evaluate the modules allowed + if (!empty($action)) { + $numberComponent = []; + foreach ($_POST as $k => $value) { + if (strpos($k, 'module_check_') >= 0 && $value == 1) { + $tmpNumberComponent = explode('_', $k); + $numberComponent[] = $tmpNumberComponent[2]; + } + } + + switch ($action) { + case 'Update': + $dbResult_tnp = db_process_sql_update( + 'tnetwork_profile', + [ + 'name' => $name, + 'description' => $description, + ], + ['id_np' => $this->id_np] + ); + + $getProfilePens = db_get_all_rows_sql(sprintf('SELECT pen FROM tpen WHERE id_np = %s', $this->id_np)); + + $dbResult_pen = db_process_sql_update( + 'tpen', + [ + 'pen' => $pen, + 'manufacturer' => '', + 'description' => '', + 'id_np' => $this->id_np, + ], + ['id_np' => $this->id_np] + ); + + break; + + case 'Create': + $dbResult_tnp = db_process_sql_insert( + 'tnetwork_profile', + [ + 'name' => $name, + 'description' => $description, + ] + ); + + if ($dbResult_tnp != false) { + foreach ($pensList as $currentPen) { + $dbResult_pen = db_process_sql_insert( + 'tpen', + [ + 'pen' => $currentPen, + 'manufacturer' => '', + 'description' => '', + 'id_np' => $this->id_np, + ] + ); + + if ($dbResult_pen === false) { + break; + } + } + } + break; + + default: + $dbResult_tnp = false; + break; + } + + if ($dbResult_tnp === false || $dbResult_pen === false) { + ui_print_error_message(__('Error saving data')); + } else { + ui_print_success_message(__('Changes saved sucessfully')); + } + } + } @@ -200,18 +301,235 @@ class ManageBlock extends HTML * * @return void */ - private function saveData() + public function addingModulesForm() { - // if ($) - $name = get_parameter('name', ''); - $description = get_parameter('description', ''); - $pen = get_parameter('pen', ''); - hd($name); - hd($description); - hd($pen); + + // Get the groups for select input + $result = db_get_all_rows_in_table('tnetwork_component_group', 'name'); + if ($result === false) { + $result = []; + } + + // 2 arrays. 1 with the groups, 1 with the groups by parent + $groups = []; + $groups_compound = []; + foreach ($result as $row) { + $groups[$row['id_sg']] = $row['name']; + } + + foreach ($result as $row) { + $groups_compound[$row['id_sg']] = ''; + if ($row['parent'] > 1) { + $groups_compound[$row['id_sg']] = $groups[$row['parent']].' / '; + } + + $groups_compound[$row['id_sg']] .= $row['name']; + } + + # For erase + #$group_filter .= html_print_select($groups_compound, 'ncgroup', $ncgroup, 'javascript:this.form.submit();', __('Group').' - '.__('All'), -1, true, false, true, '" style="width:350px'); + + // Get the components for show in a list for select + if ($this->ncGroup > 0) { + $sql = sprintf( + " + SELECT id_nc, name, id_group + FROM tnetwork_component + WHERE id_group = %d AND name LIKE '%".$this->ncFilter."%' + ORDER BY name", + $this->ncGroup + ); + } else { + $sql = " + SELECT id_nc, name, id_group + FROM tnetwork_component + WHERE name LIKE '%".$this->ncFilter."%' + ORDER BY name"; + } + + $result = db_get_all_rows_sql($sql); + $components = []; + if ($result === false) { + $result = []; + } + + foreach ($result as $row) { + $components[$row['id_nc']] = $row['name']; + } + + // Main form. + $form = [ + 'action' => $this->baseUrl, + 'id' => 'add_module_form', + 'method' => 'POST', + 'class' => 'databox filters', + 'extra' => '', + ]; + + // Inputs. + $inputs = []; + + $inputs[] = [ + 'id' => 'inp-id_np', + 'arguments' => [ + 'name' => 'id_np', + 'type' => 'hidden', + 'value' => $this->id_np, + 'return' => true, + ], + ]; + + $inputs[] = [ + 'label' => __('Filter'), + 'id' => 'add-modules-filter', + 'arguments' => [ + 'name' => 'add-modules-filter', + 'input_class' => 'flex-row', + 'type' => 'text', + 'value' => '', + 'return' => true, + ], + ]; + + $inputs[] = [ + 'label' => __('Group'), + 'id' => 'add-modules-group', + 'arguments' => [ + 'name' => 'add-modules-group', + 'input_class' => 'flex-row', + 'type' => 'select', + 'script' => 'this.form.submit()', + 'fields' => $groups_compound, + 'return' => true, + ], + ]; + + $inputs[] = [ + 'label' => __('Components'), + 'id' => 'add-modules-components', + 'arguments' => [ + 'name' => 'add-modules-components', + 'input_class' => 'flex-row', + 'type' => 'select', + 'multiple' => true, + 'fields' => $components, + 'return' => true, + ], + ]; + + $inputs[] = [ + 'arguments' => [ + 'label' => __('Add components'), + 'name' => 'add-modules-submit', + 'type' => 'submit', + 'attributes' => 'class="sub wand"', + 'return' => true, + ], + ]; + + $this->printFormAsList( + [ + 'form' => $form, + 'inputs' => $inputs, + true + ] + ); +/* + $table = new StdClasS(); + + $table->head = []; + $table->data = []; + $table->align = []; + $table->width = '100%'; + $table->cellpadding = 0; + $table->cellspacing = 0; + $table->class = 'databox filters'; + + $table->style[0] = 'font-weight: bold'; + + // The form to submit when adding a list of components + $filter = '
      '; + $filter .= html_print_input_text('ncfilter', $ncfilter, '', 50, 255, true); + $filter .= '  '.html_print_submit_button(__('Filter'), 'ncgbutton', false, 'class="sub search"', true); + $filter .= '
      '; + + $group_filter = '
      '; + $group_filter .= '
      '; + $result = db_get_all_rows_in_table('tnetwork_component_group', 'name'); + if ($result === false) { + $result = []; + } + + // 2 arrays. 1 with the groups, 1 with the groups by parent + $groups = []; + $groups_compound = []; + foreach ($result as $row) { + $groups[$row['id_sg']] = $row['name']; + } + + foreach ($result as $row) { + $groups_compound[$row['id_sg']] = ''; + if ($row['parent'] > 1) { + $groups_compound[$row['id_sg']] = $groups[$row['parent']].' / '; + } + + $groups_compound[$row['id_sg']] .= $row['name']; + } + + $group_filter .= html_print_select($groups_compound, 'ncgroup', $ncgroup, 'javascript:this.form.submit();', __('Group').' - '.__('All'), -1, true, false, true, '" style="width:350px'); + + $group_filter .= '
      '; + + if ($ncgroup > 0) { + $sql = sprintf( + " + SELECT id_nc, name, id_group + FROM tnetwork_component + WHERE id_group = %d AND name LIKE '%".$ncfilter."%' + ORDER BY name", + $ncgroup + ); + } else { + $sql = " + SELECT id_nc, name, id_group + FROM tnetwork_component + WHERE name LIKE '%".$ncfilter."%' + ORDER BY name"; + } + + $result = db_get_all_rows_sql($sql); + $components = []; + if ($result === false) { + $result = []; + } + + foreach ($result as $row) { + $components[$row['id_nc']] = $row['name']; + } + + $components_select = '
      '; + $components_select .= html_print_select($components, 'components[]', $id_nc, '', '', -1, true, true, false, '" style="width:350px'); + + $table->data[0][0] = __('Filter'); + $table->data[0][1] = $filter; + $table->data[1][0] = __('Group'); + $table->data[1][1] = $group_filter; + $table->data[2][0] = __('Components'); + $table->data[2][1] = $components_select; + + html_print_table($table); + + echo '
      '; + html_print_submit_button(__('Add'), 'crtbutton', false, 'class="sub wand"'); + echo '
      ';*/ } + /** + * Undocumented function + * + * @return void + */ private function setNetworkProfile() { if ($this->id_np !== 0) { @@ -352,17 +670,17 @@ class ManageBlock extends HTML */ public function moduleTemplateForm() { - $createNewBlock = ($this->id_np === 0) ? true : false; + $createNewBlock = ($this->id_np == 0) ? true : false; if ($createNewBlock) { // Assignation for submit button. $formButtonClass = 'sub wand'; - $formButtonName = 'crtbutton'; + $formButtonValue = 'create'; $formButtonLabel = __('Create'); } else { // Assignation for submit button. $formButtonClass = 'sub upd'; - $formButtonName = 'updbutton'; + $formButtonValue = 'update'; $formButtonLabel = __('Update'); // Profile exists. Set the attributes with the info. $this->setNetworkProfile(); @@ -382,6 +700,16 @@ class ManageBlock extends HTML // Inputs. $rawInputs = ''; + $inputs[] = [ + 'id' => 'inp-id_np', + 'arguments' => [ + 'name' => 'id_np', + 'type' => 'hidden', + 'value' => $this->id_np, + 'return' => true, + ], + ]; + $inputs[] = [ 'label' => __('Name'), 'id' => 'inp-name', @@ -420,9 +748,10 @@ class ManageBlock extends HTML $inputs[] = [ 'arguments' => [ - 'name' => $formButtonName, + 'name' => 'submit_button', 'label' => $formButtonLabel, 'type' => 'submit', + 'value' => $formButtonValue, 'attributes' => 'class="'.$formButtonClass.'"', 'return' => true, ], @@ -506,7 +835,7 @@ class ManageBlock extends HTML $data[0] = $module['name']; $data[1] = ui_print_moduletype_icon($module['type'], true); $data[2] = mb_strimwidth(io_safe_output($module['description']), 0, 150, '...'); - $data[3] = html_print_checkbox_switch_extended('switch_'.$id_group.'_'.$module['component_id'], 1, 0, false, 'switchBlockControl(event)', '', true); + $data[3] = html_print_checkbox_switch_extended('module_check_'.$id_group.'_'.$module['component_id'], 1, 0, false, 'switchBlockControl(event)', '', true); array_push($table->data, $data); } @@ -551,14 +880,10 @@ class ManageBlock extends HTML echo $javascript; + $this->addingModulesForm(); + $this->printGoBackButton($this->baseUrl); } } - -/* - ui_require_jquery_file('tag-editor'); - ui_require_css_file('jquery.tag-editor'); - $(\'#text-community\').tagEditor(); -*/ From dc55ca5eff66ce1755aecadbed898022f064facd Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 30 Mar 2020 17:02:34 +0200 Subject: [PATCH 046/111] WIP: Changes with PEN tables --- pandora_console/extras/mr/37.sql | 18 ++++++++++++++++-- .../pandoradb_migrate_6.0_to_7.0.mysql.sql | 18 ++++++++++++++---- pandora_console/pandoradb.sql | 18 ++++++++++++++---- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/pandora_console/extras/mr/37.sql b/pandora_console/extras/mr/37.sql index a3aef948b8..aad1cd6f61 100644 --- a/pandora_console/extras/mr/37.sql +++ b/pandora_console/extras/mr/37.sql @@ -35,16 +35,30 @@ CREATE TABLE `tdiscovery_tmp_connections` ( REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- ---------------------------------------------------------------------- +-- New table `tpen` +-- ---------------------------------------------------------------------- CREATE TABLE `tpen` ( `pen` int(10) unsigned NOT NULL, `manufacturer` TEXT, `description` TEXT, - `id_np` int(10) unsigned, + PRIMARY KEY (`pen`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- ---------------------------------------------------------------------- +-- New table `tnetwork_profile_pen` +-- ---------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` ( + `pen` int(10) unsigned NOT NULL, + `id_np` int(10) unsigned NOT NULL, PRIMARY KEY (`pen`), - CONSTRAINT `fk_np_id` FOREIGN KEY (`id_np`) + CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`) + REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE + CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`) REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + ALTER TABLE `twidget_dashboard` ADD COLUMN `position` TEXT NOT NULL default ''; ALTER TABLE `tagente_estado` ADD COLUMN `last_status_change` bigint(20) NOT NULL default '0'; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index 4de9b6a1f3..92ef97325f 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -1476,6 +1476,19 @@ ALTER TABLE tnetwork_component ADD COLUMN `dynamic_two_tailed` tinyint(1) unsign ALTER TABLE `tnetwork_component` ADD COLUMN `ff_type` tinyint(1) unsigned default '0'; ALTER TABLE `tnetwork_component` MODIFY COLUMN `ff_type` tinyint(1) unsigned NULL DEFAULT '0'; +-- ---------------------------------------------------------------------- +-- Table `tnetwork_profile_pen` +-- ---------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` ( + `pen` int(10) unsigned NOT NULL, + `id_np` int(10) unsigned NOT NULL, + PRIMARY KEY (`pen`), + CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`) + REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE + CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`) + REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + -- ---------------------------------------------------------------------- -- Table `tpen` -- ---------------------------------------------------------------------- @@ -1483,10 +1496,7 @@ CREATE TABLE IF NOT EXISTS `tpen` ( `pen` int(10) unsigned NOT NULL, `manufacturer` TEXT, `description` TEXT, - `id_np` int(10) unsigned, - PRIMARY KEY (`pen`), - CONSTRAINT `fk_np_id` FOREIGN KEY (`id_np`) - REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE + PRIMARY KEY (`pen`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- --------------------------------------------------------------------- diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 1c88e65d43..8013735d17 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -953,6 +953,19 @@ CREATE TABLE IF NOT EXISTS `tnetwork_profile_component` ( KEY `id_np` (`id_np`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- ---------------------------------------------------------------------- +-- Table `tnetwork_profile_pen` +-- ---------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` ( + `pen` int(10) unsigned NOT NULL, + `id_np` int(10) unsigned NOT NULL, + PRIMARY KEY (`pen`), + CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`) + REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE + CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`) + REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + -- ---------------------------------------------------------------------- -- Table `tpen` -- ---------------------------------------------------------------------- @@ -960,10 +973,7 @@ CREATE TABLE IF NOT EXISTS `tpen` ( `pen` int(10) unsigned NOT NULL, `manufacturer` TEXT, `description` TEXT, - `id_np` int(10) unsigned, - PRIMARY KEY (`pen`), - CONSTRAINT `fk_np_id` FOREIGN KEY (`id_np`) - REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE + PRIMARY KEY (`pen`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------------------------------------------------- From c0b7c7e3399af262193b5d015ec7d91272398a4b Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 30 Mar 2020 17:12:49 +0200 Subject: [PATCH 047/111] Changed breadcrumb for PEN form --- pandora_console/include/class/ConfigPEN.class.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pandora_console/include/class/ConfigPEN.class.php b/pandora_console/include/class/ConfigPEN.class.php index 5f2fb6ae37..0c2e67c8e7 100644 --- a/pandora_console/include/class/ConfigPEN.class.php +++ b/pandora_console/include/class/ConfigPEN.class.php @@ -318,7 +318,12 @@ class ConfigPEN extends HTML [ [ 'link' => '', - 'label' => __('Wizard Setup'), + 'label' => __('Configuration'), + 'selected' => false, + ], + [ + 'link' => '', + 'label' => __('Templates'), 'selected' => false, ], [ From fa372656f4d684aabecc12523d5d4c103668aef6 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 30 Mar 2020 17:48:09 +0200 Subject: [PATCH 048/111] Fixed issue with DB --- pandora_console/extras/mr/37.sql | 5 ++-- .../pandoradb_migrate_6.0_to_7.0.mysql.sql | 26 +++++++++---------- pandora_console/pandoradb.sql | 26 +++++++++---------- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/pandora_console/extras/mr/37.sql b/pandora_console/extras/mr/37.sql index aad1cd6f61..fedc4b477e 100644 --- a/pandora_console/extras/mr/37.sql +++ b/pandora_console/extras/mr/37.sql @@ -46,19 +46,18 @@ CREATE TABLE `tpen` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------------------------------------------------- --- New table `tnetwork_profile_pen` +-- Table `tnetwork_profile_pen` -- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` ( `pen` int(10) unsigned NOT NULL, `id_np` int(10) unsigned NOT NULL, PRIMARY KEY (`pen`), CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`) - REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE + REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`) REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; - ALTER TABLE `twidget_dashboard` ADD COLUMN `position` TEXT NOT NULL default ''; ALTER TABLE `tagente_estado` ADD COLUMN `last_status_change` bigint(20) NOT NULL default '0'; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index 92ef97325f..f3a3f612a1 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -1476,19 +1476,6 @@ ALTER TABLE tnetwork_component ADD COLUMN `dynamic_two_tailed` tinyint(1) unsign ALTER TABLE `tnetwork_component` ADD COLUMN `ff_type` tinyint(1) unsigned default '0'; ALTER TABLE `tnetwork_component` MODIFY COLUMN `ff_type` tinyint(1) unsigned NULL DEFAULT '0'; --- ---------------------------------------------------------------------- --- Table `tnetwork_profile_pen` --- ---------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` ( - `pen` int(10) unsigned NOT NULL, - `id_np` int(10) unsigned NOT NULL, - PRIMARY KEY (`pen`), - CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`) - REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE - CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`) - REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -- ---------------------------------------------------------------------- -- Table `tpen` -- ---------------------------------------------------------------------- @@ -1499,6 +1486,19 @@ CREATE TABLE IF NOT EXISTS `tpen` ( PRIMARY KEY (`pen`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- ---------------------------------------------------------------------- +-- Table `tnetwork_profile_pen` +-- ---------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` ( + `pen` int(10) unsigned NOT NULL, + `id_np` int(10) unsigned NOT NULL, + PRIMARY KEY (`pen`), + CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`) + REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`) + REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + -- --------------------------------------------------------------------- -- Table `tagente` -- --------------------------------------------------------------------- diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 8013735d17..fa8f8d3043 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -953,19 +953,6 @@ CREATE TABLE IF NOT EXISTS `tnetwork_profile_component` ( KEY `id_np` (`id_np`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; --- ---------------------------------------------------------------------- --- Table `tnetwork_profile_pen` --- ---------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` ( - `pen` int(10) unsigned NOT NULL, - `id_np` int(10) unsigned NOT NULL, - PRIMARY KEY (`pen`), - CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`) - REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE - CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`) - REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -- ---------------------------------------------------------------------- -- Table `tpen` -- ---------------------------------------------------------------------- @@ -976,6 +963,19 @@ CREATE TABLE IF NOT EXISTS `tpen` ( PRIMARY KEY (`pen`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- ---------------------------------------------------------------------- +-- Table `tnetwork_profile_pen` +-- ---------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` ( + `pen` int(10) unsigned NOT NULL, + `id_np` int(10) unsigned NOT NULL, + PRIMARY KEY (`pen`), + CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`) + REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`) + REFERENCES `tnetwork_profile` (`id_np`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + -- ---------------------------------------------------------------------- -- Table `tnota` -- ---------------------------------------------------------------------- From c2d81238d6ffc95a03ef791f1ed7d09c063b4230 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 30 Mar 2020 19:03:55 +0200 Subject: [PATCH 049/111] WIP: Near to finish --- .../include/class/ModuleTemplates.class.php | 227 +++++++++--------- 1 file changed, 120 insertions(+), 107 deletions(-) diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php index 36381c8ff3..fdd86a5fe8 100644 --- a/pandora_console/include/class/ModuleTemplates.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -86,7 +86,7 @@ class ModuleTemplates extends HTML /** * Group for adding modules - * + * * @var string */ private $ncGroup; @@ -131,11 +131,14 @@ class ModuleTemplates extends HTML $this->id_np = get_parameter('id_np', -1); $this->name = get_parameter('name', ''); $this->description = get_parameter('description', ''); - $this->pen = get_parameter('pen', ''); + $pensList = get_parameter('pen', []); + // Separate all PENs received. + $this->pen = explode(',', $pensList); $this->offset = get_parameter('offset', 0); $this->ajaxController = $ajax_controller; $this->ncGroup = get_parameter('ncgroup', -1); $this->ncFilter = get_parameter('ncfilter', ''); + return $this; } @@ -205,19 +208,15 @@ class ModuleTemplates extends HTML /** - * Undocumented function + * Save or Update the data received. * * @return void */ public function processData() { - // This data is sent always - $name = get_parameter('name', ''); - $description = get_parameter('description', ''); - $pensList = get_parameter('pen', ''); + // Get action if is needed. $action = get_parameter('submit_button', ''); - - // Evaluate the modules allowed + // Evaluate the modules allowed. if (!empty($action)) { $numberComponent = []; foreach ($_POST as $k => $value) { @@ -232,48 +231,51 @@ class ModuleTemplates extends HTML $dbResult_tnp = db_process_sql_update( 'tnetwork_profile', [ - 'name' => $name, - 'description' => $description, + 'name' => $this->name, + 'description' => $this->description, ], ['id_np' => $this->id_np] ); - - $getProfilePens = db_get_all_rows_sql(sprintf('SELECT pen FROM tpen WHERE id_np = %s', $this->id_np)); - - $dbResult_pen = db_process_sql_update( - 'tpen', - [ - 'pen' => $pen, - 'manufacturer' => '', - 'description' => '', - 'id_np' => $this->id_np, - ], - ['id_np' => $this->id_np] - ); - + // The update gone fine! + if ($dbResult_tnp != false) { + // Clean the PENs associated with this id_np. + db_process_sql_delete('tnetwork_profile_pen', ['id_np' => $this->id_np]); + // Set again the new PENs associated. + foreach ($this->pen as $currentPen) { + $dbResult_pen = db_process_sql_insert( + 'tnetwork_profile_pen', + [ + 'pen' => $currentPen, + 'id_np' => $this->id_np, + ] + ); + } + } break; case 'Create': $dbResult_tnp = db_process_sql_insert( 'tnetwork_profile', [ - 'name' => $name, - 'description' => $description, + 'name' => $this->name, + 'description' => $this->description, ] ); - + // The insert gone fine! if ($dbResult_tnp != false) { - foreach ($pensList as $currentPen) { + // Set the new id_np. + $this->id_np = $dbResult_tnp; + // Insert all of new PENs associated with this id_np. + foreach ($this->pen as $currentPen) { + hd($currentPen); $dbResult_pen = db_process_sql_insert( - 'tpen', + 'tnetwork_profile_pen', [ - 'pen' => $currentPen, - 'manufacturer' => '', - 'description' => '', - 'id_np' => $this->id_np, + 'pen' => $currentPen, + 'id_np' => $this->id_np, ] ); - + // If something is wrong, is better stop. if ($dbResult_pen === false) { break; } @@ -296,6 +298,18 @@ class ModuleTemplates extends HTML } + /** + * Get the match between this id_np and one pen in db + * + * @param integer $pen + * @return void + */ + private function penMatch($pen) + { + return db_get_num_rows('SELECT * FROM tnetwork_profile_pen WHERE pen = %d AND id_np = %d', $pen, $this->id_np); + } + + /** * Undocumented function * @@ -303,7 +317,6 @@ class ModuleTemplates extends HTML */ public function addingModulesForm() { - // Get the groups for select input $result = db_get_all_rows_in_table('tnetwork_component_group', 'name'); if ($result === false) { @@ -326,9 +339,8 @@ class ModuleTemplates extends HTML $groups_compound[$row['id_sg']] .= $row['name']; } - # For erase - #$group_filter .= html_print_select($groups_compound, 'ncgroup', $ncgroup, 'javascript:this.form.submit();', __('Group').' - '.__('All'), -1, true, false, true, '" style="width:350px'); - + // For erase + // $group_filter .= html_print_select($groups_compound, 'ncgroup', $ncgroup, 'javascript:this.form.submit();', __('Group').' - '.__('All'), -1, true, false, true, '" style="width:350px'); // Get the components for show in a list for select if ($this->ncGroup > 0) { $sql = sprintf( @@ -434,53 +446,53 @@ class ModuleTemplates extends HTML true ] ); -/* - $table = new StdClasS(); + /* + $table = new StdClasS(); - $table->head = []; - $table->data = []; - $table->align = []; - $table->width = '100%'; - $table->cellpadding = 0; - $table->cellspacing = 0; - $table->class = 'databox filters'; - - $table->style[0] = 'font-weight: bold'; - - // The form to submit when adding a list of components - $filter = '
      '; - $filter .= html_print_input_text('ncfilter', $ncfilter, '', 50, 255, true); - $filter .= '  '.html_print_submit_button(__('Filter'), 'ncgbutton', false, 'class="sub search"', true); - $filter .= '
      '; - - $group_filter = '
      '; - $group_filter .= '
      '; - $result = db_get_all_rows_in_table('tnetwork_component_group', 'name'); - if ($result === false) { + $table->head = []; + $table->data = []; + $table->align = []; + $table->width = '100%'; + $table->cellpadding = 0; + $table->cellspacing = 0; + $table->class = 'databox filters'; + + $table->style[0] = 'font-weight: bold'; + + // The form to submit when adding a list of components + $filter = ''; + $filter .= html_print_input_text('ncfilter', $ncfilter, '', 50, 255, true); + $filter .= '  '.html_print_submit_button(__('Filter'), 'ncgbutton', false, 'class="sub search"', true); + $filter .= ''; + + $group_filter = '
      '; + $group_filter .= '
      '; + $result = db_get_all_rows_in_table('tnetwork_component_group', 'name'); + if ($result === false) { $result = []; - } - - // 2 arrays. 1 with the groups, 1 with the groups by parent - $groups = []; - $groups_compound = []; - foreach ($result as $row) { + } + + // 2 arrays. 1 with the groups, 1 with the groups by parent + $groups = []; + $groups_compound = []; + foreach ($result as $row) { $groups[$row['id_sg']] = $row['name']; - } - - foreach ($result as $row) { + } + + foreach ($result as $row) { $groups_compound[$row['id_sg']] = ''; if ($row['parent'] > 1) { $groups_compound[$row['id_sg']] = $groups[$row['parent']].' / '; } - + $groups_compound[$row['id_sg']] .= $row['name']; - } - - $group_filter .= html_print_select($groups_compound, 'ncgroup', $ncgroup, 'javascript:this.form.submit();', __('Group').' - '.__('All'), -1, true, false, true, '" style="width:350px'); - - $group_filter .= '
      '; - - if ($ncgroup > 0) { + } + + $group_filter .= html_print_select($groups_compound, 'ncgroup', $ncgroup, 'javascript:this.form.submit();', __('Group').' - '.__('All'), -1, true, false, true, '" style="width:350px'); + + $group_filter .= '
      '; + + if ($ncgroup > 0) { $sql = sprintf( " SELECT id_nc, name, id_group @@ -489,38 +501,38 @@ class ModuleTemplates extends HTML ORDER BY name", $ncgroup ); - } else { + } else { $sql = " SELECT id_nc, name, id_group FROM tnetwork_component WHERE name LIKE '%".$ncfilter."%' ORDER BY name"; - } - - $result = db_get_all_rows_sql($sql); - $components = []; - if ($result === false) { + } + + $result = db_get_all_rows_sql($sql); + $components = []; + if ($result === false) { $result = []; - } - - foreach ($result as $row) { + } + + foreach ($result as $row) { $components[$row['id_nc']] = $row['name']; - } - - $components_select = '
      '; - $components_select .= html_print_select($components, 'components[]', $id_nc, '', '', -1, true, true, false, '" style="width:350px'); - - $table->data[0][0] = __('Filter'); - $table->data[0][1] = $filter; - $table->data[1][0] = __('Group'); - $table->data[1][1] = $group_filter; - $table->data[2][0] = __('Components'); - $table->data[2][1] = $components_select; - - html_print_table($table); - - echo '
      '; - html_print_submit_button(__('Add'), 'crtbutton', false, 'class="sub wand"'); + } + + $components_select = ''; + $components_select .= html_print_select($components, 'components[]', $id_nc, '', '', -1, true, true, false, '" style="width:350px'); + + $table->data[0][0] = __('Filter'); + $table->data[0][1] = $filter; + $table->data[1][0] = __('Group'); + $table->data[1][1] = $group_filter; + $table->data[2][0] = __('Components'); + $table->data[2][1] = $components_select; + + html_print_table($table); + + echo '
      '; + html_print_submit_button(__('Add'), 'crtbutton', false, 'class="sub wand"'); echo '
      ';*/ } @@ -533,10 +545,11 @@ class ModuleTemplates extends HTML private function setNetworkProfile() { if ($this->id_np !== 0) { - $output = db_get_row('tnetwork_profile', 'id_np', $this->id_np); - $this->name = $output['name']; - $this->description = $output['description']; - $this->pen = $output['pen']; + $profileInfo = db_get_row('tnetwork_profile', 'id_np', $this->id_np); + $this->name = $profileInfo['name']; + $this->description = $profileInfo['description']; + $penInfo = db_get_all_rows_filter('tnetwork_profile_pen', ['id_np' => $this->id_np]); + $this->pen = $penInfo['pen']; } } From acabe543c4119d82a68fdae060fb9703c9090f07 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 30 Mar 2020 19:44:44 +0200 Subject: [PATCH 050/111] csv recon0 --- pandora_console/extras/mr/37.sql | 2 + .../pandoradb_migrate_6.0_to_7.0.mysql.sql | 3 +- .../godmode/wizards/HostDevices.class.php | 124 ++++++++++++++++-- .../godmode/wizards/Wizard.main.php | 48 ++----- pandora_console/include/functions_html.php | 8 +- pandora_console/include/javascript/pandora.js | 12 +- pandora_console/include/styles/wizard.css | 55 +++++++- pandora_console/pandoradb.sql | 1 + pandora_server/lib/PandoraFMS/Core.pm | 6 - 9 files changed, 195 insertions(+), 64 deletions(-) diff --git a/pandora_console/extras/mr/37.sql b/pandora_console/extras/mr/37.sql index fedc4b477e..b879112ff3 100644 --- a/pandora_console/extras/mr/37.sql +++ b/pandora_console/extras/mr/37.sql @@ -2,6 +2,8 @@ START TRANSACTION; ALTER TABLE trecon_task MODIFY COLUMN `id_network_profile` TEXT; ALTER TABLE `trecon_task` CHANGE COLUMN `create_incident` `review_mode` TINYINT(1) UNSIGNED DEFAULT 0; +ALTER TABLE `trecon_task` ADD COLUMN `subnet_csv` TINYINT(1) UNSIGNED DEFAULT 0; + UPDATE `trecon_task` SET `review_mode` = 1; ALTER TABLE trecon_task add column `auto_monitor` TINYINT(1) UNSIGNED DEFAULT 1 AFTER `auth_strings`; UPDATE `trecon_task` SET `auto_monitor` = 0; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index f3a3f612a1..9e5382c2b5 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -1686,7 +1686,8 @@ ALTER TABLE `trecon_task` ADD COLUMN `type` int(11) NOT NULL DEFAULT '0', MODIFY COLUMN `autoconfiguration_enabled` tinyint(1) unsigned NULL DEFAULT '0', MODIFY COLUMN `summary` text NULL, MODIFY COLUMN `id_network_profile` text, - CHANGE COLUMN `create_incident` `review_mode` TINYINT(1) UNSIGNED DEFAULT 0; + CHANGE COLUMN `create_incident` `review_mode` TINYINT(1) UNSIGNED DEFAULT 0, + ADD COLUMN `subnet_csv` TINYINT(1) UNSIGNED DEFAULT 0; -- Old recon always report. UPDATE `trecon_task` SET `review_mode` = 1; diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php index 43825c31e5..ff2c10b0ed 100755 --- a/pandora_console/godmode/wizards/HostDevices.class.php +++ b/pandora_console/godmode/wizards/HostDevices.class.php @@ -300,9 +300,50 @@ class HostDevices extends Wizard $comment = get_parameter('comment', ''); $server_id = get_parameter('id_recon_server', ''); $network = get_parameter('network', ''); + $network_csv_enabled = (bool) get_parameter_switch( + 'network_csv_enabled', + false + ); $id_group = get_parameter('id_group', ''); $interval = get_parameter('interval', 0); + if ($network_csv_enabled) { + if ($_FILES['network_csv']['type'] != 'text/csv') { + $this->msg = __( + 'Invalid mimetype for csv file: %s', + $_FILES['network_csv']['type'] + ); + return false; + } + + $network = preg_split( + "/\n|,|;/", + trim( + file_get_contents( + $_FILES['network_csv']['tmp_name'] + ) + ) + ); + unlink($_FILES['network_csv']['tmp_name']); + if (empty($network) || is_array($network) === false) { + $this->msg = __( + 'Invalid content readed from csv file: %s', + $_FILES['network_csv']['name'] + ); + return false; + } + + // Sanitize. + $network = array_unique($network); + $network = array_filter( + $network, + function ($item) { + return (!empty($item)); + } + ); + $network = join(',', $network); + } + if (isset($task_id) === true) { // We're updating this task. $task = db_get_row( @@ -338,6 +379,7 @@ class HostDevices extends Wizard && $server_id == null && empty($id_group) === true && empty($network) === true + && empty($network_csv) === true && $interval === 0 ) { // Default values, no data received. @@ -385,6 +427,7 @@ class HostDevices extends Wizard $this->task['id_recon_server'] = $server_id; $this->task['id_group'] = $id_group; $this->task['interval_sweep'] = $interval; + $this->task['subnet_csv'] = $network_csv_enabled; if (isset($this->task['id_rt']) === false) { // Create. @@ -701,7 +744,7 @@ class HostDevices extends Wizard $form['rows'][0]['columns'][0] = [ 'width' => '30%', - 'style' => 'padding: 9px;', + 'style' => 'padding: 9px;min-width: 250px;', 'inputs' => [ '0' => [ 'arguments' => [ @@ -728,7 +771,10 @@ class HostDevices extends Wizard 'name' => 'interval_manual_defined', 'return' => true, ], - 'extra' => ''.html_print_extended_select_for_time( + 'extra' => '
      '.ui_print_help_tip( + __('The minimum recomended interval for Recon Task is 5 minutes'), + true + ).html_print_extended_select_for_time( 'interval', $this->task['interval_sweep'], '', @@ -738,10 +784,7 @@ class HostDevices extends Wizard true, false, false - ).ui_print_help_tip( - __('The minimum recomended interval for Recon Task is 5 minutes'), - true - ).'', + ).'
      ', ], ], @@ -751,6 +794,7 @@ class HostDevices extends Wizard 'width' => '40%', 'padding-right' => '12%', 'padding-left' => '5%', + 'style' => 'min-width: 350px', 'inputs' => [ '0' => [ 'label' => ''.__('Task name').':', @@ -783,6 +827,54 @@ class HostDevices extends Wizard ], ], '2' => [ + 'label' => ''.__('Use CSV file definition').':'.ui_print_help_tip( + __('Define targets using csv o network definition.'), + true + ), + 'class' => 'no-margin', + 'arguments' => [ + 'name' => 'network_csv_enabled', + 'value' => $this->task['subnet_csv'], + 'type' => 'switch', + 'inline' => true, + 'class' => 'discovery_full_width_input', + 'onclick' => 'toggleNetwork(this);', + ], + ], + '3' => [ + 'hidden' => (($this->task['subnet_csv'] == '1') ? 0 : 1), + 'block_id' => 'csv_subnet', + 'block_content' => [ + [ + 'label' => ''.__('Networks (csv)').':'.ui_print_help_tip( + __('You can upload a CSV file. Each line must contain a network in IP/MASK format. For instance: 192.168.1.1/32'), + true + ), + 'arguments' => [ + 'name' => 'network_csv', + 'type' => 'file', + 'columns' => 25, + 'rows' => 10, + 'class' => 'discovery_full_width_input', + ], + ], + [ + 'label' => ''.__('Networks (current)').':'.ui_print_help_tip( + __('Plese upload a new file to overwrite this content.'), + true + ), + 'arguments' => [ + 'attributes' => 'readonly', + 'type' => 'textarea', + 'size' => 25, + 'value' => $this->task['subnet'], + ], + ], + ], + ], + '4' => [ + 'hidden' => (($this->task['subnet_csv'] == '1') ? 1 : 0), + 'id' => 'std_subnet', 'label' => ''.__('Network').':'.ui_print_help_tip( __('You can specify several networks, separated by commas, for example: 192.168.50.0/24,192.168.60.0/24'), true @@ -817,6 +909,7 @@ class HostDevices extends Wizard $form['rows'][0]['columns'][2] = [ 'width' => '30%', + 'style' => 'min-width: 250px', 'inputs' => ['0' => $group_select], ]; @@ -846,8 +939,9 @@ class HostDevices extends Wizard } $form['form'] = [ - 'method' => 'POST', - 'action' => $this->url.'&mode=netscan&page='.($this->page + 1).$task_url, + 'method' => 'POST', + 'enctype' => 'multipart/form-data', + 'action' => $this->url.'&mode=netscan&page='.($this->page + 1).$task_url, ]; // Default. @@ -871,7 +965,19 @@ class HostDevices extends Wizard $("#hidden-interval").val('.$interval.'); $("#interval_units").val('.$unit.'); } - }).change();'; + }).change(); + + function toggleNetwork(e) { + if (e.checked) { + $(\'#csv_subnet\').removeClass("hidden"); + $(\'#std_subnet\').addClass("hidden"); + } else { + $(\'#csv_subnet\').addClass("hidden"); + $(\'#std_subnet\').removeClass("hidden"); + } + }; + + '; $this->printFormAsGrid($form); $this->printGoBackButton($this->url.'&page='.($this->page - 1)); diff --git a/pandora_console/godmode/wizards/Wizard.main.php b/pandora_console/godmode/wizards/Wizard.main.php index 13da3c269d..7320934826 100644 --- a/pandora_console/godmode/wizards/Wizard.main.php +++ b/pandora_console/godmode/wizards/Wizard.main.php @@ -587,66 +587,40 @@ class Wizard if (is_array($input['block_content']) === true) { // Print independent block of inputs. - $output .= '
    • '; + $output .= '
      '; $output .= '
        '; foreach ($input['block_content'] as $input) { $output .= $this->printBlockAsGrid($input, $return); } - $output .= '
    • '; + $output .= '
      '; } else { if ($input['arguments']['type'] != 'hidden' && $input['arguments']['type'] != 'hidden_extended' ) { - if ($input['arguments']['inline'] != 'true') { - $output .= '
      '; - } else { - $output .= '
      '; - if (!isset($input['extra'])) { - $output .= '
      '; - } - - if (isset($input['extra'])) { - $output .= '
      '; - } + $id = ''; + if ($input['id']) { + $id = $input['id']; } - if ($input['arguments']['inline'] == 'true' && isset($input['extra'])) { - $output .= '
      '; + if ($input['arguments']['inline'] != 'true') { + $output .= '
      '; + } else { + $output .= '
      '; } $output .= '
      '; $output .= $input['label']; $output .= '
      '; - if ($input['arguments']['inline'] == 'true' && isset($input['extra'])) { - $output .= '
      '; - } - - if ($input['arguments']['inline'] == 'true' && !isset($input['extra'])) { - $output .= '
      '; - } - if ($input['arguments']['type'] == 'text' || $input['arguments']['type'] == 'text_extended') { $output .= '
      '; $output .= $this->printInput($input['arguments']); $output .= '
      '; } else if ($input['arguments']['inline'] == 'true') { - if (isset($input['extra'])) { - $output .= '
      '; - $output .= '
      '; - } else { - $output .= '
      '; - $output .= '
      '; - } - + $output .= '
      '; $output .= $this->printInput($input['arguments']); $output .= '
      '; - $output .= '
      '; - - if (isset($input['extra'])) { - $output .= '
      '; - } } else { $output .= $this->printInput($input['arguments']); } @@ -821,7 +795,7 @@ class Wizard $cb_function = $data['cb_function']; $cb_args = $data['cb_args']; - $output_head = '
      '; if ($return === false) { diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php index 237d7457f9..f578cc9ed2 100644 --- a/pandora_console/include/functions_html.php +++ b/pandora_console/include/functions_html.php @@ -1087,7 +1087,7 @@ function html_print_extended_select_for_time( ob_start(); // Use the no_meta parameter because this image is only in the base console - echo '
      '; + echo '
      '; html_print_select( $fields, $uniq_name.'_select', @@ -1121,7 +1121,7 @@ function html_print_extended_select_for_time( echo '
      '; - echo '
      '; + echo '
      '; html_print_input_text($uniq_name.'_text', $selected, '', $size, 255, false, $readonly, false, '', $class); html_print_input_hidden($name, $selected, false, $uniq_name); @@ -1159,8 +1159,8 @@ function html_print_extended_select_for_time( $('#text-".$uniq_name."_text').val(seconds); adjustTextUnits('".$uniq_name."'); calculateSeconds('".$uniq_name."'); - $('#".$uniq_name."_manual').show(); - $('#".$uniq_name."_default').hide(); + $('#".$uniq_name."_manual').css('display', 'flex'); + $('#".$uniq_name."_default').css('display', 'none'); } "; $returnString = ob_get_clean(); diff --git a/pandora_console/include/javascript/pandora.js b/pandora_console/include/javascript/pandora.js index 9a9c8bcba0..c91339f0c6 100644 --- a/pandora_console/include/javascript/pandora.js +++ b/pandora_console/include/javascript/pandora.js @@ -837,8 +837,8 @@ function post_process_select_events(name) { */ function period_select_init(name, allow_zero) { // Manual mode is hidden by default - $("#" + name + "_manual").hide(); - $("#" + name + "_default").show(); + $("#" + name + "_manual").css("display", "none"); + $("#" + name + "_default").css("display", "flex"); // If the text input is empty, we put on it 5 minutes by default if ($("#text-" + name + "_text").val() == "") { @@ -852,8 +852,8 @@ function period_select_init(name, allow_zero) { } } else if ($("#text-" + name + "_text").val() == 0 && allow_zero != true) { $("#" + name + "_units option:last").prop("selected", false); - $("#" + name + "_manual").show(); - $("#" + name + "_default").hide(); + $("#" + name + "_manual").css("display", "flex"); + $("#" + name + "_default").css("display", "none"); } } @@ -941,13 +941,13 @@ function selectFirst(name) { */ function toggleBoth(name) { if ($("#" + name + "_default").css("display") == "none") { - $("#" + name + "_default").css("display", "inline"); + $("#" + name + "_default").css("display", "flex"); } else { $("#" + name + "_default").css("display", "none"); } if ($("#" + name + "_manual").css("display") == "none") { - $("#" + name + "_manual").css("display", "inline"); + $("#" + name + "_manual").css("display", "flex"); } else { $("#" + name + "_manual").css("display", "none"); } diff --git a/pandora_console/include/styles/wizard.css b/pandora_console/include/styles/wizard.css index 366c60c1ae..572c3496bf 100644 --- a/pandora_console/include/styles/wizard.css +++ b/pandora_console/include/styles/wizard.css @@ -2,7 +2,11 @@ * Discovery > Wizard css global style */ +#main > form.discovery.wizard > .white_box { + min-width: 1024px; +} ul.wizard { + list-style-type: none; } ul.wizard li { @@ -24,13 +28,50 @@ ul.wizard li > textarea { } .wizard .hidden { - display: none; + display: none !important; } .wizard .indented { margin-left: 2em; } +.wizard .std_input { + display: flex; + margin-bottom: 25px; + flex-wrap: wrap; + justify-content: space-between; +} + +.wizard .std_input > .label_select { + flex: 1 1 100%; +} +.wizard .std_input > * { + flex: 1 1 auto; + align-self: baseline; +} + +.wizard .inline_input.no-margin { + margin-bottom: 0px; +} +.wizard .inline_input { + display: flex; + margin-bottom: 25px; + flex-wrap: wrap; + justify-content: space-between; + align-items: baseline; +} + +.wizard .inline_input * { + flex: 1 1 auto; +} + +.wizard .discovery_inline_input { + display: flex; + align-content: end; + flex: 0; + align-self: flex-start; +} + /* override tag-editor styles */ .wizard .tag-editor.ui-sortable { width: 450px; @@ -57,3 +98,15 @@ ul.wizard li > textarea { padding: 5px; background: #e63c52; } + +.wizard .time_selection_container { + display: flex; + align-items: baseline; + justify-items: center; + align-content: space-between; + margin-top: 1em; +} + +.wizard #interval_manual_container #interval_manual > * { + flex: 1 1 auto; +} diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index fa8f8d3043..7d91216d11 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -810,6 +810,7 @@ CREATE TABLE IF NOT EXISTS `trecon_task` ( `autoconfiguration_enabled` tinyint(1) unsigned default 0, `summary` text, `type` int NOT NULL default 0, + `subnet_csv` TINYINT(1) UNSIGNED DEFAULT 0, PRIMARY KEY (`id_rt`), KEY `recon_task_daemon` (`id_recon_server`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index b387de5283..6cf2204ff3 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -6275,9 +6275,6 @@ sub notification_get_users { ', safe_input($source) ); - - @results = map { $_->{'id_user'} } @results; - return @results; } ########################################################################## @@ -6299,9 +6296,6 @@ sub notification_get_groups { ', safe_input($source) ); - - @results = map { $_->{'id_group'} } @results; - return @results; } From f28de6f4d03f52acbd00364375d80b32eb91b3ed Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Tue, 31 Mar 2020 10:45:30 +0200 Subject: [PATCH 051/111] Fixed db issue --- pandora_console/extras/mr/37.sql | 1 - pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql | 1 - pandora_console/pandoradb.sql | 1 - 3 files changed, 3 deletions(-) diff --git a/pandora_console/extras/mr/37.sql b/pandora_console/extras/mr/37.sql index fedc4b477e..7007d78745 100644 --- a/pandora_console/extras/mr/37.sql +++ b/pandora_console/extras/mr/37.sql @@ -51,7 +51,6 @@ CREATE TABLE `tpen` ( CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` ( `pen` int(10) unsigned NOT NULL, `id_np` int(10) unsigned NOT NULL, - PRIMARY KEY (`pen`), CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`) REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`) diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index f3a3f612a1..adfeaa0b7f 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -1492,7 +1492,6 @@ CREATE TABLE IF NOT EXISTS `tpen` ( CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` ( `pen` int(10) unsigned NOT NULL, `id_np` int(10) unsigned NOT NULL, - PRIMARY KEY (`pen`), CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`) REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`) diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index fa8f8d3043..c42bfebe24 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -969,7 +969,6 @@ CREATE TABLE IF NOT EXISTS `tpen` ( CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` ( `pen` int(10) unsigned NOT NULL, `id_np` int(10) unsigned NOT NULL, - PRIMARY KEY (`pen`), CONSTRAINT `fk_network_profile_pen_pen` FOREIGN KEY (`pen`) REFERENCES `tpen` (`pen`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `fk_network_profile_pen_id_np` FOREIGN KEY (`id_np`) From 4c332a354353fe3a940523cf69edfa0f6180767c Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Tue, 31 Mar 2020 10:47:00 +0200 Subject: [PATCH 052/111] WIP: Must do low changes --- .../modules/manage_module_templates.php | 9 +- .../include/class/ModuleTemplates.class.php | 105 +++++++++++------- 2 files changed, 67 insertions(+), 47 deletions(-) diff --git a/pandora_console/godmode/modules/manage_module_templates.php b/pandora_console/godmode/modules/manage_module_templates.php index 1dba12e625..b2f262b6c9 100644 --- a/pandora_console/godmode/modules/manage_module_templates.php +++ b/pandora_console/godmode/modules/manage_module_templates.php @@ -13,13 +13,15 @@ // GNU General Public License for more details. // Load global vars // TESTING - - /* ini_set('display_errors', 1); + /* + ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); */ // END global $config; -hd($_POST); +/* + hd($_POST); +hd($_REQUEST); */ check_login(); if (! check_acl($config['id_user'], 0, 'PM')) { @@ -69,7 +71,6 @@ if (is_ajax()) { // Stop any execution. exit; } else { - //hd($_POST); // Run. $moduleTemplates->run(); // Get the id_np. diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php index fdd86a5fe8..1fd5c99d68 100644 --- a/pandora_console/include/class/ModuleTemplates.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -80,7 +80,7 @@ class ModuleTemplates extends HTML /** * Private Enterprise Numbers of Block Templates * - * @var [type] + * @var array */ private $pen; @@ -131,9 +131,8 @@ class ModuleTemplates extends HTML $this->id_np = get_parameter('id_np', -1); $this->name = get_parameter('name', ''); $this->description = get_parameter('description', ''); - $pensList = get_parameter('pen', []); + $this->pen = get_parameter('pen', ''); // Separate all PENs received. - $this->pen = explode(',', $pensList); $this->offset = get_parameter('offset', 0); $this->ajaxController = $ajax_controller; $this->ncGroup = get_parameter('ncgroup', -1); @@ -216,6 +215,8 @@ class ModuleTemplates extends HTML { // Get action if is needed. $action = get_parameter('submit_button', ''); + // Success variable. + $success = false; // Evaluate the modules allowed. if (!empty($action)) { $numberComponent = []; @@ -236,19 +237,30 @@ class ModuleTemplates extends HTML ], ['id_np' => $this->id_np] ); - // The update gone fine! - if ($dbResult_tnp != false) { - // Clean the PENs associated with this id_np. + if ($dbResult_tnp === false) { + $success = false; + } else { db_process_sql_delete('tnetwork_profile_pen', ['id_np' => $this->id_np]); - // Set again the new PENs associated. - foreach ($this->pen as $currentPen) { - $dbResult_pen = db_process_sql_insert( - 'tnetwork_profile_pen', - [ - 'pen' => $currentPen, - 'id_np' => $this->id_np, - ] - ); + $pensList = explode(',', $this->pen); + if (count($pensList) > 0) { + // Set again the new PENs associated. + foreach ($pensList as $currentPen) { + $dbResult_pen = db_process_sql_insert( + 'tnetwork_profile_pen', + [ + 'pen' => $currentPen, + 'id_np' => $this->id_np, + ] + ); + if ($dbResult_pen === false) { + $success = false; + break; + } + + $success = true; + } + } else { + $success = true; } } break; @@ -265,9 +277,9 @@ class ModuleTemplates extends HTML if ($dbResult_tnp != false) { // Set the new id_np. $this->id_np = $dbResult_tnp; + $pensList = explode(',', $this->pen); // Insert all of new PENs associated with this id_np. - foreach ($this->pen as $currentPen) { - hd($currentPen); + foreach ($pensList as $currentPen) { $dbResult_pen = db_process_sql_insert( 'tnetwork_profile_pen', [ @@ -279,16 +291,28 @@ class ModuleTemplates extends HTML if ($dbResult_pen === false) { break; } + + $success = true; } } break; + case 'Delete': + // Only in this case, catch delete_profile. + $deleteProfile = get_parameter('delete_profile', -1); + $dbResult = db_process_sql_delete('tnetwork_profile', ['id_np' => $deleteProfile]); + + if ($dbResult != false) { + $success = true; + } + break; + default: - $dbResult_tnp = false; + $success = false; break; } - if ($dbResult_tnp === false || $dbResult_pen === false) { + if ($success === false) { ui_print_error_message(__('Error saving data')); } else { ui_print_success_message(__('Changes saved sucessfully')); @@ -299,19 +323,7 @@ class ModuleTemplates extends HTML /** - * Get the match between this id_np and one pen in db - * - * @param integer $pen - * @return void - */ - private function penMatch($pen) - { - return db_get_num_rows('SELECT * FROM tnetwork_profile_pen WHERE pen = %d AND id_np = %d', $pen, $this->id_np); - } - - - /** - * Undocumented function + * Show the adding modules form * * @return void */ @@ -326,6 +338,7 @@ class ModuleTemplates extends HTML // 2 arrays. 1 with the groups, 1 with the groups by parent $groups = []; $groups_compound = []; + $groups_compound[0] = 'Group - All'; foreach ($result as $row) { $groups[$row['id_sg']] = $row['name']; } @@ -339,8 +352,6 @@ class ModuleTemplates extends HTML $groups_compound[$row['id_sg']] .= $row['name']; } - // For erase - // $group_filter .= html_print_select($groups_compound, 'ncgroup', $ncgroup, 'javascript:this.form.submit();', __('Group').' - '.__('All'), -1, true, false, true, '" style="width:350px'); // Get the components for show in a list for select if ($this->ncGroup > 0) { $sql = sprintf( @@ -412,6 +423,7 @@ class ModuleTemplates extends HTML 'type' => 'select', 'script' => 'this.form.submit()', 'fields' => $groups_compound, + 'nothing' => $groups_compound[0], 'return' => true, ], ]; @@ -538,19 +550,24 @@ class ModuleTemplates extends HTML /** - * Undocumented function + * General setter * * @return void */ private function setNetworkProfile() { - if ($this->id_np !== 0) { - $profileInfo = db_get_row('tnetwork_profile', 'id_np', $this->id_np); - $this->name = $profileInfo['name']; - $this->description = $profileInfo['description']; - $penInfo = db_get_all_rows_filter('tnetwork_profile_pen', ['id_np' => $this->id_np]); - $this->pen = $penInfo['pen']; + // Get t + $profileInfo = db_get_row('tnetwork_profile', 'id_np', $this->id_np); + $this->name = $profileInfo['name']; + $this->description = $profileInfo['description']; + + $penInfo = db_get_all_rows_filter('tnetwork_profile_pen', ['id_np' => $this->id_np]); + $penList = []; + foreach ($penInfo as $pen) { + $penList[] = $pen['pen']; } + + $this->pen = implode(',', $penList); } @@ -630,7 +647,7 @@ class ModuleTemplates extends HTML true, ['title' => 'Export to CSV'] ); - $data[3] = ''.html_print_image('images/cross.png', true, ['title' => __('Delete')]).''; + $data[3] = ''.html_print_image('images/cross.png', true, ['title' => __('Delete')]).''; $data[3] .= ''.html_print_image('images/csv.png', true, ['title' => __('Export to CSV')]).''; array_push($table->data, $data); @@ -893,7 +910,9 @@ class ModuleTemplates extends HTML echo $javascript; - $this->addingModulesForm(); + if ($createNewBlock === false) { + $this->addingModulesForm(); + } $this->printGoBackButton($this->baseUrl); } From a715b7d74a5ed319f7933d74153ad3d7b8858834 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Tue, 31 Mar 2020 13:00:07 +0200 Subject: [PATCH 053/111] WIP --- .../modules/manage_module_templates.php | 56 +++---- .../include/class/ModuleTemplates.class.php | 143 +++++------------- 2 files changed, 57 insertions(+), 142 deletions(-) diff --git a/pandora_console/godmode/modules/manage_module_templates.php b/pandora_console/godmode/modules/manage_module_templates.php index b2f262b6c9..99ca1bb0d6 100644 --- a/pandora_console/godmode/modules/manage_module_templates.php +++ b/pandora_console/godmode/modules/manage_module_templates.php @@ -13,15 +13,15 @@ // GNU General Public License for more details. // Load global vars // TESTING - /* - ini_set('display_errors', 1); - ini_set('display_startup_errors', 1); +/* + ini_set('display_errors', 1); + ini_set('display_startup_errors', 1); error_reporting(E_ALL); */ // END global $config; -/* - hd($_POST); -hd($_REQUEST); */ + +hd($_POST); +hd($_REQUEST); check_login(); if (! check_acl($config['id_user'], 0, 'PM')) { @@ -33,44 +33,12 @@ if (! check_acl($config['id_user'], 0, 'PM')) { return; } - require_once $config['homedir'].'/include/class/ModuleTemplates.class.php'; $ajaxPage = ENTERPRISE_DIR.'/godmode/agentes/ModuleTemplates'; // Control call flow. try { // User access and validation is being processed on class constructor. $moduleTemplates = new ModuleTemplates(''); -} catch (Exception $e) { - echo '[ModuleTemplates]'.$e->getMessage(); - /* - if (is_ajax()) { - echo json_encode(['error' => '[MiFuncionalidad]'.$e->getMessage() ]); - exit; - } else { - echo '[MiFuncionalidad]'.$e->getMessage(); - } - */ - // Stop this execution, but continue 'globally'. - return; -} - -// AJAX controller. -if (is_ajax()) { - $method = get_parameter('method'); - /* - if (method_exists($miFuncionalidad, $method) === true) { - if ($miFuncionalidad>ajaxMethod($method) === true) { - $miFuncionalidad>{$method}(); - } else { - $miFuncionalidad>error('Unavailable method.'); - } - } else { - $miFuncionalidad->error('Method not found. ['.$method.']'); - } - */ - // Stop any execution. - exit; -} else { // Run. $moduleTemplates->run(); // Get the id_np. @@ -83,14 +51,24 @@ if (is_ajax()) { // Create new o update Template. $moduleTemplates->moduleTemplateForm(); } +} catch (Exception $e) { + echo '[ModuleTemplates]'.$e->getMessage(); + // Stop this execution, but continue 'globally'. + return; } ?> \ No newline at end of file diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php index 1fd5c99d68..bf712012be 100644 --- a/pandora_console/include/class/ModuleTemplates.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -132,11 +132,10 @@ class ModuleTemplates extends HTML $this->name = get_parameter('name', ''); $this->description = get_parameter('description', ''); $this->pen = get_parameter('pen', ''); - // Separate all PENs received. $this->offset = get_parameter('offset', 0); $this->ajaxController = $ajax_controller; - $this->ncGroup = get_parameter('ncgroup', -1); - $this->ncFilter = get_parameter('ncfilter', ''); + $this->ncGroup = get_parameter('add-modules-group', '0'); + $this->ncFilter = get_parameter('add-modules-filter', ''); return $this; } @@ -214,7 +213,8 @@ class ModuleTemplates extends HTML public function processData() { // Get action if is needed. - $action = get_parameter('submit_button', ''); + $action = get_parameter('submit_button', ''); + $modules_submit = get_parameter('add-modules-submit', ''); // Success variable. $success = false; // Evaluate the modules allowed. @@ -317,6 +317,19 @@ class ModuleTemplates extends HTML } else { ui_print_success_message(__('Changes saved sucessfully')); } + } else if ($modules_submit != '') { + $modulesToAdd = get_parameter('add-modules-components-values', ''); + $modulesToAddList = explode(',', $modulesToAdd); + + foreach ($modulesToAddList as $module) { + db_process_sql_insert( + 'tnetwork_profile_component', + [ + 'id_nc' => $module, + 'id_np' => $this->id_np, + ] + ); + } } } @@ -338,6 +351,7 @@ class ModuleTemplates extends HTML // 2 arrays. 1 with the groups, 1 with the groups by parent $groups = []; $groups_compound = []; + // Default group filter. $groups_compound[0] = 'Group - All'; foreach ($result as $row) { $groups[$row['id_sg']] = $row['name']; @@ -402,9 +416,19 @@ class ModuleTemplates extends HTML ], ]; + $inputs[] = [ + 'id' => 'add-modules-components-values', + 'arguments' => [ + 'name' => 'add-modules-components-values', + 'type' => 'hidden', + 'value' => '', + 'return' => true, + ], + ]; + $inputs[] = [ 'label' => __('Filter'), - 'id' => 'add-modules-filter', + 'id' => 'txt-add-modules-filter', 'arguments' => [ 'name' => 'add-modules-filter', 'input_class' => 'flex-row', @@ -423,14 +447,14 @@ class ModuleTemplates extends HTML 'type' => 'select', 'script' => 'this.form.submit()', 'fields' => $groups_compound, - 'nothing' => $groups_compound[0], + 'nothing' => $groups_compound[$this->ncGroup], 'return' => true, ], ]; $inputs[] = [ 'label' => __('Components'), - 'id' => 'add-modules-components', + 'id' => 'slc-add-modules-components2', 'arguments' => [ 'name' => 'add-modules-components', 'input_class' => 'flex-row', @@ -458,94 +482,6 @@ class ModuleTemplates extends HTML true ] ); - /* - $table = new StdClasS(); - - $table->head = []; - $table->data = []; - $table->align = []; - $table->width = '100%'; - $table->cellpadding = 0; - $table->cellspacing = 0; - $table->class = 'databox filters'; - - $table->style[0] = 'font-weight: bold'; - - // The form to submit when adding a list of components - $filter = ''; - $filter .= html_print_input_text('ncfilter', $ncfilter, '', 50, 255, true); - $filter .= '  '.html_print_submit_button(__('Filter'), 'ncgbutton', false, 'class="sub search"', true); - $filter .= ''; - - $group_filter = '
      '; - $group_filter .= '
      '; - $result = db_get_all_rows_in_table('tnetwork_component_group', 'name'); - if ($result === false) { - $result = []; - } - - // 2 arrays. 1 with the groups, 1 with the groups by parent - $groups = []; - $groups_compound = []; - foreach ($result as $row) { - $groups[$row['id_sg']] = $row['name']; - } - - foreach ($result as $row) { - $groups_compound[$row['id_sg']] = ''; - if ($row['parent'] > 1) { - $groups_compound[$row['id_sg']] = $groups[$row['parent']].' / '; - } - - $groups_compound[$row['id_sg']] .= $row['name']; - } - - $group_filter .= html_print_select($groups_compound, 'ncgroup', $ncgroup, 'javascript:this.form.submit();', __('Group').' - '.__('All'), -1, true, false, true, '" style="width:350px'); - - $group_filter .= '
      '; - - if ($ncgroup > 0) { - $sql = sprintf( - " - SELECT id_nc, name, id_group - FROM tnetwork_component - WHERE id_group = %d AND name LIKE '%".$ncfilter."%' - ORDER BY name", - $ncgroup - ); - } else { - $sql = " - SELECT id_nc, name, id_group - FROM tnetwork_component - WHERE name LIKE '%".$ncfilter."%' - ORDER BY name"; - } - - $result = db_get_all_rows_sql($sql); - $components = []; - if ($result === false) { - $result = []; - } - - foreach ($result as $row) { - $components[$row['id_nc']] = $row['name']; - } - - $components_select = '
      '; - $components_select .= html_print_select($components, 'components[]', $id_nc, '', '', -1, true, true, false, '" style="width:350px'); - - $table->data[0][0] = __('Filter'); - $table->data[0][1] = $filter; - $table->data[1][0] = __('Group'); - $table->data[1][1] = $group_filter; - $table->data[2][0] = __('Components'); - $table->data[2][1] = $components_select; - - html_print_table($table); - - echo '
      '; - html_print_submit_button(__('Add'), 'crtbutton', false, 'class="sub wand"'); - echo '
      ';*/ } @@ -802,7 +738,7 @@ class ModuleTemplates extends HTML $this->id_np ); $moduleBlocks = db_get_all_rows_sql($sql); - + // hd($moduleBlocks); if ($moduleBlocks) { $blockTables = []; // Build the information of the blocks @@ -812,14 +748,14 @@ class ModuleTemplates extends HTML 'name' => $block['group_name'], 'data' => [], ]; - } else { - $blockTables[$block['group']]['data'][] = [ - 'component_id' => $block['component_id'], - 'name' => $block['name'], - 'type' => $block['type'], - 'description' => $block['description'], - ]; } + + $blockTables[$block['group']]['data'][] = [ + 'component_id' => $block['component_id'], + 'name' => $block['name'], + 'type' => $block['type'], + 'description' => $block['description'], + ]; } if (count($blockTables) === 0) { @@ -911,6 +847,7 @@ class ModuleTemplates extends HTML echo $javascript; if ($createNewBlock === false) { + echo '

      Add modules

      '; $this->addingModulesForm(); } From 7f1d4725bd34ad3e8a7f0fbe0e00889d2258a6b2 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Tue, 31 Mar 2020 17:52:20 +0200 Subject: [PATCH 054/111] minor fix mr --- pandora_console/extras/mr/37.sql | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/pandora_console/extras/mr/37.sql b/pandora_console/extras/mr/37.sql index 9207ee2df7..ef6cf7b015 100644 --- a/pandora_console/extras/mr/37.sql +++ b/pandora_console/extras/mr/37.sql @@ -24,22 +24,13 @@ CREATE TABLE `tdiscovery_tmp_agents` ( CREATE TABLE `tdiscovery_tmp_connections` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `id_rt` int(10) unsigned NOT NULL, - `id1` int(10) unsigned NOT NULL AUTO_INCREMENT, - `id2` int(10) unsigned NOT NULL, - `if1` text, - `if2` text, - PRIMARY KEY (`id1`,`id2`), - CONSTRAINT `tdtc_trt` FOREIGN KEY (`id_rt`) - REFERENCES `trecon_task` (`id_rt`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `tdtc_tdta1` FOREIGN KEY (`id1`) - REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `tdtc_tdta2` FOREIGN KEY (`id2`) - REFERENCES `tdiscovery_tmp_agents` (`id`) ON DELETE CASCADE ON UPDATE CASCADE + `dev_1` text, + `dev_2` text, + `if_1` text, + `if_2` text, + PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; --- ---------------------------------------------------------------------- --- New table `tpen` --- ---------------------------------------------------------------------- CREATE TABLE `tpen` ( `pen` int(10) unsigned NOT NULL, `manufacturer` TEXT, @@ -47,9 +38,6 @@ CREATE TABLE `tpen` ( PRIMARY KEY (`pen`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; --- ---------------------------------------------------------------------- --- Table `tnetwork_profile_pen` --- ---------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `tnetwork_profile_pen` ( `pen` int(10) unsigned NOT NULL, `id_np` int(10) unsigned NOT NULL, From faf7c5462e4c08b90080d8ac487c417ab6e01f70 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Wed, 1 Apr 2020 09:25:18 +0200 Subject: [PATCH 055/111] Applied solution for image size issues in toggle bar --- pandora_console/include/functions_ui.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index a8041c7e9a..de05c0f402 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -3711,8 +3711,8 @@ function ui_toggle( // Generate unique Id. $uniqid = uniqid(''); - $image_a = html_print_image($img_a, true, false, true); - $image_b = html_print_image($img_b, true, false, true); + $image_a = html_print_image($img_a, true, [ 'style' => 'object-fit: contain;' ], true); + $image_b = html_print_image($img_b, true, [ 'style' => 'object-fit: contain;' ], true); // Options. if ($hidden_default) { $style = 'display:none'; @@ -3736,6 +3736,7 @@ function ui_toggle( $original, true, [ + 'style' => 'object-fit: contain;', 'title' => $title, 'id' => 'image_'.$uniqid, ] From 4f2ad67f585b24386e00081dd1210274af6ae352 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Wed, 1 Apr 2020 13:13:31 +0200 Subject: [PATCH 056/111] WIP: Deleted legacy menu entry --- pandora_console/godmode/menu.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/pandora_console/godmode/menu.php b/pandora_console/godmode/menu.php index 85b2864c05..7a5295f1c5 100644 --- a/pandora_console/godmode/menu.php +++ b/pandora_console/godmode/menu.php @@ -143,8 +143,6 @@ if (check_acl($config['id_user'], 0, 'PM')) { $sub['templates']['type'] = 'direct'; $sub['templates']['subtype'] = 'nolink'; $sub2 = []; - $sub2['godmode/modules/manage_network_templates']['text'] = __('Module templates (legacy)'); - $sub2['godmode/modules/manage_network_templates']['id'] = 'Module templates'; $sub2['godmode/modules/manage_module_templates']['text'] = __('Module templates'); $sub2['godmode/modules/manage_module_templates']['id'] = 'Module templates'; $sub2['godmode/modules/private_enterprise_numbers']['text'] = __('Private Enterprise Numbers'); From 6be6e19ad3093f337c1c438c7b9506711816de57 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Wed, 1 Apr 2020 16:21:28 +0200 Subject: [PATCH 057/111] WIP: Ready for testing --- .../modules/manage_module_templates.php | 178 ++++-- .../include/class/ConfigPEN.class.php | 8 +- .../include/class/ModuleTemplates.class.php | 592 +++++++++++++++--- 3 files changed, 632 insertions(+), 146 deletions(-) diff --git a/pandora_console/godmode/modules/manage_module_templates.php b/pandora_console/godmode/modules/manage_module_templates.php index 99ca1bb0d6..8b6abcc72d 100644 --- a/pandora_console/godmode/modules/manage_module_templates.php +++ b/pandora_console/godmode/modules/manage_module_templates.php @@ -1,42 +1,111 @@ '[ModuleTemplates]'.$e->getMessage() ]); + exit; + } else { + echo '[ModuleTemplates]'.$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(); +} + +/* + moduleTemplateForm(); } -} catch (Exception $e) { + } catch (Exception $e) { echo '[ModuleTemplates]'.$e->getMessage(); // Stop this execution, but continue 'globally'. return; -} + } -?> - \ No newline at end of file + diff --git a/pandora_console/include/class/ConfigPEN.class.php b/pandora_console/include/class/ConfigPEN.class.php index 0c2e67c8e7..155a8adb1f 100644 --- a/pandora_console/include/class/ConfigPEN.class.php +++ b/pandora_console/include/class/ConfigPEN.class.php @@ -531,8 +531,8 @@ class ConfigPEN extends HTML 'tpen', [ 'pen' => $pen, - 'manufacturer' => io_safe_input($manufacturer), - 'description' => io_safe_input($description), + 'manufacturer' => $manufacturer, + 'description' => $description, ] ); $str = __('created'); @@ -550,8 +550,8 @@ class ConfigPEN extends HTML $rs = db_process_sql_update( 'tpen', [ - 'manufacturer' => io_safe_input($manufacturer), - 'description' => io_safe_input($description), + 'manufacturer' => $manufacturer, + 'description' => $description, ], ['pen' => $pen] ); diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php index bf712012be..dd89ae3c31 100644 --- a/pandora_console/include/class/ModuleTemplates.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -1,6 +1,6 @@ baseUrl = ui_get_full_url('index.php?sec=gmodules&sec2=godmode/modules/manage_module_templates'); // Capture all parameters before start. $this->id_np = get_parameter('id_np', -1); - $this->name = get_parameter('name', ''); - $this->description = get_parameter('description', ''); - $this->pen = get_parameter('pen', ''); + if ($this->id_np > 0) { + // Profile exists. Set the attributes with the info. + $this->setNetworkProfile(); + } else { + $this->name = get_parameter('name', ''); + $this->description = get_parameter('description', ''); + $this->pen = get_parameter('pen', ''); + } + + $this->action = get_parameter('action_button', ''); $this->offset = get_parameter('offset', 0); $this->ajaxController = $ajax_controller; $this->ncGroup = get_parameter('add-modules-group', '0'); $this->ncFilter = get_parameter('add-modules-filter', ''); + // Get all of PENs valid for autocomplete. + $getPENs = db_get_all_rows_sql('SELECT pen,manufacturer FROM tpen'); + $outputPENs = []; + + $this->validPen = ''; + $this->penRefs = []; + foreach ($getPENs as $pen) { + $this->validPen .= ((int) $pen['pen']).','; + $this->penRefs[] = [ + 'label' => io_safe_output($pen['manufacturer']), + 'value' => $pen['pen'], + ]; + // Reverse autocompletion. + $this->penRefs[] = [ + 'label' => $pen['pen'], + 'value' => $pen['pen'], + ]; + } + + chop($this->validPen); return $this; } @@ -148,35 +196,53 @@ class ModuleTemplates extends HTML */ public function run() { - // Require specific CSS and JS. + // CSS. ui_require_css_file('wizard'); ui_require_css_file('discovery'); - // Header section. + // Javascript. + ui_require_javascript_file('jquery.caret.min'); + // Breadcrums. $this->setBreadcrum([]); - $this->prepareBreadcrum( - [ - [ - 'link' => '', - 'label' => __('Configuration'), - 'selected' => false, - ], - [ - 'link' => '', - 'label' => __('Templates'), - 'selected' => false, - ], - [ - 'link' => $this->baseUrl, - 'label' => __('Module template management'), - 'selected' => true, - ], - ], - true - ); + if ($this->id_np > 0) { + // Add a breadcrumb with the current template. + $urlToGo = $this->baseUrl.'&id_np='.$this->id_np; + $this->prepareBreadcrum( + [ + ['label' => __('Configuration')], + ['label' => __('Templates')], + [ + 'link' => $this->baseUrl, + 'label' => __('Module template management'), + 'selected' => false, + ], + [ + 'link' => $urlToGo, + 'label' => $this->name, + 'selected' => true, + ], + ], + true + ); + } else { + $this->prepareBreadcrum( + [ + ['label' => __('Configuration')], + ['label' => __('Templates')], + [ + 'link' => $this->baseUrl, + 'label' => __('Module template management'), + 'selected' => true, + ], + ], + true + ); + } + + // Prints the header. ui_print_page_header( __('Module template management'), '', @@ -191,17 +257,56 @@ class ModuleTemplates extends HTML $this->printHeader(true) ); + // Process the data if action is required + if (!empty($this->action)) { + $this->processData(); + } + + if ($this->id_np === -1) { + // List all Module Blocks. + $this->moduleTemplateList(); + } else { + // Show form for create or update template. + $this->moduleTemplateForm(); + } + + $this->loadJS(); } /** - * Get the value of this current thing ??? + * Minor function to dump json message as ajax response. * - * @return integer Id of this thing ??? + * @param string $type Type: result || error. + * @param string $msg Message. + * + * @return void */ - public function getIdNp() + private function ajaxMsg($type, $msg) { - return $this->id_np; + if ($type == 'error') { + echo json_encode( + [ + $type => ui_print_error_message( + __($msg), + '', + true + ), + ] + ); + } else { + echo json_encode( + [ + $type => ui_print_success_message( + __($msg), + '', + true + ), + ] + ); + } + + exit; } @@ -212,13 +317,12 @@ class ModuleTemplates extends HTML */ public function processData() { - // Get action if is needed. - $action = get_parameter('submit_button', ''); + // Only needed if process data. $modules_submit = get_parameter('add-modules-submit', ''); // Success variable. $success = false; // Evaluate the modules allowed. - if (!empty($action)) { + if (!empty($this->action)) { $numberComponent = []; foreach ($_POST as $k => $value) { if (strpos($k, 'module_check_') >= 0 && $value == 1) { @@ -227,7 +331,7 @@ class ModuleTemplates extends HTML } } - switch ($action) { + switch ($this->action) { case 'Update': $dbResult_tnp = db_process_sql_update( 'tnetwork_profile', @@ -263,6 +367,12 @@ class ModuleTemplates extends HTML $success = true; } } + + if ($success === true) { + $msg = __('Template %s successfully updated', $this->name); + } else { + $msg = __('Error updating template'); + } break; case 'Create': @@ -295,30 +405,74 @@ class ModuleTemplates extends HTML $success = true; } } - break; - case 'Delete': - // Only in this case, catch delete_profile. - $deleteProfile = get_parameter('delete_profile', -1); - $dbResult = db_process_sql_delete('tnetwork_profile', ['id_np' => $deleteProfile]); - - if ($dbResult != false) { - $success = true; + if ($success === true) { + $msg = __('Template %s successfully created', $this->name); + } else { + $msg = __('Error creating template'); } break; + case 'Delete': + $success = db_process_sql_delete('tnetwork_profile', ['id_np' => $this->id_np]); + + if ($success != false) { + $msg = __('Template %s successfully deleted', $this->name); + } else { + $msg = __('Error deleting %s template', $this->name); + } + + // Reset id_np for show the templates list. + $this->id_np = -1; + break; + default: - $success = false; + // There is possible want do an action detailed. + $action_detailed = explode('_', $this->action); + // Action deletion. + if ($action_detailed[0] === 'del') { + // Block or Module is affected. + switch ($action_detailed[1]) { + case 'module': + $success = $this->deleteModule($action_detailed[2]); + + if ($success != false) { + $msg = __('Module successfully deleted'); + } else { + $msg = __('Error deleting module'); + } + break; + + case 'block': + $block = explode('-', $action_detailed[2]); + foreach ($block as $module) { + $success = $this->deleteModule($module); + } + + if ($success != false) { + $msg = __('Block successfully deleted'); + } else { + $msg = __('Error deleting block'); + } + break; + + default: + // Do nothing. + break; + } + } else { + $msg = __('Something gone wrong. Please, try again'); + } break; } if ($success === false) { - ui_print_error_message(__('Error saving data')); + ui_print_error_message($msg); } else { - ui_print_success_message(__('Changes saved sucessfully')); + ui_print_success_message($msg); } } else if ($modules_submit != '') { - $modulesToAdd = get_parameter('add-modules-components-values', ''); + $modulesToAdd = get_parameter('add-modules-components', ''); $modulesToAddList = explode(',', $modulesToAdd); foreach ($modulesToAddList as $module) { @@ -330,8 +484,30 @@ class ModuleTemplates extends HTML ] ); } - } + $this->ajaxMsg('result', __('Components added sucessfully')); + } + } + + + /** + * Delete of block the module desired + * + * @param integer $id_module Id of module that must delete. + * + * @return mixed Return false if something went wrong. + */ + private function deleteModule($id_module) + { + $dbResult = db_process_sql_delete( + 'tnetwork_profile_component', + [ + 'id_np' => $this->id_np, + 'id_nc' => $id_module, + ] + ); + + return $dbResult; } @@ -342,7 +518,7 @@ class ModuleTemplates extends HTML */ public function addingModulesForm() { - // Get the groups for select input + // Get the groups for select input. $result = db_get_all_rows_in_table('tnetwork_component_group', 'name'); if ($result === false) { $result = []; @@ -362,11 +538,9 @@ class ModuleTemplates extends HTML if ($row['parent'] > 1) { $groups_compound[$row['id_sg']] = $groups[$row['parent']].' / '; } - - $groups_compound[$row['id_sg']] .= $row['name']; } - // Get the components for show in a list for select + // Get the components for show in a list for select. if ($this->ncGroup > 0) { $sql = sprintf( " @@ -399,7 +573,7 @@ class ModuleTemplates extends HTML 'action' => $this->baseUrl, 'id' => 'add_module_form', 'method' => 'POST', - 'class' => 'databox filters', + 'class' => 'modal', 'extra' => '', ]; @@ -438,6 +612,17 @@ class ModuleTemplates extends HTML ], ]; + $inputs[] = [ + 'arguments' => [ + 'label' => __('Filter'), + 'name' => 'add-modules-submit', + 'type' => 'button', + 'script' => 'this.form.submit()', + 'attributes' => 'class="sub search"', + 'return' => true, + ], + ]; + $inputs[] = [ 'label' => __('Group'), 'id' => 'add-modules-group', @@ -454,7 +639,7 @@ class ModuleTemplates extends HTML $inputs[] = [ 'label' => __('Components'), - 'id' => 'slc-add-modules-components2', + 'id' => 'slc-add-modules-components', 'arguments' => [ 'name' => 'add-modules-components', 'input_class' => 'flex-row', @@ -465,17 +650,7 @@ class ModuleTemplates extends HTML ], ]; - $inputs[] = [ - 'arguments' => [ - 'label' => __('Add components'), - 'name' => 'add-modules-submit', - 'type' => 'submit', - 'attributes' => 'class="sub wand"', - 'return' => true, - ], - ]; - - $this->printFormAsList( + $this->printForm( [ 'form' => $form, 'inputs' => $inputs, @@ -492,7 +667,6 @@ class ModuleTemplates extends HTML */ private function setNetworkProfile() { - // Get t $profileInfo = db_get_row('tnetwork_profile', 'id_np', $this->id_np); $this->name = $profileInfo['name']; $this->description = $profileInfo['description']; @@ -510,9 +684,9 @@ class ModuleTemplates extends HTML /** * Create the table with the list of Blocks Templates * - * @return html Formed table + * @return void */ - public function moduleBlockList() + public function moduleTemplateList() { global $config; // Get the count of Blocks. @@ -583,7 +757,7 @@ class ModuleTemplates extends HTML true, ['title' => 'Export to CSV'] ); - $data[3] = ''.html_print_image('images/cross.png', true, ['title' => __('Delete')]).''; + $data[3] = ''.html_print_image('images/cross.png', true, ['title' => __('Delete')]).''; $data[3] .= ''.html_print_image('images/csv.png', true, ['title' => __('Export to CSV')]).''; array_push($table->data, $data); @@ -633,6 +807,8 @@ class ModuleTemplates extends HTML /** * Prints Form for template management + * + * @return mixed */ public function moduleTemplateForm() { @@ -648,17 +824,15 @@ class ModuleTemplates extends HTML $formButtonClass = 'sub upd'; $formButtonValue = 'update'; $formButtonLabel = __('Update'); - // Profile exists. Set the attributes with the info. - $this->setNetworkProfile(); } // Main form. $form = [ 'action' => $this->baseUrl, - 'id' => 'module_block_form', + 'id' => 'module_template_form', 'method' => 'POST', 'class' => 'databox filters', - 'extra' => '', + 'extra' => 'id="module_template_form"', ]; // Inputs. @@ -676,6 +850,16 @@ class ModuleTemplates extends HTML ], ]; + $inputs[] = [ + 'id' => 'inp-valid-pen', + 'arguments' => [ + 'name' => 'valid-pen', + 'type' => 'hidden', + 'value' => $this->validPen, + 'return' => true, + ], + ]; + $inputs[] = [ 'label' => __('Name'), 'id' => 'inp-name', @@ -714,7 +898,7 @@ class ModuleTemplates extends HTML $inputs[] = [ 'arguments' => [ - 'name' => 'submit_button', + 'name' => 'action_button', 'label' => $formButtonLabel, 'type' => 'submit', 'value' => $formButtonValue, @@ -723,11 +907,21 @@ class ModuleTemplates extends HTML ], ]; + // Adding components button. + $inputs[] = [ + 'arguments' => [ + 'name' => 'add_components_button', + 'label' => __('Add components'), + 'type' => 'button', + 'attributes' => 'class="sub cog"', + 'script' => 'showAddComponent();', + 'return' => true, + ], + ]; + // Required for PEN field. ui_require_jquery_file('tag-editor'); ui_require_css_file('jquery.tag-editor'); - $js = '$(\'#text-pen\').tagEditor();'; - if ($createNewBlock === false) { // Get the data. $sql = sprintf( @@ -738,10 +932,10 @@ class ModuleTemplates extends HTML $this->id_np ); $moduleBlocks = db_get_all_rows_sql($sql); - // hd($moduleBlocks); + if ($moduleBlocks) { $blockTables = []; - // Build the information of the blocks + // Build the information of the blocks. foreach ($moduleBlocks as $block) { if (key_exists($block['group'], $blockTables) === false) { $blockTables[$block['group']] = [ @@ -762,9 +956,32 @@ class ModuleTemplates extends HTML ui_print_info_message(__('No module blocks for this profile')); } else { foreach ($blockTables as $id_group => $blockTable) { + // Data with all components. $blockData = $blockTable['data']; - $blockTitle = $blockTable['name']; - $blockTitle .= '
      '.html_print_checkbox_switch_extended('block_id_'.$id_group, 1, 0, false, '', '', true).'
      '; + // Creation of list of all components. + $blockComponentList = ''; + foreach ($blockData as $component) { + $blockComponentList .= $component['component_id'].'-'; + } + + $blockComponentList = chop($blockComponentList, '-'); + // Title of Block. + $blockTitle = '
      '; + $blockTitle .= $blockTable['name']; + $blockTitle .= '
      '; + $blockTitle .= html_print_input_image( + 'del_block_'.$id_group.'_', + 'images/cross.png', + 1, + false, + true, + [ + 'title' => __('Delete this block'), + 'onclick' => 'if(confirm(\''.__('Do you want delete this block?').'\')){deleteModuleTemplate(\'block\',\''.$blockComponentList.'\')};return false;', + ] + ); + + $blockTitle .= '
      '; $table = new StdClasS(); $table->class = 'databox data'; @@ -782,7 +999,7 @@ class ModuleTemplates extends HTML $table->head[0] = __('Module Name'); $table->head[1] = __('Type'); $table->head[2] = __('Description'); - $table->head[3] = ''.__('Add').''; + $table->head[3] = ''.__('Delete').''; $table->size = []; $table->size[0] = '20%'; @@ -801,7 +1018,17 @@ class ModuleTemplates extends HTML $data[0] = $module['name']; $data[1] = ui_print_moduletype_icon($module['type'], true); $data[2] = mb_strimwidth(io_safe_output($module['description']), 0, 150, '...'); - $data[3] = html_print_checkbox_switch_extended('module_check_'.$id_group.'_'.$module['component_id'], 1, 0, false, 'switchBlockControl(event)', '', true); + $data[3] = html_print_input_image( + 'del_module_'.$module['component_id'].'_', + 'images/cross.png', + 1, + '', + true, + [ + 'title' => __('Delete this module'), + 'onclick' => 'if(confirm(\''.__('Do you want delete this module?').'\')){deleteModuleTemplate(\'module\','.$module['component_id'].')};return false;', + ] + ); array_push($table->data, $data); } @@ -821,38 +1048,195 @@ class ModuleTemplates extends HTML 'form' => $form, 'inputs' => $inputs, 'rawInputs' => $rawInputs, - 'js' => $js, true ] ); - $javascript = " - - "; - - echo $javascript; - if ($createNewBlock === false) { - echo '

      Add modules

      '; - $this->addingModulesForm(); + echo ''; + echo ''; } $this->printGoBackButton($this->baseUrl); } + /** + * Loads JS and return code. + * + * @return string + */ + public function loadJS() + { + $str = ''; + + ob_start(); + ?> + + + Date: Wed, 1 Apr 2020 16:36:06 +0200 Subject: [PATCH 058/111] Minor fixes applied --- .../modules/manage_module_templates.php | 109 ------------------ .../include/class/ModuleTemplates.class.php | 14 +-- 2 files changed, 7 insertions(+), 116 deletions(-) diff --git a/pandora_console/godmode/modules/manage_module_templates.php b/pandora_console/godmode/modules/manage_module_templates.php index 8b6abcc72d..f23394be52 100644 --- a/pandora_console/godmode/modules/manage_module_templates.php +++ b/pandora_console/godmode/modules/manage_module_templates.php @@ -65,112 +65,3 @@ if (is_ajax()) { // Run. $obj->run(); } - -/* - run(); - // Get the id_np. - $id_np = $moduleTemplates->getIdNp(); - $moduleTemplates->processData(); - if ($id_np === -1) { - // List all Module Blocks. - $moduleTemplates->moduleBlockList(); - } else { - // Create new o update Template. - $moduleTemplates->moduleTemplateForm(); - } - } catch (Exception $e) { - echo '[ModuleTemplates]'.$e->getMessage(); - // Stop this execution, but continue 'globally'. - return; - } - - ?> - diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php index dd89ae3c31..5760f26a89 100644 --- a/pandora_console/include/class/ModuleTemplates.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -150,16 +150,12 @@ class ModuleTemplates extends HTML $this->baseUrl = ui_get_full_url('index.php?sec=gmodules&sec2=godmode/modules/manage_module_templates'); // Capture all parameters before start. $this->id_np = get_parameter('id_np', -1); - if ($this->id_np > 0) { + $this->action = get_parameter('action_button', ''); + if ($this->id_np > 0 || empty($this->action)) { // Profile exists. Set the attributes with the info. $this->setNetworkProfile(); - } else { - $this->name = get_parameter('name', ''); - $this->description = get_parameter('description', ''); - $this->pen = get_parameter('pen', ''); } - $this->action = get_parameter('action_button', ''); $this->offset = get_parameter('offset', 0); $this->ajaxController = $ajax_controller; $this->ncGroup = get_parameter('add-modules-group', '0'); @@ -257,7 +253,7 @@ class ModuleTemplates extends HTML $this->printHeader(true) ); - // Process the data if action is required + // Process the data if action is required. if (!empty($this->action)) { $this->processData(); } @@ -331,6 +327,10 @@ class ModuleTemplates extends HTML } } + $this->name = get_parameter('name', ''); + $this->description = get_parameter('description', ''); + $this->pen = get_parameter('pen', ''); + switch ($this->action) { case 'Update': $dbResult_tnp = db_process_sql_update( From e249233205eaed0f28362f5137bcc4bcfa419208 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Wed, 1 Apr 2020 16:43:04 +0200 Subject: [PATCH 059/111] minor fixes --- .../godmode/wizards/HostDevices.class.php | 37 +++---------------- pandora_console/include/styles/wizard.css | 2 +- .../lib/PandoraFMS/DiscoveryServer.pm | 3 ++ 3 files changed, 9 insertions(+), 33 deletions(-) diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php index ff2c10b0ed..22ff8f5301 100755 --- a/pandora_console/godmode/wizards/HostDevices.class.php +++ b/pandora_console/godmode/wizards/HostDevices.class.php @@ -1020,11 +1020,10 @@ class HostDevices extends Wizard true ), 'arguments' => [ - 'name' => 'auto_monitor', - 'type' => 'switch', - 'return' => true, - 'value' => (isset($this->task['auto_monitor'])) ? $this->task['auto_monitor'] : 1, - 'onclick' => 'toggleTemplatesSelection();', + 'name' => 'auto_monitor', + 'type' => 'switch', + 'return' => true, + 'value' => (isset($this->task['auto_monitor'])) ? $this->task['auto_monitor'] : 1, ], ]; @@ -1129,36 +1128,10 @@ class HostDevices extends Wizard } } - $form['js'] .= ' - - function toggleTemplatesSelection() { - if (document.getElementsByName("auto_monitor")[0].checked) { - document.getElementById("templates_selection").style["display"] = "none"; - var snmp = document.getElementsByName("snmp_enabled"); - if (snmp[0] != undefined) { - if(snmp[0].checked != 1) { - snmp[0].click(); - } - } else { - // Not found. - document.getElementById("templates_selection").style["display"] = "block"; - document.getElementsByName("auto_monitor")[0].checked = false; - } - } else { - document.getElementById("templates_selection").style["display"] = "block"; - } - } - - $(document).ready(function () { - toggleTemplatesSelection(); - }); - -'; - // Submit button. $form['inputs'][] = [ 'arguments' => [ - 'name' => 'submit', + 'name' => 'submit-finish', 'label' => __('Finish'), 'type' => 'submit', 'attributes' => 'class="sub next"', diff --git a/pandora_console/include/styles/wizard.css b/pandora_console/include/styles/wizard.css index 572c3496bf..f80b0078b1 100644 --- a/pandora_console/include/styles/wizard.css +++ b/pandora_console/include/styles/wizard.css @@ -28,7 +28,7 @@ ul.wizard li > textarea { } .wizard .hidden { - display: none !important; + display: none; } .wizard .indented { diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index 2c3d9f1c9f..d2e47fba59 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -938,6 +938,9 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($;$) { $self->{'task_data'}{'id_rt'} ); + # Return if no entries. + return unless scalar @rows > 0; + my @agents; my $progress = 0; From c31a288cfd56e5479dfe1964a11104f0817bccc7 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Wed, 1 Apr 2020 17:26:04 +0200 Subject: [PATCH 060/111] Minor fix when create a template and add components --- .../include/class/ModuleTemplates.class.php | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php index 5760f26a89..d066f91607 100644 --- a/pandora_console/include/class/ModuleTemplates.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -151,8 +151,8 @@ class ModuleTemplates extends HTML // Capture all parameters before start. $this->id_np = get_parameter('id_np', -1); $this->action = get_parameter('action_button', ''); + // Profile exists. Set the attributes with the info. if ($this->id_np > 0 || empty($this->action)) { - // Profile exists. Set the attributes with the info. $this->setNetworkProfile(); } @@ -907,17 +907,20 @@ class ModuleTemplates extends HTML ], ]; - // Adding components button. - $inputs[] = [ - 'arguments' => [ - 'name' => 'add_components_button', - 'label' => __('Add components'), - 'type' => 'button', - 'attributes' => 'class="sub cog"', - 'script' => 'showAddComponent();', - 'return' => true, - ], - ]; + if ($createNewBlock === false) { + // Adding components button. + $inputs[] = [ + 'arguments' => [ + 'name' => 'add_components_button', + 'label' => __('Add components'), + 'type' => 'button', + 'attributes' => 'class="sub cog"', + 'script' => 'showAddComponent();', + 'return' => true, + ], + ]; + } + // Required for PEN field. ui_require_jquery_file('tag-editor'); ui_require_css_file('jquery.tag-editor'); @@ -1190,7 +1193,8 @@ class ModuleTemplates extends HTML if (!failed) { $(".ui-dialog-content").dialog("close"); $(".info").hide(); - location.reload(); + var id_np = id_np; ?>; + window.location = window.location.href+'&id_np='+id_np; } else { $(this).dialog("close"); } From bb1ad4d2a92ed34f5eaa6cdfad484db68b4c9c97 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Wed, 1 Apr 2020 18:16:57 +0200 Subject: [PATCH 061/111] Updates sat. compatibility --- pandora_server/lib/PandoraFMS/Recon/Base.pm | 2 ++ pandora_server/lib/PandoraFMS/Tools.pm | 2 ++ 2 files changed, 4 insertions(+) diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 81e7d5993f..7966e97de0 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -1421,6 +1421,8 @@ sub scan_subnet($) { # By default 200, (20 * 10) my $host_block_size = $self->{'block_size'}; + $host_block_size = 50 unless defined($self->{'block_size'}); + # The first 50% of the recon task approx. my $step = 25.0 / scalar(@subnets) / (($total_hosts / $host_block_size)+1); my $subnet_step = 50.0 / (($total_hosts / $host_block_size)+1); diff --git a/pandora_server/lib/PandoraFMS/Tools.pm b/pandora_server/lib/PandoraFMS/Tools.pm index 92c6a06cd5..76aaefc344 100755 --- a/pandora_server/lib/PandoraFMS/Tools.pm +++ b/pandora_server/lib/PandoraFMS/Tools.pm @@ -1453,6 +1453,8 @@ sub pandora_block_ping($@) { my ($pa_config, @hosts) = @_; my ($cmd, $output); + return () if is_empty(@hosts); + if (-x $pa_config->{'fping'}) { # fping timeout in milliseconds $cmd = $pa_config->{'fping'} . " -a -q -t " . (1000 * $pa_config->{'networktimeout'}) . " " . (join (' ', @hosts)); From 933bdef165c3dc51d932275a643fa20617a7da67 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Thu, 2 Apr 2020 08:10:37 +0200 Subject: [PATCH 062/111] Added solution for multiple template delete --- .../modules/manage_module_templates.php | 1 + .../include/class/ModuleTemplates.class.php | 174 ++++++++++-------- 2 files changed, 94 insertions(+), 81 deletions(-) diff --git a/pandora_console/godmode/modules/manage_module_templates.php b/pandora_console/godmode/modules/manage_module_templates.php index f23394be52..3d40569b7a 100644 --- a/pandora_console/godmode/modules/manage_module_templates.php +++ b/pandora_console/godmode/modules/manage_module_templates.php @@ -25,6 +25,7 @@ * GNU General Public License for more details. * ============================================================================ */ + // Begin. global $config; diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php index d066f91607..7be6b20f21 100644 --- a/pandora_console/include/class/ModuleTemplates.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -319,14 +319,6 @@ class ModuleTemplates extends HTML $success = false; // Evaluate the modules allowed. if (!empty($this->action)) { - $numberComponent = []; - foreach ($_POST as $k => $value) { - if (strpos($k, 'module_check_') >= 0 && $value == 1) { - $tmpNumberComponent = explode('_', $k); - $numberComponent[] = $tmpNumberComponent[2]; - } - } - $this->name = get_parameter('name', ''); $this->description = get_parameter('description', ''); $this->pen = get_parameter('pen', ''); @@ -434,7 +426,10 @@ class ModuleTemplates extends HTML // Block or Module is affected. switch ($action_detailed[1]) { case 'module': - $success = $this->deleteModule($action_detailed[2]); + $success = db_process_sql_delete( + 'tnetwork_profile_component', + 'id_nc='.$action_detailed[2].' AND id_np='.$this->id_np + ); if ($success != false) { $msg = __('Module successfully deleted'); @@ -444,10 +439,10 @@ class ModuleTemplates extends HTML break; case 'block': - $block = explode('-', $action_detailed[2]); - foreach ($block as $module) { - $success = $this->deleteModule($module); - } + $success = db_process_sql_delete( + 'tnetwork_profile_component', + 'id_nc in ('.$action_detailed[2].') AND id_np='.$this->id_np + ); if ($success != false) { $msg = __('Block successfully deleted'); @@ -456,6 +451,34 @@ class ModuleTemplates extends HTML } break; + case 'template': + if ($action_detailed[2] === 'all') { + $success = db_process_sql_delete( + 'tnetwork_profile', + ['1' => 1] + ); + + if ($success != false) { + $msg = __('All templates deleted'); + } else { + $msg = __('Error deleting all templates'); + } + } else { + $success = db_process_sql_delete( + 'tnetwork_profile', + 'id_np in ('.$action_detailed[2].')' + ); + + if ($success != false) { + $msg = __('Selected templates deleted'); + } else { + $msg = __('Error deleting selected templates'); + } + } + + $this->id_np = -1; + break; + default: // Do nothing. break; @@ -490,27 +513,6 @@ class ModuleTemplates extends HTML } - /** - * Delete of block the module desired - * - * @param integer $id_module Id of module that must delete. - * - * @return mixed Return false if something went wrong. - */ - private function deleteModule($id_module) - { - $dbResult = db_process_sql_delete( - 'tnetwork_profile_component', - [ - 'id_np' => $this->id_np, - 'id_nc' => $id_module, - ] - ); - - return $dbResult; - } - - /** * Show the adding modules form * @@ -690,13 +692,13 @@ class ModuleTemplates extends HTML { global $config; // Get the count of Blocks. - $countModuleBlocks = db_get_value( + $countModuleTemplates = db_get_value( 'count(*)', 'tnetwork_profile' ); // Get all the data. - $resultModuleBlocksTable = db_get_all_rows_filter( + $resultModuleTemplatesTable = db_get_all_rows_filter( 'tnetwork_profile', [ 'order' => 'name', @@ -705,7 +707,7 @@ class ModuleTemplates extends HTML ] ); - ui_pagination($countModuleBlocks, false, $this->offset); + ui_pagination($countModuleTemplates, false, $this->offset); // Create the table with Module Block list. $table = new StdClasS(); $table->class = 'databox data'; @@ -735,7 +737,7 @@ class ModuleTemplates extends HTML $table->data = []; - foreach ($resultModuleBlocksTable as $row) { + foreach ($resultModuleTemplatesTable as $row) { $data = []; $data[0] = html_print_checkbox_extended('delete_multiple[]', $row['id_np'], false, false, '', 'class="check_delete"', true); $data[1] = ''.io_safe_output($row['name']).''; @@ -770,6 +772,7 @@ class ModuleTemplates extends HTML $form = [ 'method' => 'POST', 'action' => $this->baseUrl, + 'id' => 'main_management_form', ]; $inputs[] = [ @@ -791,6 +794,16 @@ class ModuleTemplates extends HTML ], ]; + $inputs[] = [ + 'arguments' => [ + 'label' => __('Delete selected'), + 'name' => 'erase', + 'type' => 'button', + 'attributes' => 'class="sub cancel"', + 'return' => true, + ], + ]; + $output .= $this->printForm( [ 'form' => $form, @@ -812,9 +825,9 @@ class ModuleTemplates extends HTML */ public function moduleTemplateForm() { - $createNewBlock = ($this->id_np == 0) ? true : false; + $createNewTemplate = ($this->id_np == 0) ? true : false; - if ($createNewBlock) { + if ($createNewTemplate) { // Assignation for submit button. $formButtonClass = 'sub wand'; $formButtonValue = 'create'; @@ -907,7 +920,7 @@ class ModuleTemplates extends HTML ], ]; - if ($createNewBlock === false) { + if ($createNewTemplate === false) { // Adding components button. $inputs[] = [ 'arguments' => [ @@ -925,7 +938,7 @@ class ModuleTemplates extends HTML ui_require_jquery_file('tag-editor'); ui_require_css_file('jquery.tag-editor'); - if ($createNewBlock === false) { + if ($createNewTemplate === false) { // Get the data. $sql = sprintf( 'SELECT npc.id_nc AS component_id, nc.name, nc.type, nc.description, nc.id_group AS `group`, ncg.name AS `group_name` @@ -964,10 +977,10 @@ class ModuleTemplates extends HTML // Creation of list of all components. $blockComponentList = ''; foreach ($blockData as $component) { - $blockComponentList .= $component['component_id'].'-'; + $blockComponentList .= $component['component_id'].','; } - $blockComponentList = chop($blockComponentList, '-'); + $blockComponentList = chop($blockComponentList, ','); // Title of Block. $blockTitle = '
      '; $blockTitle .= $blockTable['name']; @@ -1055,7 +1068,7 @@ class ModuleTemplates extends HTML ] ); - if ($createNewBlock === false) { + if ($createNewTemplate === false) { echo ''; echo ''; } @@ -1077,44 +1090,18 @@ class ModuleTemplates extends HTML ?> + Date: Mon, 6 Apr 2020 11:04:53 +0200 Subject: [PATCH 070/111] Minor fixes, group and review while exceeded license --- pandora_console/godmode/wizards/HostDevices.class.php | 7 ++++++- pandora_server/lib/PandoraFMS/DiscoveryServer.pm | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php index 22ff8f5301..4593208547 100755 --- a/pandora_console/godmode/wizards/HostDevices.class.php +++ b/pandora_console/godmode/wizards/HostDevices.class.php @@ -466,7 +466,7 @@ class HostDevices extends Wizard } $id_network_profile = get_parameter('id_network_profile', []); - $review_results = get_parameter_switch('review_results'); + $review_results = get_parameter_switch('review_results', -1); $auto_monitor = get_parameter_switch('auto_monitor'); $autoconf_enabled = get_parameter_switch( 'autoconfiguration_enabled' @@ -504,6 +504,11 @@ class HostDevices extends Wizard ); } + if ($review_results < 0) { + // License limited, force review. + $this->task['review_mode'] = DISCOVERY_REVIEW; + } + if ($review_results) { if ($this->task['review_mode'] != DISCOVERY_RESULTS) { $this->task['review_mode'] = DISCOVERY_REVIEW; diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index d2e47fba59..bacda962d4 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -1016,7 +1016,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($;$) { # Agent creation. $agent_id = pandora_create_agent( $self->{'pa_config'}, $self->{'servername'}, $data->{'agent'}{'nombre'}, - $data->{'agent'}{'direccion'}, $self->{'task_data'}{'group_id'}, $parent_id, + $data->{'agent'}{'direccion'}, $self->{'task_data'}{'id_group'}, $parent_id, $os_id, $data->{'agent'}->{'description'}, $data->{'agent'}{'interval'}, $self->{'dbh'}, $data->{'agent'}{'timezone_offset'} From a93812d1a808cda0bfcc8fe3e4a5b578261c3860 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 6 Apr 2020 11:58:42 +0200 Subject: [PATCH 071/111] Solved issues in ModuleTemplates class --- .../include/class/ModuleTemplates.class.php | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php index 05fdaadd09..32bda687d3 100644 --- a/pandora_console/include/class/ModuleTemplates.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -337,8 +337,10 @@ class ModuleTemplates extends HTML $success = false; } else { db_process_sql_delete('tnetwork_profile_pen', ['id_np' => $this->id_np]); - $pensList = explode(',', $this->pen); - if (count($pensList) > 0) { + if (empty($this->pen)) { + $success = true; + } else { + $pensList = explode(',', $this->pen); // Set again the new PENs associated. foreach ($pensList as $currentPen) { $dbResult_pen = db_process_sql_insert( @@ -355,8 +357,6 @@ class ModuleTemplates extends HTML $success = true; } - } else { - $success = true; } } @@ -379,22 +379,26 @@ class ModuleTemplates extends HTML if ($dbResult_tnp != false) { // Set the new id_np. $this->id_np = $dbResult_tnp; - $pensList = explode(',', $this->pen); - // Insert all of new PENs associated with this id_np. - foreach ($pensList as $currentPen) { - $dbResult_pen = db_process_sql_insert( - 'tnetwork_profile_pen', - [ - 'pen' => $currentPen, - 'id_np' => $this->id_np, - ] - ); - // If something is wrong, is better stop. - if ($dbResult_pen === false) { - break; - } - + if (empty($this->pen)) { $success = true; + } else { + $pensList = explode(',', $this->pen); + // Insert all of new PENs associated with this id_np. + foreach ($pensList as $currentPen) { + $dbResult_pen = db_process_sql_insert( + 'tnetwork_profile_pen', + [ + 'pen' => $currentPen, + 'id_np' => $this->id_np, + ] + ); + // If something is wrong, is better stop. + if ($dbResult_pen === false) { + break; + } + + $success = true; + } } } @@ -527,8 +531,7 @@ class ModuleTemplates extends HTML // 2 arrays. 1 with the groups, 1 with the groups by parent $groups = []; $groups_compound = []; - // Default group filter. - $groups_compound[0] = 'Group - All'; + foreach ($result as $row) { $groups[$row['id_sg']] = $row['name']; } @@ -612,7 +615,7 @@ class ModuleTemplates extends HTML 'script' => 'filterGroupComponents(event);', 'class' => 'float-right', 'fields' => $groups_compound, - 'nothing' => $groups_compound[$this->ncGroup], + 'nothing' => 'Group - All', 'return' => true, ], ]; From 5205e0e06f78a42909f8b38bb6f8e08f3fe0f498 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 6 Apr 2020 12:05:03 +0200 Subject: [PATCH 072/111] minor update --- .../wizards/DiscoveryTaskList.class.php | 91 +++++++++++++++---- .../lib/PandoraFMS/DiscoveryServer.pm | 2 +- 2 files changed, 72 insertions(+), 21 deletions(-) diff --git a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php index 3b3f6dcf36..434c79fbc4 100644 --- a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php +++ b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php @@ -1033,32 +1033,83 @@ class DiscoveryTaskList extends HTML $table->rowid = []; $table->data = []; - // Content. - $table->data[$i][0] = ''.__('Hosts discovered').''; - $table->data[$i][1] = ''; - $table->data[$i][1] .= $task['stats']['summary']['discovered']; - $table->data[$i++][1] .= ''; + if ($task['review_mode'] == DISCOVERY_RESULTS) { + $agents_review = db_get_all_rows_filter( + 'tdiscovery_tmp_agents', + ['id_rt' => $task['id_rt']] + ); - $table->data[$i][0] = ''.__('Alive').''; - $table->data[$i][1] = ''; - $table->data[$i][1] .= $task['stats']['summary']['alive']; - $table->data[$i++][1] .= ''; + $agents = 0; + $total = 0; + if (is_array($agents_review)) { + foreach ($agents_review as $agent) { + $data = json_decode(base64_decode($agent['data']), true); - $table->data[$i][0] = ''.__('Not alive').''; - $table->data[$i][1] = ''; - $table->data[$i][1] .= $task['stats']['summary']['not_alive']; - $table->data[$i++][1] .= ''; + if (is_array($data) === false) { + continue; + } - if ($task['type'] == DISCOVERY_HOSTDEVICES) { - $table->data[$i][0] = ''.__('Responding SNMP').''; - $table->data[$i][1] = ''; - $table->data[$i][1] .= $task['stats']['summary']['SNMP']; + if (is_array($data['agent']) === false) { + continue; + } + + // Ensure agent_id really exists. + $agent_id = agents_get_agent_id( + $data['agent']['nombre'], + true + ); + + if ($agent_id > 0) { + $agents++; + } + + $total++; + } + } + + // Content. + $table->data[$i][0] = ''.__('Host&devices total').''; + $table->data[$i][1] = ''; + $table->data[$i][1] .= $total; $table->data[$i++][1] .= ''; - $table->data[$i][0] = ''.__('Responding WMI').''; - $table->data[$i][1] = ''; - $table->data[$i][1] .= $task['stats']['summary']['WMI']; + $table->data[$i][0] = ''.__('Agents monitored').''; + $table->data[$i][1] = ''; + $table->data[$i][1] .= $agents; $table->data[$i++][1] .= ''; + + $table->data[$i][0] = ''.__('Agents pending').''; + $table->data[$i][1] = ''; + $table->data[$i][1] .= ($total - $agents); + $table->data[$i++][1] .= ''; + } else { + // Content. + $table->data[$i][0] = ''.__('Hosts discovered').''; + $table->data[$i][1] = ''; + $table->data[$i][1] .= $task['stats']['summary']['discovered']; + $table->data[$i++][1] .= ''; + + $table->data[$i][0] = ''.__('Alive').''; + $table->data[$i][1] = ''; + $table->data[$i][1] .= $task['stats']['summary']['alive']; + $table->data[$i++][1] .= ''; + + $table->data[$i][0] = ''.__('Not alive').''; + $table->data[$i][1] = ''; + $table->data[$i][1] .= $task['stats']['summary']['not_alive']; + $table->data[$i++][1] .= ''; + + if ($task['type'] == DISCOVERY_HOSTDEVICES) { + $table->data[$i][0] = ''.__('Responding SNMP').''; + $table->data[$i][1] = ''; + $table->data[$i][1] .= $task['stats']['summary']['SNMP']; + $table->data[$i++][1] .= ''; + + $table->data[$i][0] = ''.__('Responding WMI').''; + $table->data[$i][1] = ''; + $table->data[$i][1] .= $task['stats']['summary']['WMI']; + $table->data[$i++][1] .= ''; + } } $output = '
      '.__('Summary').'
      '; diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index bacda962d4..ad71eb829f 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -1595,7 +1595,7 @@ sub PandoraFMS::Recon::Base::update_progress ($$) { my $stats = {}; if (defined($self->{'summary'}) && $self->{'summary'} ne '') { - $stats->{'summary'} = $self->{'summary'}; + $stats->{'summary'} = $self->{'task_data'}{'summary'}; } $stats->{'step'} = $self->{'step'}; $stats->{'c_network_name'} = $self->{'c_network_name'}; From fc2ea5aabf9d2d48b3b5cb6d17cbff2b47fae85b Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 6 Apr 2020 12:14:57 +0200 Subject: [PATCH 073/111] Solved issue with CSV Export --- .../include/class/ModuleTemplates.class.php | 113 +++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php index 32bda687d3..7bc4ac65bf 100644 --- a/pandora_console/include/class/ModuleTemplates.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -422,6 +422,117 @@ class ModuleTemplates extends HTML $this->id_np = -1; break; + case 'Export': + global $config; + + $id_network_profile = safe_int($this->id_np); + if (empty($id_network_profile)) { + return false; + } + + $filter['id_np'] = $id_network_profile; + + $profile_info = @db_get_row_filter('tnetwork_profile', $filter, false); + + if (empty($profile_info)) { + $success = false; + // ui_print_error_message(__('This template does not exist')); + return; + } + + // It's important to keep the structure and order in the same way for backwards compatibility. + switch ($config['dbtype']) { + case 'mysql': + $sql = sprintf( + ' + SELECT components.name, components.description, components.type, components.max, components.min, components.module_interval, + components.tcp_port, components.tcp_send, components.tcp_rcv, components.snmp_community, components.snmp_oid, + components.id_module_group, components.id_modulo, components.plugin_user, components.plugin_pass, components.plugin_parameter, + components.max_timeout, components.max_retries, components.history_data, components.min_warning, components.max_warning, components.str_warning, components.min_critical, + components.max_critical, components.str_critical, components.min_ff_event, components.dynamic_interval, components.dynamic_max, components.dynamic_min, components.dynamic_two_tailed, comp_group.name AS group_name, components.critical_instructions, components.warning_instructions, components.unknown_instructions + FROM `tnetwork_component` AS components, tnetwork_profile_component AS tpc, tnetwork_component_group AS comp_group + WHERE tpc.id_nc = components.id_nc + AND components.id_group = comp_group.id_sg + AND tpc.id_np = %d', + $this->id_np + ); + break; + + case 'postgresql': + $sql = sprintf( + ' + SELECT components.name, components.description, components.type, components.max, components.min, components.module_interval, + components.tcp_port, components.tcp_send, components.tcp_rcv, components.snmp_community, components.snmp_oid, + components.id_module_group, components.id_modulo, components.plugin_user, components.plugin_pass, components.plugin_parameter, + components.max_timeout, components.max_retries, components.history_data, components.min_warning, components.max_warning, components.str_warning, components.min_critical, + components.max_critical, components.str_critical, components.min_ff_event, comp_group.name AS group_name, components.critical_instructions, components.warning_instructions, components.unknown_instructions + FROM "tnetwork_component" AS components, tnetwork_profile_component AS tpc, tnetwork_component_group AS comp_group + WHERE tpc.id_nc = components.id_nc + AND components.id_group = comp_group.id_sg + AND tpc.id_np = %d', + $this->id_np + ); + break; + + case 'oracle': + $sql = sprintf( + ' + SELECT components.name, components.description, components.type, components.max, components.min, components.module_interval, + components.tcp_port, components.tcp_send, components.tcp_rcv, components.snmp_community, components.snmp_oid, + components.id_module_group, components.id_modulo, components.plugin_user, components.plugin_pass, components.plugin_parameter, + components.max_timeout, components.max_retries, components.history_data, components.min_warning, components.max_warning, components.str_warning, components.min_critical, + components.max_critical, components.str_critical, components.min_ff_event, comp_group.name AS group_name, components.critical_instructions, components.warning_instructions, components.unknown_instructions + FROM tnetwork_component AS components, tnetwork_profile_component AS tpc, tnetwork_component_group AS comp_group + WHERE tpc.id_nc = components.id_nc + AND components.id_group = comp_group.id_sg + AND tpc.id_np = %d', + $this->id_np + ); + break; + } + + $components = db_get_all_rows_sql($sql); + + $row_names = []; + $inv_names = []; + // Find the names of the rows that we are getting and throw away the duplicate numeric keys + foreach ($components[0] as $row_name => $detail) { + if (is_numeric($row_name)) { + $inv_names[] = $row_name; + } else { + $row_names[] = $row_name; + } + } + + // Send headers to tell the browser we're sending a file + header('Content-type: application/octet-stream'); + header('Content-Disposition: attachment; filename='.preg_replace('/\s/', '_', $profile_info['name']).'.csv'); + header('Pragma: no-cache'); + header('Expires: 0'); + + // Clean up output buffering + while (@ob_end_clean()) { + } + + // Then print the first line (row names) + echo '"'.implode('","', $row_names).'"'; + echo "\n"; + + // Then print the rest of the data. Encapsulate in quotes in case we have comma's in any of the descriptions + foreach ($components as $row) { + foreach ($inv_names as $bad_key) { + unset($row[$bad_key]); + } + + echo '"'.implode('","', $row).'"'; + echo "\n"; + } + + // We're done here. The original page will still be there + exit; + + break; + default: // There is possible want do an action detailed. $action_detailed = explode('_', $this->action); @@ -752,7 +863,7 @@ class ModuleTemplates extends HTML ['title' => 'Export to CSV'] ); $data[3] = ''.html_print_image('images/cross.png', true, ['title' => __('Delete')]).''; - $data[3] .= ''.html_print_image('images/csv.png', true, ['title' => __('Export to CSV')]).''; + $data[3] .= ''.html_print_image('images/csv.png', true, ['title' => __('Export to CSV')]).''; array_push($table->data, $data); } From 3f9bdf65df137a4d503e4dac742b35e9976da414 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 6 Apr 2020 13:00:09 +0200 Subject: [PATCH 074/111] minor fixes and target selection (buttons) --- .../godmode/wizards/DiscoveryTaskList.class.php | 4 ++-- pandora_console/include/styles/task_list.css | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php index 434c79fbc4..f41eada844 100644 --- a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php +++ b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php @@ -1295,10 +1295,10 @@ class DiscoveryTaskList extends HTML echo ''; echo __('Please select devices to be monitored'); echo '
      '; - echo ''; - echo ''; echo ''; echo '
      '; echo '
      '; - echo '
      '; echo '
      '; echo parent::printTree( @@ -1317,6 +1337,12 @@ class DiscoveryTaskList extends HTML $simple_data ); echo '
      '; + } else { + echo '
      '; + echo ''; + echo __('No devices found in temporary resources, please re-launch.'); + echo ''; + echo '
      '; } } diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php index 2737a959a1..9ed11dd29c 100755 --- a/pandora_console/godmode/wizards/HostDevices.class.php +++ b/pandora_console/godmode/wizards/HostDevices.class.php @@ -308,7 +308,18 @@ class HostDevices extends Wizard $interval = get_parameter('interval', 0); if ($network_csv_enabled) { - if ($_FILES['network_csv']['type'] != 'text/csv') { + if ($_FILES['network_csv']['type'] != 'text/csv' + && $_FILES['network_csv']['type'] != 'text/plain' + && $_FILES['network_csv']['type'] != 'application/octet-stream' + && $_FILES['network_csv']['type'] != 'application/vnd.ms-excel' + && $_FILES['network_csv']['type'] != 'text/x-csv' + && $_FILES['network_csv']['type'] != 'application/csv' + && $_FILES['network_csv']['type'] != 'application/x-csv' + && $_FILES['network_csv']['type'] != 'text/csv' + && $_FILES['network_csv']['type'] != 'text/comma-separated-values' + && $_FILES['network_csv']['type'] != 'text/x-comma-separated-values' + && $_FILES['network_csv']['type'] != 'text/tab-separated-values' + ) { $this->msg = __( 'Invalid mimetype for csv file: %s', $_FILES['network_csv']['type'] @@ -1057,6 +1068,7 @@ class HostDevices extends Wizard 'nothing_value' => 0, 'nothing' => __('None'), 'multiple' => true, + 'class' => 'select_multiple', ], ]; diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php index 6ee12bea9d..0fdb98267d 100644 --- a/pandora_console/include/functions_html.php +++ b/pandora_console/include/functions_html.php @@ -722,6 +722,7 @@ function html_print_select( * @param string $style The string of style. * @param mixed $size Max elements showed in select or default (size=10) * @param integer $truncante_size Truncate size of the element, by default is set to GENERIC_SIZE_TEXT constant + * @param integer $class Class to apply. * * @return string HTML code if return parameter is true. */ @@ -738,7 +739,8 @@ function html_print_select_from_sql( $disabled=false, $style=false, $size=false, - $trucate_size=GENERIC_SIZE_TEXT + $trucate_size=GENERIC_SIZE_TEXT, + $class='' ) { global $config; @@ -770,7 +772,7 @@ function html_print_select_from_sql( $return, $multiple, $sort, - '', + $class, $disabled, $style, '', @@ -3589,7 +3591,8 @@ function html_print_input($data, $wrapper='div', $input_only=false) ((isset($data['disabled']) === true) ? $data['disabled'] : false), ((isset($data['style']) === true) ? $data['style'] : false), ((isset($data['size']) === true) ? $data['size'] : false), - ((isset($data['trucate_size']) === true) ? $data['trucate_size'] : GENERIC_SIZE_TEXT) + ((isset($data['trucate_size']) === true) ? $data['trucate_size'] : GENERIC_SIZE_TEXT), + ((isset($data['class']) === true) ? $data['class'] : '') ); break; diff --git a/pandora_console/include/styles/hostdevices.css b/pandora_console/include/styles/hostdevices.css index ebd13988d5..e378e24d97 100644 --- a/pandora_console/include/styles/hostdevices.css +++ b/pandora_console/include/styles/hostdevices.css @@ -2,6 +2,13 @@ * TODO: This may be at hostdevices.css */ -#id_network_profile { - width: 300px; +select.select_multiple { + min-width: 500px; + width: 50%; + height: 250px; +} + +.indented select.select_multiple { + min-width: calc(500px - 1em); + width: calc(50% - 1em); } diff --git a/pandora_console/include/styles/wizard.css b/pandora_console/include/styles/wizard.css index 0609010dfb..7976971d74 100644 --- a/pandora_console/include/styles/wizard.css +++ b/pandora_console/include/styles/wizard.css @@ -32,7 +32,7 @@ ul.wizard li > textarea { } .wizard .indented { - margin-left: 2em; + margin-left: 1em; } .wizard .std_input { diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index e32911bb53..83b842eee3 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -822,7 +822,7 @@ CREATE TABLE `tdiscovery_tmp_agents` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `id_rt` int(10) unsigned NOT NULL, `label` varchar(600) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', - `data` text, + `data` MEDIUMTEXT, `review_date` datetime DEFAULT NULL, `created` datetime DEFAULT NULL, PRIMARY KEY (`id`), diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index cee5efe451..73211f1aff 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -497,19 +497,32 @@ sub PandoraFMS::Recon::Base::test_module($$) { } elsif (($test->{'id_tipo_modulo'} >= 1 && $test->{'id_tipo_modulo'} <= 5) || ($test->{'id_tipo_modulo'} >= 21 && $test->{'id_tipo_modulo'} <= 23) - && is_enabled($test->{'id_plugin'}) ) { # Generic, plugins. (21-23 ASYNC) - # XXX TODO: Test plugins. - return 1; + if ($test->{'id_modulo'} == 6) { + # WMI commands. + $value = $self->call( + 'wmi_get_value', + $test->{'ip_target'}, + # WMI query. + $test->{'snmp_oid'}, + # Column + $test->{'tcp_port'} + ); + } elsif(is_enabled($test->{'id_plugin'})) { + # XXX TODO: Test plugins. How to identify arguments? and values? + # Disabled until we can ensure result. + return 0; + } } elsif ($test->{'id_tipo_modulo'} >= 34 && $test->{'id_tipo_modulo'} <= 37) { # Remote command. # XXX TODO: Test remote commands. - return 1; + # Disabled until we can ensure result. + return 0; + } elsif ($test->{'id_tipo_modulo'} >= 8 && $test->{'id_tipo_modulo'} <= 11) { # TCP - return 0 unless is_numeric($test->{'tcp_port'}) && $test->{'tcp_port'} > 0 && $test->{'tcp_port'} <= 65535; diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 9130fccb6a..21418c32e0 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -2175,7 +2175,7 @@ sub wmi_credentials_calculation { my ($self, $target) = @_; # Test empty credentials. - my @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -N //$target "SELECT * FROM Win32_ComputerSystem" 2>&1`; + my @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -N //$target "SELECT * FROM Win32_ComputerSystem" 2>$DEVNULL`; my $rs = $self->wmi_output_check($?, @output); if ($rs == WMI_OK) { @@ -2198,7 +2198,7 @@ sub wmi_credentials_calculation { my $auth = $cred->{'username'}.'%'.$cred->{'password'}; next if $auth eq '%'; - @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -U $auth //$target "SELECT * FROM Win32_ComputerSystem" 2>&1`; + @output = `$self->{'timeout_cmd'}$self->{'wmi_client'} -U $auth //$target "SELECT * FROM Win32_ComputerSystem" 2>$DEVNULL`; my $rs = $self->wmi_output_check($?, @output); @@ -2288,11 +2288,13 @@ sub wmi_get { sub wmi_get_command { my ($self, $target, $auth, $query) = @_; + return () if is_empty($target); + my @output; if (defined($auth) && $auth ne '') { - @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -U $auth //$target "$query" 2>&1`; + @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -U $auth //$target "$query" 2>$DEVNULL`; }else { - @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -N //$target "$query" 2>&1`; + @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -N //$target "$query" 2>$DEVNULL`; } my $rs = $self->wmi_output_check($?, @output); @@ -2301,9 +2303,12 @@ sub wmi_get_command { return @output; } + my $err = $self->{'last_wmi_error'}; + $err = 'Not OK, empty error' if is_empty($err); + $self->call( 'message', - "[".$target."] WMI error: ".$self->{'last_wmi_error'}, + "[".$target."] WMI error: ".$err, 10 ); From f88dceb4ec1a4c534c8bdc3fa5cb4b3b0fcdca1f Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Tue, 7 Apr 2020 19:03:10 +0200 Subject: [PATCH 089/111] Some missing functions --- pandora_server/lib/PandoraFMS/DiscoveryServer.pm | 3 +++ pandora_server/lib/PandoraFMS/Tools.pm | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index 73211f1aff..4944e03ab5 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -1330,6 +1330,9 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($;$) { $notification->{'subject'} = safe_input('Discovery task '); $notification->{'subject'} .= $self->{'task_data'}{'name'}; $notification->{'subject'} .= safe_input(' review pending'); + $notification->{'url'} = ui_get_full_url( + 'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=tasklist#' + ); $notification->{'mensaje'} = safe_input( 'Discovery task (host&devices) \''.safe_output($self->{'task_data'}{'name'}) diff --git a/pandora_server/lib/PandoraFMS/Tools.pm b/pandora_server/lib/PandoraFMS/Tools.pm index 76aaefc344..10f57b1e15 100755 --- a/pandora_server/lib/PandoraFMS/Tools.pm +++ b/pandora_server/lib/PandoraFMS/Tools.pm @@ -151,6 +151,7 @@ our @EXPORT = qw( get_enabled_servers dateTimeToTimestamp get_user_agent + ui_get_full_url ); # ID of the different servers @@ -2333,12 +2334,24 @@ sub get_user_agent { return $ua; } +################################################################################ +# Returns 'valid' url relative to current pandora_console installation. +################################################################################ +sub ui_get_full_url { + my ($pa_config, $url) = @_; + if (is_empty($pa_config->{'console_api_url'})) { + # Do not relativize if console_api_url is empty. + return $url; + } + my $console_url = $pa_config->{'console_api_url'}; + $console_url =~ s/include\/api.php$//; + return $console_url.$url; - +} 1; __END__ From 56e9275b1a63417bac2bfc46dea928804610a712 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Tue, 7 Apr 2020 19:10:37 +0200 Subject: [PATCH 090/111] minor fix --- pandora_console/godmode/wizards/DiscoveryTaskList.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php index 033395510c..bed5969f07 100644 --- a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php +++ b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php @@ -1256,6 +1256,7 @@ class DiscoveryTaskList extends HTML if ($agent_id > 0) { $tmp['disabled'] = 1; $tmp['agent_id'] = $agent_id; + $tmp['checked'] = 1; } // Store. From 47857de79f020aab16225fbbd3f426b8490d81a5 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Wed, 8 Apr 2020 11:48:31 +0200 Subject: [PATCH 091/111] some css adjustments --- .../godmode/wizards/HostDevices.class.php | 19 ++++++++++++------- pandora_console/include/styles/discovery.css | 1 + 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php index 9ed11dd29c..78f29ef67a 100755 --- a/pandora_console/godmode/wizards/HostDevices.class.php +++ b/pandora_console/godmode/wizards/HostDevices.class.php @@ -681,10 +681,21 @@ class HostDevices extends Wizard } if ($this->page < $this->maxPagesNetScan) { + $title = __('NetScan'); + + if ($this->page == 1) { + $title = __( + '"%s" features', + io_safe_output( + $this->task['name'] + ) + ); + } + // Avoid to print header out of wizard. $this->prepareBreadcrum($breadcrum); ui_print_page_header( - __('NetScan'), + $title, '', false, '', @@ -1023,12 +1034,6 @@ class HostDevices extends Wizard ], ]; - $form['inputs'][] = [ - 'extra' => '

      Please, customize task '.io_safe_output( - $this->task['name'] - ).'

      ', - ]; - $form['inputs'][] = [ 'label' => __('Auto discover known hardware').ui_print_help_tip( __( diff --git a/pandora_console/include/styles/discovery.css b/pandora_console/include/styles/discovery.css index fc5749b4a8..158a75a009 100644 --- a/pandora_console/include/styles/discovery.css +++ b/pandora_console/include/styles/discovery.css @@ -169,6 +169,7 @@ span.breadcrumb_link { form.discovery * { font-size: 10pt; + font-family: "lato", "Open Sans", sans-serif; } form.discovery .label_select b { From 725e7d9c165da16a22f6df870d65aec4e0ded46f Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Wed, 8 Apr 2020 12:17:22 +0200 Subject: [PATCH 092/111] Solved issue with wrong position in filter --- pandora_console/include/class/ModuleTemplates.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php index cea3593a0f..576dcec628 100644 --- a/pandora_console/include/class/ModuleTemplates.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -694,7 +694,7 @@ class ModuleTemplates extends HTML 'input_class' => 'flex-row', 'name' => 'filter', 'type' => 'text', - 'size' => '45', + 'size' => '40', 'class' => 'float-right', 'onKeyDown' => 'filterTextComponents(event);', 'value' => '', From 95d7a5d267e0828f86b8081e28e2a93aa5019aa3 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Wed, 8 Apr 2020 12:26:01 +0200 Subject: [PATCH 093/111] minor fix --- .../godmode/wizards/HostDevices.class.php | 90 ++++++++++--------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php index 78f29ef67a..3ccdb91d9d 100755 --- a/pandora_console/godmode/wizards/HostDevices.class.php +++ b/pandora_console/godmode/wizards/HostDevices.class.php @@ -308,51 +308,53 @@ class HostDevices extends Wizard $interval = get_parameter('interval', 0); if ($network_csv_enabled) { - if ($_FILES['network_csv']['type'] != 'text/csv' - && $_FILES['network_csv']['type'] != 'text/plain' - && $_FILES['network_csv']['type'] != 'application/octet-stream' - && $_FILES['network_csv']['type'] != 'application/vnd.ms-excel' - && $_FILES['network_csv']['type'] != 'text/x-csv' - && $_FILES['network_csv']['type'] != 'application/csv' - && $_FILES['network_csv']['type'] != 'application/x-csv' - && $_FILES['network_csv']['type'] != 'text/csv' - && $_FILES['network_csv']['type'] != 'text/comma-separated-values' - && $_FILES['network_csv']['type'] != 'text/x-comma-separated-values' - && $_FILES['network_csv']['type'] != 'text/tab-separated-values' - ) { - $this->msg = __( - 'Invalid mimetype for csv file: %s', - $_FILES['network_csv']['type'] - ); - return false; - } - - $network = preg_split( - "/\n|,|;/", - trim( - file_get_contents( - $_FILES['network_csv']['tmp_name'] - ) - ) - ); - unlink($_FILES['network_csv']['tmp_name']); - if (empty($network) || is_array($network) === false) { - $this->msg = __( - 'Invalid content readed from csv file: %s', - $_FILES['network_csv']['name'] - ); - return false; - } - - // Sanitize. - $network = array_unique($network); - $network = array_filter( - $network, - function ($item) { - return (!empty($item)); + if (isset($_FILES['network_csv']['type'])) { + if ($_FILES['network_csv']['type'] != 'text/csv' + && $_FILES['network_csv']['type'] != 'text/plain' + && $_FILES['network_csv']['type'] != 'application/octet-stream' + && $_FILES['network_csv']['type'] != 'application/vnd.ms-excel' + && $_FILES['network_csv']['type'] != 'text/x-csv' + && $_FILES['network_csv']['type'] != 'application/csv' + && $_FILES['network_csv']['type'] != 'application/x-csv' + && $_FILES['network_csv']['type'] != 'text/csv' + && $_FILES['network_csv']['type'] != 'text/comma-separated-values' + && $_FILES['network_csv']['type'] != 'text/x-comma-separated-values' + && $_FILES['network_csv']['type'] != 'text/tab-separated-values' + ) { + $this->msg = __( + 'Invalid mimetype for csv file: %s', + $_FILES['network_csv']['type'] + ); + return false; } - ); - $network = join(',', $network); + + $network = preg_split( + "/\n|,|;/", + trim( + file_get_contents( + $_FILES['network_csv']['tmp_name'] + ) + ) + ); + unlink($_FILES['network_csv']['tmp_name']); + if (empty($network) || is_array($network) === false) { + $this->msg = __( + 'Invalid content readed from csv file: %s', + $_FILES['network_csv']['name'] + ); + return false; + } + + // Sanitize. + $network = array_unique($network); + $network = array_filter( + $network, + function ($item) { + return (!empty($item)); + } + ); + $network = join(',', $network); + } } if (isset($task_id) === true) { From 748582509a299faccceca94b1905739007c5790c Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Wed, 8 Apr 2020 12:29:44 +0200 Subject: [PATCH 094/111] avoid process csv while updating task with no csv changes --- pandora_console/godmode/wizards/HostDevices.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php index 3ccdb91d9d..5f6f0c7dba 100755 --- a/pandora_console/godmode/wizards/HostDevices.class.php +++ b/pandora_console/godmode/wizards/HostDevices.class.php @@ -308,7 +308,7 @@ class HostDevices extends Wizard $interval = get_parameter('interval', 0); if ($network_csv_enabled) { - if (isset($_FILES['network_csv']['type'])) { + if (empty($_FILES['network_csv']['type']) === false) { if ($_FILES['network_csv']['type'] != 'text/csv' && $_FILES['network_csv']['type'] != 'text/plain' && $_FILES['network_csv']['type'] != 'application/octet-stream' From bb11403c4bd93fddb678d2c22da6662710a455ac Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Wed, 8 Apr 2020 13:01:11 +0200 Subject: [PATCH 095/111] Fixes - default module --- pandora_server/lib/PandoraFMS/DiscoveryServer.pm | 8 +++++++- pandora_server/lib/PandoraFMS/Recon/Base.pm | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index 4944e03ab5..3d36bcfbaa 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -469,7 +469,13 @@ sub PandoraFMS::Recon::Base::test_module($$) { $test->{'id_tipo_modulo'} = $module->{'type'}; } else { # Module. - $test->{'id_tipo_modulo'} = $module->{'id_modulo'}; + if (!defined($self->{'module_types'}{$module->{'type'}})) { + $self->{'module_types'}{$module->{'type'}} = get_module_id( + $self->{'dbh'},$module->{'type'} + ); + } + + $test->{'id_tipo_modulo'} = $self->{'module_types'}{$module->{'type'}}; } my $value; diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 21418c32e0..20a31da76b 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -1475,6 +1475,12 @@ sub scan_subnet($) { $self->call('update_progress', ceil($progress)); $total_hosts = scalar keys %hosts_alive; + if ($total_hosts == 0) { + # Populate. + $self->{'c_network_percent'} += 50; + $self->call('update_progress', ceil($progress)+25); + next; + } $step = 25.0 / scalar(@subnets) / $total_hosts; $subnet_step = 50.0 / $total_hosts; From 8a0215dcc9d8a34ba55e332b827a8f3db2257fe3 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Wed, 8 Apr 2020 14:14:03 +0200 Subject: [PATCH 096/111] minor fixes --- pandora_server/lib/PandoraFMS/Core.pm | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index f05785755d..213efdf070 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -1648,6 +1648,17 @@ sub pandora_process_module ($$$$$$$$$;$) { "' for agent " . (defined ($agent) && $agent ne '' ? "'" . safe_output($agent->{'nombre'}) . "'" : 'ID ' . $module->{'id_agente'}) . ".", 10); + + # Ensure default values. + $module->{'min_ff_event'} = 0 unless defined($module->{'min_ff_event'}); + $module->{'ff_timeout'} = 0 unless defined($module->{'ff_timeout'}); + $module->{'module_interval'} = 0 unless defined($module->{'module_interval'}); + + if (ref($agent) eq 'HASH') { + if (!defined($agent->{'interval'}) && defined($agent->{'interval'})) { + $agent->{'intervalo'} = $agent->{'interval'}; + } + } # Get agent information if (! defined ($agent) || $agent eq '') { From a75964fcbac380a2cbcc201589764fb3db532c15 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Wed, 8 Apr 2020 16:06:39 +0200 Subject: [PATCH 097/111] minor fix --- pandora_console/extras/mr/37.sql | 2 +- .../extras/pandoradb_migrate_6.0_to_7.0.mysql.sql | 2 +- pandora_console/pandoradb.sql | 2 +- pandora_server/lib/PandoraFMS/Recon/Base.pm | 7 +++++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pandora_console/extras/mr/37.sql b/pandora_console/extras/mr/37.sql index 8d29b06a53..40aa379f3a 100644 --- a/pandora_console/extras/mr/37.sql +++ b/pandora_console/extras/mr/37.sql @@ -2,7 +2,7 @@ START TRANSACTION; ALTER TABLE trecon_task MODIFY COLUMN `id_network_profile` TEXT; ALTER TABLE `trecon_task` CHANGE COLUMN `create_incident` `review_mode` TINYINT(1) UNSIGNED DEFAULT 0; -ALTER TABLE `trecon_task` ADD COLUMN `subnet_csv` TINYINT(1) UNSIGNED DEFAULT 0; +ALTER TABLE `trecon_task` ADD COLUMN `subnet_csv` TINYINT(1) UNSIGNED DEFAULT 1; UPDATE `trecon_task` SET `review_mode` = 1; ALTER TABLE trecon_task add column `auto_monitor` TINYINT(1) UNSIGNED DEFAULT 1 AFTER `auth_strings`; diff --git a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql index 6dce97ee8a..c6972632b8 100644 --- a/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql +++ b/pandora_console/extras/pandoradb_migrate_6.0_to_7.0.mysql.sql @@ -1685,7 +1685,7 @@ ALTER TABLE `trecon_task` ADD COLUMN `type` int(11) NOT NULL DEFAULT '0', MODIFY COLUMN `autoconfiguration_enabled` tinyint(1) unsigned NULL DEFAULT '0', MODIFY COLUMN `summary` text NULL, MODIFY COLUMN `id_network_profile` text, - CHANGE COLUMN `create_incident` `review_mode` TINYINT(1) UNSIGNED DEFAULT 0, + CHANGE COLUMN `create_incident` `review_mode` TINYINT(1) UNSIGNED DEFAULT 1, ADD COLUMN `subnet_csv` TINYINT(1) UNSIGNED DEFAULT 0; -- Old recon always report. diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 83b842eee3..a58b0a6320 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -774,7 +774,7 @@ CREATE TABLE IF NOT EXISTS `trecon_task` ( `description` varchar(250) NOT NULL default '', `subnet` text NOT NULL, `id_network_profile` text, - `review_mode` tinyint(1) unsigned NOT NULL default 0, + `review_mode` tinyint(1) unsigned NOT NULL default 1, `id_group` int(10) unsigned NOT NULL default 1, `utimestamp` bigint(20) unsigned NOT NULL default 0, `status` tinyint(4) NOT NULL default 0, diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 20a31da76b..0c89e3060e 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -1341,7 +1341,10 @@ sub prepare_agent($$) { ################################################################################ sub add_agent($$) { my ($self, $addr) = @_; - + + # Avoid create empty agents. + return if is_empty($addr); + $self->prepare_agent($addr); } @@ -2141,7 +2144,7 @@ sub traceroute_connectivity($$) { # Look for parents. my $device = $host; for (my $i = 0; $i < $self->{'parent_recursion'}; $i++) { - next unless defined($hops[$i]); + next if is_empty($hops[$i]); my $parent = $hops[$i]->ipaddr(); # Create an agent for the parent. From 805d96108ca580f44f46960e0033e07bc4edd9a9 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Wed, 8 Apr 2020 16:52:34 +0200 Subject: [PATCH 098/111] Changed position of buttons --- .../include/class/ModuleTemplates.class.php | 18 +++++++++++++----- pandora_console/include/styles/wizard.css | 8 ++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php index 576dcec628..8076deffba 100644 --- a/pandora_console/include/class/ModuleTemplates.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -997,24 +997,25 @@ class ModuleTemplates extends HTML ], ]; - $inputs[] = [ + $availableButtons = []; + + $availableButtons[] = [ 'arguments' => [ 'name' => 'action_button', 'label' => $formButtonLabel, 'type' => 'submit', 'value' => $formButtonValue, - 'attributes' => 'class="'.$formButtonClass.'"', + 'attributes' => 'class="float-right '.$formButtonClass.'"', 'return' => true, ], ]; if ($createNewTemplate === false) { - // Adding components button. - $inputs[] = [ + $availableButtons[] = [ 'arguments' => [ 'name' => 'add_components_button', 'label' => __('Add components'), - 'type' => 'button', + 'type' => 'submit', 'attributes' => 'class="sub cog"', 'script' => 'showAddComponent();', 'return' => true, @@ -1022,6 +1023,13 @@ class ModuleTemplates extends HTML ]; } + $inputs[] = [ + 'class' => 'action_button_list', + 'direct' => false, + 'wrapper' => 'div', + 'block_content' => $availableButtons, + ]; + // Required for PEN field. ui_require_jquery_file('tag-editor'); ui_require_css_file('jquery.tag-editor'); diff --git a/pandora_console/include/styles/wizard.css b/pandora_console/include/styles/wizard.css index 7976971d74..3d66e165ff 100644 --- a/pandora_console/include/styles/wizard.css +++ b/pandora_console/include/styles/wizard.css @@ -116,3 +116,11 @@ ul.wizard li > textarea { width: 33%; text-align: center; } + +.action_button_list { + height: 60px; +} + +.action_button_list li { + display: inline; +} From 3f1e7d2cedf3565513ccfa53e9144a84fdae0f45 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 13 Apr 2020 10:57:32 +0200 Subject: [PATCH 099/111] Solve minor fix --- pandora_console/include/class/ModuleTemplates.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandora_console/include/class/ModuleTemplates.class.php b/pandora_console/include/class/ModuleTemplates.class.php index 8076deffba..585a40aa13 100644 --- a/pandora_console/include/class/ModuleTemplates.class.php +++ b/pandora_console/include/class/ModuleTemplates.class.php @@ -1015,8 +1015,8 @@ class ModuleTemplates extends HTML 'arguments' => [ 'name' => 'add_components_button', 'label' => __('Add components'), - 'type' => 'submit', - 'attributes' => 'class="sub cog"', + 'type' => 'button', + 'attributes' => 'class="float-right sub cog"', 'script' => 'showAddComponent();', 'return' => true, ], From 9c74306e957683ca7e685d70a3468f2664c2cc22 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 13 Apr 2020 14:11:43 +0200 Subject: [PATCH 100/111] minor change --- pandora_server/lib/PandoraFMS/DiscoveryServer.pm | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index 3d36bcfbaa..ba09f41162 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -469,13 +469,17 @@ sub PandoraFMS::Recon::Base::test_module($$) { $test->{'id_tipo_modulo'} = $module->{'type'}; } else { # Module. - if (!defined($self->{'module_types'}{$module->{'type'}})) { - $self->{'module_types'}{$module->{'type'}} = get_module_id( - $self->{'dbh'},$module->{'type'} - ); - } + $module->{'type'} = $module->{'module_type'} if is_empty($module->{'type'}); - $test->{'id_tipo_modulo'} = $self->{'module_types'}{$module->{'type'}}; + if (defined($module->{'type'})) { + if(!defined($self->{'module_types'}{$module->{'type'}})) { + $self->{'module_types'}{$module->{'type'}} = get_module_id( + $self->{'dbh'},$module->{'type'} + ); + } + + $test->{'id_tipo_modulo'} = $self->{'module_types'}{$module->{'type'}}; + } } my $value; From 73954108316663f9a325bbc12c70775f0fff1f52 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 13 Apr 2020 15:04:03 +0200 Subject: [PATCH 101/111] fix parent-connection --- pandora_server/lib/PandoraFMS/DiscoveryServer.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index ba09f41162..e2c62d1711 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -1221,7 +1221,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($;$) { # Update parent relationships. foreach my $agent (@agents) { # Avoid processing if does not exist. - next unless (defined($agent->{'agent_id'})); + next unless (defined($agent->{'agent'}{'agent_id'})); # Avoid processing undefined parents. next unless defined($agent->{'parent'}); @@ -1234,12 +1234,12 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($;$) { next unless defined($parent); # Is the agent in learning mode? - next unless ($agent->{'modo'} == 1); + next unless ($agent->{'agent'}{'modo'} == 1); # Connect the host to its parent. db_do($self->{'dbh'}, 'UPDATE tagente SET id_parent=? WHERE id_agente=?', - $parent->{'id_agente'}, $agent->{'agent_id'} + $parent->{'id_agente'}, $agent->{'agent'}{'agent_id'} ); } From 189d85d659540ca9d414ff371b023cf668587651 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 13 Apr 2020 15:30:13 +0200 Subject: [PATCH 102/111] minor fix --- pandora_server/lib/PandoraFMS/DiscoveryServer.pm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index e2c62d1711..7a5af26d07 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -1221,7 +1221,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($;$) { # Update parent relationships. foreach my $agent (@agents) { # Avoid processing if does not exist. - next unless (defined($agent->{'agent'}{'agent_id'})); + next unless (defined($agent->{'agent_id'})); # Avoid processing undefined parents. next unless defined($agent->{'parent'}); @@ -1234,12 +1234,12 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($;$) { next unless defined($parent); # Is the agent in learning mode? - next unless ($agent->{'agent'}{'modo'} == 1); + next unless ($agent->{'modo'} == 1); # Connect the host to its parent. db_do($self->{'dbh'}, 'UPDATE tagente SET id_parent=? WHERE id_agente=?', - $parent->{'id_agente'}, $agent->{'agent'}{'agent_id'} + $parent->{'id_agente'}, $agent->{'agent_id'} ); } @@ -1612,7 +1612,7 @@ sub PandoraFMS::Recon::Base::set_parent($$$) { # Do not edit 'not scaned' agents. return if is_empty($self->{'agents_found'}{$host}{'agent'}); - $self->{'agents_found'}{$host}{'parent'} = $parent; + $self->{'agents_found'}{$host}{'agent'}{'parent'} = $parent; } From d19a667ce92f7bd160b828619196b88f950e1725 Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 13 Apr 2020 15:41:00 +0200 Subject: [PATCH 103/111] Added form attribute for inputs --- pandora_console/include/functions_html.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php index 0fdb98267d..5f04e421be 100644 --- a/pandora_console/include/functions_html.php +++ b/pandora_console/include/functions_html.php @@ -1336,6 +1336,7 @@ function html_print_input_text_extended( 'onkeyup', 'required', 'autocomplete', + 'form', ]; $output = ' Date: Mon, 13 Apr 2020 15:41:35 +0200 Subject: [PATCH 104/111] Added invisible class --- pandora_console/include/styles/pandora.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pandora_console/include/styles/pandora.css b/pandora_console/include/styles/pandora.css index 29e53bece5..aa6df2cb0c 100644 --- a/pandora_console/include/styles/pandora.css +++ b/pandora_console/include/styles/pandora.css @@ -628,6 +628,9 @@ select:-internal-list-box { .float-right { float: right; } +.invisible { + display: none; +} div#page { background: #fbfbfb; From f6746ba9d8043c2b715d0b0a3f80b7ff7dfcce82 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 13 Apr 2020 17:16:47 +0200 Subject: [PATCH 105/111] parent calculation --- pandora_server/lib/PandoraFMS/DiscoveryServer.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm index 7a5af26d07..903a9014c3 100644 --- a/pandora_server/lib/PandoraFMS/DiscoveryServer.pm +++ b/pandora_server/lib/PandoraFMS/DiscoveryServer.pm @@ -1220,6 +1220,7 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($;$) { # Update parent relationships. foreach my $agent (@agents) { + # Avoid processing if does not exist. next unless (defined($agent->{'agent_id'})); From cf67dda2ebd5a31e594c46acb23b755bda8d669f Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 13 Apr 2020 17:26:49 +0200 Subject: [PATCH 106/111] prioritize AFT relationships --- pandora_server/lib/PandoraFMS/Recon/Base.pm | 29 +++++++++++---------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 0c89e3060e..e2c57aea34 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -1887,15 +1887,17 @@ sub scan($) { # Delete previous connections. $self->call('delete_connections'); - # Connectivity from address forwarding tables. - $self->call('message', "[2/6] Finding address forwarding table connectivity...", 3); + # Connect hosts that are still unconnected using known gateways. + $self->call('message', "[2/6] Finding host to gateway connectivity.", 3); $self->{'c_network_name'} = ''; - $self->{'step'} = STEP_AFT; - ($progress, $step) = (50, 10.0 / scalar(@hosts)); # From 50% to 60%. - for (my $i = 0; defined($hosts[$i]); $i++) { + $self->{'step'} = STEP_GATEWAY; + ($progress, $step) = (50, 10.0 / scalar(@hosts)); # From 70% to 80%. + $self->get_routes(); # Update the route cache. + foreach my $host (@hosts) { $self->call('update_progress', $progress); $progress += $step; - $self->aft_connectivity($hosts[$i]); + next if ($self->has_parent($host)); + $self->gateway_connectivity($host); } # Connect hosts that are still unconnected using traceroute. @@ -1910,18 +1912,17 @@ sub scan($) { $self->traceroute_connectivity($host); } - # Connect hosts that are still unconnected using known gateways. - $self->call('message', "[4/6] Finding host to gateway connectivity.", 3); + # Connectivity from address forwarding tables. + $self->call('message', "[4/6] Finding address forwarding table connectivity...", 3); $self->{'c_network_name'} = ''; - $self->{'step'} = STEP_GATEWAY; - ($progress, $step) = (70, 10.0 / scalar(@hosts)); # From 70% to 80%. - $self->get_routes(); # Update the route cache. - foreach my $host (@hosts) { + $self->{'step'} = STEP_AFT; + ($progress, $step) = (70, 10.0 / scalar(@hosts)); # From 50% to 60%. + for (my $i = 0; defined($hosts[$i]); $i++) { $self->call('update_progress', $progress); $progress += $step; - next if ($self->has_parent($host)); - $self->gateway_connectivity($host); + $self->aft_connectivity($hosts[$i]); } + } # Apply monitoring templates From 3fd09c9828df747975fe1de57c547d25f1d5b03a Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Mon, 13 Apr 2020 17:30:21 +0200 Subject: [PATCH 107/111] WIP: Reverse develop version for agent_wizard --- .../godmode/agentes/agent_wizard.php | 94 +++---------------- 1 file changed, 12 insertions(+), 82 deletions(-) diff --git a/pandora_console/godmode/agentes/agent_wizard.php b/pandora_console/godmode/agentes/agent_wizard.php index 36236a89bc..c04edf4d66 100644 --- a/pandora_console/godmode/agentes/agent_wizard.php +++ b/pandora_console/godmode/agentes/agent_wizard.php @@ -1,74 +1,5 @@ '[AgentWizard]'.$e->getMessage() ]); - exit; - } else { - echo '[AgentWizard]'.$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(); -} - - -// OLD. FOR ERASE. // Pandora FMS - http://pandorafms.com // ================================================== // Copyright (c) 2005-2011 Artica Soluciones Tecnologicas @@ -80,16 +11,15 @@ if (is_ajax()) { // 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. -/* - global $config; +global $config; - check_login(); +check_login(); - $wizard_section = get_parameter('wizard_section', 'snmp_interfaces_explorer'); - $idAgent = (int) get_parameter('id_agente', 0); - $ipAgent = db_get_value('direccion', 'tagente', 'id_agente', $idAgent); +$wizard_section = get_parameter('wizard_section', 'snmp_interfaces_explorer'); +$idAgent = (int) get_parameter('id_agente', 0); +$ipAgent = db_get_value('direccion', 'tagente', 'id_agente', $idAgent); - switch ($wizard_section) { +switch ($wizard_section) { case 'snmp_interfaces_explorer': $snmp_interfaces_explorer_style = 'font-weight: bold;'; $wmi_explorer_style = ''; @@ -104,9 +34,9 @@ if (is_ajax()) { $snmp_interfaces_explorer_style = ''; $wmi_explorer_style = 'font-weight: bold;'; break; - } +} - /* +/* echo "
      "; echo "" . __('SNMP Interfaces explorer') . ""; echo " | "; @@ -114,10 +44,10 @@ if (is_ajax()) { echo "
      "; */ -// require 'agent_wizard.'.$wizard_section.'.php'; -?> +require 'agent_wizard.'.$wizard_section.'.php'; - \ No newline at end of file + \ No newline at end of file From 1057f76e5efb79a057479c02120ae8207c2fc045 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 13 Apr 2020 17:50:18 +0200 Subject: [PATCH 108/111] undo changes, maintain classic ATF calculation --- pandora_server/lib/PandoraFMS/Recon/Base.pm | 29 ++++++++++----------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index e2c57aea34..0c89e3060e 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -1887,17 +1887,15 @@ sub scan($) { # Delete previous connections. $self->call('delete_connections'); - # Connect hosts that are still unconnected using known gateways. - $self->call('message', "[2/6] Finding host to gateway connectivity.", 3); + # Connectivity from address forwarding tables. + $self->call('message', "[2/6] Finding address forwarding table connectivity...", 3); $self->{'c_network_name'} = ''; - $self->{'step'} = STEP_GATEWAY; - ($progress, $step) = (50, 10.0 / scalar(@hosts)); # From 70% to 80%. - $self->get_routes(); # Update the route cache. - foreach my $host (@hosts) { + $self->{'step'} = STEP_AFT; + ($progress, $step) = (50, 10.0 / scalar(@hosts)); # From 50% to 60%. + for (my $i = 0; defined($hosts[$i]); $i++) { $self->call('update_progress', $progress); $progress += $step; - next if ($self->has_parent($host)); - $self->gateway_connectivity($host); + $self->aft_connectivity($hosts[$i]); } # Connect hosts that are still unconnected using traceroute. @@ -1912,17 +1910,18 @@ sub scan($) { $self->traceroute_connectivity($host); } - # Connectivity from address forwarding tables. - $self->call('message', "[4/6] Finding address forwarding table connectivity...", 3); + # Connect hosts that are still unconnected using known gateways. + $self->call('message', "[4/6] Finding host to gateway connectivity.", 3); $self->{'c_network_name'} = ''; - $self->{'step'} = STEP_AFT; - ($progress, $step) = (70, 10.0 / scalar(@hosts)); # From 50% to 60%. - for (my $i = 0; defined($hosts[$i]); $i++) { + $self->{'step'} = STEP_GATEWAY; + ($progress, $step) = (70, 10.0 / scalar(@hosts)); # From 70% to 80%. + $self->get_routes(); # Update the route cache. + foreach my $host (@hosts) { $self->call('update_progress', $progress); $progress += $step; - $self->aft_connectivity($hosts[$i]); + next if ($self->has_parent($host)); + $self->gateway_connectivity($host); } - } # Apply monitoring templates From 58eeffd04d1b0e2407ec023fdfe65f8fcf9d414e Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 13 Apr 2020 18:28:56 +0200 Subject: [PATCH 109/111] clearer maps --- .../godmode/wizards/DiscoveryTaskList.class.php | 12 +++++++++--- .../operation/agentes/pandora_networkmap.editor.php | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php index bed5969f07..840e25ce26 100644 --- a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php +++ b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php @@ -1201,9 +1201,15 @@ class DiscoveryTaskList extends HTML $map = new NetworkMap( [ - 'id_task' => $id_task, - 'pure' => 1, - 'widget' => true, + 'id_task' => $id_task, + 'pure' => 1, + 'widget' => true, + 'map_options' => [ + 'map_filter' => [ + 'x_offs' => 120, + 'node_sep' => 10, + ], + ], ] ); $map->printMap(); diff --git a/pandora_console/operation/agentes/pandora_networkmap.editor.php b/pandora_console/operation/agentes/pandora_networkmap.editor.php index d719df08cd..16a26257ac 100644 --- a/pandora_console/operation/agentes/pandora_networkmap.editor.php +++ b/pandora_console/operation/agentes/pandora_networkmap.editor.php @@ -57,10 +57,10 @@ if ($new_networkmap) { $offset_x = ''; $offset_y = ''; $scale_z = 0.5; - $node_sep = 0.1; + $node_sep = 10; $rank_sep = 1.0; $mindist = 1.0; - $kval = 0.1; + $kval = 5; } $disabled_generation_method_select = false; From 13a1e44a5e77fcc6b34a5f9503e08b491c0a4c6e Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Mon, 13 Apr 2020 19:34:36 +0200 Subject: [PATCH 110/111] operation icons on small screens --- .../godmode/wizards/DiscoveryTaskList.class.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php index 840e25ce26..73b2626010 100644 --- a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php +++ b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php @@ -386,18 +386,22 @@ class DiscoveryTaskList extends HTML $table->data = []; $table->align = []; $table->headstyle = []; + $table->style = []; + $table->style[4] = 'word-break: break-word;'; for ($i = 0; $i < 9; $i++) { $table->headstyle[$i] = 'text-align: left;'; } + // Name. + $table->headstyle[4] .= 'min-width: 100px; width: 100px;'; // Status. - $table->headstyle[5] .= 'min-width: 100px; width: 100px;'; + $table->headstyle[5] .= 'min-width: 50px; width: 100px;'; // Task type. - $table->headstyle[6] .= 'min-width: 200px; width: 150px;'; + $table->headstyle[6] .= 'min-width: 150px; width: 150px;'; // Progress. - $table->headstyle[7] .= 'min-width: 150px; width: 150px;'; + $table->headstyle[7] .= 'min-width: 50px; width: 150px;'; // Updated at. - $table->headstyle[8] .= 'min-width: 150px; width: 150px;'; + $table->headstyle[8] .= 'min-width: 50px; width: 150px;'; // Operations. $table->headstyle[9] .= 'min-width: 150px; width: 150px;'; From 3b71297d569db6606f2ad5e4d8b3b6b2bad7d857 Mon Sep 17 00:00:00 2001 From: fbsanchez Date: Tue, 14 Apr 2020 11:57:18 +0200 Subject: [PATCH 111/111] escaped single quotes (wmi) + refresh button --- .../godmode/wizards/DiscoveryTaskList.class.php | 10 ++++++++++ pandora_console/include/functions_ui.php | 11 ++++++++++- pandora_server/lib/PandoraFMS/Recon/Base.pm | 3 ++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php index 73b2626010..431cad5a7c 100644 --- a/pandora_console/godmode/wizards/DiscoveryTaskList.class.php +++ b/pandora_console/godmode/wizards/DiscoveryTaskList.class.php @@ -168,6 +168,16 @@ class DiscoveryTaskList extends HTML 'attributes' => 'class="sub cancel"', 'return' => true, ], + ],[ + 'class' => 'action-buttons rule-builder-actions', + 'arguments' => [ + 'name' => 'refresh', + 'label' => __('Refresh'), + 'type' => 'button', + 'attributes' => 'class="sub upd"', + 'return' => true, + 'script' => 'location.reload();', + ], ], ], ]; diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index de05c0f402..0ce95daf78 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -2912,7 +2912,16 @@ function ui_progress( try { val = JSON.parse(data); $("#'.$id.'").attr("data-label", val + " %"); - $("#'.$id.'_progress").width(val+"%"); + $("#'.$id.'_progress").width(val+"%");'; + if (isset($ajax['oncomplete'])) { + $output .= ' + if (val == 100) { + '.$ajax['oncomplete'].'($("#'.$id.'")); + } + '; + } + + $output .= ' } catch (e) { console.error(e); } diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index 0c89e3060e..01f8e824b8 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -2301,7 +2301,8 @@ sub wmi_get_command { my @output; if (defined($auth) && $auth ne '') { - @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -U $auth //$target "$query" 2>$DEVNULL`; + $auth =~ s/'/\'/g; + @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -U '$auth' //$target "$query" 2>$DEVNULL`; }else { @output = `$self->{'timeout_cmd'}"$self->{'wmi_client'}" -N //$target "$query" 2>$DEVNULL`; }