target discovery task id. * id_group => target group. * network => target CIDR. * graph => target graph (already built). * nodes => target agents or nodes. * relations => target array of relationships. * mode => simple (0) or advanced (1). * map_options => Map options. * * @return object New networkmap manager. */ public function __construct($options=false) { // Default mapOptions values. // Defines the command to generate positions. $this->mapOptions['generation_method'] = LAYOUT_SPRING1; $this->mapOptions['simple'] = 0; $this->mapOptions['font_size'] = 12; $this->mapOptions['nooverlap'] = 1; $this->mapOptions['z_dash'] = 0.5; $this->mapOptions['ranksep'] = 0.5; $this->mapOptions['center'] = 0; $this->mapOptions['regen'] = 0; $this->mapOptions['pure'] = 1; $this->mapOptions['show_snmp_modules'] = false; $this->mapOptions['cut_names'] = false; $this->mapOptions['relative'] = true; $this->mapOptions['text_filter'] = ''; $this->mapOptions['dont_show_subgroups'] = false; $this->mapOptions['strict_user'] = false; $this->mapOptions['size_canvas'] = null; $this->mapOptions['old_mode'] = false; $this->mapOptions['map_filter'] = [ 'dont_show_subgroups' => 0, 'node_radius' => 40, 'x_offs' => 0, 'y_offs' => 0, 'z_dash' => 0.5, 'node_sep' => 0.1, 'rank_sep' => 0.1, 'mindist' => 1, 'kval' => 0.1, ]; if (is_array($options)) { // Previously nodes_and_relations. if (isset($options['graph'])) { $this->graph = $options['graph']; } // String dotmap. if (isset($options['dot_graph'])) { $this->dotGraph = $options['dot_graph']; } // Array of nodes, agents, virtual, etc. if (isset($options['nodes'])) { $this->nodes = $options['nodes']; } // Array of relations. if (isset($options['relations'])) { $this->relations = $options['relations']; } // User interface type. Simple or advanced. if (isset($options['mode'])) { $this->mode = $options['mode']; } // Map options, check default values above. // This is only used while generating new maps using // (generateDotGraph). if (is_array($options['map_options'])) { foreach ($options['map_options'] as $k => $v) { $this->mapOptions[$k] = $v; } } // Load from tmap. if ($options['id_map']) { $this->idMap = $options['id_map']; // Update nodes and relations. $this->loadMap(); if (empty($this->nodes) || empty($this->relations) ) { $this->createMap(); } } else { // Generate from group, task or network. if ($options['id_group']) { $this->idGroup = $options['id_group']; } if ($options['id_task']) { $this->idTask = $options['id_task']; } if ($options['network']) { $this->network = $options['network']; } $this->createMap(); } } return $this; } /** * Creates a new map based on a target. * * Target is specified from constructor arguments. * options: * - id_task => create a map from task. * - id_group => create a map from group. * - network => create a map from network. * * @return void */ public function createMap() { // If exists, load from DB. if ($this->idMap) { $this->loadMap(); return; } // Simulated map. $this->idMap = uniqid(); // No tmap definition. Paint data. if ($this->idTask) { $recon_task = db_get_row_filter( 'trecon_task', ['id_rt' => $this->idTask] ); $this->network = $recon_task['subnet']; } // Simulate map entry. $this->map = [ 'id' => $this->idMap, '__simulated' => 1, 'background' => '', 'background_options' => 0, 'source_period' => 60, 'filter' => $this->mapOptions['map_filter'], 'width' => 0, 'height' => 0, 'center_x' => 0, 'center_y' => 0, ]; // Will be stored in $this->graph. $this->generateNetworkMap(); } /** * Loads a map from a target map ID. * * @return void. */ public function loadMap() { if ($this->map) { // Already loaded. return; } if ($this->idMap) { $this->map = db_get_row('tmap', 'id', $this->idMap); $this->mapOptions['map_filter'] = json_decode( $this->map['filter'], true ); foreach ($this->map as $k => $v) { $this->mapOptions[$k] = $v; } // Retrieve data origin. $this->network = null; $this->idTask = null; $this->idGroup = $this->map['id_group']; switch ($this->map['source']) { case SOURCE_GROUP: $this->idGroup = $this->map['source_data']; break; case SOURCE_TASK: $this->idTask = $this->map['source_data']; break; case SOURCE_NETWORK: $this->network = $this->map['source_data']; break; default: // Ignore. break; } if ($this->idTask) { $recon_task = db_get_row_filter( 'trecon_task', ['id_rt' => $networkmap['source_data']] ); $this->network = $recon_task['subnet']; } // Retrieve or update nodes and relations. $this->getNodes(); $this->getRelations(); // Nodes and relations will be stored in $this->graph. $this->loadGraph(); } } /** * Return nodes of current map. * * @return array Nodes. */ public function getNodes() { if ($this->nodes) { return $this->nodes; } if ($this->idMap !== false) { if (enterprise_installed()) { // Enterprise environment: LOAD. $this->nodes = enterprise_hook( 'get_nodes_from_db', [$this->idMap] ); } } return $this->nodes; } /** * Return relations of current map. * * @return array Relations. */ public function getRelations() { if ($this->relations) { return $this->relations; } if ($this->idMap !== false) { if (enterprise_installed()) { $this->relations = enterprise_hook( 'get_relations_from_db', [$this->idMap] ); } } return $this->relations; } /** * Generates or loads nodes&relations array from data load * and stores it in $this->graph. * * @return void */ public function loadGraph() { $nodes = $this->nodes; $relations = $this->relations; // Generate if there's no data in DB about nodes or relations. if (empty($nodes) || empty($relations)) { $this->generateNetworkMap(); return; } $nodes_and_relations = []; $nodes_and_relations['nodes'] = []; $index_nodes = 0; foreach ($nodes as $node) { if (!$node['deleted']) { $nodes_and_relations['nodes'][$index_nodes]['id_map'] = $node['id_map']; $nodes_and_relations['nodes'][$index_nodes]['x'] = $node['x']; $nodes_and_relations['nodes'][$index_nodes]['y'] = $node['y']; $nodes_and_relations['nodes'][$index_nodes]['source_data'] = $node['source_data']; $nodes_and_relations['nodes'][$index_nodes]['type'] = $node['type']; $style_node = json_decode($node['style'], true); $style = []; $style['shape'] = $style_node['shape']; $style['image'] = $style_node['image']; $style['width'] = $style_node['width']; $style['height'] = $style_node['height']; $style['label'] = $style_node['label']; $style['id_networkmap'] = $style_node['networkmap']; $nodes_and_relations['nodes'][$index_nodes]['style'] = json_encode($style); if ($node['type'] == 1) { $nodes_and_relations['nodes'][$index_nodes]['id_agent'] = $style_node['id_agent']; } $nodes_and_relations['nodes'][$index_nodes]['id_in_db'] = $node['id']; $index_nodes++; } } $nodes_and_relations['relations'] = []; $index_relations = 0; foreach ($relations as $relation) { $nodes_and_relations['relations'][$index_relations]['id_map'] = $relation['id_map']; $nodes_and_relations['relations'][$index_relations]['id_parent'] = $relation['id_parent']; $nodes_and_relations['relations'][$index_relations]['id_child'] = $relation['id_child']; $nodes_and_relations['relations'][$index_relations]['parent_type'] = $relation['parent_type']; $nodes_and_relations['relations'][$index_relations]['child_type'] = $relation['child_type']; $nodes_and_relations['relations'][$index_relations]['id_parent_source_data'] = $relation['id_parent_source_data']; $nodes_and_relations['relations'][$index_relations]['id_child_source_data'] = $relation['id_child_source_data']; $index_relations++; } $this->graph = $nodes_and_relations; } /** * Generate a graphviz string structure to be used later. * * @return void */ public function generateDotGraph() { if (!isset($this->dotGraph)) { // Generate dot file. $this->dotGraph = networkmap_generate_dot( get_product_name(), $this->idGroup, $this->mapOptions['simple'], $this->mapOptions['font_size'], $this->mapOptions['layout'], $this->mapOptions['nooverlap'], $this->mapOptions['z_dash'], $this->mapOptions['ranksep'], $this->mapOptions['center'], $this->mapOptions['regen'], $this->mapOptions['pure'], $this->mapOptions['id'], $this->mapOptions['show_snmp_modules'], $this->mapOptions['cut_names'], $this->mapOptions['relative'], $this->mapOptions['text_filter'], $this->network, $this->mapOptions['dont_show_subgroups'], // Strict user (strict_user). false, // Canvas size (size_canvas). null, $this->mapOptions['old_mode'], $this->mapOptions['map_filter'] ); } } /** * Creates an empty dot graph (with only base node) * * @return void */ public function generateEmptyDotGraph() { // Create an empty map dot structure. $graph = networkmap_open_graph( $this->mapOptions['layout'], $this->mapOptions['nooverlap'], $this->mapOptions['pure'], $this->mapOptions['z_dash'], $this->mapOptions['ranksep'], $this->mapOptions['font_size'], null ); $graph .= networkmap_create_pandora_node( get_product_name(), $this->mapOptions['font_size'], $this->mapOptions['simple'] ); $graph .= networkmap_close_graph(); $this->dotGraph = $graph; } /** * Generates a nodes - relationships array using graphviz dot * schema and stores nodes&relations into $this->graph. * * @return void */ public function generateNetworkMap() { global $config; include_once 'include/functions_os.php'; $map_filter = json_decode( $this->map['filter'], true ); /* * Let graphviz place the nodes. */ switch ($this->mapOptions['generation_method']) { case LAYOUT_CIRCULAR: $filter = 'circo'; $this->mapOptions['layout'] = 'circular'; break; case LAYOUT_FLAT: $filter = 'dot'; $this->mapOptions['layout'] = 'flat'; break; case LAYOUT_RADIAL: $filter = 'twopi'; $this->mapOptions['layout'] = 'radial'; break; case LAYOUT_SPRING1: default: $filter = 'neato'; $this->mapOptions['layout'] = 'spring1'; break; case LAYOUT_SPRING2: $filter = 'fdp'; $this->mapOptions['layout'] = 'spring2'; break; } if ($map_filter['empty_map']) { $this->generateEmptyDotGraph(); } else if (!isset($this->dotGraph)) { $this->generateDotGraph(); } switch (PHP_OS) { case 'WIN32': case 'WINNT': case 'Windows': $filename_dot = sys_get_temp_dir()."\\networkmap_".$filter; break; default: $filename_dot = sys_get_temp_dir().'/networkmap_'.$filter; break; } if ($simple) { $filename_dot .= '_simple'; } if ($nooverlap) { $filename_dot .= '_nooverlap'; } $filename_dot .= uniqid().'_'.$this->idMap.'.dot'; file_put_contents($filename_dot, $this->dotGraph); $plain_file = 'plain'.uniqid().'.txt'; switch (PHP_OS) { case 'WIN32': case 'WINNT': case 'Windows': $filename_plain = sys_get_temp_dir().'\\'.$plain_file; $cmd = io_safe_output( $config['graphviz_bin_dir'].'\\'.$filter.'.exe -Tplain -o '.$filename_plain.' '.$filename_dot ); break; default: $filename_plain = sys_get_temp_dir().'/'.$plain_file; $cmd = $filter.' -Tplain -o '.$filename_plain.' '.$filename_dot; break; } $retval = 0; $r = system($cmd, $retval); if ($retval != 0) { ui_print_error_message( __('Failed to generate dotmap, please select different layout schema') ); $this->graph = networkmap_process_networkmap($this->idMap); return; } unlink($filename_dot); $nodes = networkmap_loadfile( $this->idMap, $filename_plain, $relation_nodes, $this->dotGraph ); unlink($filename_plain); /* * Graphviz section ends here. */ /* * Calculate references. */ // Set the position of modules. foreach ($nodes as $key => $node) { if ($node['type'] == 'module') { // Search the agent of this module for to get the // position. foreach ($nodes as $key2 => $node2) { if ($node2['id_agent'] != 0 && $node2['type'] == 'agent') { if ($node2['id_agent'] == $node['id_agent']) { $nodes[$key]['coords'][0] = ($nodes[$key2]['coords'][0] + $node['height'] / 2); $nodes[$key]['coords'][1] = ($nodes[$key2]['coords'][1] + $node['width'] / 2); } } } } } $nodes_and_relations['nodes'] = []; $index = 0; $node_center = []; foreach ($nodes as $key => $node) { $nodes_and_relations['nodes'][$index]['id'] = $node['id']; $nodes_and_relations['nodes'][$index]['id_map'] = $this->idMap; $children_count = 0; foreach ($relation_nodes as $relation) { if (($relation['parent_type'] == 'agent') || ($relation['parent_type'] == '')) { if ($nodes[$relation['id_parent']]['id_agent'] == $node['id_agent']) { $children_count++; } } else if ($relation['parent_type'] == 'module') { if ($nodes[$relation['id_parent']]['id_module'] == $node['id_module']) { $children_count++; } } } if (empty($node_center) || $node_center['counter'] < $children_count) { $node_center['x'] = (int) $node['coords'][0]; $node_center['y'] = (int) $node['coords'][1]; $node_center['counter'] = $children_count; } $nodes_and_relations['nodes'][$index]['x'] = (int) $node['coords'][0]; $nodes_and_relations['nodes'][$index]['y'] = (int) $node['coords'][1]; if (($node['type'] == 'agent') || ($node['type'] == '')) { $nodes_and_relations['nodes'][$index]['source_data'] = $node['id_agent']; $nodes_and_relations['nodes'][$index]['type'] = 0; } else { $nodes_and_relations['nodes'][$index]['source_data'] = $node['id_module']; $nodes_and_relations['nodes'][$index]['id_agent'] = $node['id_agent']; $nodes_and_relations['nodes'][$index]['type'] = 1; } $style = []; $style['shape'] = 'circle'; $style['image'] = $node['image']; $style['width'] = $node['width']; $style['height'] = $node['height']; $style['label'] = $node['text']; $nodes_and_relations['nodes'][$index]['style'] = json_encode($style); $index++; } $nodes_and_relations['relations'] = []; $index = 0; foreach ($relation_nodes as $relation) { $nodes_and_relations['relations'][$index]['id_map'] = $this->idMap; if (($relation['parent_type'] == 'agent') || ($relation['parent_type'] == '')) { $nodes_and_relations['relations'][$index]['id_parent'] = $relation['id_parent']; $nodes_and_relations['relations'][$index]['id_parent_source_data'] = $nodes[$relation['id_parent']]['id_agent']; $nodes_and_relations['relations'][$index]['parent_type'] = 0; } else if ($relation['parent_type'] == 'module') { $nodes_and_relations['relations'][$index]['id_parent'] = $relation['id_parent']; $nodes_and_relations['relations'][$index]['id_parent_source_data'] = $nodes[$relation['id_parent']]['id_module']; $nodes_and_relations['relations'][$index]['parent_type'] = 1; } else { $nodes_and_relations['relations'][$index]['id_parent'] = $relation['id_parent']; $nodes_and_relations['relations'][$index]['id_child_source_data'] = -2; $nodes_and_relations['relations'][$index]['parent_type'] = 3; } if (($relation['child_type'] == 'agent') || ($relation['child_type'] == '')) { $nodes_and_relations['relations'][$index]['id_child'] = $relation['id_child']; $nodes_and_relations['relations'][$index]['id_child_source_data'] = $nodes[$relation['id_child']]['id_agent']; $nodes_and_relations['relations'][$index]['child_type'] = 0; } else if ($relation['child_type'] == 'module') { $nodes_and_relations['relations'][$index]['id_child'] = $relation['id_child']; $nodes_and_relations['relations'][$index]['id_child_source_data'] = $nodes[$relation['id_child']]['id_module']; $nodes_and_relations['relations'][$index]['child_type'] = 1; } else { $nodes_and_relations['relations'][$index]['id_child'] = $relation['id_child']; $nodes_and_relations['relations'][$index]['id_child_source_data'] = -2; $nodes_and_relations['relations'][$index]['child_type'] = 3; } $index++; } if ($this->idMap > 0 && (!isset($this->map['__simulated']))) { if (enterprise_installed()) { $nodes_and_relations = enterprise_hook( 'save_generate_nodes', [ $this->idMap, $nodes_and_relations, ] ); } $center = [ 'x' => $node_center['x'], 'y' => $node_center['y'], ]; $this->map['center_x'] = $center['x']; $this->map['center_y'] = $center['y']; db_process_sql_update( 'tmap', [ 'center_x' => $this->map['center_x'], 'center_y' => $this->map['center_y'], ], ['id' => $this->idMap] ); } else { $this->map['center_x'] = $node_center['x']; $this->map['center_y'] = $node_center['y']; } $this->graph = $nodes_and_relations; } /** * Transform node information into JS data. * * @return string HTML code with JS data. */ public function loadMapData() { $networkmap = $this->map; $simulate = false; if (!isset($networkmap['__simulated'])) { $networkmap['filter'] = json_decode( $networkmap['filter'], true ); $networkmap['filter']['holding_area'] = [ 500, 500, ]; $holding_area_title = __('Holding Area'); } else { $simulate = true; $holding_area_title = ''; $networkmap['filter']['holding_area'] = [ 0, 0, ]; } $this->graph['relations'] = clean_duplicate_links( $this->graph['relations'] ); // Print some params to handle it in js. html_print_input_hidden('product_name', get_product_name()); html_print_input_hidden('center_logo', ui_get_full_url(ui_get_logo_to_center_networkmap())); $output .= ''; return $output; } /** * Show an advanced interface to manage dialogs. * * @return string HTML code with dialogs. */ public function loadAdvancedInterface() { $list_networkmaps = get_networkmaps($this->idMap); if (empty($list_networkmaps)) { $list_networkmaps = []; } $output .= '
'; $output .= ' '; $output .= ' '; $output .= ' '; return $output; } /** * Loads advanced map controller (JS). * * @return string HTML code for advanced controller. */ public function loadController() { $output = ''; // Generate JS for advanced controller. $output .= ' '; if ($return === false) { echo $output; } return $output; } /** * Load networkmap HTML skel and JS requires. * * @return string HTML code for skel. */ public function loadMapSkel() { global $config; ui_require_css_file('networkmap'); ui_require_css_file('jquery.contextMenu', 'include/styles/js/'); $output = ''; $minimap_display = ''; if ($this->mapOptions['pure']) { $minimap_display = 'none'; } $networkmap = $this->map; $networkmap['filter'] = json_decode($networkmap['filter'], true); $networkmap['filter']['l2_network_interfaces'] = 1; $output .= ''; $output .= ''; $output .= ''; // Open networkconsole_id div. $output .= '