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 ]), ))
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 ] ), ) )
def feed_is_outdated(self, current_feed): """ Compare the current feed with the one in the disk. Return: False if there is no new feed. True if the feed version in disk is newer than the feed in redis cache. None if there is no feed the disk. """ plugins_folder = self.scan_only_params.get('plugins_folder') if not plugins_folder: raise OspdOpenvasError("Error: Path to plugins folder not found.") feed_info_file = Path(plugins_folder) / 'plugin_feed_info.inc' if not feed_info_file.exists(): self.parse_param() msg = 'Plugins feed file %s not found.' % feed_info_file logger.debug(msg) return None date = 0 with open(str(feed_info_file)) as fcontent: for line in fcontent: if "PLUGIN_SET" in line: date = line.split(' = ')[1] date = date.replace(';', '') date = date.replace('"', '') if int(current_feed) < int(date) or int(date) == 0: return True return False
def get_feed_info(self) -> Dict[str, Any]: """Parses the current plugin_feed_info.inc file""" plugins_folder = self.scan_only_params.get('plugins_folder') if not plugins_folder: raise OspdOpenvasError("Error: Path to plugins folder not found.") feed_info_file = Path(plugins_folder) / 'plugin_feed_info.inc' if not feed_info_file.exists(): self.set_params_from_openvas_settings() logger.debug('Plugins feed file %s not found.', feed_info_file) return {} feed_info = {} with feed_info_file.open(encoding='utf-8') as fcontent: for line in fcontent: try: key, value = line.split('=', 1) except ValueError: continue key = key.strip() value = value.strip() value = value.replace(';', '') value = value.replace('"', '') if value: feed_info[key] = value return feed_info
def nvti(self) -> NVTICache: if self._nvti is None: try: maindb = MainDB() self._nvti = NVTICache(maindb) except SystemExit: raise OspdOpenvasError( "Could not connect to the Redis KB") from None return self._nvti
def add_vt_to_cache(self, vt_id: str, vt: List[str]): if not vt_id: raise RequiredArgument('add_vt_to_cache', 'vt_id') if not vt: raise RequiredArgument('add_vt_to_cache', 'vt') if not isinstance(vt, list) or len(vt) != 15: raise OspdOpenvasError('Error trying to load the VT' ' {} in cache'.format(vt)) OpenvasDB.add_single_list(self.ctx, vt_id, vt)
def max_db_index(self): """Set the number of databases have been configured into kbr struct. """ ctx = self.kb_connect() resp = ctx.config_get('databases') if len(resp) == 1: self.max_dbindex = int(resp.get('databases')) else: raise OspdOpenvasError( 'Redis Error: Not possible to get max_dbindex.')
def _get_gvm_libs_version_string(self) -> str: """ Parse version of gvm-libs """ try: result = subprocess.check_output(['openvas', '--version'], ) except (CalledProcessError, PermissionError) as e: raise OspdOpenvasError( "Not possible to get the installed gvm-libs version. %s" % e) output = result.decode('utf-8').rstrip() if 'gvm-libs' not in output: raise OspdOpenvasError( "Not possible to get the installed gvm-libs version. " "Outdated openvas version. openvas version needs to be at " "least 7.0.1.") lines = output.splitlines() _, version_string = lines[1].split(' ', 1) return version_string
def max_database_index(self): """Set the number of databases have been configured into kbr struct.""" if self._max_dbindex is None: resp = self.ctx.config_get('databases') if len(resp) == 1: self._max_dbindex = int(resp.get('databases')) else: raise OspdOpenvasError( 'Redis Error: Not possible to get max_dbindex.') from None return self._max_dbindex
def add_vt_to_cache(self, vt_id: str, vt: List[str]): if not vt_id: raise RequiredArgument('add_vt_to_cache', 'vt_id') if not vt: raise RequiredArgument('add_vt_to_cache', 'vt') if not isinstance(vt, list) or len(vt) != 15: raise OspdOpenvasError( f'Error trying to load the VT {vt} in cache') OpenvasDB.add_single_list(self.ctx, vt_id, vt) OpenvasDB.add_single_item(self.ctx, f'filename:{vt[0]}', [int(time())])
def get_kb_context(self) -> RedisCtx: """ Get redis context if it is already connected or do a connection. """ if self.rediscontext is not None: return self.rediscontext self.rediscontext = self.db_find(self.DBINDEX_NAME) if self.rediscontext is None: raise OspdOpenvasError( 'Redis Error: Problem retrieving Redis Context') return self.rediscontext
def _set_nvti_cache_name(self): """Set nvticache name""" version_string = self._get_gvm_libs_version_string() 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 ]), ))
def get_db_connection(self): """ Retrieve the db address from openvas config. """ if self.db_address: return try: result = subprocess.check_output(['openvas', '-s'], stderr=subprocess.STDOUT) except (PermissionError, OSError, subprocess.CalledProcessError) as e: raise OspdOpenvasError( "{}: Not possible to run openvas. {}".format( self.get_db_connection.__name__, e)) if result: path = self._parse_openvas_db_address(result) self.db_address = path
def _parse_openvas_db_address(result: bytes) -> str: """ Return the path to the redis socket. Arguments: result: Output of `openvas -s` Return redis unix socket path. """ path = None result = result.decode('ascii') for conf in result.split('\n'): if conf.find('db_address') == 0: path = conf.split('=') break if not path: raise OspdOpenvasError('Redis Error: Not possible to ' 'find the path to the redis socket.') return path[1].strip()
def feed_is_outdated(self, current_feed: str) -> Optional[bool]: """Compare the current feed with the one in the disk. Return: False if there is no new feed. True if the feed version in disk is newer than the feed in redis cache. None if there is no feed on the disk. """ plugins_folder = self.scan_only_params.get('plugins_folder') if not plugins_folder: raise OspdOpenvasError("Error: Path to plugins folder not found.") feed_info_file = Path(plugins_folder) / 'plugin_feed_info.inc' if not feed_info_file.exists(): self.set_params_from_openvas_settings() logger.debug('Plugins feed file %s not found.', feed_info_file) return None current_feed = safe_int(current_feed) if current_feed is None: logger.debug( "Wrong PLUGIN_SET format in plugins feed file %s. Format has to" " be yyyymmddhhmm. For example 'PLUGIN_SET = \"201910251033\"'", feed_info_file, ) feed_date = None with feed_info_file.open() as fcontent: for line in fcontent: if "PLUGIN_SET" in line: feed_date = line.split('=', 1)[1] feed_date = feed_date.strip() feed_date = feed_date.replace(';', '') feed_date = feed_date.replace('"', '') feed_date = safe_int(feed_date) break logger.debug("Current feed version: %s", current_feed) logger.debug("Plugin feed version: %s", feed_date) return ( (not feed_date) or (not current_feed) or (current_feed < feed_date) )
def try_database(self, index: int) -> bool: """ Check if a redis db is already in use. If not, set it as in use and return. Arguments: ctx: Redis object connected to the kb with the DBINDEX_NAME key. index: Number intended to be used. Return True if it is possible to use the db. False if the given db number is already in use. """ _in_use = 1 try: resp = self.ctx.hsetnx(DBINDEX_NAME, index, _in_use) except: raise OspdOpenvasError('Redis Error: Not possible to set %s.' % DBINDEX_NAME) return resp == 1
def try_database_index(self, ctx: RedisCtx, kb: int) -> bool: """ Check if a redis kb is already in use. If not, set it as in use and return. Arguments: ctx: Redis object connected to the kb with the DBINDEX_NAME key. kb: Kb number intended to be used. Return True if it is possible to use the kb. False if the given kb number is already in use. """ _in_use = 1 try: resp = ctx.hsetnx(self.DBINDEX_NAME, kb, _in_use) except: raise OspdOpenvasError('Redis Error: Not possible to set %s.' % self.DBINDEX_NAME) if resp == 1: return True return False
def kb_connect(self, dbnum=0): """ Connect to redis to the given database or to the default db 0 . Arguments: dbnum (int, optional): The db number to connect to. Return a redis context on success. """ self.get_db_connection() tries = 5 while tries: try: ctx = redis.Redis( unix_socket_path=self.db_address, db=dbnum, socket_timeout=SOCKET_TIMEOUT, encoding="latin-1", decode_responses=True, ) ctx.keys("test") except (redis.exceptions.ConnectionError, FileNotFoundError) as err: logger.debug( 'Redis connection lost: %s. Trying again in 5 seconds.', err) tries = tries - 1 time.sleep(5) continue break if not tries: raise OspdOpenvasError( 'Redis Error: Not possible to connect to the kb.') self.db_index = dbnum return ctx