def handle_xml(self, xml: Element) -> bytes: help_format = xml.get('format') if help_format is None or help_format == "text": # Default help format is text. return simple_response_str('help', 200, 'OK', self._daemon.get_help_text()) elif help_format == "xml": text = get_elements_from_dict( {k: v.as_dict() for k, v in self._daemon.commands.items()}) return simple_response_str('help', 200, 'OK', text) raise OspdCommandError('Bogus help format', 'help')
def handle_xml(self, xml: Element) -> bytes: """ Handles <delete_scan> command. @return: Response string for <delete_scan> command. """ scan_id = xml.get('scan_id') if scan_id is None: return simple_response_str('delete_scan', 404, 'No scan_id attribute') if not self._daemon.scan_exists(scan_id): text = "Failed to find scan '{0}'".format(scan_id) return simple_response_str('delete_scan', 404, text) self._daemon.check_scan_process(scan_id) if self._daemon.delete_scan(scan_id): return simple_response_str('delete_scan', 200, 'OK') raise OspdCommandError('Scan in progress', 'delete_scan')
def handle_xml(self, xml: Element) -> bytes: """ Handles <get_scans> command. @return: Response string for <get_scans> command. """ scan_id = xml.get('scan_id') details = xml.get('details') pop_res = xml.get('pop_results') max_res = xml.get('max_results') if details and details == '0': details = False else: details = True if pop_res and pop_res == '1': pop_res = True else: pop_res = False if max_res: max_res = int(max_res) responses = [] if scan_id and scan_id in self._daemon.scan_collection.ids_iterator(): self._daemon.check_scan_process(scan_id) scan = self._daemon.get_scan_xml(scan_id, details, pop_res, max_res) responses.append(scan) elif scan_id: text = "Failed to find scan '{0}'".format(scan_id) return simple_response_str('get_scans', 404, text) else: for scan_id in self._daemon.scan_collection.ids_iterator(): self._daemon.check_scan_process(scan_id) scan = self._daemon.get_scan_xml(scan_id, details, pop_res, max_res) responses.append(scan) return simple_response_str('get_scans', 200, 'OK', responses)
def handle_xml(self, xml: Element) -> bytes: """ Handles <get_scanner_details> command. @return: Response string for <get_scanner_details> command. """ desc_xml = Element('description') desc_xml.text = self._daemon.get_scanner_description() scanner_params = self._daemon.get_scanner_params() details = [ desc_xml, OspResponse.create_scanner_params_xml(scanner_params), ] return simple_response_str('get_scanner_details', 200, 'OK', details)
def handle_xml(self, xml: Element) -> bytes: """Handles <get_performance> command. @return: Response string for <get_performance> command. """ start = xml.attrib.get('start') end = xml.attrib.get('end') titles = xml.attrib.get('titles') cmd = ['gvmcg'] if start: try: int(start) except ValueError: raise OspdCommandError( 'Start argument must be integer.', 'get_performance' ) from None cmd.append(start) if end: try: int(end) except ValueError: raise OspdCommandError( 'End argument must be integer.', 'get_performance' ) from None cmd.append(end) if titles: combined = "(" + ")|(".join(GVMCG_TITLES) + ")" forbidden = "^[^|&;]+$" if re.match(combined, titles) and re.match(forbidden, titles): cmd.append(titles) else: raise OspdCommandError( 'Arguments not allowed', 'get_performance' ) try: output = subprocess.check_output(cmd) except (subprocess.CalledProcessError, OSError) as e: raise OspdCommandError( 'Bogus get_performance format. %s' % e, 'get_performance' ) from None return simple_response_str( 'get_performance', 200, 'OK', output.decode() )
def handle_xml(self, xml: Element) -> bytes: """Handles <get_scans> command. @return: Response string for <get_scans> command. """ scan_id = xml.get('scan_id') if scan_id is None or scan_id == '': raise OspdCommandError('No scan_id attribute', 'get_scans') details = xml.get('details') pop_res = xml.get('pop_results') max_res = xml.get('max_results') progress = xml.get('progress') if details and details == '0': details = False else: details = True pop_res = pop_res and pop_res == '1' if max_res: max_res = int(max_res) progress = progress and progress == '1' responses = [] if scan_id in self._daemon.scan_collection.ids_iterator(): self._daemon.check_scan_process(scan_id) scan = self._daemon.get_scan_xml(scan_id, details, pop_res, max_res, progress) responses.append(scan) else: text = f"Failed to find scan '{scan_id}'" return simple_response_str('get_scans', 404, text) return simple_response_str('get_scans', 200, 'OK', responses)
def handle_xml(self, xml: Element) -> bytes: """Handles <get_version> command. Return: Response string for <get_version> command. """ protocol = Element('protocol') for name, value in [ ('name', 'OSP'), ('version', self._daemon.get_protocol_version()), ]: elem = SubElement(protocol, name) elem.text = value daemon = Element('daemon') for name, value in [ ('name', self._daemon.get_daemon_name()), ('version', self._daemon.get_daemon_version()), ]: elem = SubElement(daemon, name) elem.text = value scanner = Element('scanner') for name, value in [ ('name', self._daemon.get_scanner_name()), ('version', self._daemon.get_scanner_version()), ]: elem = SubElement(scanner, name) elem.text = value content = [protocol, daemon, scanner] vts_version = self._daemon.get_vts_version() if vts_version: vts = Element('vts') elem = SubElement(vts, 'version') elem.text = vts_version elem = SubElement(vts, 'vendor') elem.text = self._daemon.get_feed_vendor() elem = SubElement(vts, 'home') elem.text = self._daemon.get_feed_home() elem = SubElement(vts, 'name') elem.text = self._daemon.get_feed_name() content.append(vts) return simple_response_str('get_version', 200, 'OK', content)
def handle_xml(self, xml: Element) -> bytes: """Handles <stop_scan> command. @return: Response string for <stop_scan> command. """ scan_id = xml.get('scan_id') if scan_id is None or scan_id == '': raise OspdCommandError('No scan_id attribute', 'stop_scan') self._daemon.stop_scan(scan_id) # Don't send response until the scan is stopped. try: self._daemon.scan_processes[scan_id].join() except KeyError: pass return simple_response_str('stop_scan', 200, 'OK')
def handle_xml(self, xml: Element) -> bytes: processes_element = Element('processes') unit = xml.get('unit') current_process = multiprocessing.current_process() process_element = self._create_process_element(current_process.name, current_process.pid) self._add_memory_info(process_element, current_process.pid, unit) processes_element.append(process_element) for proc in multiprocessing.active_children(): process_element = self._create_process_element(proc.name, proc.pid) self._add_memory_info(process_element, proc.pid, unit) processes_element.append(process_element) return simple_response_str('get_memory', 200, 'OK', processes_element)
def handle_xml(self, xml: Element) -> bytes: """Handles <check_feed> command. Return: Response string for <check_feed> command. """ feed = Element('feed') feed_status = self._daemon.check_feed_self_test() if not feed_status or not isinstance(feed_status, dict): raise OspdCommandError('No feed status available', 'check_feed') for key, value in feed_status.items(): elem = SubElement(feed, key) elem.text = value content = [feed] return simple_response_str('check_feed', 200, 'OK', content)
def handle_xml(self, xml: Element) -> bytes: """Handles <get_scanner_details> command. @return: Response string for <get_scanner_details> command. """ list_all = xml.get('list_all') list_all = True if list_all == '1' else False desc_xml = Element('description') desc_xml.text = self._daemon.get_scanner_description() scanner_params = self._daemon.get_scanner_params() if not list_all: scanner_params = { key: value for (key, value) in scanner_params.items() if value.get('visible_for_client') } details = [ desc_xml, OspResponse.create_scanner_params_xml(scanner_params), ] return simple_response_str('get_scanner_details', 200, 'OK', details)
def as_xml(self) -> str: """ Return the error in xml format. """ return simple_response_str(self.command, self.status, self.message)
def handle_xml(self, xml: Element) -> bytes: """Handles <start_scan> command. Return: Response string for <start_scan> command. """ current_queued_scans = self._daemon.get_count_queued_scans() if ( self._daemon.max_queued_scans and current_queued_scans >= self._daemon.max_queued_scans ): logger.info( 'Maximum number of queued scans set to %d reached.', self._daemon.max_queued_scans, ) raise OspdCommandError( 'Maximum number of queued scans set to %d reached.' % self._daemon.max_queued_scans, 'start_scan', ) target_str = xml.get('target') ports_str = xml.get('ports') # For backward compatibility, if target and ports attributes are set, # <targets> element is ignored. if target_str is None or ports_str is None: target_element = xml.find('targets/target') if target_element is None: raise OspdCommandError('No targets or ports', 'start_scan') else: scan_target = OspRequest.process_target_element(target_element) else: scan_target = { 'hosts': target_str, 'ports': ports_str, 'credentials': {}, 'exclude_hosts': '', 'finished_hosts': '', 'options': {}, } logger.warning( "Legacy start scan command format is being used, which " "is deprecated since 20.08. Please read the documentation " "for start scan command." ) scan_id = xml.get('scan_id') if scan_id is not None and scan_id != '' and not valid_uuid(scan_id): raise OspdCommandError('Invalid scan_id UUID', 'start_scan') if xml.get('parallel'): logger.warning( "parallel attribute of start_scan will be ignored, sice " "parallel scan is not supported by OSPd." ) scanner_params = xml.find('scanner_params') if scanner_params is None: raise OspdCommandError('No scanner_params element', 'start_scan') # params are the parameters we got from the <scanner_params> XML. params = self._daemon.preprocess_scan_params(scanner_params) # VTS is an optional element. If present should not be empty. vt_selection = {} # type: Dict scanner_vts = xml.find('vt_selection') if scanner_vts is not None: if len(scanner_vts) == 0: raise OspdCommandError('VTs list is empty', 'start_scan') else: vt_selection = OspRequest.process_vts_params(scanner_vts) scan_params = self._daemon.process_scan_params(params) scan_id_aux = scan_id scan_id = self._daemon.create_scan( scan_id, scan_target, scan_params, vt_selection ) if not scan_id: id_ = Element('id') id_.text = scan_id_aux return simple_response_str('start_scan', 100, 'Continue', id_) logger.info( 'Scan %s added to the queue in position %d.', scan_id, current_queued_scans + 1, ) id_ = Element('id') id_.text = scan_id return simple_response_str('start_scan', 200, 'OK', id_)
def handle_xml(self, xml: Element) -> bytes: """ Handles <start_scan> command. Return: Response string for <start_scan> command. """ target_str = xml.get('target') ports_str = xml.get('ports') # For backward compatibility, if target and ports attributes are set, # <targets> element is ignored. if target_str is None or ports_str is None: target_element = xml.find('targets/target') if target_element is None: raise OspdCommandError('No targets or ports', 'start_scan') else: scan_target = OspRequest.process_target_element(target_element) else: scan_target = { 'hosts': target_str, 'ports': ports_str, 'credentials': {}, 'exclude_hosts': '', 'finished_hosts': '', 'options': {}, } logger.warning( "Legacy start scan command format is beeing used, which " "is deprecated since 20.04. Please read the documentation " "for start scan command.") scan_id = xml.get('scan_id') if scan_id is not None and scan_id != '' and not valid_uuid(scan_id): raise OspdCommandError('Invalid scan_id UUID', 'start_scan') if xml.get('parallel'): logger.warning( "parallel attribute of start_scan will be ignored, sice " "parallel scan is not supported by OSPd.") scanner_params = xml.find('scanner_params') if scanner_params is None: raise OspdCommandError('No scanner_params element', 'start_scan') params = self._daemon.preprocess_scan_params(scanner_params) # VTS is an optional element. If present should not be empty. vt_selection = {} # type: Dict scanner_vts = xml.find('vt_selection') if scanner_vts is not None: if len(scanner_vts) == 0: raise OspdCommandError('VTs list is empty', 'start_scan') else: vt_selection = OspRequest.process_vts_params(scanner_vts) # Dry run case. if 'dry_run' in params and int(params['dry_run']): scan_func = self._daemon.dry_run_scan scan_params = None else: scan_func = self._daemon.start_scan scan_params = self._daemon.process_scan_params(params) scan_id_aux = scan_id scan_id = self._daemon.create_scan(scan_id, scan_target, scan_params, vt_selection) if not scan_id: id_ = Element('id') id_.text = scan_id_aux return simple_response_str('start_scan', 100, 'Continue', id_) scan_process = create_process(func=scan_func, args=(scan_id, scan_target)) self._daemon.scan_processes[scan_id] = scan_process scan_process.start() id_ = Element('id') id_.text = scan_id return simple_response_str('start_scan', 200, 'OK', id_)