def stop_scan_cleanup( self, kbdb: BaseDB, scan_id: str, ovas_process: psutil.Popen, # pylint: disable=arguments-differ ): """Set a key in redis to indicate the wrapper is stopped. It is done through redis because it is a new multiprocess instance and it is not possible to reach the variables of the grandchild process. Indirectly sends SIGUSR1 to the running openvas scan process via an invocation of openvas with the --scan-stop option to stop it.""" if kbdb: # Set stop flag in redis kbdb.stop_scan(scan_id) # Check if openvas is running if ovas_process.is_running(): # Cleaning in case of Zombie Process if ovas_process.status() == psutil.STATUS_ZOMBIE: logger.debug( '%s: Process with PID %s is a Zombie process.' ' Cleaning up...', scan_id, ovas_process.pid, ) ovas_process.wait() # Stop openvas process and wait until it stopped else: can_stop_scan = Openvas.stop_scan( scan_id, not self.is_running_as_root and self.sudo_available, ) if not can_stop_scan: logger.debug( 'Not possible to stop scan process: %s.', ovas_process, ) return logger.debug('Stopping process: %s', ovas_process) while ovas_process.is_running(): if ovas_process.status() == psutil.STATUS_ZOMBIE: ovas_process.wait() else: time.sleep(0.1) else: logger.debug( "%s: Process with PID %s already stopped", scan_id, ovas_process.pid, ) # Clean redis db for scan_db in kbdb.get_scan_databases(): self.main_db.release_database(scan_db)
def is_openvas_process_alive(self, kbdb: BaseDB, ovas_pid: str, scan_id: str) -> bool: parent_exists = True parent = None try: parent = psutil.Process(int(ovas_pid)) except psutil.NoSuchProcess: logger.debug('Process with pid %s already stopped', ovas_pid) parent_exists = False except TypeError: logger.debug( 'Scan with ID %s never started and stopped unexpectedly', scan_id, ) parent_exists = False is_zombie = False if parent and parent.status() == psutil.STATUS_ZOMBIE: is_zombie = True if (not parent_exists or is_zombie) and kbdb: if kbdb and kbdb.scan_is_stopped(scan_id): return True return False return True
def report_openvas_scan_status(self, kbdb: BaseDB, scan_id: str): """Get all status entries from redis kb. Arguments: scan_id: Scan ID to identify the current scan. current_host: Host to be updated. """ all_status = kbdb.get_scan_status() all_hosts = dict() finished_hosts = list() for res in all_status: try: current_host, launched, total = res.split('/') except ValueError: continue try: if float(total) == 0: continue elif float(total) == ScanProgress.DEAD_HOST: host_prog = ScanProgress.DEAD_HOST else: host_prog = int((float(launched) / float(total)) * 100) except TypeError: continue all_hosts[current_host] = host_prog if (host_prog == ScanProgress.DEAD_HOST or host_prog == ScanProgress.FINISHED): finished_hosts.append(current_host) self.set_scan_progress_batch(scan_id, host_progress=all_hosts) self.sort_host_finished(scan_id, finished_hosts)
def report_openvas_results(self, db: BaseDB, scan_id: str) -> bool: """Get all result entries from redis kb. Arguments: db: KB context where to get the results from. scan_id: Scan ID to identify the current scan. """ # result_type|||host ip|||hostname|||port|||OID|||value[|||uri] all_results = db.get_result() results = [] for res in all_results: if not res: continue msg = res.split('|||') result = { "result_type": msg[0], "host_ip": msg[1], "host_name": msg[2], "port": msg[3], "oid": msg[4], "value": msg[5], } if len(msg) > 6: result["uri"] = msg[6] results.append(result) return self.report_results(results, scan_id)
def report_openvas_results(self, db: BaseDB, scan_id: str) -> bool: """ Get all result entries from redis kb. """ vthelper = VtHelper(self.nvti) # Result messages come in the next form, with optional uri field # type ||| host ip ||| hostname ||| port ||| OID ||| value [|||uri] all_results = db.get_result() res_list = ResultList() total_dead = 0 for res in all_results: if not res: continue msg = res.split('|||') roid = msg[4].strip() rqod = '' rname = '' current_host = msg[1].strip() if msg[1] else '' rhostname = msg[2].strip() if msg[2] else '' host_is_dead = "Host dead" in msg[5] or msg[0] == "DEADHOST" host_deny = "Host access denied" in msg[5] start_end_msg = msg[0] == "HOST_START" or msg[0] == "HOST_END" vt_aux = None # URI is optional and msg list length must be checked ruri = '' if len(msg) > 6: ruri = msg[6] if (roid and not host_is_dead and not host_deny and not start_end_msg): vt_aux = vthelper.get_single_vt(roid) if (not vt_aux and not host_is_dead and not host_deny and not start_end_msg): logger.warning('Invalid VT oid %s for a result', roid) if vt_aux: if vt_aux.get('qod_type'): qod_t = vt_aux.get('qod_type') rqod = self.nvti.QOD_TYPES[qod_t] elif vt_aux.get('qod'): rqod = vt_aux.get('qod') rname = vt_aux.get('name') if msg[0] == 'ERRMSG': res_list.add_scan_error_to_list( host=current_host, hostname=rhostname, name=rname, value=msg[5], port=msg[3], test_id=roid, uri=ruri, ) elif msg[0] == 'HOST_START' or msg[0] == 'HOST_END': res_list.add_scan_log_to_list( host=current_host, name=msg[0], value=msg[5], ) elif msg[0] == 'LOG': res_list.add_scan_log_to_list( host=current_host, hostname=rhostname, name=rname, value=msg[5], port=msg[3], qod=rqod, test_id=roid, uri=ruri, ) elif msg[0] == 'HOST_DETAIL': res_list.add_scan_host_detail_to_list( host=current_host, hostname=rhostname, name=rname, value=msg[5], uri=ruri, ) elif msg[0] == 'ALARM': rseverity = self.get_severity_score(vt_aux) res_list.add_scan_alarm_to_list( host=current_host, hostname=rhostname, name=rname, value=msg[5], port=msg[3], test_id=roid, severity=rseverity, qod=rqod, uri=ruri, ) # To process non-scanned dead hosts when # test_alive_host_only in openvas is enable elif msg[0] == 'DEADHOST': try: total_dead = int(msg[5]) except TypeError: logger.debug('Error processing dead host count') # Insert result batch into the scan collection table. if len(res_list): self.scan_collection.add_result_list(scan_id, res_list) if total_dead: self.scan_collection.set_amount_dead_hosts(scan_id, total_dead=total_dead) return len(res_list) > 0
def report_openvas_results( self, db: BaseDB, scan_id: str, current_host: str ): """ Get all result entries from redis kb. """ res = db.get_result() while res: msg = res.split('|||') roid = msg[3].strip() rqod = '' rname = '' rhostname = msg[1].strip() if msg[1] else '' host_is_dead = "Host dead" in msg[4] vt_aux = None if roid and not host_is_dead: vt_aux = copy.deepcopy(self.vts.get(roid)) if not vt_aux and not host_is_dead: logger.warning('Invalid VT oid %s for a result', roid) if vt_aux: if vt_aux.get('qod_type'): qod_t = vt_aux.get('qod_type') rqod = self.nvti.QOD_TYPES[qod_t] elif vt_aux.get('qod'): rqod = vt_aux.get('qod') rname = vt_aux.get('name') if msg[0] == 'ERRMSG': self.add_scan_error( scan_id, host=current_host, hostname=rhostname, name=rname, value=msg[4], port=msg[2], test_id=roid, ) if msg[0] == 'LOG': self.add_scan_log( scan_id, host=current_host, hostname=rhostname, name=rname, value=msg[4], port=msg[2], qod=rqod, test_id=roid, ) if msg[0] == 'HOST_DETAIL': self.add_scan_host_detail( scan_id, host=current_host, hostname=rhostname, name=rname, value=msg[4], ) if msg[0] == 'ALARM': rseverity = self.get_severity_score(vt_aux) self.add_scan_alarm( scan_id, host=current_host, hostname=rhostname, name=rname, value=msg[4], port=msg[2], test_id=roid, severity=rseverity, qod=rqod, ) vt_aux = None del vt_aux res = db.get_result()
def report_openvas_results(self, db: BaseDB, scan_id: str, current_host: str): """ Get all result entries from redis kb. """ res = db.get_result() res_list = ResultList() host_progress_batch = dict() finished_host_batch = list() while res: msg = res.split('|||') roid = msg[3].strip() rqod = '' rname = '' rhostname = msg[1].strip() if msg[1] else '' host_is_dead = "Host dead" in msg[4] vt_aux = None if roid and not host_is_dead: vt_aux = copy.deepcopy(self.vts.get(roid)) if not vt_aux and not host_is_dead: logger.warning('Invalid VT oid %s for a result', roid) if vt_aux: if vt_aux.get('qod_type'): qod_t = vt_aux.get('qod_type') rqod = self.nvti.QOD_TYPES[qod_t] elif vt_aux.get('qod'): rqod = vt_aux.get('qod') rname = vt_aux.get('name') if msg[0] == 'ERRMSG': res_list.add_scan_error_to_list( host=current_host, hostname=rhostname, name=rname, value=msg[4], port=msg[2], test_id=roid, ) if msg[0] == 'LOG': res_list.add_scan_log_to_list( host=current_host, hostname=rhostname, name=rname, value=msg[4], port=msg[2], qod=rqod, test_id=roid, ) if msg[0] == 'HOST_DETAIL': res_list.add_scan_host_detail_to_list( host=current_host, hostname=rhostname, name=rname, value=msg[4], ) if msg[0] == 'ALARM': rseverity = self.get_severity_score(vt_aux) res_list.add_scan_alarm_to_list( host=current_host, hostname=rhostname, name=rname, value=msg[4], port=msg[2], test_id=roid, severity=rseverity, qod=rqod, ) # To process non scanned dead hosts when # test_alive_host_only in openvas is enable if msg[0] == 'DEADHOST': hosts = msg[3].split(',') for _host in hosts: if _host: host_progress_batch[_host] = 100 finished_host_batch.append(_host) res_list.add_scan_log_to_list( host=_host, hostname=rhostname, name=rname, value=msg[4], port=msg[2], qod=rqod, test_id='', ) timestamp = time.ctime(time.time()) res_list.add_scan_log_to_list( host=_host, name='HOST_START', value=timestamp, ) res_list.add_scan_log_to_list( host=_host, name='HOST_END', value=timestamp, ) vt_aux = None del vt_aux res = db.get_result() # Insert result batch into the scan collection table. if len(res_list): self.scan_collection.add_result_list(scan_id, res_list) if host_progress_batch: self.set_scan_progress_batch(scan_id, host_progress=host_progress_batch) if finished_host_batch: self.set_scan_host_finished(scan_id, finished_hosts=finished_host_batch)
def report_openvas_results(self, db: BaseDB, scan_id: str, current_host: str): """ Get all result entries from redis kb. """ vthelper = VtHelper(self.nvti) # Result messages come in the next form, with optional uri field # type ||| hostname ||| port ||| OID ||| value [|||uri] res = db.get_result() res_list = ResultList() total_dead = 0 while res: msg = res.split('|||') roid = msg[3].strip() rqod = '' rname = '' rhostname = msg[1].strip() if msg[1] else '' host_is_dead = "Host dead" in msg[4] or msg[0] == "DEADHOST" host_deny = "Host access denied" in msg[4] vt_aux = None # URI is optional and msg list length must be checked ruri = '' if len(msg) > 5: ruri = msg[5] if roid and not host_is_dead and not host_deny: vt_aux = vthelper.get_single_vt(roid) if not vt_aux and not host_is_dead and not host_deny: logger.warning('Invalid VT oid %s for a result', roid) if vt_aux: if vt_aux.get('qod_type'): qod_t = vt_aux.get('qod_type') rqod = self.nvti.QOD_TYPES[qod_t] elif vt_aux.get('qod'): rqod = vt_aux.get('qod') rname = vt_aux.get('name') if msg[0] == 'ERRMSG': # Some errors are generated before a host is scanned # use the hostname passed in the message if # no current host is available. if not current_host and rhostname: current_host = rhostname res_list.add_scan_error_to_list( host=current_host, hostname=rhostname, name=rname, value=msg[4], port=msg[2], test_id=roid, uri=ruri, ) if msg[0] == 'LOG': res_list.add_scan_log_to_list( host=current_host, hostname=rhostname, name=rname, value=msg[4], port=msg[2], qod=rqod, test_id=roid, uri=ruri, ) if msg[0] == 'HOST_DETAIL': res_list.add_scan_host_detail_to_list( host=current_host, hostname=rhostname, name=rname, value=msg[4], uri=ruri, ) if msg[0] == 'ALARM': rseverity = self.get_severity_score(vt_aux) res_list.add_scan_alarm_to_list( host=current_host, hostname=rhostname, name=rname, value=msg[4], port=msg[2], test_id=roid, severity=rseverity, qod=rqod, uri=ruri, ) # To process non-scanned dead hosts when # test_alive_host_only in openvas is enable if msg[0] == 'DEADHOST': try: total_dead = int(msg[4]) except TypeError: logger.debug('Error processing dead host count') res = db.get_result() # Insert result batch into the scan collection table. if len(res_list): self.scan_collection.add_result_list(scan_id, res_list) if total_dead: self.scan_collection.set_amount_dead_hosts(scan_id, total_dead=total_dead)