Пример #1
0
    def test_stop_scan_with_error(self, mock_check_call: MagicMock,
                                  mock_logger: MagicMock):
        mock_check_call.side_effect = subprocess.SubprocessError('foo')

        success = Openvas.stop_scan('scan_1')

        mock_check_call.assert_called_with(
            ['openvas', '--scan-stop', 'scan_1'])

        self.assertFalse(success)

        self.assertEqual(mock_logger.warning.call_count, 1)

        mock_check_call.reset_mock()
        mock_logger.reset_mock()

        mock_check_call.side_effect = OSError('foo')

        success = Openvas.stop_scan('scan_1')

        mock_check_call.assert_called_with(
            ['openvas', '--scan-stop', 'scan_1'])

        self.assertFalse(success)

        self.assertEqual(mock_logger.warning.call_count, 1)
Пример #2
0
    def test_get_settings_with_error(
        self, mock_check_output: MagicMock, _mock_logger: MagicMock
    ):
        mock_check_output.side_effect = subprocess.SubprocessError('foo')

        settings = Openvas.get_settings()

        mock_check_output.assert_called_with(['openvas', '-s'])

        self.assertFalse(settings)  # settings dict is empty

        mock_check_output.reset_mock()

        mock_check_output.side_effect = OSError('foo')

        settings = Openvas.get_settings()

        mock_check_output.assert_called_with(['openvas', '-s'])

        self.assertFalse(settings)  # settings dict is empty

        mock_check_output.reset_mock()

        # https://gehrcke.de/2015/12/how-to-raise-unicodedecodeerror-in-python-3/
        mock_check_output.side_effect = UnicodeDecodeError(
            'funnycodec', b'\x00\x00', 1, 2, 'This is just a fake reason!'
        )

        settings = Openvas.get_settings()

        mock_check_output.assert_called_with(['openvas', '-s'])

        self.assertFalse(settings)  # settings dict is empty
Пример #3
0
    def test_load_vts_into_redis(self, mock_check_call, mock_logger):
        Openvas.load_vts_into_redis()

        mock_check_call.assert_called_with(['openvas', '--update-vt-info'],
                                           stdout=subprocess.DEVNULL)

        mock_logger.error.assert_not_called()
Пример #4
0
    def check_feed(self):
        """Check if there is a feed update.

        Wait until all the running scans finished. Set a flag to announce there
        is a pending feed update, which avoids to start a new scan.
        """
        if not self.vts.is_cache_available:
            return

        current_feed = self.nvti.get_feed_version()
        is_outdated = self.feed_is_outdated(current_feed)

        # Check if the nvticache in redis is outdated
        if not current_feed or is_outdated:
            with self.feed_lock as fl:
                if fl.has_lock():
                    self.initialized = False
                    Openvas.load_vts_into_redis()
                    notushandler = NotusMetadataHandler(nvti=self.nvti)
                    notushandler.update_metadata()
                    current_feed = self.nvti.get_feed_version()
                    self.set_vts_version(vts_version=current_feed)

                    vthelper = VtHelper(self.nvti)
                    self.vts.sha256_hash = (
                        vthelper.calculate_vts_collection_hash())
                    self.initialized = True
                else:
                    logger.debug("The feed was not upload or it is outdated, "
                                 "but other process is locking the update. "
                                 "Trying again later...")
                    return
    def __init__(self, metadata_path: str = None):

        openvas_object = Openvas()
        self.openvas_settings_dict = openvas_object.get_settings()
        self.__no_signature_check = self.openvas_settings_dict[
            "nasl_no_signature_check"]

        # Figure out the path to the metadata
        if not metadata_path:
            self.__metadata_path = self._get_metadata_path()
        else:
            self.__metadata_path = metadata_path

        self.__metadata_relative_path_string = "{}/".format(
            METADATA_DIRECTORY_NAME)

        # Get a list of all CSV files in that directory with their absolute path
        self.__csv_abs_filepaths_list = self._get_csv_filepaths()

        # Connect to the Redis KB
        try:
            self.__db_ctx = db.OpenvasDB.create_context(1)
            main_db = db.MainDB()
            self.__nvti_cache = nvticache.NVTICache(main_db)
        except SystemExit:
            # Maybe replace this with just a log message
            raise Exception("Could not connect to the Redis KB") from None
Пример #6
0
    def test_start_scan_error(self, mock_popen: MagicMock,
                              mock_logger: MagicMock):
        mock_popen.side_effect = subprocess.SubprocessError('foo')

        proc = Openvas.start_scan('scan_1')

        mock_popen.assert_called_with(['openvas', '--scan-start', 'scan_1'],
                                      shell=False)

        self.assertIsNone(proc)

        self.assertEqual(mock_logger.warning.call_count, 1)

        mock_popen.reset_mock()
        mock_logger.reset_mock()

        mock_popen.side_effect = OSError('foo')

        proc = Openvas.start_scan('scan_1')

        mock_popen.assert_called_with(['openvas', '--scan-start', 'scan_1'],
                                      shell=False)

        self.assertIsNone(proc)

        self.assertEqual(mock_logger.warning.call_count, 1)
Пример #7
0
    def test_load_vts_into_redis_with_error(self, mock_check_call: MagicMock,
                                            mock_logger: MagicMock):
        mock_check_call.side_effect = subprocess.SubprocessError('foo')

        Openvas.load_vts_into_redis()

        mock_check_call.assert_called_with(['openvas', '--update-vt-info'],
                                           stdout=subprocess.DEVNULL)

        self.assertEqual(mock_logger.error.call_count, 1)
Пример #8
0
    def test_check_sudo_with_error(self, mock_check_call: MagicMock):
        mock_check_call.side_effect = subprocess.SubprocessError('foo')

        self.assertFalse(Openvas.check_sudo())
        mock_check_call.assert_called_with(['sudo', '-n', 'openvas', '-s'],
                                           stdout=subprocess.DEVNULL)

        mock_check_call.reset_mock()
        mock_check_call.side_effect = OSError('foo')

        self.assertFalse(Openvas.check_sudo())
        mock_check_call.assert_called_with(['sudo', '-n', 'openvas', '-s'],
                                           stdout=subprocess.DEVNULL)
Пример #9
0
    def test_get_version_with_error(self, mock_check_output: MagicMock):
        mock_check_output.side_effect = subprocess.SubprocessError('foo')

        self.assertIsNone(Openvas.get_version())

        mock_check_output.assert_called_with(['openvas', '-V'],
                                             stderr=subprocess.STDOUT)

        mock_check_output.reset_mock()
        mock_check_output.side_effect = OSError('foo')

        self.assertIsNone(Openvas.get_version())

        mock_check_output.assert_called_with(['openvas', '-V'],
                                             stderr=subprocess.STDOUT)
Пример #10
0
    def init(self, server: BaseServer) -> None:

        server.start(self.handle_client_stream)

        self.scanner_info['version'] = Openvas.get_version()

        self.set_params_from_openvas_settings()

        if not self.nvti.ctx:
            with self.feed_lock.wait_for_lock():
                Openvas.load_vts_into_redis()

        self.load_vts()

        self.initialized = True
Пример #11
0
    def test_get_version(self, mock_check_output: MagicMock):
        mock_check_output.return_value = b"OpenVAS 20.08"

        self.assertEqual(Openvas.get_version(), 'OpenVAS 20.08')

        mock_check_output.assert_called_with(['openvas', '-V'],
                                             stderr=subprocess.STDOUT)
Пример #12
0
    def get_database_address(cls) -> Optional[str]:
        if not cls._db_address:
            settings = Openvas.get_settings()

            cls._db_address = settings.get('db_address')

        return cls._db_address
Пример #13
0
 def prepare_alive_test_option_for_openvas(self):
     """ Set alive test option. Overwrite the scan config settings."""
     settings = Openvas.get_settings()
     if settings and self.target_options.get('alive_test'):
         alive_test_opt = self.build_alive_test_opt_as_prefs(
             self.target_options)
         self.kbdb.add_scan_preferences(self.scan_id, alive_test_opt)
Пример #14
0
    def _set_nvti_cache_name(self):
        """Set nvticache name"""
        version_string = Openvas.get_gvm_libs_version()
        if not version_string:
            raise OspdOpenvasError(
                "Not possible to get the installed gvm-libs version. "
                "Outdated openvas version. openvas version needs to be at "
                "least 7.0.1.")
        # Remove pre-release sufix and git revision if exists
        # as the gvm-libs version has the  format
        # e.g "20.8+beta1-git-a41b140d-zero-padding"
        version_string = version_string.split("+")[0]

        if self._is_compatible_version(version_string):
            self._nvti_cache_name = "nvticache{}".format(version_string)
        else:
            raise OspdOpenvasError(
                "Error setting nvticache. Incompatible nvticache "
                "version {}. Supported versions are {}.".format(
                    version_string,
                    ", ".join([
                        str(spec)
                        for spec in SUPPORTED_NVTICACHE_VERSIONS_SPECIFIER
                    ]),
                ))
Пример #15
0
 def prepare_alive_test_option_for_openvas(self):
     """ Set alive test option. Overwrite the scan config settings."""
     settings = Openvas.get_settings()
     if settings and self.target_options.get('alive_test'):
         alive_test_opt = self.build_alive_test_opt_as_prefs(
             self.target_options)
         self._nvts_params.update(alive_test_opt)
Пример #16
0
    def test_start_scan_with_sudo(self, mock_popen: MagicMock):
        proc = Openvas.start_scan('scan_1', sudo=True)

        mock_popen.assert_called_with(
            ['sudo', '-n', 'openvas', '--scan-start', 'scan_1'], shell=False)

        self.assertIsNotNone(proc)
Пример #17
0
 def prepare_alive_test_option_for_openvas(self):
     """ Set alive test option. Overwrite the scan config settings.
     Check if test_alive_hosts_only feature of openvas is active.
     If active, put ALIVE_TEST enum in preferences. """
     settings = Openvas.get_settings()
     if settings:
         test_alive_hosts_only = settings.get('test_alive_hosts_only')
         if test_alive_hosts_only:
             if self.target_options.get('alive_test'):
                 try:
                     alive_test = int(self.target_options.get('alive_test'))
                 except ValueError:
                     logger.debug(
                         'Alive test settings not applied. '
                         'Invalid alive test value %s',
                         self.target_options.get('alive_test'),
                     )
                 # Put ALIVE_TEST enum in db, this is then taken
                 # by openvas to determine the method to use
                 # for the alive test.
                 if alive_test >= 1 and alive_test <= 31:
                     item = 'ALIVE_TEST|||%s' % str(alive_test)
                     self.kbdb.add_scan_preferences(self._openvas_scan_id,
                                                    [item])
         elif self.target_options.get('alive_test'):
             alive_test_opt = self.build_alive_test_opt_as_prefs(
                 self.target_options)
             self.kbdb.add_scan_preferences(self._openvas_scan_id,
                                            alive_test_opt)
Пример #18
0
    def test_get_version_not_found(self, mock_check_output: MagicMock):
        mock_check_output.return_value = b"Foo 20.04"

        self.assertIsNone(Openvas.get_version())

        mock_check_output.assert_called_with(['openvas', '-V'],
                                             stderr=subprocess.STDOUT)
Пример #19
0
    def _set_nvti_cache_name(self):
        """Set nvticache name"""
        version_string = Openvas.get_gvm_libs_version()
        if not version_string:
            raise OspdOpenvasError(
                "Not possible to get the installed gvm-libs version. "
                "Outdated openvas version. openvas version needs to be at "
                "least 7.0.1."
            )

        if self._is_compatible_version(version_string):
            self._nvti_cache_name = "nvticache{}".format(version_string)
        else:
            raise OspdOpenvasError(
                "Error setting nvticache. Incompatible nvticache "
                "version {}. Supported versions are {}.".format(
                    version_string,
                    ", ".join(
                        [
                            str(spec)
                            for spec in SUPPORTED_NVTICACHE_VERSIONS_SPECIFIER
                        ]
                    ),
                )
            )
Пример #20
0
    def test_get_gvm_libs_version_not_version(self, mock_check_output):
        mock_check_output.return_value = b"OpenVAS 20.04\n"

        self.assertIsNone(Openvas.get_gvm_libs_version())

        mock_check_output.assert_called_with(['openvas', '-V'],
                                             stderr=subprocess.STDOUT)
Пример #21
0
    def test_get_gvm_libs_version(self, mock_check_output):
        mock_check_output.return_value = b"OpenVAS 20.04\ngvm-libs 20.04"

        self.assertEqual(Openvas.get_gvm_libs_version(), '20.04')

        mock_check_output.assert_called_with(['openvas', '-V'],
                                             stderr=subprocess.STDOUT)
Пример #22
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)
Пример #23
0
    def init(self, server: BaseServer) -> None:

        server.start(self.handle_client_stream)

        self.scanner_info['version'] = Openvas.get_version()

        self.set_params_from_openvas_settings()

        with self.feed_lock.wait_for_lock():
            Openvas.load_vts_into_redis()
            current_feed = self.nvti.get_feed_version()
            self.set_vts_version(vts_version=current_feed)

        vthelper = VtHelper(self.nvti)
        self.vts.sha256_hash = vthelper.calculate_vts_collection_hash()

        self.initialized = True
Пример #24
0
    def test_stop_scan_with_sudo(self, mock_check_call: MagicMock,
                                 _mock_logger: MagicMock):
        success = Openvas.stop_scan('scan_1', sudo=True)

        mock_check_call.assert_called_with(
            ['sudo', '-n', 'openvas', '--scan-stop', 'scan_1'])

        self.assertTrue(success)
Пример #25
0
    def test_start_scan_with_niceness(self, mock_popen: MagicMock):
        proc = Openvas.start_scan('scan_1', niceness=4)

        mock_popen.assert_called_with(
            ['nice', '-n', 4, 'openvas', '--scan-start', 'scan_1'],
            shell=False)

        self.assertIsNotNone(proc)
Пример #26
0
 def check(self) -> bool:
     """Checks that openvas command line tool is found and
     is executable."""
     has_openvas = Openvas.check()
     if not has_openvas:
         logger.error(
             'openvas executable not available. Please install openvas'
             ' into your PATH.')
     return has_openvas
Пример #27
0
    def set_params_from_openvas_settings(self):
        """Set OSPD_PARAMS with the params taken from the openvas executable."""
        param_list = Openvas.get_settings()

        for elem in param_list:
            if elem not in OSPD_PARAMS:
                self.scan_only_params[elem] = param_list[elem]
            else:
                OSPD_PARAMS[elem]['default'] = param_list[elem]
Пример #28
0
    def init(self, server: BaseServer) -> None:

        notus_handler = NotusResultHandler(self.report_results)

        if self._mqtt_broker_address:
            try:
                client = MQTTClient(self._mqtt_broker_address,
                                    self._mqtt_broker_port, "ospd")
                daemon = MQTTDaemon(client)
                subscriber = MQTTSubscriber(client)

                subscriber.subscribe(ResultMessage,
                                     notus_handler.result_handler)
                daemon.run()
            except (ConnectionRefusedError, gaierror, ValueError) as e:
                logger.error(
                    "Could not connect to MQTT broker at %s, error was: %s."
                    " Unable to get results from Notus.",
                    self._mqtt_broker_address,
                    e,
                )
        else:
            logger.info(
                "MQTT Broker Adress empty. MQTT disabled. Unable to get Notus"
                " results.")

        self.scan_collection.init()

        server.start(self.handle_client_stream)

        self.scanner_info['version'] = Openvas.get_version()

        self.set_params_from_openvas_settings()

        with self.feed_lock.wait_for_lock():
            Openvas.load_vts_into_redis()
            self.set_feed_info()

            logger.debug("Calculating vts integrity check hash...")
            vthelper = VtHelper(self.nvti)
            self.vts.sha256_hash = vthelper.calculate_vts_collection_hash()

        self.initialized = True
Пример #29
0
    def test_get_settings_with_error(self, mock_check_output: MagicMock,
                                     _mock_logger: MagicMock):
        mock_check_output.side_effect = subprocess.SubprocessError('foo')

        settings = Openvas.get_settings()

        mock_check_output.assert_called_with(['openvas', '-s'])

        self.assertFalse(settings)  # settings dict is empty

        mock_check_output.reset_mock()

        mock_check_output.side_effect = OSError('foo')

        settings = Openvas.get_settings()

        mock_check_output.assert_called_with(['openvas', '-s'])

        self.assertFalse(settings)  # settings dict is empty
Пример #30
0
    def sudo_available(self) -> bool:
        """ Checks that sudo is available """
        if self._sudo_available is not None:
            return self._sudo_available

        if self.is_running_as_root:
            self._sudo_available = False
            return self._sudo_available

        self._sudo_available = Openvas.check_sudo()

        return self._sudo_available