WIP multiple changes

This commit is contained in:
fbsanchez 2020-03-16 23:52:20 +01:00
parent ce11d89953
commit f3da919abc
20 changed files with 1934 additions and 524 deletions

View File

@ -1,5 +1,35 @@
START TRANSACTION; 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; 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;

View File

@ -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 `auth_strings` text NULL,
MODIFY COLUMN `autoconfiguration_enabled` tinyint(1) unsigned NULL DEFAULT '0', 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; 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` -- Table `tdiscovery_tmp`
-- ---------------------------------------------------------------------- -- ----------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `tdiscovery_tmp` ( CREATE TABLE `tdiscovery_tmp_agents` (
`id` int(10) unsigned NOT NULL auto_increment, `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id_rt` int(10) unsigned NOT NULL, `id_rt` int(10) unsigned NOT NULL,
`label` varchar(600) BINARY NOT NULL default '', `label` varchar(600) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`data` text, `data` text,
`review_date` datetime, `review_date` datetime DEFAULT NULL,
`created` int(1) unsigned NOT NULL default 0, `created` int(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
FOREIGN KEY (`id_rt`) REFERENCES `trecon_task`(`id_rt`) KEY `id_rt` (`id_rt`),
ON DELETE CASCADE ON UPDATE CASCADE INDEX `label` (`label`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 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` -- Table `twidget` AND Table `twidget_dashboard`

View File

@ -48,6 +48,9 @@ function get_wiz_class($str)
case 'ctask': case 'ctask':
return 'ConsoleTasks'; return 'ConsoleTasks';
case 'deploymentCenter':
return 'DeploymentCenter';
default: default:
// Main, show header. // Main, show header.
ui_print_page_header( ui_print_page_header(
@ -124,13 +127,28 @@ $classname_selected = get_wiz_class($wiz_in_use);
// Else: class not found pseudo exception. // Else: class not found pseudo exception.
if ($classname_selected !== null) { if ($classname_selected !== null) {
$wiz = new $classname_selected($page); $wiz = new $classname_selected((int) $page);
$result = $wiz->run();
if (is_array($result) === true) { // AJAX controller.
// Redirect control and messages to DiscoveryTasklist. if (is_ajax()) {
$classname_selected = 'DiscoveryTaskList'; $method = get_parameter('method');
$wiz = new $classname_selected($page);
$result = $wiz->run($result['msg'], $result['result']); 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']);
}
} }
} }

View File

@ -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_users.php';
require_once $config['homedir'].'/include/functions_reports.php'; require_once $config['homedir'].'/include/functions_reports.php';
require_once $config['homedir'].'/include/functions_cron.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'); enterprise_include_once('include/functions_cron.php');
ui_require_css_file('task_list'); 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. * 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 ($task['disabled'] == 0 && $server_name !== '') {
if (check_acl($config['id_user'], 0, 'AW')) { if (check_acl($config['id_user'], 0, 'AW')) {
$data[0] = '<a href="'.ui_get_full_url( $data[0] = '<span class="link" onclick="force_task(\'';
$data[0] .= ui_get_full_url(
'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=tasklist&server_id='.$id_server.'&force='.$task['id_rt'] 'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=tasklist&server_id='.$id_server.'&force='.$task['id_rt']
).'">'; );
$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] .= html_print_image('images/target.png', true, ['title' => __('Force')]);
$data[0] .= '</a>'; $data[0] .= '</span>';
} }
} else if ($task['disabled'] == 2) { } else if ($task['disabled'] == 2) {
$data[0] = ui_print_help_tip( $data[0] = ui_print_help_tip(
@ -472,12 +485,12 @@ class DiscoveryTaskList extends Wizard
// Name task. // Name task.
$data[1] = ''; $data[1] = '';
if ($task['disabled'] != 2) { if ($task['disabled'] != 2) {
$data[1] .= '<a href="#" onclick="progress_task_list('.$task['id_rt'].',\''.$task['name'].'\')">'; $data[1] .= '<span class="link" onclick="progress_task_list('.$task['id_rt'].',\''.$task['name'].'\')">';
} }
$data[1] .= '<b>'.$task['name'].'</b>'; $data[1] .= '<b>'.$task['name'].'</b>';
if ($task['disabled'] != 2) { if ($task['disabled'] != 2) {
$data[1] .= '</a>'; $data[1] .= '</span>';
} }
$data[2] = $server_name; $data[2] = $server_name;
@ -496,10 +509,20 @@ class DiscoveryTaskList extends Wizard
$data[4] = '-'; $data[4] = '-';
} }
if ($task['status'] <= 0) { if ($task['direct_report'] == 1) {
$data[5] = __('Done'); if ($task['status'] <= 0) {
$data[5] = __('Done');
} else {
$data[5] = __('Pending');
}
} else { } else {
$data[5] = __('Pending'); if ($task['status'] <= 0) {
$data[5] = '<span class="link review" onclick="show_review('.$task['id_rt'].',\''.$task['name'].'\')">';
$data[5] .= __('Review');
$data[5] .= '</span>';
} else {
$data[5] = __('Searching');
}
} }
switch ($task['type']) { switch ($task['type']) {
@ -595,7 +618,28 @@ class DiscoveryTaskList extends Wizard
if ($task['status'] <= 0 || $task['status'] > 100) { if ($task['status'] <= 0 || $task['status'] > 100) {
$data[7] = '-'; $data[7] = '-';
} else { } 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) { if ($task['utimestamp'] > 0) {
@ -700,9 +744,15 @@ class DiscoveryTaskList extends Wizard
// Div neccesary for modal map task. // Div neccesary for modal map task.
echo '<div id="map_task" style="display:none"></div>'; echo '<div id="map_task" style="display:none"></div>';
echo '<div id="task_review" style="display:none"></div>';
echo '<div id="msg" style="display:none"></div>';
echo '<input type="hidden" id="ajax-url" value="'.ui_get_full_url('ajax.php').'"/>';
echo '<input type="hidden" id="success-str" value="'.__('Success').'"/>';
echo '<input type="hidden" id="failed-str" value="'.__('Failed').'"/>';
unset($table); unset($table);
ui_require_javascript_file('pandora_ui');
ui_require_javascript_file('pandora_taskList'); ui_require_javascript_file('pandora_taskList');
return $return; 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 .= '<div style="display: flex;">';
$result .= '<div style="width: 100%; text-align: center; margin-top: 40px;">';
$result .= '<span style="font-size: 1.9em; font-family: "lato-bolder", "Open Sans", sans-serif !important;">'._('Overall Progress').'</span>';
$result .= '<div style="margin-top: 25px;">';
$result .= progress_circular_bar(
$task['id_rt'],
($task['status'] < 0) ? 100 : $task['status'],
200,
200,
'#7eb641',
'%',
'',
'#3A3A3A',
0
);
$result .= '</div>';
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 .= '</div>';
$result .= '<div style="width: 100%; text-align: center; margin-top: 40px;">';
$result .= '<span style="font-size: 1.9em; font-family: "lato-bolder", "Open Sans", sans-serif !important;">'.$str.' ';
if (!empty($str)) {
$result .= $task['stats']['c_network_name'];
}
$result .= '</span>';
$result .= '<div style="margin-top: 25px;">';
$result .= progress_circular_bar(
$task['id_rt'].'_detail',
$task['stats']['c_network_percent'],
200,
200,
'#7eb641',
'%',
'',
'#3A3A3A',
0
);
$result .= '</div></div>';
}
$result .= '</div></div>';
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] = '<b>'.__('Hosts discovered').'</b>';
$table->data[$i][1] = '<span id="discovered">';
$table->data[$i][1] .= $task['stats']['summary']['discovered'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Alive').'</b>';
$table->data[$i][1] = '<span id="alive">';
$table->data[$i][1] .= $task['stats']['summary']['alive'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Not alive').'</b>';
$table->data[$i][1] = '<span id="not_alive">';
$table->data[$i][1] .= $task['stats']['summary']['not_alive'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Responding SNMP').'</b>';
$table->data[$i][1] = '<span id="SNMP">';
$table->data[$i][1] .= $task['stats']['summary']['SNMP'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Responding WMI').'</b>';
$table->data[$i][1] = '<span id="WMI">';
$table->data[$i][1] .= $task['stats']['summary']['WMI'];
$table->data[$i++][1] .= '</span>';
$output = '<div style="margin-top: 40px; text-align: center;"><span style="font-size: 1.9em; font-family: "lato-bolder", "Open Sans", sans-serif !important;">'.__('Summary').'</span></div>';
$output .= html_print_table($table, true).'</div>';
}
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
).'</div>';
} 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 '<div id="tree"></div>';
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]
);
}
} }

View File

@ -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. * To be overwritten.
* *

View File

@ -24,154 +24,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * 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 = '<div id = progress_task_'.$id_task.'>';
if ($task['utimestamp']) {
$result .= '<div style="display: flex;">';
$result .= '<div style="width: 100%; text-align: center; margin-top: 40px;">';
$result .= '<span style="font-size: 1.9em; font-family: "lato-bolder", "Open Sans", sans-serif !important;">'._('Overall Progress').'</span>';
$result .= '<div style="margin-top: 25px;">';
$result .= progress_circular_bar(
$id_task,
($global_progress < 0) ? 100 : $global_progress,
200,
200,
'#7eb641',
'%',
'',
'#3A3A3A',
0
);
$result .= '</div>';
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 .= '</div>';
$result .= '<div style="width: 100%; text-align: center; margin-top: 40px;">';
$result .= '<span style="font-size: 1.9em; font-family: "lato-bolder", "Open Sans", sans-serif !important;">'.$str.' ';
$result .= $summary['c_network_name'];
$result .= '</span>';
$result .= '<div style="margin-top: 25px;">';
$result .= progress_circular_bar(
$id_task.'_detail',
$summary['c_network_percent'],
200,
200,
'#7eb641',
'%',
'',
'#3A3A3A',
0
);
$result .= '</div></div>';
}
$result .= '</div></div>';
$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] = '<b>'.__('Hosts discovered').'</b>';
$table->data[$i][1] = '<span id="discovered">';
$table->data[$i][1] .= $summary['summary']['discovered'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Alive').'</b>';
$table->data[$i][1] = '<span id="alive">';
$table->data[$i][1] .= $summary['summary']['alive'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Not alive').'</b>';
$table->data[$i][1] = '<span id="not_alive">';
$table->data[$i][1] .= $summary['summary']['not_alive'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Responding SNMP').'</b>';
$table->data[$i][1] = '<span id="SNMP">';
$table->data[$i][1] .= $summary['summary']['SNMP'];
$table->data[$i++][1] .= '</span>';
$table->data[$i][0] = '<b>'.__('Responding WMI').'</b>';
$table->data[$i][1] = '<span id="WMI">';
$table->data[$i][1] .= $summary['summary']['WMI'];
$table->data[$i++][1] .= '</span>';
$result .= '<div style="margin-top: 40px; text-align: center;"><span style="font-size: 1.9em; font-family: "lato-bolder", "Open Sans", sans-serif !important;">'.__('Summary').'</span></div>';
$result .= html_print_table($table, true).'</div>';
} else {
$global_progress = -1;
$result .= ui_print_error_message(
__('No data to show'),
'',
true
).'</div>';
}
$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();
}

View File

@ -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 = '
<script type="text/javascript">
$(document).ready(function() {
simTree({
el: $('.$target.'),
data: '.json_encode($data).',
onClick: function (item) {'.$callback.';},
check: true,
linkParent: true
});
});
</script>';
return $output;
}
} }

View File

@ -527,6 +527,9 @@ define('STEP_SCANNING', 1);
define('STEP_AFT', 2); define('STEP_AFT', 2);
define('STEP_TRACEROUTE', 3); define('STEP_TRACEROUTE', 3);
define('STEP_GATEWAY', 4); define('STEP_GATEWAY', 4);
define('STEP_STATISTICS', 1);
define('STEP_APP_SCAN', 2);
define('STEP_CUSTOM_QUERIES', 3);
// Networkmap node types. // Networkmap node types.
define('NODE_AGENT', 0); define('NODE_AGENT', 0);

View File

@ -2839,6 +2839,7 @@ function ui_print_status_sets(
* [ * [
* 'page' => 'operation/agentes/ver_agente', Target page. * 'page' => 'operation/agentes/ver_agente', Target page.
* 'interval' => 100 / $agent["intervalo"], Ask every interval seconds. * 'interval' => 100 / $agent["intervalo"], Ask every interval seconds.
* 'simple' => 0,
* 'data' => [ Data to be sent to target page. * 'data' => [ Data to be sent to target page.
* 'id_agente' => $id_agente, * 'id_agente' => $id_agente,
* 'refresh_contact' => 1, * 'refresh_contact' => 1,
@ -2879,7 +2880,38 @@ function ui_progress(
$output .= '</span>'; $output .= '</span>';
if ($ajax !== false && is_array($ajax)) { if ($ajax !== false && is_array($ajax)) {
$output .= '<script type="text/javascript"> if ($ajax['simple']) {
$output .= '<script type="text/javascript">
$(document).ready(function() {
setInterval(() => {
$.post({
url: "'.ui_get_full_url('ajax.php', false, false, false).'",
data: {';
if (is_array($ajax['data'])) {
foreach ($ajax['data'] as $token => $value) {
$output .= '
'.$token.':"'.$value.'",';
}
}
$output .= '
page: "'.$ajax['page'].'"
},
success: function(data) {
try {
val = JSON.parse(data);
$(".progress_main").attr("data-label", val + " %");
$(".progress").width(val+"%");
} catch (e) {
console.error(e);
}
}
});
}, '.($ajax['interval'] > 0 ? $ajax['interval'] * 1000 : 30000 ).');
});
</script>';
} else {
$output .= '<script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {
setInterval(() => { setInterval(() => {
last = $(".progress_main").attr("data-label").split(" ")[0]*1; last = $(".progress_main").attr("data-label").split(" ")[0]*1;
@ -2889,14 +2921,14 @@ function ui_progress(
$.post({ $.post({
url: "'.ui_get_full_url('ajax.php', false, false, false).'", url: "'.ui_get_full_url('ajax.php', false, false, false).'",
data: {'; data: {';
if (is_array($ajax['data'])) { if (is_array($ajax['data'])) {
foreach ($ajax['data'] as $token => $value) { foreach ($ajax['data'] as $token => $value) {
$output .= ' $output .= '
'.$token.':"'.$value.'",'; '.$token.':"'.$value.'",';
}
} }
}
$output .= ' $output .= '
page: "'.$ajax['page'].'" page: "'.$ajax['page'].'"
}, },
success: function(data) { success: function(data) {
@ -2922,6 +2954,7 @@ function ui_progress(
}, 1000); }, 1000);
}); });
</script>'; </script>';
}
} }
if (!$return) { if (!$return) {

View File

@ -22,7 +22,7 @@ function progress_task_list(id, title) {
autoOpen: false, autoOpen: false,
modal: false, modal: false,
resizable: false, resizable: false,
draggable: false, draggable: true,
closeOnEscape: true, closeOnEscape: true,
width: 800, width: 800,
height: 600, height: 600,
@ -35,19 +35,23 @@ function progress_task_list(id, title) {
// Function var. // Function var.
var handleFetchTaskList = function(err, data) { var handleFetchTaskList = function(err, data) {
if (err) { if (err) {
console.error(err);
}
if (data.error) {
// TODO: Show info about the problem. // 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 (!$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); xhr = fetchTaskList(id, handleFetchTaskList);
} }
@ -60,12 +64,13 @@ function progress_task_list(id, title) {
function fetchTaskList(id, callback) { function fetchTaskList(id, callback) {
return jQuery.ajax({ return jQuery.ajax({
data: { data: {
page: "include/ajax/task_list.ajax", page: "godmode/servers/discovery",
progress_task_discovery: 1, wiz: "tasklist",
method: "progress_task_discovery",
id: id id: id
}, },
type: "POST", type: "POST",
url: "ajax.php", url: $("#ajax-url").val(),
dataType: "json", dataType: "json",
success: function(data) { success: function(data) {
callback(null, data); callback(null, data);
@ -93,12 +98,13 @@ function show_map(id, name) {
jQuery.ajax({ jQuery.ajax({
data: { data: {
page: "include/ajax/task_list.ajax", page: "godmode/servers/discovery",
showmap: 1, wiz: "tasklist",
method: "task_showmap",
id: id id: id
}, },
type: "POST", type: "POST",
url: "ajax.php", url: $("#ajax-url").val(),
dataType: "html", dataType: "html",
success: function(data) { success: function(data) {
$("#map_task") $("#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 += "<br>" + 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);
}
}

View File

@ -383,6 +383,7 @@ function confirmDialog(settings) {
"ui-widget ui-state-default ui-corner-all ui-button-text-only sub upd submit-cancel", "ui-widget ui-state-default ui-corner-all ui-button-text-only sub upd submit-cancel",
click: function() { click: function() {
$(this).dialog("close"); $(this).dialog("close");
$(this).remove();
if (typeof settings.onDeny == "function") settings.onDeny(); 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", "ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next",
click: function() { click: function() {
$(this).dialog("close"); $(this).dialog("close");
$(this).remove();
if (typeof settings.onAccept == "function") settings.onAccept(); if (typeof settings.onAccept == "function") settings.onAccept();
} }
} }

View File

@ -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 =
'<i data-type="{{asy}}" class="sim-tree-spread {{spreadIcon}}"></i><a href="javascript:;"><i class="sim-tree-checkbox"></i>{{text}}</a>',
b = e === this.$el,
y = $(i.createElement("ul")),
w = f.childNodeAsy ? "asy" : "";
for (
f.check ||
(C = C.replace('<i class="sim-tree-checkbox"></i>', ""));
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) {}
]);

View File

@ -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;
}

View File

@ -40,3 +40,15 @@ ul.progress_task_discovery li span {
font-size: 9pt; font-size: 9pt;
margin-left: 20px; margin-left: 20px;
} }
.ui-dialog.ui-widget-content {
cursor: initial;
}
span.link {
cursor: pointer;
}
span.link.review {
font-weight: bold;
}

View File

@ -770,14 +770,14 @@ CREATE TABLE IF NOT EXISTS `trecon_task` (
`name` varchar(100) NOT NULL default '', `name` varchar(100) NOT NULL default '',
`description` varchar(250) NOT NULL default '', `description` varchar(250) NOT NULL default '',
`subnet` text NOT NULL, `subnet` text NOT NULL,
`id_network_profile` int(10) unsigned NOT NULL default '0', `id_network_profile` text,
`create_incident` tinyint(3) unsigned NOT NULL default '0', `direct_report` tinyint(1) unsigned NOT NULL default 0,
`id_group` int(10) unsigned NOT NULL default '1', `id_group` int(10) unsigned NOT NULL default 1,
`utimestamp` bigint(20) unsigned NOT NULL default '0', `utimestamp` bigint(20) unsigned NOT NULL default 0,
`status` tinyint(4) NOT NULL default '0', `status` tinyint(4) NOT NULL default 0,
`interval_sweep` int(10) unsigned NOT NULL default '0', `interval_sweep` int(10) unsigned NOT NULL default 0,
`id_recon_server` 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_os` tinyint(4) NOT NULL default 0,
`recon_ports` varchar(250) NOT NULL default '', `recon_ports` varchar(250) NOT NULL default '',
`snmp_community` varchar(64) NOT NULL default 'public', `snmp_community` varchar(64) NOT NULL default 'public',
`id_recon_script` int(10), `id_recon_script` int(10),
@ -785,31 +785,62 @@ CREATE TABLE IF NOT EXISTS `trecon_task` (
`field2` varchar(250) NOT NULL default '', `field2` varchar(250) NOT NULL default '',
`field3` varchar(250) NOT NULL default '', `field3` varchar(250) NOT NULL default '',
`field4` varchar(250) NOT NULL default '', `field4` varchar(250) NOT NULL default '',
`os_detect` tinyint(1) unsigned default '0', `os_detect` tinyint(1) unsigned default 0,
`resolve_names` tinyint(1) unsigned default '0', `resolve_names` tinyint(1) unsigned default 0,
`parent_detection` tinyint(1) unsigned default '0', `parent_detection` tinyint(1) unsigned default 0,
`parent_recursion` tinyint(1) unsigned default '0', `parent_recursion` tinyint(1) unsigned default 0,
`disabled` tinyint(1) unsigned NOT NULL DEFAULT '0', `disabled` tinyint(1) unsigned NOT NULL DEFAULT 0,
`macros` TEXT, `macros` TEXT,
`alias_as_name` tinyint(2) NOT NULL default '0', `alias_as_name` tinyint(2) NOT NULL default 0,
`snmp_enabled` tinyint(1) unsigned default '0', `snmp_enabled` tinyint(1) unsigned default 0,
`vlan_enabled` tinyint(1) unsigned default '0', `vlan_enabled` tinyint(1) unsigned default 0,
`snmp_version` varchar(5) NOT NULL default '1', `snmp_version` varchar(5) NOT NULL default 1,
`snmp_auth_user` varchar(255) NOT NULL default '', `snmp_auth_user` varchar(255) NOT NULL default '',
`snmp_auth_pass` varchar(255) NOT NULL default '', `snmp_auth_pass` varchar(255) NOT NULL default '',
`snmp_auth_method` varchar(25) NOT NULL default '', `snmp_auth_method` varchar(25) NOT NULL default '',
`snmp_privacy_method` varchar(25) NOT NULL default '', `snmp_privacy_method` varchar(25) NOT NULL default '',
`snmp_privacy_pass` varchar(255) NOT NULL default '', `snmp_privacy_pass` varchar(255) NOT NULL default '',
`snmp_security_level` varchar(25) 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, `auth_strings` text,
`autoconfiguration_enabled` tinyint(1) unsigned default '0', `autoconfiguration_enabled` tinyint(1) unsigned default 0,
`summary` text, `summary` text,
`type` int NOT NULL default 0, `type` int NOT NULL default 0,
PRIMARY KEY (`id_rt`), PRIMARY KEY (`id_rt`),
KEY `recon_task_daemon` (`id_recon_server`) KEY `recon_task_daemon` (`id_recon_server`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) 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` -- Table `tmodule_relationship`
-- ---------------------------------------------------------------------- -- ----------------------------------------------------------------------

View File

@ -20,6 +20,7 @@ package PandoraFMS::DB;
use strict; use strict;
use warnings; use warnings;
use DBI; use DBI;
use Carp qw/croak/;
use lib '/usr/lib/perl5'; use lib '/usr/lib/perl5';
use PandoraFMS::Tools; use PandoraFMS::Tools;
@ -894,7 +895,7 @@ sub db_insert ($$$;@) {
$insert_id = $dbh->{'mysql_insertid'}; $insert_id = $dbh->{'mysql_insertid'};
} }
else { else {
die($exception); croak (join(', ', @_));
} }
} }
@ -917,7 +918,7 @@ sub db_update ($$;@) {
$rows = $dbh->do($query, undef, @values); $rows = $dbh->do($query, undef, @values);
} }
else { else {
die($exception); croak (join(', ', @_));
} }
} }
@ -1163,7 +1164,7 @@ sub db_do ($$;@) {
$dbh->do($query, undef, @values); $dbh->do($query, undef, @values);
} }
else { else {
die($exception); croak (join(', ', @_));
} }
} }
} }

View File

@ -1,8 +1,8 @@
package PandoraFMS::DiscoveryServer; package PandoraFMS::DiscoveryServer;
########################################################################## ################################################################################
# Pandora FMS Discovery Server. # Pandora FMS Discovery Server.
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org # Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
########################################################################## ################################################################################
# Copyright (c) 2005-2009 Artica Soluciones Tecnologicas S.L # Copyright (c) 2005-2009 Artica Soluciones Tecnologicas S.L
# #
# This program is free software; you can redistribute it and/or # 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 # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
########################################################################## ################################################################################
use strict; use strict;
use warnings; use warnings;
@ -77,9 +77,9 @@ use constant {
DISCOVERY_APP_SAP => 10, DISCOVERY_APP_SAP => 10,
}; };
######################################################################################## ################################################################################
# Discovery Server class constructor. # Discovery Server class constructor.
######################################################################################## ################################################################################
sub new ($$$$$$) { sub new ($$$$$$) {
my ($class, $config, $dbh) = @_; my ($class, $config, $dbh) = @_;
@ -113,9 +113,9 @@ sub new ($$$$$$) {
return $self; return $self;
} }
############################################################################### ################################################################################
# Run. # Run.
############################################################################### ################################################################################
sub run ($) { sub run ($) {
my $self = shift; my $self = shift;
my $pa_config = $self->getConfig (); my $pa_config = $self->getConfig ();
@ -132,9 +132,9 @@ sub run ($) {
$self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem); $self->SUPER::run (\@TaskQueue, \%PendingTasks, $Sem, $TaskSem);
} }
############################################################################### ################################################################################
# Data producer. # Data producer.
############################################################################### ################################################################################
sub data_producer ($) { sub data_producer ($) {
my $self = shift; my $self = shift;
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ()); my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
@ -174,9 +174,9 @@ sub data_producer ($) {
return @tasks; return @tasks;
} }
############################################################################### ################################################################################
# Data consumer. # Data consumer.
############################################################################### ################################################################################
sub data_consumer ($$) { sub data_consumer ($$) {
my ($self, $task_id) = @_; my ($self, $task_id) = @_;
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ()); my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
@ -300,18 +300,18 @@ sub data_consumer ($$) {
} }
} }
########################################################################## ################################################################################
# Update recon task status. # Update recon task status.
########################################################################## ################################################################################
sub update_recon_task ($$$) { sub update_recon_task ($$$) {
my ($dbh, $id_task, $status) = @_; my ($dbh, $id_task, $status) = @_;
db_do ($dbh, 'UPDATE trecon_task SET utimestamp = ?, status = ? WHERE id_rt = ?', time (), $status, $id_task); db_do ($dbh, 'UPDATE trecon_task SET utimestamp = ?, status = ? WHERE id_rt = ?', time (), $status, $id_task);
} }
########################################################################## ################################################################################
# Executes recon scripts # Executes recon scripts
########################################################################## ################################################################################
sub exec_recon_script ($$$) { sub exec_recon_script ($$$) {
my ($pa_config, $dbh, $task) = @_; my ($pa_config, $dbh, $task) = @_;
@ -380,9 +380,9 @@ sub exec_recon_script ($$$) {
return 0; return 0;
} }
########################################################################## ################################################################################
# Guess the OS using xprobe2 or nmap. # Guess the OS using xprobe2 or nmap.
########################################################################## ################################################################################
sub PandoraFMS::Recon::Base::guess_os($$) { sub PandoraFMS::Recon::Base::guess_os($$) {
my ($self, $device) = @_; my ($self, $device) = @_;
@ -422,9 +422,9 @@ sub PandoraFMS::Recon::Base::guess_os($$) {
return OS_OTHER; return OS_OTHER;
} }
############################################################################## ################################################################################
# Returns the number of open ports from the given list. # Returns the number of open ports from the given list.
############################################################################## ################################################################################
sub PandoraFMS::Recon::Base::tcp_scan ($$) { sub PandoraFMS::Recon::Base::tcp_scan ($$) {
my ($self, $host) = @_; my ($self, $host) = @_;
@ -436,14 +436,23 @@ sub PandoraFMS::Recon::Base::tcp_scan ($$) {
return $open_ports; return $open_ports;
} }
########################################################################## ################################################################################
# Create network profile modules for the given agent. # Create network profile modules for the given agent.
########################################################################## ################################################################################
sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) { sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) {
my ($self, $agent_id, $device) = @_; 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. # 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'}); 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) { foreach my $np_component (@np_components) {
@ -455,6 +464,10 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$$) {
next; 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 # Use snmp_community from network task instead the component snmp_community
$component->{'snmp_community'} = safe_output($self->get_community($device)); $component->{'snmp_community'} = safe_output($self->get_community($device));
$component->{'tcp_send'} = $self->{'snmp_version'}; $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. # Connect the given devices in the Pandora FMS database.
########################################################################## ################################################################################
sub PandoraFMS::Recon::Base::connect_agents($$$$$) { 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) = @_;
@ -490,12 +578,12 @@ sub PandoraFMS::Recon::Base::connect_agents($$$$$) {
return unless defined($agent_2); return unless defined($agent_2);
# Use ping modules by default. # Use ping modules by default.
$if_1 = 'ping' if ($if_1 eq ''); $if_1 = 'Host Alive' if ($if_1 eq '');
$if_2 = 'ping' if ($if_2 eq ''); $if_2 = 'Host Alive' if ($if_2 eq '');
# Check whether the modules exists. # Check whether the modules exists.
my $module_name_1 = $if_1 eq 'ping' ? 'ping' : "${if_1}_ifOperStatus"; my $module_name_1 = $if_1 eq 'Host Alive' ? 'Host Alive' : "${if_1}_ifOperStatus";
my $module_name_2 = $if_2 eq 'ping' ? 'ping' : "${if_2}_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'}); my $module_id_1 = get_agent_module_id($self->{'dbh'}, $module_name_1, $agent_1->{'id_agente'});
if ($module_id_1 <= 0) { if ($module_id_1 <= 0) {
$self->call('message', "ERROR: Module " . safe_output($module_name_1) . " does not exist for agent $dev_1.", 5); $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. # Create agents from db_scan. Uses DataServer methods.
# data = [ # data = [
# 'agent_data' => {}, # 'agent_data' => {},
# 'module_data' => [] # 'module_data' => []
# ] # ]
########################################################################## ################################################################################
sub PandoraFMS::Recon::Base::create_agents($$) { sub PandoraFMS::Recon::Base::create_agents($$) {
my ($self, $data) = @_; 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 # Create an agent for the given device. Returns the ID of the new (or
# existing) agent, undef on error. # existing) agent, undef on error.
########################################################################## ################################################################################
sub PandoraFMS::Recon::Base::create_agent($$) { sub PandoraFMS::Recon::Base::create_agent($$) {
my ($self, $device) = @_; my ($self, $device) = @_;
@ -930,9 +1018,9 @@ sub PandoraFMS::Recon::Base::create_agent($$) {
return $agent_id; return $agent_id;
} }
########################################################################## ################################################################################
# Delete already existing connections. # Delete already existing connections.
########################################################################## ################################################################################
sub PandoraFMS::Recon::Base::delete_connections($) { sub PandoraFMS::Recon::Base::delete_connections($) {
my ($self) = @_; 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'}); db_do($self->{'dbh'}, 'DELETE FROM tmodule_relationship WHERE id_rt=?', $self->{'task_id'});
} }
####################################################################### ################################################################################
# Print log messages. # Print log messages.
####################################################################### ################################################################################
sub PandoraFMS::Recon::Base::message($$$) { 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. # Connect the given hosts to its parent.
########################################################################## ################################################################################
sub PandoraFMS::Recon::Base::set_parent($$$) { sub PandoraFMS::Recon::Base::set_parent($$$) {
my ($self, $host, $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'}); 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. # Create a WMI module for the given agent.
########################################################################## ################################################################################
sub PandoraFMS::Recon::Base::wmi_module { sub PandoraFMS::Recon::Base::wmi_module {
my ($self, $agent_id, $target, $wmi_query, $wmi_auth, $column, my ($self, $agent_id, $target, $wmi_query, $wmi_auth, $column,
$module_name, $module_description, $module_type, $unit) = @_; $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'}); pandora_create_module_from_hash($self->{'pa_config'}, \%module, $self->{'dbh'});
} }
########################################################################## ################################################################################
# Update recon task status. # Update recon task status.
########################################################################## ################################################################################
sub PandoraFMS::Recon::Base::update_progress ($$) { sub PandoraFMS::Recon::Base::update_progress ($$) {
my ($self, $progress) = @_; my ($self, $progress) = @_;

View File

@ -7,13 +7,14 @@ use strict;
use warnings; use warnings;
# Default lib dir for RPM and DEB packages # Default lib dir for RPM and DEB packages
use lib '/usr/lib/perl5';
use NetAddr::IP; use NetAddr::IP;
use POSIX qw/ceil/; use POSIX qw/ceil/;
use Socket qw/inet_aton/;
use lib '/usr/lib/perl5';
use PandoraFMS::Tools;
use PandoraFMS::Recon::NmapParser; use PandoraFMS::Recon::NmapParser;
use PandoraFMS::Recon::Util; use PandoraFMS::Recon::Util;
use Socket qw/inet_aton/;
# Constants. # Constants.
use constant { 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 $SYSSERVICES = ".1.3.6.1.2.1.1.7";
our $SYSUPTIME = ".1.3.6.1.2.1.1.3"; 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 $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 @ISA = ("Exporter");
our %EXPORT_TAGS = ( 'all' => [qw( )] ); our %EXPORT_TAGS = ( 'all' => [qw( )] );
@ -389,6 +391,27 @@ sub are_connected($$$$$) {
return 0; 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. # Discover as much information as possible from the given device using SNMP.
################################################################################ ################################################################################
@ -425,13 +448,15 @@ sub snmp_discovery($$) {
# Check remote ARP caches. # Check remote ARP caches.
$self->remote_arp($device); $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. # 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; my $mac = undef;
eval { eval {
$mac = `arping -c 1 -r $host 2>$DEVNULL`; $mac = `arping -c 1 $host 2>$DEVNULL`;
$mac = undef unless ($? == 0); $mac = undef unless ($? == 0);
}; };
return unless defined($mac); return unless defined($mac);
($mac) = $mac =~ /\[(.*?)\]/ if defined($mac);
# Clean-up the MAC address. # Clean-up the MAC address.
chomp($mac); chomp($mac);
$mac = parse_mac($mac); $mac = parse_mac($mac);
@ -1104,11 +1131,11 @@ sub mark_connected($$;$$$) {
$child = $self->{'aliases'}->{$child} if defined($self->{'aliases'}->{$child}); $child = $self->{'aliases'}->{$child} if defined($self->{'aliases'}->{$child});
# Use ping modules when interfaces are unknown. # Use ping modules when interfaces are unknown.
$parent_if = "ping" if $parent_if eq ''; $parent_if = "Host Alive" if $parent_if eq '';
$child_if = "ping" if $child_if eq ''; $child_if = "Host Alive" if $child_if eq '';
# Do not connect devices using ping modules. A parent-child relationship is enough. # 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->{'connections'}->{"${parent}\t${parent_if}\t${child}\t${child_if}"} = 1;
$self->call('connect_agents', $parent, $parent_if, $child, $child_if); $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 ($$$) { sub prepare_agent($$) {
my ($self, $host) = @_; my ($self, $addr) = @_;
my ($timeout, $retries, $packets) = ($self->{'icmp_timeout'},$self->{'icmp_checks'},1,); $self->{'agents_found'} = {} if ref($self->{'agents_found'}) ne 'HASH';
# Windows # Already initialized.
if (($^O eq "MSWin32") || ($^O eq "MSWin32-x64") || ($^O eq "cygwin")){ return if ref($self->{'agents_found'}->{$addr}) eq 'HASH';
$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; $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 # WMI discovery.
if ($^O eq "solaris"){ if (is_enabled($self->{'wmi_enabled'})) {
my $ping_command = $host =~ /\d+:|:\d+/ ? "ping -A inet6" : "ping"; # Add wmi scan if enabled.
for (my $i = 0; $i < $retries; $i++) { $self->wmi_scan($addr);
# 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;
} }
################################################################################ ################################################################################
@ -1343,6 +1363,7 @@ sub scan_subnet($) {
foreach my $subnet (@subnets) { foreach my $subnet (@subnets) {
$self->{'c_network_percent'} = 0; $self->{'c_network_percent'} = 0;
$self->{'c_network_name'} = $subnet; $self->{'c_network_name'} = $subnet;
$self->call('update_progress', ceil($progress));
# Clean blanks. # Clean blanks.
$subnet =~ s/\s+//g; $subnet =~ s/\s+//g;
@ -1357,81 +1378,82 @@ sub scan_subnet($) {
my $network = $net_addr->network(); my $network = $net_addr->network();
my $broadcast = $net_addr->broadcast(); my $broadcast = $net_addr->broadcast();
# fping scan. my @hosts = map { (split('/', $_))[0] } $net_addr->hostenum;
if (-x $self->{'fping'} && $net_addr->num() > 1) { my $total_hosts = scalar(@hosts);
$self->call('message', "Calling fping...", 5); my %hosts_alive = ();
my @hosts = `"$self->{'fping'}" -ga "$subnet" 2>DEVNULL`; # By default 200, (20 * 10)
next if (scalar(@hosts) == 0); 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. for (my $block_index=0;
my $subnet_step = 100.0 / scalar(@hosts); $block_index < $total_hosts;
foreach my $line (@hosts) { $block_index += $host_block_size
chomp($line); ) {
# 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); my $c_block_size = $to - $block_index;
if (scalar(@temp) != 1) { 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. # check alive hosts in current block
# Increase summary.not_alive hosts. %hosts_alive = (
$self->{'summary'}->{'not_alive'} += 1; %hosts_alive,
next; map {chomp; $_ => 1} @block
} );
my $host = $temp[0];
# Skip network and broadcast addresses. $self->{'summary'}->{'not_alive'} += $c_block_size - (scalar @block);
next if ($host eq $network->addr() || $host eq $broadcast->addr()); $self->{'summary'}->{'alive'} += scalar @block;
# Increase self summary.alive hosts. # Update progress.
$self->{'summary'}->{'alive'} += 1; $progress += $step;
$self->call('message', "Scanning host: $host", 5); $self->{'c_network_percent'} += $subnet_step;
$self->call('update_progress', ceil($progress));
$progress += $step;
$self->{'c_network_percent'} += $subnet_step;
$self->snmp_discovery($host); # Populate.
$self->call('update_progress', ceil($progress));
# Add wmi scan if enabled.
$self->wmi_scan($host) if ($self->{'wmi_enabled'} == 1);
}
} }
# ping scan. # Update progress.
else { $self->call('message', "Searching for hosts (".$total_hosts." / ".$total_hosts.")", 5);
my @hosts = map { (split('/', $_))[0] } $net_addr->hostenum; $progress = ceil($progress);
next if (scalar(@hosts) == 0); $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. $total_hosts = scalar keys %hosts_alive;
my $subnet_step = 100.0 / scalar(@hosts); $step = 40.0 / scalar(@subnets) / $total_hosts;
foreach my $host (@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); # Update progress.
$self->call('update_progress', ceil($progress)); $progress += $step;
$progress += $step; $self->{'c_network_percent'} += $subnet_step;
# Check if the host is up. # Populate.
if ($self->ping($host) == 0) { $self->call('update_progress', ceil($progress));
$self->{'summary'}->{'not_alive'} += 1;
next;
}
$self->{'summary'}->{'alive'} += 1; # Enable/ disable capabilities.
$self->{'c_network_percent'} += $subnet_step; $self->test_capabilities($addr);
$self->snmp_discovery($host);
# Add wmi scan if enabled.
$self->wmi_scan($host) if ($self->{'wmi_enabled'} == 1);
}
} }
} }
} }
################################################################################ ################################################################################
# Perform a Cloud scan # Perform a Cloud scan
################################################################################ ################################################################################
@ -1441,7 +1463,7 @@ sub cloud_scan($) {
my $type = ''; 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) { || $self->{'task_data'}->{'type'} == DISCOVERY_CLOUD_AWS_RDS) {
$type = 'Aws'; $type = 'Aws';
} else { } 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. # Find devices.
$self->call('message', "[1/4] Scanning the network...", 3); $self->call('message', "[1/4] Scanning the network...", 3);
$self->{'step'} = STEP_SCANNING; $self->{'step'} = STEP_SCANNING;
$self->call('update_progress', $progress); $self->call('update_progress', $progress);
$self->scan_subnet();
$self->scan_subnet();
# Read the local ARP cache. # Read the local ARP cache.
$self->local_arp(); $self->local_arp();
@ -1802,7 +1831,7 @@ sub scan($) {
# Connectivity from address forwarding tables. # Connectivity from address forwarding tables.
$self->call('message', "[2/4] Finding address forwarding table connectivity...", 3); $self->call('message', "[2/4] Finding address forwarding table connectivity...", 3);
$self->{'step'} = STEP_AFT; $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++) { for (my $i = 0; defined($hosts[$i]); $i++) {
$self->call('update_progress', $progress); $self->call('update_progress', $progress);
$progress += $step; $progress += $step;
@ -1812,7 +1841,7 @@ sub scan($) {
# Connect hosts that are still unconnected using traceroute. # Connect hosts that are still unconnected using traceroute.
$self->call('message', "[3/4] Finding traceroute connectivity.", 3); $self->call('message', "[3/4] Finding traceroute connectivity.", 3);
$self->{'step'} = STEP_TRACEROUTE; $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) { foreach my $host (@hosts) {
$self->call('update_progress', $progress); $self->call('update_progress', $progress);
$progress += $step; $progress += $step;
@ -1823,7 +1852,7 @@ sub scan($) {
# Connect hosts that are still unconnected using known gateways. # Connect hosts that are still unconnected using known gateways.
$self->call('message', "[4/4] Finding host to gateway connectivity.", 3); $self->call('message', "[4/4] Finding host to gateway connectivity.", 3);
$self->{'step'} = STEP_GATEWAY; $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. $self->get_routes(); # Update the route cache.
foreach my $host (@hosts) { foreach my $host (@hosts) {
$self->call('update_progress', $progress); $self->call('update_progress', $progress);
@ -1852,6 +1881,10 @@ sub scan($) {
$dev_info .= ')'; $dev_info .= ')';
$self->call('message', $dev_info, 3); $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; $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. # Performs an SNMP WALK and returns the response as an array.
################################################################################ ################################################################################
@ -2015,7 +2064,7 @@ sub traceroute_connectivity($$) {
my $parent = $hops[$i]->ipaddr(); my $parent = $hops[$i]->ipaddr();
# Create an agent for the parent. # 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->call('message', "Host $device is one hop away from host $parent.", 5);
$self->mark_connected($parent, '', $device, ''); $self->mark_connected($parent, '', $device, '');
@ -2064,27 +2113,61 @@ sub wmi_scan {
$self->call('message', "[".$target."] WMI available.", 10); $self->call('message', "[".$target."] WMI available.", 10);
# Create the agent if it does not exist. # Register agent.
my $agent_id = $self->call('create_agent', $target); $self->add_agent($target);
next unless defined($agent_id);
# Add modules.
# CPU. # CPU.
my @cpus = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceId FROM Win32_Processor', 0); my @cpus = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceId FROM Win32_Processor', 0);
foreach my $cpu (@cpus) { 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. # Memory.
my $mem = $self->wmi_get_value($target, $auth, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0); my $mem = $self->wmi_get_value($target, $auth, 'SELECT FreePhysicalMemory FROM Win32_OperatingSystem', 0);
if (defined($mem)) { 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. # Disk.
my @units = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceID FROM Win32_LogicalDisk', 0); my @units = $self->wmi_get_value_array($target, $auth, 'SELECT DeviceID FROM Win32_LogicalDisk', 0);
foreach my $unit (@units) { 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',
}
);
} }
} }
################################################################################ ################################################################################

View File

@ -23,9 +23,9 @@ our @EXPORT = qw(
subnet_matches subnet_matches
); );
######################################################################################## ################################################################################
# Return an Enterprise Recon object. # Return an Enterprise Recon object.
######################################################################################## ################################################################################
sub enterprise_new($$) { sub enterprise_new($$) {
my ($class, $arguments) = @_; my ($class, $arguments) = @_;
@ -53,18 +53,18 @@ sub enterprise_new($$) {
} }
######################################################################################## ################################################################################
# Return the numeric representation of the given IP address. # Return the numeric representation of the given IP address.
######################################################################################## ################################################################################
sub ip_to_long($) { sub ip_to_long($) {
my $ip_address = shift; my $ip_address = shift;
return unpack('N', inet_aton($ip_address)); return unpack('N', inet_aton($ip_address));
} }
######################################################################################## ################################################################################
# Returns 1 if the two given MAC addresses are the same. # Returns 1 if the two given MAC addresses are the same.
######################################################################################## ################################################################################
sub mac_matches($$) { sub mac_matches($$) {
my ($mac_1, $mac_2) = @_; my ($mac_1, $mac_2) = @_;
@ -75,9 +75,9 @@ sub mac_matches($$) {
return 0; return 0;
} }
######################################################################################## ################################################################################
# Convert a MAC address to decimal dotted notation. # Convert a MAC address to decimal dotted notation.
######################################################################################## ################################################################################
sub mac_to_dec($) { sub mac_to_dec($) {
my $mac = shift; my $mac = shift;
@ -91,9 +91,9 @@ sub mac_to_dec($) {
return $dec_mac; return $dec_mac;
} }
######################################################################################## ################################################################################
# Make sure all MAC addresses are in the same format (00 11 22 33 44 55 66). # Make sure all MAC addresses are in the same format (00 11 22 33 44 55 66).
######################################################################################## ################################################################################
sub parse_mac($) { sub parse_mac($) {
my ($mac) = @_; my ($mac) = @_;
@ -114,9 +114,9 @@ sub parse_mac($) {
return $mac; return $mac;
} }
######################################################################################## ################################################################################
# Returns 1 if the given IP address belongs to the given subnet. # Returns 1 if the given IP address belongs to the given subnet.
######################################################################################## ################################################################################
sub subnet_matches($$;$) { sub subnet_matches($$;$) {
my ($ipaddr, $subnet, $mask) = @_; my ($ipaddr, $subnet, $mask) = @_;
my ($netaddr, $netmask); my ($netaddr, $netmask);

View File

@ -1,8 +1,8 @@
package PandoraFMS::Tools; package PandoraFMS::Tools;
######################################################################## ################################################################################
# Tools Package # Tools Package
# Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org # Pandora FMS. the Flexible Monitoring System. http://www.pandorafms.org
######################################################################## ################################################################################
# Copyright (c) 2005-2011 Artica Soluciones Tecnologicas S.L # Copyright (c) 2005-2011 Artica Soluciones Tecnologicas S.L
# #
# This program is free software; you can redistribute it and/or # 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 # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
########################################################################## ################################################################################
use warnings; use warnings;
use Time::Local; use Time::Local;
@ -109,8 +109,10 @@ our @EXPORT = qw(
float_equal float_equal
sqlWrap sqlWrap
is_numeric is_numeric
is_enabled
is_metaconsole is_metaconsole
is_offline is_offline
is_empty
to_number to_number
clean_blank clean_blank
credential_store_get_key credential_store_get_key
@ -128,6 +130,7 @@ our @EXPORT = qw(
pandora_ping pandora_ping
pandora_ping_latency pandora_ping_latency
pandora_block_ping pandora_block_ping
ping
resolve_hostname resolve_hostname
ticks_totime ticks_totime
safe_input safe_input
@ -361,9 +364,9 @@ my @ServerThreads;
# Keep threads running. # Keep threads running.
our $THRRUN :shared = 1; our $THRRUN :shared = 1;
########################################################################## ################################################################################
## Reads a file and returns entire content or undef if error. ## Reads a file and returns entire content or undef if error.
########################################################################## ################################################################################
sub read_file { sub read_file {
my $path = shift; my $path = shift;
@ -383,9 +386,9 @@ sub read_file {
} }
############################################################################### ################################################################################
# Sets user:group owner for the given file # Sets user:group owner for the given file
############################################################################### ################################################################################
sub set_file_permissions($$;$) { sub set_file_permissions($$;$) {
my ($pa_config, $file, $grants) = @_; my ($pa_config, $file, $grants) = @_;
if ($^O !~ /win/i ) { # Only for Linux environments if ($^O !~ /win/i ) { # Only for Linux environments
@ -410,10 +413,10 @@ sub set_file_permissions($$;$) {
} }
######################################################################## ################################################################################
## SUB pandora_trash_ascii ## SUB pandora_trash_ascii
# Generate random ascii strings with variable lenght # Generate random ascii strings with variable lenght
######################################################################## ################################################################################
sub pandora_trash_ascii { sub pandora_trash_ascii {
my $config_depth = $_[0]; my $config_depth = $_[0];
@ -426,9 +429,9 @@ sub pandora_trash_ascii {
return $output return $output
} }
######################################################################## ################################################################################
## Convert the $value encode in html entity to clear char string. ## Convert the $value encode in html entity to clear char string.
######################################################################## ################################################################################
sub safe_input($) { sub safe_input($) {
my $value = shift; my $value = shift;
@ -439,9 +442,9 @@ sub safe_input($) {
return $value; return $value;
} }
######################################################################## ################################################################################
## Convert the html entities to value encode to rebuild char string. ## Convert the html entities to value encode to rebuild char string.
######################################################################## ################################################################################
sub safe_output($) { sub safe_output($) {
my $value = shift; my $value = shift;
@ -452,10 +455,10 @@ sub safe_output($) {
return $value; return $value;
} }
######################################################################## ################################################################################
# Sub daemonize () # Sub daemonize ()
# Put program in background (for daemon mode) # Put program in background (for daemon mode)
######################################################################## ################################################################################
sub pandora_daemonize { sub pandora_daemonize {
my $pa_config = $_[0]; my $pa_config = $_[0];
@ -492,13 +495,13 @@ sub pandora_daemonize {
# Pandora other General functions | # Pandora other General functions |
# -------------------------------------------+ # -------------------------------------------+
######################################################################## ################################################################################
# SUB credential_store_get_key # SUB credential_store_get_key
# Retrieve all information related to target identifier. # Retrieve all information related to target identifier.
# param1 - config hash # param1 - config hash
# param2 - dbh link # param2 - dbh link
# param3 - string identifier # param3 - string identifier
######################################################################## ################################################################################
sub credential_store_get_key($$$) { sub credential_store_get_key($$$) {
my ($pa_config, $dbh, $identifier) = @_; my ($pa_config, $dbh, $identifier) = @_;
@ -520,7 +523,7 @@ sub credential_store_get_key($$$) {
} }
######################################################################## ################################################################################
# SUB pandora_sendmail # SUB pandora_sendmail
# Send a mail, connecting directly to MTA # Send a mail, connecting directly to MTA
# param1 - config hash # param1 - config hash
@ -528,7 +531,7 @@ sub credential_store_get_key($$$) {
# param3 - Email subject # param3 - Email subject
# param4 - Email Message body # param4 - Email Message body
# param4 - Email content type # param4 - Email content type
######################################################################## ################################################################################
sub pandora_sendmail { sub pandora_sendmail {
@ -584,10 +587,10 @@ sub pandora_sendmail {
}; };
} }
########################################################################## ################################################################################
# SUB is_numeric # SUB is_numeric
# Return TRUE if given argument is numeric # Return TRUE if given argument is numeric
########################################################################## ################################################################################
sub is_numeric { sub is_numeric {
my $val = $_[0]; 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) # SUB md5check (param_1, param_2)
# Verify MD5 file .checksum # Verify MD5 file .checksum
########################################################################## ################################################################################
# param_1 : Name of data file # param_1 : Name of data file
# param_2 : Name of md5 file # param_2 : Name of md5 file
@ -647,10 +696,10 @@ sub md5check {
} }
} }
######################################################################## ################################################################################
# SUB logger (pa_config, message, level) # SUB logger (pa_config, message, level)
# Log to file # Log to file
######################################################################## ################################################################################
sub logger ($$;$) { sub logger ($$;$) {
my ($pa_config, $message, $level) = @_; my ($pa_config, $message, $level) = @_;
@ -701,10 +750,10 @@ sub logger ($$;$) {
} }
} }
######################################################################## ################################################################################
# SUB pandora_rotate_log (pa_config) # SUB pandora_rotate_log (pa_config)
# Log to file # Log to file
######################################################################## ################################################################################
sub pandora_rotate_logfile ($) { sub pandora_rotate_logfile ($) {
my ($pa_config) = @_; my ($pa_config) = @_;
@ -720,9 +769,9 @@ sub pandora_rotate_logfile ($) {
} }
} }
######################################################################## ################################################################################
# limpia_cadena (string) - Purge a string for any forbidden characters (esc, etc) # limpia_cadena (string) - Purge a string for any forbidden characters (esc, etc)
######################################################################## ################################################################################
sub limpia_cadena { sub limpia_cadena {
my $micadena; my $micadena;
$micadena = $_[0]; $micadena = $_[0];
@ -736,9 +785,9 @@ sub limpia_cadena {
} }
} }
######################################################################## ################################################################################
# clean_blank (string) - Remove leading and trailing blanks # clean_blank (string) - Remove leading and trailing blanks
######################################################################## ################################################################################
sub clean_blank { sub clean_blank {
my $input = $_[0]; my $input = $_[0];
$input =~ s/^\s+//g; $input =~ s/^\s+//g;
@ -746,10 +795,10 @@ sub clean_blank {
return $input; return $input;
} }
######################################################################################## ################################################################################
# sub sqlWrap(texto) # sub sqlWrap(texto)
# Elimina comillas y caracteres problematicos y los sustituye por equivalentes # Elimina comillas y caracteres problematicos y los sustituye por equivalentes
######################################################################################## ################################################################################
sub sqlWrap { sub sqlWrap {
my $toBeWrapped = shift(@_); my $toBeWrapped = shift(@_);
@ -760,21 +809,21 @@ sub sqlWrap {
} }
} }
########################################################################## ################################################################################
# sub float_equal (num1, num2, decimals) # sub float_equal (num1, num2, decimals)
# This function make possible to compare two float numbers, using only x decimals # This function make possible to compare two float numbers, using only x decimals
# in comparation. # in comparation.
# Taken from Perl Cookbook, O'Reilly. Thanks, guys. # Taken from Perl Cookbook, O'Reilly. Thanks, guys.
########################################################################## ################################################################################
sub float_equal { sub float_equal {
my ($A, $B, $dp) = @_; my ($A, $B, $dp) = @_;
return sprintf("%.${dp}g", $A) eq sprintf("%.${dp}g", $B); return sprintf("%.${dp}g", $A) eq sprintf("%.${dp}g", $B);
} }
########################################################################## ################################################################################
# Tries to load the PandoraEnterprise module. Must be called once before # Tries to load the PandoraEnterprise module. Must be called once before
# enterprise_hook (). # enterprise_hook ().
########################################################################## ################################################################################
sub enterprise_load ($) { sub enterprise_load ($) {
my $pa_config = shift; my $pa_config = shift;
@ -809,9 +858,9 @@ sub enterprise_load ($) {
return 1; return 1;
} }
########################################################################## ################################################################################
# Tries to call a PandoraEnterprise function. Returns undef if unsuccessful. # Tries to call a PandoraEnterprise function. Returns undef if unsuccessful.
########################################################################## ################################################################################
sub enterprise_hook ($$) { sub enterprise_hook ($$) {
my $func = shift; my $func = shift;
my @args = @{shift ()}; my @args = @{shift ()};
@ -840,19 +889,19 @@ sub enterprise_hook ($$) {
return $output; return $output;
} }
######################################################################## ################################################################################
# Prints a message to STDOUT at the given log level. # Prints a message to STDOUT at the given log level.
######################################################################## ################################################################################
sub print_message ($$$) { sub print_message ($$$) {
my ($pa_config, $message, $log_level) = @_; my ($pa_config, $message, $log_level) = @_;
print STDOUT $message . "\n" if ($pa_config->{'verbosity'} >= $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 # Returns the value of an XML tag from a hash returned by XMLin (one level
# depth). # depth).
########################################################################## ################################################################################
sub get_tag_value ($$$;$) { sub get_tag_value ($$$;$) {
my ($hash_ref, $tag, $def_value, $all_array) = @_; my ($hash_ref, $tag, $def_value, $all_array) = @_;
$all_array = 0 unless defined ($all_array); $all_array = 0 unless defined ($all_array);
@ -871,10 +920,10 @@ sub get_tag_value ($$$;$) {
return $def_value; return $def_value;
} }
######################################################################## ################################################################################
# Initialize some variables needed by the MD5 algorithm. # Initialize some variables needed by the MD5 algorithm.
# See http://en.wikipedia.org/wiki/MD5#Pseudocode. # See http://en.wikipedia.org/wiki/MD5#Pseudocode.
######################################################################## ################################################################################
my (@R, @K); my (@R, @K);
sub md5_init () { sub md5_init () {
@ -890,10 +939,10 @@ sub md5_init () {
} }
} }
############################################################################### ################################################################################
# Return the MD5 checksum of the given string. # Return the MD5 checksum of the given string.
# Pseudocode from http://en.wikipedia.org/wiki/MD5#Pseudocode. # Pseudocode from http://en.wikipedia.org/wiki/MD5#Pseudocode.
############################################################################### ################################################################################
sub md5 ($) { sub md5 ($) {
my $str = shift; 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)); 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. # MD5 leftrotate function. See http://en.wikipedia.org/wiki/MD5#Pseudocode.
############################################################################### ################################################################################
sub leftrotate ($$) { sub leftrotate ($$) {
my ($x, $c) = @_; my ($x, $c) = @_;
return (0xFFFFFFFF & ($x << $c)) | ($x >> (32 - $c)); return (0xFFFFFFFF & ($x << $c)) | ($x >> (32 - $c));
} }
########################################################################## ################################################################################
## Convert a date (yyy-mm-ddThh:ii:ss) to Timestamp. ## Convert a date (yyy-mm-ddThh:ii:ss) to Timestamp.
########################################################################## ################################################################################
sub dateTimeToTimestamp { sub dateTimeToTimestamp {
$_[0] =~ /(\d{4})-(\d{2})-(\d{2})([ |T])(\d{2}):(\d{2}):(\d{2})/; $_[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); 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"; #print "BST\t" . mktime($sec, $min, $hour, $day, $mon - 1, $year - 1900, 0, 0) . "\n";
} }
############################################################################## ################################################################################
# Below some "internal" functions for automonitoring feature # Below some "internal" functions for automonitoring feature
# TODO: Implement the same for other systems like Solaris or BSD # TODO: Implement the same for other systems like Solaris or BSD
############################################################################## ################################################################################
sub disk_free ($) { sub disk_free ($) {
my $target = $_[0]; my $target = $_[0];
@ -1082,10 +1131,10 @@ sub free_mem {
return $free_mem; return $free_mem;
} }
########################################################################## ################################################################################
## SUB ticks_totime ## SUB ticks_totime
# Transform a snmp timeticks count in a date # Transform a snmp timeticks count in a date
########################################################################## ################################################################################
sub ticks_totime ($){ sub ticks_totime ($){
@ -1109,7 +1158,7 @@ sub ticks_totime ($){
return "$days days, $hours hours, $minutes minutes, $seconds seconds"; return "$days days, $hours hours, $minutes minutes, $seconds seconds";
} }
############################################################################## ################################################################################
=head2 C<< pandora_ping (I<$pa_config>, I<$host>) >> =head2 C<< pandora_ping (I<$pa_config>, I<$host>) >>
Ping the given host. Ping the given host.
@ -1118,7 +1167,7 @@ Returns:
0 otherwise. 0 otherwise.
=cut =cut
############################################################################## ################################################################################
sub pandora_ping ($$$$) { sub pandora_ping ($$$$) {
my ($pa_config, $host, $timeout, $retries) = @_; my ($pa_config, $host, $timeout, $retries) = @_;
@ -1236,13 +1285,13 @@ sub pandora_ping ($$$$) {
return $output; return $output;
} }
######################################################################## ################################################################################
=head2 C<< pandora_ping_latency (I<$pa_config>, I<$host>) >> =head2 C<< pandora_ping_latency (I<$pa_config>, I<$host>) >>
Ping the given host. Returns the average round-trip time. Returns undef if fails. Ping the given host. Returns the average round-trip time. Returns undef if fails.
=cut =cut
######################################################################## ################################################################################
sub pandora_ping_latency ($$$$) { sub pandora_ping_latency ($$$$) {
my ($pa_config, $host, $timeout, $retries) = @_; my ($pa_config, $host, $timeout, $retries) = @_;
@ -1375,32 +1424,118 @@ sub pandora_ping_latency ($$$$) {
return $output; return $output;
} }
######################################################################## ################################################################################
=head2 C<< pandora_block_ping (I<$pa_config>, I<$hosts>) >> =head2 C<< pandora_block_ping (I<$pa_config>, I<$hosts>) >>
Ping all given hosts. Returns an array with all hosts detected as alive. Ping all given hosts. Returns an array with all hosts detected as alive.
=cut =cut
######################################################################## ################################################################################
sub pandora_block_ping($@) { sub pandora_block_ping($@) {
my ($pa_config, @hosts) = @_; my ($pa_config, @hosts) = @_;
my ($cmd, $output);
# fping timeout in milliseconds if (-x $pa_config->{'fping'}) {
my $cmd = $pa_config->{'fping'} . " -a -q -t " . (1000 * $pa_config->{'networktimeout'}) . " " . (join (' ', @hosts)); # fping timeout in milliseconds
$cmd = $pa_config->{'fping'} . " -a -q -t " . (1000 * $pa_config->{'networktimeout'}) . " " . (join (' ', @hosts));
my @output = `$cmd 2>$DEVNULL`; @output = `$cmd 2>$DEVNULL`;
} else {
# Ping scan
foreach my $host (@hosts) {
if (ping($pa_config, $host) > 0) {
push @output, $host;
}
}
}
return @output; 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>) >> =head2 C<< month_have_days (I<$month>, I<$year>) >>
Pass a $month (as january 0 number and each month with numbers) and the 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. as number (for example 1981). And return the days of this month.
=cut =cut
######################################################################## ################################################################################
sub month_have_days($$) { sub month_have_days($$) {
my $month= shift(@_); my $month= shift(@_);
my $year= @_ ? shift(@_) : (1900 + (localtime())[5]); my $year= @_ ? shift(@_) : (1900 + (localtime())[5]);
@ -1428,9 +1563,9 @@ sub month_have_days($$) {
return $monthDays[$month]; return $monthDays[$month];
} }
############################################################################### ################################################################################
# Convert a text obj tag to an OID and update the module configuration. # Convert a text obj tag to an OID and update the module configuration.
############################################################################### ################################################################################
sub translate_obj ($$$) { sub translate_obj ($$$) {
my ($pa_config, $dbh, $obj) = @_; my ($pa_config, $dbh, $obj) = @_;
@ -1448,9 +1583,9 @@ sub translate_obj ($$$) {
return $oid; return $oid;
} }
############################################################################### ################################################################################
# Get the number of seconds left to the next execution of the given cron entry. # Get the number of seconds left to the next execution of the given cron entry.
############################################################################### ################################################################################
sub cron_next_execution { sub cron_next_execution {
my ($cron, $interval) = @_; my ($cron, $interval) = @_;
@ -1482,18 +1617,18 @@ sub cron_next_execution {
return $nex_time - $cur_time; return $nex_time - $cur_time;
} }
############################################################################### ################################################################################
# Get the number of seconds left to the next execution of the given cron entry. # Get the number of seconds left to the next execution of the given cron entry.
############################################################################### ################################################################################
sub cron_check_syntax ($) { sub cron_check_syntax ($) {
my ($cron) = @_; my ($cron) = @_;
return 0 if !defined ($cron); return 0 if !defined ($cron);
return ($cron =~ m/^(\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+$/); return ($cron =~ m/^(\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+ (\d|\*|-)+$/);
} }
############################################################################### ################################################################################
# Check if a value is inside an interval. # Check if a value is inside an interval.
############################################################################### ################################################################################
sub cron_check_interval { sub cron_check_interval {
my ($elem_cron, $elem_curr_time) = @_; my ($elem_cron, $elem_curr_time) = @_;
@ -1515,9 +1650,9 @@ sub cron_check_interval {
return 1; return 1;
} }
############################################################################### ################################################################################
# Get the next execution date for the given cron entry in seconds since epoch. # Get the next execution date for the given cron entry in seconds since epoch.
############################################################################### ################################################################################
sub cron_next_execution_date { sub cron_next_execution_date {
my ($cron, $cur_time, $interval) = @_; my ($cron, $cur_time, $interval) = @_;
@ -1646,11 +1781,11 @@ sub cron_next_execution_date {
return $nex_time; return $nex_time;
} }
############################################################################### ################################################################################
# Returns if a date is in a cron. Recursive. # Returns if a date is in a cron. Recursive.
# Needs the cron like an array reference and # Needs the cron like an array reference and
# current time in cron format to works properly # current time in cron format to works properly
############################################################################### ################################################################################
sub cron_is_in_cron { sub cron_is_in_cron {
my ($elems_cron, $elems_curr_time) = @_; my ($elems_cron, $elems_curr_time) = @_;
@ -1687,11 +1822,11 @@ sub cron_get_next_time_element {
? $floor_data ? $floor_data
: $elem_down; : $elem_down;
} }
############################################################################### ################################################################################
# Returns the interval of a cron element. If there is not a range, # 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 # returns an array with the first element in the first place of array
# and the second place undefined. # and the second place undefined.
############################################################################### ################################################################################
sub cron_get_interval { sub cron_get_interval {
my ($element) = @_; my ($element) = @_;
@ -1702,10 +1837,10 @@ sub cron_get_interval {
return ($1, $2); return ($1, $2);
} }
############################################################################### ################################################################################
# Returns the closest number to the target inside the given range (including # Returns the closest number to the target inside the given range (including
# the target itself). # the target itself).
############################################################################### ################################################################################
sub cron_get_closest_in_range ($$) { sub cron_get_closest_in_range ($$) {
my ($target, $range) = @_; my ($target, $range) = @_;
@ -1727,9 +1862,9 @@ sub cron_get_closest_in_range ($$) {
return $target; return $target;
} }
############################################################################### ################################################################################
# Check if a date is valid to get timelocal # Check if a date is valid to get timelocal
############################################################################### ################################################################################
sub cron_valid_date { sub cron_valid_date {
my ($min, $hour, $mday, $month, $year) = @_; my ($min, $hour, $mday, $month, $year) = @_;
my $utime; my $utime;
@ -1743,9 +1878,9 @@ sub cron_valid_date {
return $utime; return $utime;
} }
############################################################################### ################################################################################
# Attempt to resolve the given hostname. # Attempt to resolve the given hostname.
############################################################################### ################################################################################
sub resolve_hostname ($) { sub resolve_hostname ($) {
my ($hostname) = @_; my ($hostname) = @_;
@ -1755,9 +1890,9 @@ sub resolve_hostname ($) {
return inet_ntoa($resolved_hostname); return inet_ntoa($resolved_hostname);
} }
############################################################################### ################################################################################
# Returns 1 if the given regular expression is valid, 0 otherwise. # Returns 1 if the given regular expression is valid, 0 otherwise.
############################################################################### ################################################################################
sub valid_regex ($) { sub valid_regex ($) {
my $regex = shift; my $regex = shift;
@ -1773,9 +1908,9 @@ sub valid_regex ($) {
return 1; return 1;
} }
############################################################################### ################################################################################
# Returns 1 if a valid metaconsole license is configured, 0 otherwise. # Returns 1 if a valid metaconsole license is configured, 0 otherwise.
############################################################################### ################################################################################
sub is_metaconsole ($) { sub is_metaconsole ($) {
my ($pa_config) = @_; my ($pa_config) = @_;
@ -1788,9 +1923,9 @@ sub is_metaconsole ($) {
return 0; return 0;
} }
############################################################################### ################################################################################
# Returns 1 if a valid offline license is configured, 0 otherwise. # Returns 1 if a valid offline license is configured, 0 otherwise.
############################################################################### ################################################################################
sub is_offline ($) { sub is_offline ($) {
my ($pa_config) = @_; my ($pa_config) = @_;
@ -1802,9 +1937,9 @@ sub is_offline ($) {
return 0; return 0;
} }
############################################################################### ################################################################################
# Check if a given variable contents a number # Check if a given variable contents a number
############################################################################### ################################################################################
sub to_number($) { sub to_number($) {
my $n = shift; my $n = shift;
if ($n =~ /[\d+,]*\d+\.\d+/) { 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 sha256(join('|', ($agent_alias, $server_ip, time(), sprintf("%04d", rand(10000)))));
} }
############################################################################### ################################################################################
# Return the SHA256 checksum of the given string as a hex string. # Return the SHA256 checksum of the given string as a hex string.
# Pseudocode from: http://en.wikipedia.org/wiki/SHA-2#Pseudocode # Pseudocode from: http://en.wikipedia.org/wiki/SHA-2#Pseudocode
############################################################################### ################################################################################
my @K2 = ( my @K2 = (
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
@ -2079,34 +2214,34 @@ sub sha256 {
unpack ("H*", pack ("N", $h7)); unpack ("H*", pack ("N", $h7));
} }
############################################################################### ################################################################################
# Rotate a 32-bit number a number of bits to the right. # Rotate a 32-bit number a number of bits to the right.
############################################################################### ################################################################################
sub rightrotate { sub rightrotate {
my ($x, $c) = @_; my ($x, $c) = @_;
return (0xFFFFFFFF & ($x << (32 - $c))) | ($x >> $c); return (0xFFFFFFFF & ($x << (32 - $c))) | ($x >> $c);
} }
############################################################################### ################################################################################
# Returns IP address(v4) in longint format # Returns IP address(v4) in longint format
############################################################################### ################################################################################
sub ip_to_long { sub ip_to_long($) {
my $ip_str = shift; my $ip_str = shift;
return unpack "N", inet_aton($ip_str); return unpack "N", inet_aton($ip_str);
} }
############################################################################### ################################################################################
# Returns IP address(v4) in longint format # Returns IP address(v4) in longint format
############################################################################### ################################################################################
sub long_to_ip { sub long_to_ip {
my $ip_long = shift; my $ip_long = shift;
return inet_ntoa pack("N", ($ip_long)); return inet_ntoa pack("N", ($ip_long));
} }
############################################################################### ################################################################################
# Returns a list with enabled servers. # Returns a list with enabled servers.
############################################################################### ################################################################################
sub get_enabled_servers { sub get_enabled_servers {
my $conf = shift; my $conf = shift;