Example #1
0
    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)
Example #2
0
    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
Example #3
0
    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)
Example #4
0
    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)
Example #5
0
    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
Example #6
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()
Example #7
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()
        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)
Example #8
0
    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)