From 895b7c74032bc4b04e3b05a424b629c59514cc5e Mon Sep 17 00:00:00 2001 From: alejandro Date: Mon, 23 Jan 2023 18:17:05 +0100 Subject: [PATCH 01/24] added exchange mail plugin --- .../Exchange_mail/exchange_mail.py | 451 ++++++++++++++++++ 1 file changed, 451 insertions(+) create mode 100644 pandora_plugins/Exchange_mail/exchange_mail.py diff --git a/pandora_plugins/Exchange_mail/exchange_mail.py b/pandora_plugins/Exchange_mail/exchange_mail.py new file mode 100644 index 0000000000..638c00d07e --- /dev/null +++ b/pandora_plugins/Exchange_mail/exchange_mail.py @@ -0,0 +1,451 @@ +# -*- coding: utf-8 -*- +from exchangelib import DELEGATE, Account, Credentials, Configuration,Message, Mailbox +from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter +from exchangelib import EWSTimeZone, EWSDateTime +BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter + +import urllib3 +urllib3.disable_warnings() + +import argparse,sys,re,json,os,traceback +from datetime import datetime,timedelta,timezone + + +__author__ = "Alejandro Sánchez Carrion" +__copyright__ = "Copyright 2022, PandoraFMS" +__maintainer__ = "Operations department" +__status__ = "Production" +__version__= '1.0' + +info = f""" +Pandora FMS Exchange Mail +Version = {__version__} +Description = This plugin can search for matches in your mail and find the number of matches, as well as list them. + +Manual execution + +./exchange_mail --server --username --password [ --subject ] [ --sender ] [ --date_start ] [ --date_end ] [ --agent_name ] [ --as_agent_plugin ] [ --tentacle_port ] [ --tentacle_address ] [ -g ] [ --data_dir ] + +there are four parameters with which to filter the mails + +subject +email +date + +You can use only one and filter from that or use the following combinations: + +subject +subject + sender +subject + sender + date +""" + +parser = argparse.ArgumentParser(description= info, formatter_class=argparse.RawTextHelpFormatter) +parser.add_argument('--server', help="Server name") +parser.add_argument('--username', help="User name") +parser.add_argument('--password', help="Password") +parser.add_argument('--smtp_address', help="SMTP address") +parser.add_argument('--subject', help="Select match in subjects") +parser.add_argument('--sender', help="Select coincidences from email") +parser.add_argument('--date_start', help="Search for matches from a certain date,Each date must be separated by a hyphen and in quotation marks, with the following format: 'year-month-day-hour-minute'. example: '2021-1-12-0-0'") +parser.add_argument('--date_end', help="Search for matches from a certain date,Each date must be separated by a hyphen and in quotation marks, with the following format: 'year-month-day-hour-minute'. example: '2021-6-12-0-0'") +parser.add_argument('--mail_list', help='List mail coincidences',type=int,default=0) + +parser.add_argument('--agent_name', help='agent name', default= "Exchange") +parser.add_argument('--module_prefix', help='module prefix', default= "Exchange") +parser.add_argument('-g', '--group', help='PandoraFMS destination group (default exchange)', default='exchange') +parser.add_argument('--data_dir', help='PandoraFMS data dir (default: /var/spool/pandora/data_in/)', default='/var/spool/pandora/data_in/') +parser.add_argument('--as_agent_plugin', help='mode plugin', default=0,type=int) +parser.add_argument('--tentacle_port', help='tentacle port', default=41121) +parser.add_argument('--tentacle_address', help='tentacle adress', default=None) + + +args = parser.parse_args() + +username,password,server,smtp_address=args.username,args.password,args.server,args.smtp_address + + +### Pandora Tools ###------------------------------------------------------------------------------------------------------- +modules = [] + +configuration = { + "data_in": args.data_dir, + "group" : args.group +} + +######################################################################################### +# print_agent +######################################################################################### +def print_agent(agent, modules, data_dir="/var/spool/pandora/data_in/", log_modules= None, print_flag = None): + """Prints agent XML. Requires agent conf (dict) and modules (list) as arguments. + - Use print_flag to show modules' XML in STDOUT. + - Returns a tuple (xml, data_file). + """ + data_file=None + + header = "\n" + header += "\n" + "\t\n" + "\t" + str(data["type"]) + "\n" + ) + + if type(data["type"]) is not str and "string" not in data["type"]: #### Strip spaces if module not generic_data_string + data["value"] = data["value"].strip() + if isinstance(data["value"], list): # Checks if value is a list + module_xml += "\t\n" + for value in data["value"]: + if type(value) is dict and "value" in value: + module_xml += "\t\n" + module_xml += "\t\t\n" + if "timestamp" in value: + module_xml += "\t\t\n" + module_xml += "\t\n" + module_xml += "\t\n" + else: + module_xml += "\t\n" + if "desc" in data: + module_xml += "\t\n" + if "unit" in data: + module_xml += "\t\n" + if "interval" in data: + module_xml += "\t\n" + if "tags" in data: + module_xml += "\t" + str(data["tags"]) + "\n" + if "module_group" in data: + module_xml += "\t" + str(data["module_group"]) + "\n" + if "module_parent" in data: + module_xml += "\t" + str(data["module_parent"]) + "\n" + if "min_warning" in data: + module_xml += "\t\n" + if "min_warning_forced" in data: + module_xml += "\t\n" + if "max_warning" in data: + module_xml += "\t\n" + if "max_warning_forced" in data: + module_xml += "\t\n" + if "min_critical" in data: + module_xml += "\t\n" + if "min_critical_forced" in data: + module_xml += "\t\n" + if "max_critical" in data: + module_xml += "\t\n" + if "max_critical_forced" in data: + module_xml += "\t\n" + if "str_warning" in data: + module_xml += "\t\n" + if "str_warning_forced" in data: + module_xml += "\t\n" + if "str_critical" in data: + module_xml += "\t\n" + if "str_critical_forced" in data: + module_xml += "\t\n" + if "critical_inverse" in data: + module_xml += "\t\n" + if "warning_inverse" in data: + module_xml += "\t\n" + if "max" in data: + module_xml += "\t\n" + if "min" in data: + module_xml += "\t\n" + if "post_process" in data: + module_xml += "\t\n" + if "disabled" in data: + module_xml += "\t\n" + if "min_ff_event" in data: + module_xml += "\t\n" + if "status" in data: + module_xml += "\t\n" + if "timestamp" in data: + module_xml += "\t\n" + if "custom_id" in data: + module_xml += "\t\n" + if "critical_instructions" in data: + module_xml += "\t\n" + if "warning_instructions" in data: + module_xml += "\t\n" + if "unknown_instructions" in data: + module_xml += "\t\n" + if "quiet" in data: + module_xml += "\t\n" + if "module_ff_interval" in data: + module_xml += "\t\n" + if "crontab" in data: + module_xml += "\t\n" + if "min_ff_event_normal" in data: + module_xml += "\t\n" + if "min_ff_event_warning" in data: + module_xml += "\t\n" + if "min_ff_event_critical" in data: + module_xml += "\t\n" + if "ff_type" in data: + module_xml += "\t\n" + if "ff_timeout" in data: + module_xml += "\t\n" + if "each_ff" in data: + module_xml += "\t\n" + if "module_parent_unlink" in data: + module_xml += "\t\n" + if "global_alerts" in data: + for alert in data["alert"]: + module_xml += "\t\n" + module_xml += "\n" + + if print_flag: + print (module_xml) + + return (module_xml) + +######################################################################################### +# write_xml +######################################################################################### + +def write_xml(xml, agent_name, data_dir="/var/spool/pandora/data_in/"): + """Creates a agent .data file in the specified data_dir folder\n + Args: + - xml (str): XML string to be written in the file. + - agent_name (str): agent name for the xml and file name. + - data_dir (str): folder in which the file will be created.""" + Utime = datetime.now().strftime('%s') + data_file = "%s/%s.%s.data" %(str(data_dir),agent_name,str(Utime)) + try: + with open(data_file, 'x') as data: + data.write(xml) + except OSError as o: + sys.exit(f"ERROR - Could not write file: {o}, please check directory permissions") + except Exception as e: + sys.exit(f"{type(e).__name__}: {e}") + return (data_file) + +# # default agent +def clean_agent() : + global agent + agent = { + "agent_name" : "", + "agent_alias" : "", + "parent_agent_name" : "", + "description" : "", + "version" : "", + "os_name" : "", + "os_version" : "", + "timestamp" : datetime.today().strftime('%Y/%m/%d %H:%M:%S'), + #"utimestamp" : int(datetime.timestamp(datetime.today())), + "address" : "", + "group" : configuration["group"], + "interval" : "", + "agent_mode" : "1", + } + return agent + +# default module +def clean_module() : + global modulo + modulo = { + "name" : "", + "type" : "generic_data_string", + "desc" : "", + "value" : "", + } + return modulo + +######################################################################################### +# tentacle_xml +######################################################################################### +def tentacle_xml(file, tentacle_ops,tentacle_path='', debug=0): + """Sends file using tentacle protocol\n + - Only works with one file at time. + - file variable needs full file path. + - tentacle_opts should be a dict with tentacle options (address [password] [port]). + - tentacle_path allows to define a custom path for tentacle client in case is not in sys path). + - if debug is enabled, the data file will not be removed after being sent. + + Returns 0 for OK and 1 for errors. + """ + + if file is None : + sys.stderr.write("Tentacle error: file path is required.") + else : + data_file = file + + if tentacle_ops['address'] is None : + sys.stderr.write("Tentacle error: No address defined") + return 1 + + try : + with open(data_file, 'r') as data: + data.read() + data.close() + except Exception as e : + sys.stderr.write(f"Tentacle error: {type(e).__name__} {e}") + return 1 + + tentacle_cmd = f"{tentacle_path}tentacle_client -v -a {tentacle_ops['address']} " + if "port" in tentacle_ops: + tentacle_cmd += f"-p {tentacle_ops['port']} " + if "password" in tentacle_ops: + tentacle_cmd += f"-x {tentacle_ops['password']} " + tentacle_cmd += f"{data_file} " + + tentacle_exe=Popen(tentacle_cmd, stdout=PIPE, shell=True) + rc=tentacle_exe.wait() + + if rc != 0 : + sys.stderr.write("Tentacle error") + return 1 + elif debug == 0 : + os.remove(file) + + return 0 + +## funcion agent +def agentplugin(modules,agent,plugin_type="server",data_dir="/var/spool/pandora/data_in/",tentacle=False,tentacle_conf=None) : + if plugin_type == "server": + for modulo in modules: + print_module(modulo,1) + + elif tentacle == True and tentacle_conf is not None: + agent_file=print_agent(agent, modules,data_dir) + if agent_file[1] is not None: + tentacle_xml(agent_file[1],tentacle_conf) + print ("1") + else: + print_agent(agent, modules,data_dir) + print ("1") + +def parse_result(list_email,sep="")-> list: + """ + + Return list containing each line as element + """ + + result=[] + + for line in list_email: + str_line=sep.join(str(elem) for elem in line) + str_dict={"value":str_line} + result.append(str_dict) + + return result + +# Create agent +clean_agent() +agent.update( + agent_name = args.agent_name , + agent_alias =args.agent_name , + description ="" +) + + +def connect(username,password,server,smtp_address): + creds = Credentials( + username=args.username, + password=args.password + ) + + try: + config = Configuration(server=args.server, credentials=creds) + + account = Account( + primary_smtp_address=args.smtp_address, + autodiscover=False, + config=config, + access_type=DELEGATE + ) + return account + except Exception as e: + sys.exit(f"{type(e).__name__}: {e}") + #print(account.root.tree()) + +account=connect(args.username,args.password,args.server,args.smtp_address) + +## Only one parameter +if args.subject and args.sender==None and args.date_start==None and args.date_end == None: + filtered_items = account.inbox.filter(subject__contains=args.subject) +if args.subject==None and args.sender and args.date_start==None and args.date_end == None: + filtered_items = account.inbox.filter(sender__icontains=args.sender) +if args.subject==None and args.sender==None and args.date_start and args.date_end : + date_start=args.date_start.split("-") + date_end=args.date_end.split("-") + filtered_items = account.inbox.filter(datetime_received__range=(datetime(int(date_start[0].strip()), int(date_start[1].strip()), int(date_start[2].strip()), int(date_start[3].strip()), int(date_start[4].strip())).replace(tzinfo=timezone.utc),datetime(int(date_end[0].strip()), int(date_end[1].strip()), int(date_end[2].strip()), int(date_end[3].strip()), int(date_end[4].strip())).replace(tzinfo=timezone.utc))) + +## Subject + sender +if args.subject and args.sender and args.date_start==None and args.date_end==None : + filtered_items = account.inbox.filter(sender__icontains=args.sender,subject__contains=args.subject) + +## All parameters +if args.subject and args.sender and args.date_start and args.date_end : + date_start=args.date_start.split("-") + date_end=args.date_end.split("-") + filtered_items = account.inbox.filter(datetime_received__range=(datetime(int(date_start[0].strip()), int(date_start[1].strip()), int(date_start[2].strip()), int(date_start[3].strip()), int(date_start[4].strip())).replace(tzinfo=timezone.utc),datetime(int(date_end[0].strip()), int(date_end[1].strip()), int(date_end[2].strip()), int(date_end[3].strip()), int(date_end[4].strip())).replace(tzinfo=timezone.utc)),sender__icontains=args.sender,subject__contains=args.subject) + +# List Number email coincidences +list_email=[] +# Count number messages coincidences +count=0 + +for item in filtered_items: + + count=count+1 + + list_email.append("("+str(item.datetime_received) + ") - "+str(item.subject)+" - "+str(item.sender)) + + #print(item.subject, item.sender, item.datetime_received) + +list_email = parse_result(list_email) + +clean_module() +modulo.update( + name = f"{args.module_prefix}.Coincidences_count", + type = "generic_data", + desc = "Number of mails matching the filter used in the run", + value = count +) +modules.append(modulo) + +if args.mail_list: + clean_module() + modulo.update( + name = f"{args.module_prefix}.Coincidences_list", + type = "generic_data_string", + desc = "List of mails matching the filter used in the run", + timestamp=datetime.today().strftime('%Y/%m/%d %H:%M:%S'), + value = list_email + ) + modules.append(modulo) + + +if args.tentacle_address is not None: + tentacle_conf={"address":args.tentacle_address,"port":args.tentacle_port} + agentplugin(modules,agent,"agent",configuration["data_in"],True,tentacle_conf) +elif args.as_agent_plugin!=1: + agentplugin(modules,agent,"agent",configuration["data_in"]) +else: + agentplugin(modules,agent) From bb8c55bf78b8cee73111a268a232df15367b42ef Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 20 Dec 2023 11:06:37 +0100 Subject: [PATCH 02/24] not show servers in metaconsole pandora_enterprise#12178 --- pandora_console/include/functions_servers.php | 58 ++++++++++++++----- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/pandora_console/include/functions_servers.php b/pandora_console/include/functions_servers.php index ff6fab73c6..d95e23494d 100644 --- a/pandora_console/include/functions_servers.php +++ b/pandora_console/include/functions_servers.php @@ -615,7 +615,7 @@ function servers_get_rate($avg_interval, $num_modules) * This function will get all the server information in an array * or a specific server. * - * @param integer $id_server An optional integer or array of integers + * @param integer|array $id_server An optional integer or array of integers * to select specific servers. * * @return mixed False in case the server doesn't exist or an array with info. @@ -624,28 +624,56 @@ function servers_get_info($id_server=-1, $sql_limit=-1) { global $config; - if (is_array($id_server)) { - $select_id = ' WHERE id_server IN ('.implode(',', $id_server).')'; + $select_id = ''; + if (is_array($id_server) === true) { + $select_id = ' AND id_server IN ('.implode(',', $id_server).')'; } else if ($id_server > 0) { - $select_id = ' WHERE id_server IN ('.(int) $id_server.')'; - } else { - $select_id = ''; + $select_id = ' AND id_server IN ('.(int) $id_server.')'; } - $sql = ' - SELECT * - FROM tserver '.$select_id.' - ORDER BY server_type'; + $types_sql = ''; + if (is_metaconsole() === true && isset($config['ndbh']) === false) { + $types_sql = sprintf( + ' AND ( + `server_type` = %d OR + `server_type` = %d OR + `server_type` = %d OR + `server_type` = %d + )', + SERVER_TYPE_AUTOPROVISION, + SERVER_TYPE_EVENT, + SERVER_TYPE_MIGRATION, + SERVER_TYPE_PREDICTION + ); + } + + $sql = sprintf( + 'SELECT * + FROM tserver + WHERE 1=1 + %s + %s + ORDER BY server_type', + $select_id, + $types_sql + ); if ($sql_limit !== -1) { - $sql = ' - SELECT * - FROM tserver '.$select_id.' - ORDER BY server_type'.$sql_limit; + $sql = sprintf( + 'SELECT * + FROM tserver + WHERE 1=1 + %s + %s + ORDER BY server_type + %s', + $select_id, + $types_sql, + $sql_limit + ); } $result = db_get_all_rows_sql($sql); - $time = get_system_time(); if (empty($result)) { return false; From f7dbd8f3b2998a4c36a210eeec6e36d25366f862 Mon Sep 17 00:00:00 2001 From: Enrique Martin Date: Fri, 2 Feb 2024 14:41:28 +0100 Subject: [PATCH 03/24] Net scan improvements --- pandora_console/extras/mr/68.sql | 22 ++ .../godmode/wizards/HostDevices.class.php | 251 +++++++++--------- .../lib/PandoraFMS/DiscoveryServer.pm | 180 +++++++++---- pandora_server/lib/PandoraFMS/Recon/Base.pm | 97 +++++-- pandora_server/lib/PandoraFMS/Tools.pm | 28 +- 5 files changed, 365 insertions(+), 213 deletions(-) diff --git a/pandora_console/extras/mr/68.sql b/pandora_console/extras/mr/68.sql index db168d5c22..c84a04f2b7 100644 --- a/pandora_console/extras/mr/68.sql +++ b/pandora_console/extras/mr/68.sql @@ -56,5 +56,27 @@ ADD COLUMN `id_agent_data` int not null default 0 AFTER `script_type`; ALTER TABLE `tusuario` CHANGE COLUMN `metaconsole_data_section` `metaconsole_data_section` TEXT NOT NULL DEFAULT '' ; ALTER TABLE `tmensajes` ADD COLUMN `icon_notification` VARCHAR(250) NULL DEFAULT NULL AFTER `url`; +-- Create SNMPv3 credentials for recon tasks and update them +SET @creds_name = 'Recon-SNMP-creds-'; +INSERT IGNORE INTO `tcredential_store` (`identifier`, `id_group`, `product`, `extra_1`) + SELECT + CONCAT(@creds_name,`id_rt`) AS `identifier`, + `id_group`, + 'SNMP' AS `product`, + CONCAT( + '{', + '"community":"',`snmp_community`,'",', + '"version":"',`snmp_version`,'",', + '"securityLevelV3":"',`snmp_security_level`,'",', + '"authUserV3":"',`snmp_auth_user`,'",', + '"authMethodV3":"',`snmp_auth_method`,'",', + '"authPassV3":"',`snmp_auth_pass`,'",', + '"privacyMethodV3":"',`snmp_privacy_method`,'",', + '"privacyPassV3":"',`snmp_privacy_pass`,'"', + '}' + ) AS `extra1` + FROM `trecon_task` WHERE `snmp_version` = 3 AND `snmp_enabled` = 1 +; +UPDATE `trecon_task` SET `auth_strings` = IF(`auth_strings` = '',`auth_strings`,CONCAT(@creds_name,`id_rt`,',',`auth_strings`)) WHERE `snmp_version` = 3 AND `snmp_enabled` = 1; COMMIT; \ No newline at end of file diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php index 4f0043f038..b3f59191f2 100755 --- a/pandora_console/godmode/wizards/HostDevices.class.php +++ b/pandora_console/godmode/wizards/HostDevices.class.php @@ -450,6 +450,26 @@ class HostDevices extends Wizard if (isset($this->task['id_rt']) === false) { // Create. + $default_templates = [ + io_safe_input('Linux System'), + io_safe_input('Windows System'), + io_safe_input('Windows Hardware'), + io_safe_input('Network Management') + ]; + + $default_templates_ids = db_get_all_rows_sql('SELECT id_np + FROM tnetwork_profile + WHERE name IN ('.implode(',', array_map(function($template) { + return "'" . $template . "'"; + }, $default_templates)).') + ORDER BY name'); + + if($default_templates_ids !== false) { + $this->task['id_network_profile'] = implode(',', + array_column($default_templates_ids, 'id_np'), + ); + } + $this->task['id_rt'] = db_process_sql_insert( 'trecon_task', $this->task @@ -1100,12 +1120,9 @@ class HostDevices extends Wizard 'arguments' => [ 'name' => 'id_network_profile[]', 'type' => 'select_from_sql', - 'sql' => 'SELECT tn.id_np, tn.name - FROM tnetwork_profile tn - LEFT JOIN `tnetwork_profile_pen` tp - ON tp.id_np = tn.id_np - WHERE tp.id_np IS NULL - ORDER BY tn.name', + 'sql' => 'SELECT id_np, name + FROM tnetwork_profile + ORDER BY name', 'return' => true, 'selected' => explode( ',', @@ -1273,114 +1290,88 @@ class HostDevices extends Wizard ], ]; - // SNMP Options pack v3. - $form['inputs'][] = [ - 'hidden' => 1, - 'block_id' => 'snmp_options_v3', - 'class' => 'indented', - 'block_content' => [ - [ - 'label' => ''.__('Context').'', - 'arguments' => [ - 'name' => 'snmp_context', - 'type' => 'text', - 'value' => $this->task['snmp_community'], - 'size' => 15, - 'return' => true, + $show_snmp_auth = false; + if (isset($this->task['snmp_enabled']) && $this->task['snmp_enabled'] > 0 + && isset($this->task['snmp_version']) && $this->task['snmp_version'] == 3 + ) { + $show_snmp_auth = true; + } - ], - ], - [ - 'label' => ''.__('Auth user').'', - 'arguments' => [ - 'name' => 'snmp_auth_user', - 'type' => 'text', - 'value' => $this->task['snmp_auth_user'], - 'size' => 15, - 'return' => true, - - ], - ], - [ - 'label' => ''.__('Security level').'', - 'arguments' => [ - 'name' => 'snmp_security_level', - 'type' => 'select', - 'fields' => [ - 'noAuthNoPriv' => __('Not auth and not privacy method'), - 'authNoPriv' => __('Auth and not privacy method'), - 'authPriv' => __('Auth and privacy method'), - ], - 'selected' => $this->task['snmp_security_level'], - 'size' => 15, - 'return' => true, - - ], - ], - [ - 'label' => ''.__('Auth method').'', - 'arguments' => [ - 'name' => 'snmp_auth_method', - 'type' => 'select', - 'fields' => [ - 'MD5' => __('MD5'), - 'SHA' => __('SHA'), - ], - 'selected' => $this->task['snmp_auth_method'], - 'size' => 15, - 'return' => true, - - ], - ], - [ - 'label' => ''.__('Auth password').''.ui_print_help_tip( - __( - 'The pass length must be eight character minimum.' - ), - true - ), - 'arguments' => [ - 'name' => 'snmp_auth_pass', - 'type' => 'password', - 'value' => $this->task['snmp_auth_pass'], - 'size' => 15, - 'return' => true, - - ], - ], - [ - 'label' => ''.__('Privacy method').'', - 'arguments' => [ - 'name' => 'snmp_privacy_method', - 'type' => 'select', - 'fields' => [ - 'DES' => __('DES'), - 'AES' => __('AES'), - ], - 'selected' => $this->task['snmp_privacy_method'], - 'size' => 15, - 'return' => true, - - ], - ], - [ - 'label' => ''.__('Privacy pass').''.ui_print_help_tip( - __( - 'The pass length must be eight character minimum.' - ), - true - ), - 'arguments' => [ - 'name' => 'snmp_privacy_pass', - 'type' => 'password', - 'value' => $this->task['snmp_privacy_pass'], - 'size' => 15, - 'return' => true, - - ], - ], + include_once $config['homedir'].'/include/class/CredentialStore.class.php'; + $all_snmp_keys = CredentialStore::getAll( + [ + 'cs.*', + 'tg.nombre as `group`', ], - ]; + ['product' => 'SNMP'] + ); + + if (is_array($all_snmp_keys) === true) { + // Improve usage and decode output. + $snmp_available_keys = array_reduce( + $all_snmp_keys, + function ($carry, $item) { + $item['extra_1'] = io_output_password($item['extra_1']); + + $extra1 = json_decode($item['extra_1'], true); + if($extra1 !== null && $extra1['version'] == 3) { + $carry[$item['identifier']] = $item['identifier']; + } + + return $carry; + }, + [] + ); + } + + hd($snmp_available_keys); + + if (check_acl($config['id_user'], 0, 'UM')) { + $link_to_cs = ''; + $link_to_cs .= __('No credentials available').', '; + $link_to_cs .= strtolower(__('Manage credentials')).''; + } else { + $link_to_cs = __('No credentials available'); + } + + if (count($snmp_available_keys) > 0) { + $form['inputs'][] = [ + 'block_id' => 'auth_block_snmp', + 'class' => 'indented', + 'hidden' => !$show_snmp_auth, + 'block_content' => [ + [ + 'label' => __('Credentials to try with'), + 'arguments' => [ + 'type' => 'select', + 'name' => 'auth_strings[]', + 'fields' => $snmp_available_keys, + 'selected' => explode( + ',', + $this->task['auth_strings'] + ), + + 'multiple' => true, + 'class' => 'select_multiple', + ], + ], + ], + ]; + } else { + $form['inputs'][] = [ + 'block_id' => 'auth_block_snmp', + 'class' => 'indented', + 'hidden' => !$show_snmp_auth, + 'block_content' => [ + [ + 'label' => __('Credentials'), + 'extra' => $link_to_cs, + ], + ], + ]; + } // Input: Enforce os detection. $form['inputs'][] = [ @@ -1453,14 +1444,12 @@ class HostDevices extends Wizard // AUTH CONFIGURATION. $show_auth = false; - if ((isset($this->task['wmi_enabled']) && $this->task['wmi_enabled'] > 0) - || (isset($this->task['rcmd_enabled']) && $this->task['rcmd_enabled'] > 0) - ) { + if (isset($this->task['wmi_enabled']) && $this->task['wmi_enabled'] > 0) { $show_auth = true; } include_once $config['homedir'].'/include/class/CredentialStore.class.php'; - $available_keys = CredentialStore::getKeys('WMI'); + $wmi_available_keys = CredentialStore::getKeys('WMI'); if (check_acl($config['id_user'], 0, 'UM')) { $link_to_cs = 'is_snmp_discovered($device)); my $community = $self->get_community($device); + my $snmp3_creds = undef; + if(defined($self->{'snmp3_auth_key'}{$device})) { + $snmp3_creds = $self->snmp3_credentials($self->{'snmp3_auth_key'}{$device}); + } + my $snmp3_params = { + 'custom_string_1' => '', + 'custom_string_2' => '', + 'custom_string_3' => '', + 'plugin_parameter' => '', + 'plugin_user' => '', + 'plugin_pass' => '' + }; + if(defined($snmp3_creds)) { + $community = $snmp3_creds->{'community'}; + $snmp3_params = { + 'custom_string_1' => $snmp3_creds->{'snmp_privacy_method'}, + 'custom_string_2' => $snmp3_creds->{'snmp_privacy_pass'}, + 'custom_string_3' => $snmp3_creds->{'snmp_security_level'}, + 'plugin_parameter' => $snmp3_creds->{'snmp_auth_method'}, + 'plugin_user' => $snmp3_creds->{'snmp_auth_user'}, + 'plugin_pass' => $snmp3_creds->{'snmp_auth_pass'} + }; + } + my @output = $self->snmp_get_value_array($device, $PandoraFMS::Recon::Base::IFINDEX); foreach my $if_index (@output) { next unless ($if_index =~ /^[0-9]+$/); @@ -1153,12 +1177,12 @@ sub PandoraFMS::Recon::Base::create_interface_modules($$) { ), 'ip_target' => $device, 'tcp_send' => $self->{'task_data'}{'snmp_version'}, - 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'}, - 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'}, - 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'}, - 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'}, + 'custom_string_1' => $snmp3_params->{'snmp_privacy_method'}, + 'custom_string_2' => $snmp3_params->{'snmp_privacy_pass'}, + 'custom_string_3' => $snmp3_params->{'snmp_security_level'}, + 'plugin_parameter' => $snmp3_params->{'snmp_auth_method'}, + 'plugin_user' => $snmp3_params->{'snmp_auth_user'}, + 'plugin_pass' => $snmp3_params->{'snmp_auth_pass'}, 'snmp_community' => $community, 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOPERSTATUS.$if_index", 'unit' => '' @@ -1183,12 +1207,12 @@ sub PandoraFMS::Recon::Base::create_interface_modules($$) { ), 'ip_target' => $device, 'tcp_send' => $self->{'task_data'}{'snmp_version'}, - 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'}, - 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'}, - 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'}, - 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'}, + 'custom_string_1' => $snmp3_params->{'snmp_privacy_method'}, + 'custom_string_2' => $snmp3_params->{'snmp_privacy_pass'}, + 'custom_string_3' => $snmp3_params->{'snmp_security_level'}, + 'plugin_parameter' => $snmp3_params->{'snmp_auth_method'}, + 'plugin_user' => $snmp3_params->{'snmp_auth_user'}, + 'plugin_pass' => $snmp3_params->{'snmp_auth_pass'}, 'snmp_community' => $community, 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCINOCTECTS.$if_index", 'unit' => safe_input('bytes/s') @@ -1210,12 +1234,12 @@ sub PandoraFMS::Recon::Base::create_interface_modules($$) { ), 'ip_target' => $device, 'tcp_send' => $self->{'task_data'}{'snmp_version'}, - 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'}, - 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'}, - 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'}, - 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'}, + 'custom_string_1' => $snmp3_params->{'snmp_privacy_method'}, + 'custom_string_2' => $snmp3_params->{'snmp_privacy_pass'}, + 'custom_string_3' => $snmp3_params->{'snmp_security_level'}, + 'plugin_parameter' => $snmp3_params->{'snmp_auth_method'}, + 'plugin_user' => $snmp3_params->{'snmp_auth_user'}, + 'plugin_pass' => $snmp3_params->{'snmp_auth_pass'}, 'snmp_community' => $community, 'snmp_oid' => "$PandoraFMS::Recon::Base::IFINOCTECTS.$if_index", 'unit' => safe_input('bytes/s') @@ -1241,12 +1265,12 @@ sub PandoraFMS::Recon::Base::create_interface_modules($$) { ), 'ip_target' => $device, 'tcp_send' => $self->{'task_data'}{'snmp_version'}, - 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'}, - 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'}, - 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'}, - 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'}, + 'custom_string_1' => $snmp3_params->{'snmp_privacy_method'}, + 'custom_string_2' => $snmp3_params->{'snmp_privacy_pass'}, + 'custom_string_3' => $snmp3_params->{'snmp_security_level'}, + 'plugin_parameter' => $snmp3_params->{'snmp_auth_method'}, + 'plugin_user' => $snmp3_params->{'snmp_auth_user'}, + 'plugin_pass' => $snmp3_params->{'snmp_auth_pass'}, 'snmp_community' => $community, 'snmp_oid' => "$PandoraFMS::Recon::Base::IFHCOUTOCTECTS.$if_index", 'unit' => safe_input('bytes/s') @@ -1268,12 +1292,12 @@ sub PandoraFMS::Recon::Base::create_interface_modules($$) { ), 'ip_target' => $device, 'tcp_send' => $self->{'task_data'}{'snmp_version'}, - 'custom_string_1' => $self->{'task_data'}{'snmp_privacy_method'}, - 'custom_string_2' => $self->{'task_data'}{'snmp_privacy_pass'}, - 'custom_string_3' => $self->{'task_data'}{'snmp_security_level'}, - 'plugin_parameter' => $self->{'task_data'}{'snmp_auth_method'}, - 'plugin_user' => $self->{'task_data'}{'snmp_auth_user'}, - 'plugin_pass' => $self->{'task_data'}{'snmp_auth_pass'}, + 'custom_string_1' => $snmp3_params->{'snmp_privacy_method'}, + 'custom_string_2' => $snmp3_params->{'snmp_privacy_pass'}, + 'custom_string_3' => $snmp3_params->{'snmp_security_level'}, + 'plugin_parameter' => $snmp3_params->{'snmp_auth_method'}, + 'plugin_user' => $snmp3_params->{'snmp_auth_user'}, + 'plugin_pass' => $snmp3_params->{'snmp_auth_pass'}, 'snmp_community' => $community, 'snmp_oid' => "$PandoraFMS::Recon::Base::IFOUTOCTECTS.$if_index", 'unit' => safe_input('bytes/s') @@ -1305,19 +1329,19 @@ sub PandoraFMS::Recon::Base::create_interface_modules($$) { # Interface index filter. $macros->{'5'}->{'value'} = $if_index; # SecurityName. - $macros->{'6'}->{'value'} = $self->{'task_data'}->{'snmp_auth_user'}; + $macros->{'6'}->{'value'} = $snmp3_params->{'snmp_auth_user'}; # SecurityContext. $macros->{'7'}->{'value'} = $community; # SecurityLevel. - $macros->{'8'}->{'value'} = $self->{'task_data'}->{'snmp_security_level'}; + $macros->{'8'}->{'value'} = $snmp3_params->{'snmp_security_level'}; # AuthProtocol. - $macros->{'9'}->{'value'} = $self->{'task_data'}->{'snmp_auth_method'}; + $macros->{'9'}->{'value'} = $snmp3_params->{'snmp_auth_method'}; # AuthKey. - $macros->{'10'}->{'value'} = $self->{'task_data'}->{'snmp_auth_pass'}; + $macros->{'10'}->{'value'} = $snmp3_params->{'snmp_auth_pass'}; # PrivProtocol. - $macros->{'11'}->{'value'} = $self->{'task_data'}->{'snmp_privacy_method'}; + $macros->{'11'}->{'value'} = $snmp3_params->{'snmp_privacy_method'}; # PrivKey. - $macros->{'12'}->{'value'} = $self->{'task_data'}->{'snmp_privacy_pass'}; + $macros->{'12'}->{'value'} = $snmp3_params->{'snmp_privacy_pass'}; # Hash identifier. $macros->{'13'}->{'value'} = PandoraFMS::Tools::generate_agent_name_hash($if_name, $device); # Get input usage. @@ -1429,6 +1453,7 @@ sub PandoraFMS::Recon::Base::create_wmi_modules { { 'ip_target' => $target, 'snmp_oid' => "SELECT LoadPercentage FROM Win32_Processor WHERE DeviceId=\'$cpu\'", + 'tcp_send' => $creds->{'extra_1'}, 'plugin_user' => $creds->{'username'}, 'plugin_pass' => $creds->{'password'}, 'tcp_port' => 1, @@ -1449,6 +1474,7 @@ sub PandoraFMS::Recon::Base::create_wmi_modules { { 'ip_target' => $target, 'snmp_oid' => "SELECT FreePhysicalMemory, TotalVisibleMemorySize FROM Win32_OperatingSystem", + 'tcp_send' => $creds->{'extra_1'}, 'plugin_user' => $creds->{'username'}, 'plugin_pass' => $creds->{'password'}, 'tcp_port' => 0, @@ -1469,6 +1495,7 @@ sub PandoraFMS::Recon::Base::create_wmi_modules { { 'ip_target' => $target, 'snmp_oid' => "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='$unit'", + 'tcp_send' => $creds->{'extra_1'}, 'plugin_user' => $creds->{'username'}, 'plugin_pass' => $creds->{'password'}, 'tcp_port' => 1, @@ -1510,14 +1537,7 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$) { # 1. Retrieve template info. my $template = get_nc_profile_advanced($self->{'dbh'}, $t_id); - # 2. Verify Private Enterprise Number matches (PEN) - if (defined($template->{'pen'})) { - my @pens = split(',', $template->{'pen'}); - - next unless (is_in_array(\@pens, $self->get_pen($device))); - } - - # 3. Retrieve module list from target template. + # 2. Retrieve module list from target template. my @np_components = get_db_rows( $self->{'dbh'}, 'SELECT * FROM tnetwork_profile_component WHERE id_np = ?', @@ -1525,7 +1545,7 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$) { ); foreach my $np_component (@np_components) { - # 4. Register each module (candidate). 'add_module' will test them. + # 3. Register each module (candidate). 'add_module' will test them. my $component = get_db_single_row( $self->{'dbh'}, 'SELECT * FROM tnetwork_component WHERE id_nc = ?', @@ -1543,18 +1563,45 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$) { } $component->{'name'} = safe_output($component->{'name'}); - if ($component->{'type'} >= 15 && $component->{'type'} <= 18) { - $component->{'snmp_community'} = safe_output($self->get_community($device)); + # SNMP Modules + if ($self->is_snmp_discovered($device) && $component->{'type'} >= 15 && $component->{'type'} <= 18) { + my $snmp3_creds = undef; + my $community = safe_output($self->get_community($device)); + if(defined($self->{'snmp3_auth_key'}{$device})) { + $snmp3_creds = $self->snmp3_credentials($self->{'snmp3_auth_key'}{$device}); + } + my $snmp3_params = { + 'custom_string_1' => '', + 'custom_string_2' => '', + 'custom_string_3' => '', + 'plugin_parameter' => '', + 'plugin_user' => '', + 'plugin_pass' => '' + }; + if(defined($snmp3_creds)) { + $community = $snmp3_creds->{'community'}; + $snmp3_params = { + 'custom_string_1' => $snmp3_creds->{'snmp_privacy_method'}, + 'custom_string_2' => $snmp3_creds->{'snmp_privacy_pass'}, + 'custom_string_3' => $snmp3_creds->{'snmp_security_level'}, + 'plugin_parameter' => $snmp3_creds->{'snmp_auth_method'}, + 'plugin_user' => $snmp3_creds->{'snmp_auth_user'}, + 'plugin_pass' => $snmp3_creds->{'snmp_auth_pass'} + }; + } + + $component->{'snmp_community'} = $community; $component->{'tcp_send'} = $self->{'snmp_version'}; - $component->{'custom_string_1'} = $self->{'snmp_privacy_method'}; - $component->{'custom_string_2'} = $self->{'snmp_privacy_pass'}; - $component->{'custom_string_3'} = $self->{'snmp_security_level'}; - $component->{'plugin_parameter'} = $self->{'snmp_auth_method'}; - $component->{'plugin_user'} = $self->{'snmp_auth_user'}; - $component->{'plugin_pass'} = $self->{'snmp_auth_pass'}; + $component->{'custom_string_1'} = $snmp3_params->{'snmp_privacy_method'}; + $component->{'custom_string_2'} = $snmp3_params->{'snmp_privacy_pass'}; + $component->{'custom_string_3'} = $snmp3_params->{'snmp_security_level'}; + $component->{'plugin_parameter'} = $snmp3_params->{'snmp_auth_method'}; + $component->{'plugin_user'} = $snmp3_params->{'snmp_auth_user'}; + $component->{'plugin_pass'} = $snmp3_params->{'snmp_auth_pass'}; } - if ($component->{'type'} >= 34 && $component->{'type'} <= 37) { + # RCMD Modules + if ($self->rcmd_responds($device) && $component->{'type'} >= 34 && $component->{'type'} <= 37) { # Update module credentials. $component->{'custom_string_1'} = $self->rcmd_credentials_key($device); $component->{'custom_string_2'} = pandora_get_os_by_id( @@ -1563,9 +1610,18 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$) { ); } + # WMI Modules + if ($self->wmi_responds($device) && $component->{'id_modulo'} == 6) { + my $key = $self->wmi_credentials_key($device); + my $creds = $self->call('get_credentials', $key); + $component->{'tcp_send'} = $creds->{'extra_1'}; + $component->{'plugin_user'} = $creds->{'username'}; + $component->{'plugin_pass'} = $creds->{'password'}; + } + $component->{'__module_component'} = 1; - # 3. Try to register module into monitoring list. + # 4. Try to register module into monitoring list. $self->call('add_module', $device, $component); } } @@ -1576,13 +1632,23 @@ sub PandoraFMS::Recon::Base::create_network_profile_modules($$) { # Retrieve a key from credential store. ################################################################################ sub PandoraFMS::Recon::Base::get_credentials { - my ($self, $key_index) = @_; + my ($self, $key_index, $product) = @_; - return credential_store_get_key( + my $cred = credential_store_get_key( $self->{'pa_config'}, $self->{'dbh'}, $key_index ); + + if(defined($product)) { + if($product eq $cred->{'product'}) { + return $cred; + } else { + return undef; + } + } + + return $cred; } ################################################################################ diff --git a/pandora_server/lib/PandoraFMS/Recon/Base.pm b/pandora_server/lib/PandoraFMS/Recon/Base.pm index f21f13de4f..a84149c4dc 100644 --- a/pandora_server/lib/PandoraFMS/Recon/Base.pm +++ b/pandora_server/lib/PandoraFMS/Recon/Base.pm @@ -1352,10 +1352,9 @@ sub snmp_responds_v122c($$) { sub snmp_responds_v3($$) { my ($self, $device) = @_; - my $command = $self->snmp_get_command($device, ".0"); - `$command`; + $self->snmp3_credentials_calculation($device); - if ($? == 0) { + if ($self->snmp3_credentials_calculation($device)) { $self->mark_discovered($device); return 1; } @@ -1363,6 +1362,81 @@ sub snmp_responds_v3($$) { return 0; } +################################################################################ +# Get SNMP3 credentials info in HASH +################################################################################ +sub snmp3_credentials { + my ($self, $key) = @_; + + my $cred = $self->call('get_credentials', $key, 'SNMP'); + return undef if !defined($cred); + return undef if ref($cred) ne 'HASH'; + + my $extra1 = {}; + eval { + local $SIG{__DIE__}; + $extra1 = p_decode_json($self->{'pa_config'}, $cred->{'extra_1'}); + }; + if ($@) { + $self->call('message', "[".$key."] Credentials ERROR JSON: $@", 10); + return undef; + } + + return undef if $extra1->{'version'} ne '3'; + + return { + 'snmp_security_level' => $extra1->{'securityLevelV3'}, + 'snmp_privacy_method' => $extra1->{'privacyMethodV3'}, + 'snmp_privacy_pass' => $extra1->{'privacyPassV3'}, + 'snmp_auth_method' => $extra1->{'authMethodV3'}, + 'snmp_auth_user' => $extra1->{'authUserV3'}, + 'snmp_auth_pass' => $extra1->{'authPassV3'}, + 'community' => $extra1->{'community'} + }; +} + +################################################################################ +# Calculate WMI credentials for target, 1 if calculated, undef if cannot +# connect to target. Credentials could be empty (-N) +################################################################################ +sub snmp3_credentials_calculation { + my ($self, $target) = @_; + + # Test all credentials selected. + foreach my $key_index (@{$self->{'auth_strings_array'}}) { + my $cred = snmp3_credentials($key_index); + next if !defined($cred); + next if ref($cred) ne 'HASH'; + + my $auth = ''; + if ($cred->{'community'}) { # Context + $auth .= " -N \'$cred->{'community'}\' "; + } + $auth .= " -l$cred->{'snmp_security_level'} "; + if ($cred->{'snmp_security_level'} ne "noAuthNoPriv") { + $auth .= " -u$cred->{'snmp_auth_user'} -a $cred->{'snmp_auth_method'} -A \'$cred->{'snmp_auth_pass'}\' "; + } + if ($cred->{'snmp_security_level'} eq "authPriv") { + $auth .= " -x$cred->{'snmp_privacy_method'} -X \'$cred->{'snmp_privacy_pass'}\' "; + } + + $self->{'snmp3_auth'}{$target} = $auth; + $self->{'snmp3_auth_key'}{$target} = $key_index; + + my $command = $self->snmp_get_command($target, ".0"); + `$command`; + + if ($? == 0) { + return 1; + } + } + + delete($self->{'snmp3_auth'}{$target}); + delete($self->{'snmp3_auth_key'}{$target}); + + return 0; +} + ################################################################################ # Parse the local ARP cache. ################################################################################ @@ -2198,16 +2272,7 @@ sub snmp_get_command { my $command = "snmpwalk -M$DEVNULL -r$self->{'snmp_checks'} -t$self->{'snmp_timeout'} -v$self->{'snmp_version'} -On -Oe "; if ($self->{'snmp_version'} eq "3") { - if ($self->{'community'}) { # Context - $command .= " -N \'$self->{'community'}\' "; - } - $command .= " -l$self->{'snmp_security_level'} "; - if ($self->{'snmp_security_level'} ne "noAuthNoPriv") { - $command .= " -u$self->{'snmp_auth_user'} -a $self->{'snmp_auth_method'} -A \'$self->{'snmp_auth_pass'}\' "; - } - if ($self->{'snmp_security_level'} eq "authPriv") { - $command .= " -x$self->{'snmp_privacy_method'} -X \'$self->{'snmp_privacy_pass'}\' "; - } + $command .= " $self->{'snmp3_auth'}{$device} "; } else { $command .= " -c\'$community\'$vlan "; } @@ -2353,7 +2418,8 @@ sub wmi_credentials_calculation { # Test all credentials selected. foreach my $key_index (@{$self->{'auth_strings_array'}}) { - my $cred = $self->call('get_credentials', $key_index); + my $cred = $self->call('get_credentials', $key_index, 'WMI'); + next if !defined($cred); next if ref($cred) ne 'HASH'; my $auth = $cred->{'username'}.'%'.$cred->{'password'}; @@ -2431,7 +2497,8 @@ sub rcmd_credentials_calculation { # Test all credentials selected. foreach my $key_index (@{$self->{'auth_strings_array'}}) { - my $cred = $self->call('get_credentials', $key_index); + my $cred = $self->call('get_credentials', $key_index, 'CUSTOM'); + next if !defined($cred); next if ref($cred) ne 'HASH'; $rcmd->clean_ssh_lib(); diff --git a/pandora_server/lib/PandoraFMS/Tools.pm b/pandora_server/lib/PandoraFMS/Tools.pm index 543ea45556..37d9ece692 100755 --- a/pandora_server/lib/PandoraFMS/Tools.pm +++ b/pandora_server/lib/PandoraFMS/Tools.pm @@ -716,19 +716,23 @@ sub credential_store_get_key($$$) { my $sql = 'SELECT * FROM tcredential_store WHERE identifier = ?'; my $key = PandoraFMS::DB::get_db_single_row($dbh, $sql, $identifier); - return { - 'username' => PandoraFMS::Core::pandora_output_password( - $pa_config, - $key->{'username'} - ), - 'password' => PandoraFMS::Core::pandora_output_password( - $pa_config, - $key->{'password'} - ), - 'extra_1' => $key->{'extra_1'}, - 'extra_2' => $key->{'extra_2'}, - }; + if(defined($key)) { + return { + 'product' => $key->{'product'}, + 'username' => PandoraFMS::Core::pandora_output_password( + $pa_config, + $key->{'username'} + ), + 'password' => PandoraFMS::Core::pandora_output_password( + $pa_config, + $key->{'password'} + ), + 'extra_1' => $key->{'extra_1'}, + 'extra_2' => $key->{'extra_2'}, + }; + } + return undef; } ################################################################################ From d1c6c9843bb1f5079851e664fa103f3d4f10ac27 Mon Sep 17 00:00:00 2001 From: Enrique Martin Date: Mon, 5 Feb 2024 23:26:55 +0100 Subject: [PATCH 04/24] Added net scan options to welcome wizard --- .../godmode/wizards/HostDevices.class.php | 6 +- .../include/ajax/task_to_perform.php | 7 +- .../include/class/WelcomeWindow.class.php | 344 +++++++++++++++++- .../include/functions_welcome_wizard.php | 90 ++++- 4 files changed, 433 insertions(+), 14 deletions(-) diff --git a/pandora_console/godmode/wizards/HostDevices.class.php b/pandora_console/godmode/wizards/HostDevices.class.php index b3f59191f2..c6b5c20c1a 100755 --- a/pandora_console/godmode/wizards/HostDevices.class.php +++ b/pandora_console/godmode/wizards/HostDevices.class.php @@ -1324,8 +1324,6 @@ class HostDevices extends Wizard ); } - hd($snmp_available_keys); - if (check_acl($config['id_user'], 0, 'UM')) { $link_to_cs = ' '', + 'content' => '
To detect and find systems on your network we will need access credentials. The SNMP community for network devices, and at least one set of credentials for Linux and Windows environments (they do not need to be super administrators, but they do need to be able to connect remotely). Without the credentials, we will only be able to detect if the devices are connected to the network.

', + ], + true + ); + + // SNMP Communities + echo html_print_label_input_block( + __('SNMP communities to try with').ui_print_help_tip( + __( + 'You can specify several values, separated by commas, for example: public,mysecret,1234' + ), + true + ), + html_print_input( + [ + 'name' => 'community', + 'type' => 'text', + 'value' => 'public', + 'size' => 25, + 'return' => true + ], + 'div', + true + ), + [ + 'div_id' => 'snmp-communities-div' + ] + ); + ui_require_jquery_file('tag-editor.min','include/javascript/',true); + ui_require_jquery_file('caret.min','include/javascript/',true); + ui_require_css_file('jquery.tag-editor','include/styles/',true); + + echo '
'; + + // WMI Credentials + echo html_print_label_input_block( + __('WMI credentials'), + html_print_div( + [ + 'id' => 'wmi-creds', + 'content' => '' + ], + true + ) + ); + echo html_print_div( + [ + 'id' => 'wmi-cred-form', + 'hidden' => true, + 'style' => 'margin: 3px; display: flex; align-items: center;', + 'content' => html_print_div( + [ + 'id' => 'wmi-cred-user-div', + 'style' => 'width: 260px;', + 'content' => html_print_label_input_block(' '.__('User').' ', html_print_input_text( + 'wmi-cred-user', + '', + '', + false, + 50, // Max length + true, + false, + true, + '', + 'w100p', + '', + 'off', + false, + '', + '', + '', + false, + '', + 'Username' + ),['div_style' => 'display: flex; align-items: center;']) + ], + true + ) + . + html_print_div( + [ + 'id' => 'wmi-cred-pass-div', + 'style' => 'width: 260px;', + 'content' => html_print_label_input_block(' '.__('Password').' ', html_print_input_password( + 'wmi-cred-pass', + '', + '', + false, + 50, // Max length + true, + false, + true, + 'w100p', + 'off', + false, + '' + ),['div_style' => 'display: flex; align-items: center;']) + ], + true + ) + . + html_print_div( + [ + 'id' => 'wmi-cred-namespace-div', + 'style' => 'width: 260px;', + 'content' => html_print_label_input_block(' '.__('Namespace').' ', html_print_input_text( + 'wmi-cred-namespace', + '', + '', + false, + 50, // Max length + true, + false, + true, + '', + 'w100p', + '', + 'off', + false, + '', + '', + '', + false, + '', + 'Namespace' + ),['div_style' => 'display: flex; align-items: center;']) + ], + true + ) + . + '
'.html_print_image( + 'images/delete.svg', + true, + [ + 'title' => __('Delete'), + 'style' => 'cursor: pointer;', + 'class' => 'main_menu_icon invert_filter', + ] + ).'' + ], + true + ); + echo '
'; + echo html_print_button( + __('Add'), + 'add-wmi-cred', + false, + 'add_discovery_credential("wmi-cred-form","wmi-creds");', + [ + 'icon' => 'plus', + 'mode' => 'secondary', + 'class' => 'mini' + ], + true, + false, + false, + '' + ); + + echo '
'; + + // RCM Credentials + echo html_print_label_input_block( + __('Remote commands credentials'), + html_print_div( + [ + 'id' => 'rcmd-creds', + 'content' => '' + ], + true + ) + ); + echo html_print_div( + [ + 'id' => 'rcmd-cred-form', + 'hidden' => true, + 'style' => 'margin: 3px; display: flex; align-items: center;', + 'content' => html_print_div( + [ + 'id' => 'rcmd-cred-user-div', + 'style' => 'width: 260px;', + 'content' => html_print_label_input_block(' '.__('User').' ', html_print_input_text( + 'rcmd-cred-user', + '', + '', + false, + 50, // Max length + true, + false, + true, + '', + 'w100p', + '', + 'off', + false, + '', + '', + '', + false, + '', + 'Username' + ),['div_style' => 'display: flex; align-items: center;']) + ], + true + ) + . + html_print_div( + [ + 'id' => 'rcmd-cred-pass-div', + 'style' => 'width: 260px;', + 'content' => html_print_label_input_block(' '.__('Password').' ', html_print_input_password( + 'rcmd-cred-pass', + '', + '', + false, + 50, // Max length + true, + false, + true, + 'w100p', + 'off', + false, + '' + ),['div_style' => 'display: flex; align-items: center;']) + ], + true + ) + . + ''.html_print_image( + 'images/delete.svg', + true, + [ + 'title' => __('Delete'), + 'style' => 'cursor: pointer;', + 'class' => 'main_menu_icon invert_filter', + ] + ).'' + ], + true + ); + echo '
'; + echo html_print_button( + __('Add'), + 'add-rcmd-cred', + false, + 'add_discovery_credential("rcmd-cred-form","rcmd-creds");', + [ + 'icon' => 'plus', + 'mode' => 'secondary', + 'class' => 'mini' + ], + true, + false, + false, + '' + ); + echo html_print_submit_button(__('Create'), 'basic_net', false, ['icon' => 'next', 'style' => 'margin-top:15px; float:right;']); ?> +