kb.c
Go to the documentation of this file.
/* SPDX-FileCopyrightText: 2014-2023 Greenbone AG
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#define _GNU_SOURCE
#include "kb.h"
#include <errno.h> /* for ENOMEM, EINVAL, EPROTO, EALREADY, ECONN... */
#include <glib.h> /* for g_log, g_free */
#include <hiredis/hiredis.h> /* for redisReply, freeReplyObject, redisCommand */
#include <stdbool.h> /* for bool, true, false */
#include <stdio.h>
#include <stdlib.h> /* for atoi */
#include <string.h> /* for strlen, strerror, strncpy, memset */
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "libgvm util"
#if GLIB_CHECK_VERSION(2, 67, 3)
#define memdup g_memdup2
#else
#define memdup g_memdup
#endif
#define GLOBAL_DBINDEX_NAME "GVM.__GlobalDBIndex"
static const struct kb_operations KBRedisOperations;
struct kb_redis
{
struct kb kb;
unsigned int max_db;
unsigned int db;
redisContext *rctx;
char *path;
};
#define redis_kb(__kb) ((struct kb_redis *) (__kb))
static int
redis_delete_all (struct kb_redis *);
static int redis_lnk_reset (kb_t);
static int
redis_flush_all (kb_t, const char *);
static redisReply *
redis_cmd (struct kb_redis *kbr, const char *fmt, ...);
static int
try_database_index (struct kb_redis *kbr, int index)
{
redisContext *ctx = kbr->rctx;
redisReply *rep;
int rc = 0;
rep = redisCommand (ctx, "HSETNX %s %d 1", GLOBAL_DBINDEX_NAME, index);
if (rep == NULL)
return -ENOMEM;
if (rep->type != REDIS_REPLY_INTEGER)
rc = -EPROTO;
else if (rep->integer == 0)
rc = -EALREADY;
else
kbr->db = index;
freeReplyObject (rep);
return rc;
}
static int
fetch_max_db_index (struct kb_redis *kbr)
{
int rc = 0;
redisContext *ctx = kbr->rctx;
redisReply *rep = NULL;
rep = redisCommand (ctx, "CONFIG GET databases");
if (rep == NULL)
{
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"%s: redis command failed with '%s'", __func__, ctx->errstr);
rc = -1;
goto err_cleanup;
}
if (rep->type != REDIS_REPLY_ARRAY)
{
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"%s: cannot retrieve max DB number: %s", __func__, rep->str);
rc = -1;
goto err_cleanup;
}
if (rep->elements == 2)
{
kbr->max_db = (unsigned) atoi (rep->element[1]->str);
}
else
{
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"%s: unexpected reply length (%zd)", __func__, rep->elements);
rc = -1;
goto err_cleanup;
}
g_debug ("%s: maximum DB number: %u", __func__, kbr->max_db);
err_cleanup:
if (rep != NULL)
freeReplyObject (rep);
return rc;
}
static int
select_database (struct kb_redis *kbr)
{
int rc;
redisContext *ctx = kbr->rctx;
redisReply *rep = NULL;
if (kbr->db == 0)
{
unsigned i;
if (kbr->max_db == 0)
fetch_max_db_index (kbr);
for (i = 1; i < kbr->max_db; i++)
{
rc = try_database_index (kbr, i);
if (rc == 0)
break;
}
}
/* No DB available, give up. */
if (kbr->db == 0)
{
rc = -1;
goto err_cleanup;
}
rep = redisCommand (ctx, "SELECT %u", kbr->db);
if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
{
rc = -1;
goto err_cleanup;
}
rc = 0;
err_cleanup:
if (rep != NULL)
freeReplyObject (rep);
return rc;
}
static int
redis_release_db (struct kb_redis *kbr)
{
int rc;
redisContext *ctx = kbr->rctx;
redisReply *rep;
if (ctx == NULL)
return -EINVAL;
rep = redisCommand (ctx, "SELECT 0"); /* Management database*/
if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
{
rc = -1;
goto err_cleanup;
}
freeReplyObject (rep);
rep = redisCommand (ctx, "HDEL %s %d", GLOBAL_DBINDEX_NAME, kbr->db);
if (rep == NULL || rep->type != REDIS_REPLY_INTEGER)
{
rc = -1;
goto err_cleanup;
}
rc = 0;
err_cleanup:
if (rep != NULL)
freeReplyObject (rep);
return rc;
}
static inline const char *
parse_port_of_addr (const char *addr, int tcp_indicator_len)
{
const char *tmp;
int is_ip_v6;
tmp = strrchr (addr + tcp_indicator_len, ':');
if (tmp == NULL)
return NULL;
is_ip_v6 = addr[tcp_indicator_len] == '[';
if (is_ip_v6 && (tmp - 1)[0] != ']')
return NULL;
return tmp + 1;
}
static redisContext *
connect_redis (const char *addr, int len)
{
const char *tcp_indicator = "tcp://";
const int tcp_indicator_len = strlen (tcp_indicator);
const int redis_default_port = 6379;
int port, host_len;
const char *tmp;
char *host;
redisContext *result;
static int warn_flag = 0;
if (len < tcp_indicator_len + 1)
goto unix_connect;
if (memcmp (addr, tcp_indicator, tcp_indicator_len) != 0)
goto unix_connect;
host_len = len - tcp_indicator_len;
tmp = parse_port_of_addr (addr, tcp_indicator_len);
if (tmp == NULL)
port = redis_default_port;
else
{
port = atoi (tmp);
host_len -= strlen (tmp) + 1;
}
host = calloc (1, host_len);
memmove (host, addr + tcp_indicator_len, host_len);
result = redisConnect (host, port);
if (warn_flag == 0)
{
g_warning ("A Redis TCP connection is being used. This feature is "
"experimental and insecure, since it is not an encrypted "
"channel. We discourage its usage in production environments");
warn_flag = 1;
}
free (host);
return result;
unix_connect:
return redisConnectUnix (addr);
}
static int
get_redis_ctx (struct kb_redis *kbr)
{
int rc;
if (kbr->rctx != NULL)
return 0;
kbr->rctx = connect_redis (kbr->path, strlen (kbr->path));
if (kbr->rctx == NULL || kbr->rctx->err)
{
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"%s: redis connection error to %s: %s", __func__, kbr->path,
kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
redisFree (kbr->rctx);
kbr->rctx = NULL;
return -1;
}
rc = select_database (kbr);
if (rc)
{
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "No redis DB available");
redisFree (kbr->rctx);
kbr->rctx = NULL;
return -2;
}
g_debug ("%s: connected to redis://%s/%d", __func__, kbr->path, kbr->db);
return 0;
}
static int
redis_test_connection (struct kb_redis *kbr)
{
int rc = 0;
redisReply *rep;
rep = redis_cmd (kbr, "PING");
if (rep == NULL)
{
/* not 100% relevant but hiredis doesn't provide us with proper error
* codes. */
rc = -ECONNREFUSED;
goto out;
}
if (rep->type != REDIS_REPLY_STATUS)
{
rc = -EINVAL;
goto out;
}
if (g_ascii_strcasecmp (rep->str, "PONG"))
{
rc = -EPROTO;
goto out;
}
out:
if (rep != NULL)
freeReplyObject (rep);
return rc;
}
static int
redis_delete (kb_t kb)
{
struct kb_redis *kbr;
kbr = redis_kb (kb);
redis_delete_all (kbr);
redis_release_db (kbr);
if (kbr->rctx != NULL)
{
g_free (kbr->path);
redisFree (kbr->rctx);
kbr->rctx = NULL;
}
g_free (kb);
return 0;
}
static int
redis_get_kb_index (kb_t kb)
{
int i;
i = ((struct kb_redis *) kb)->db;
if (i > 0)
return i;
return -1;
}
static int
redis_memory_purge (kb_t kb)
{
redisReply *rep;
int rc = 0;
rep = redis_cmd (redis_kb (kb), "MEMORY PURGE");
if (!rep || rep->type == REDIS_REPLY_ERROR)
rc = -1;
if (rep)
freeReplyObject (rep);
return rc;
}
static int
redis_new (kb_t *kb, const char *kb_path)
{
struct kb_redis *kbr;
int rc = 0;
if (kb_path == NULL)
return -3;
kbr = g_malloc0 (sizeof (struct kb_redis));
kbr->kb.kb_ops = &KBRedisOperations;
kbr->path = g_strdup (kb_path);
rc = get_redis_ctx (kbr);
if (rc < 0)
{
redis_delete ((kb_t) kbr);
return rc;
}
if (redis_test_connection (kbr))
{
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"%s: cannot access redis at '%s'", __func__, kb_path);
redis_delete ((kb_t) kbr);
kbr = NULL;
rc = -1;
}
/* Ensure that the new kb is clean */
redis_delete_all (kbr);
*kb = (kb_t) kbr;
/* Try to make unused memory available for the OS again. */
if (redis_memory_purge (*kb))
g_warning ("%s: Memory purge was not successful", __func__);
return rc;
}
static kb_t
redis_direct_conn (const char *kb_path, const int kb_index)
{
struct kb_redis *kbr;
redisReply *rep;
if (kb_path == NULL)
return NULL;
kbr = g_malloc0 (sizeof (struct kb_redis));
kbr->kb.kb_ops = &KBRedisOperations;
kbr->path = g_strdup (kb_path);
kbr->rctx = connect_redis (kbr->path, strlen (kbr->path));
if (kbr->rctx == NULL || kbr->rctx->err)
{
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"%s: redis connection error to %s: %s", __func__, kbr->path,
kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
redisFree (kbr->rctx);
g_free (kbr->path);
g_free (kbr);
return NULL;
}
kbr->db = kb_index;
rep = redisCommand (kbr->rctx, "SELECT %d", kb_index);
if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
{
if (rep != NULL)
freeReplyObject (rep);
redisFree (kbr->rctx);
kbr->rctx = NULL;
g_free (kbr->path);
g_free (kbr);
return NULL;
}
freeReplyObject (rep);
return (kb_t) kbr;
}
static kb_t
redis_find (const char *kb_path, const char *key)
{
struct kb_redis *kbr;
unsigned int i = 1;
if (kb_path == NULL)
return NULL;
kbr = g_malloc0 (sizeof (struct kb_redis));
kbr->kb.kb_ops = &KBRedisOperations;
kbr->path = g_strdup (kb_path);
do
{
redisReply *rep;
kbr->rctx = connect_redis (kbr->path, strlen (kbr->path));
if (kbr->rctx == NULL || kbr->rctx->err)
{
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"%s: redis connection error to %s: %s", __func__, kbr->path,
kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
redisFree (kbr->rctx);
g_free (kbr->path);
g_free (kbr);
return NULL;
}
if (kbr->max_db == 0)
fetch_max_db_index (kbr);
kbr->db = i;
rep = redisCommand (kbr->rctx, "HEXISTS %s %d", GLOBAL_DBINDEX_NAME, i);
if (rep == NULL || rep->type != REDIS_REPLY_INTEGER || rep->integer != 1)
{
if (rep != NULL)
freeReplyObject (rep);
i++;
redisFree (kbr->rctx);
kbr->rctx = NULL;
continue;
}
freeReplyObject (rep);
rep = redisCommand (kbr->rctx, "SELECT %u", i);
if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
{
redisFree (kbr->rctx);
kbr->rctx = NULL;
}
else
{
freeReplyObject (rep);
if (key)
{
char *tmp = kb_item_get_str (&kbr->kb, key);
if (tmp)
{
g_free (tmp);
return (kb_t) kbr;
}
}
redisFree (kbr->rctx);
}
i++;
}
while (i < kbr->max_db);
g_free (kbr->path);
g_free (kbr);
return NULL;
}
void
kb_item_free (struct kb_item *item)
{
while (item != NULL)
{
struct kb_item *next;
next = item->next;
if (item->type == KB_TYPE_STR && item->v_str != NULL)
g_free (item->v_str);
g_free (item);
item = next;
}
}
static struct kb_item *
redis2kbitem_single (const char *name, const redisReply *elt, int force_int)
{
struct kb_item *item;
size_t namelen;
if (elt->type != REDIS_REPLY_STRING && elt->type != REDIS_REPLY_INTEGER)
return NULL;
namelen = strlen (name) + 1;
item = g_malloc0 (sizeof (struct kb_item) + namelen);
if (elt->type == REDIS_REPLY_INTEGER)
{
item->type = KB_TYPE_INT;
item->v_int = elt->integer;
}
else if (force_int)
{
item->type = KB_TYPE_INT;
item->v_int = atoi (elt->str);
}
else
{
item->type = KB_TYPE_STR;
item->v_str = memdup (elt->str, elt->len + 1);
item->len = elt->len;
}
item->next = NULL;
item->namelen = namelen;
memset (item->name, 0, namelen);
memcpy (item->name, name, namelen);
return item;
}
static struct kb_item *
redis2kbitem (const char *name, const redisReply *rep)
{
struct kb_item *kbi;
kbi = NULL;
switch (rep->type)
{
unsigned int i;
case REDIS_REPLY_STRING:
case REDIS_REPLY_INTEGER:
kbi = redis2kbitem_single (name, rep, 0);
break;
case REDIS_REPLY_ARRAY:
for (i = 0; i < rep->elements; i++)
{
struct kb_item *tmpitem;
tmpitem = redis2kbitem_single (name, rep->element[i], 0);
if (tmpitem == NULL)
break;
if (kbi != NULL)
{
tmpitem->next = kbi;
kbi = tmpitem;
}
else
kbi = tmpitem;
}
break;
case REDIS_REPLY_NIL:
case REDIS_REPLY_STATUS:
case REDIS_REPLY_ERROR:
default:
break;
}
return kbi;
}
static redisReply *
redis_cmd (struct kb_redis *kbr, const char *fmt, ...)
{
redisReply *rep;
va_list ap, aq;
int retry = 0;
va_start (ap, fmt);
do
{
if (get_redis_ctx (kbr) < 0)
{
va_end (ap);
return NULL;
}
va_copy (aq, ap);
rep = redisvCommand (kbr->rctx, fmt, aq);
va_end (aq);
if (kbr->rctx->err)
{
if (rep != NULL)
freeReplyObject (rep);
redis_lnk_reset ((kb_t) kbr);
retry = !retry;
}
else
retry = 0;
}
while (retry);
va_end (ap);
return rep;
}
static struct kb_item *
redis_get_single (kb_t kb, const char *name, enum kb_item_type type)
{
struct kb_item *kbi;
struct kb_redis *kbr;
redisReply *rep;
kbr = redis_kb (kb);
kbi = NULL;
rep = redis_cmd (kbr, "LINDEX %s -1", name);
if (rep == NULL || rep->type != REDIS_REPLY_STRING)
{
kbi = NULL;
goto out;
}
kbi = redis2kbitem_single (name, rep, type == KB_TYPE_INT);
out:
if (rep != NULL)
freeReplyObject (rep);
return kbi;
}
static char *
redis_get_str (kb_t kb, const char *name)
{
struct kb_item *kbi;
kbi = redis_get_single (kb, name, KB_TYPE_STR);
if (kbi != NULL)
{
char *res;
res = kbi->v_str;
kbi->v_str = NULL;
kb_item_free (kbi);
return res;
}
return NULL;
}
static int
redis_push_str (kb_t kb, const char *name, const char *value)
{
struct kb_redis *kbr;
redisReply *rep = NULL;
int rc = 0;
if (!value)
return -1;
kbr = redis_kb (kb);
rep = redis_cmd (kbr, "LPUSH %s %s", name, value);
if (!rep || rep->type == REDIS_REPLY_ERROR)
rc = -1;
if (rep)
freeReplyObject (rep);
return rc;
}
static char *
redis_pop_str (kb_t kb, const char *name)
{
struct kb_redis *kbr;
redisReply *rep;
char *value = NULL;
kbr = redis_kb (kb);
rep = redis_cmd (kbr, "RPOP %s", name);
if (!rep)
return NULL;
if (rep->type == REDIS_REPLY_STRING)
value = g_strdup (rep->str);
freeReplyObject (rep);
return value;
}
static int
redis_get_int (kb_t kb, const char *name)
{
struct kb_item *kbi;
kbi = redis_get_single (kb, name, KB_TYPE_INT);
if (kbi != NULL)
{
int res;
res = kbi->v_int;
kb_item_free (kbi);
return res;
}
return -1;
}
static char *
redis_get_nvt (kb_t kb, const char *oid, enum kb_nvt_pos position)
{
struct kb_redis *kbr;
redisReply *rep;
char *res = NULL;
kbr = redis_kb (kb);
if (position >= NVT_TIMESTAMP_POS)
rep = redis_cmd (kbr, "LINDEX filename:%s %d", oid,
position - NVT_TIMESTAMP_POS);
else
rep = redis_cmd (kbr, "LINDEX nvt:%s %d", oid, position);
if (!rep)
return NULL;
if (rep->type == REDIS_REPLY_INTEGER)
res = g_strdup_printf ("%lld", rep->integer);
else if (rep->type == REDIS_REPLY_STRING)
res = g_strdup (rep->str);
freeReplyObject (rep);
return res;
}
static nvti_t *
redis_get_nvt_all (kb_t kb, const char *oid)
{
struct kb_redis *kbr;
redisReply *rep;
kbr = redis_kb (kb);
rep =
redis_cmd (kbr, "LRANGE nvt:%s %d %d", oid, NVT_FILENAME_POS, NVT_NAME_POS);
if (!rep)
return NULL;
if (rep->type != REDIS_REPLY_ARRAY || rep->elements != NVT_NAME_POS + 1)
{
freeReplyObject (rep);
return NULL;
}
else
{
nvti_t *nvti = nvti_new ();
nvti_set_oid (nvti, oid);
nvti_set_required_keys (nvti, rep->element[NVT_REQUIRED_KEYS_POS]->str);
nvti_set_mandatory_keys (nvti, rep->element[NVT_MANDATORY_KEYS_POS]->str);
nvti_set_excluded_keys (nvti, rep->element[NVT_EXCLUDED_KEYS_POS]->str);
nvti_set_required_udp_ports (
nvti, rep->element[NVT_REQUIRED_UDP_PORTS_POS]->str);
nvti_set_required_ports (nvti, rep->element[NVT_REQUIRED_PORTS_POS]->str);
nvti_set_dependencies (nvti, rep->element[NVT_DEPENDENCIES_POS]->str);
nvti_set_tag (nvti, rep->element[NVT_TAGS_POS]->str);
nvti_add_refs (nvti, "cve", rep->element[NVT_CVES_POS]->str, "");
nvti_add_refs (nvti, "bid", rep->element[NVT_BIDS_POS]->str, "");
nvti_add_refs (nvti, NULL, rep->element[NVT_XREFS_POS]->str, "");
nvti_set_category (nvti, atoi (rep->element[NVT_CATEGORY_POS]->str));
nvti_set_family (nvti, rep->element[NVT_FAMILY_POS]->str);
nvti_set_name (nvti, rep->element[NVT_NAME_POS]->str);
freeReplyObject (rep);
return nvti;
}
}
static struct kb_item *
redis_get_all (kb_t kb, const char *name)
{
struct kb_redis *kbr;
struct kb_item *kbi;
redisReply *rep;
kbr = redis_kb (kb);
rep = redis_cmd (kbr, "LRANGE %s 0 -1", name);
if (rep == NULL)
return NULL;
kbi = redis2kbitem (name, rep);
freeReplyObject (rep);
return kbi;
}
static struct kb_item *
redis_get_pattern (kb_t kb, const char *pattern)
{
struct kb_redis *kbr;
struct kb_item *kbi = NULL;
redisReply *rep;
unsigned int i;
kbr = redis_kb (kb);
rep = redis_cmd (kbr, "KEYS %s", pattern);
if (!rep)
return NULL;
if (rep->type != REDIS_REPLY_ARRAY)
{
freeReplyObject (rep);
return NULL;
}
if (get_redis_ctx (kbr) < 0)
return NULL;
for (i = 0; i < rep->elements; i++)
redisAppendCommand (kbr->rctx, "LRANGE %s 0 -1", rep->element[i]->str);
for (i = 0; i < rep->elements; i++)
{
struct kb_item *tmp;
redisReply *rep_range;
redisGetReply (kbr->rctx, (void **) &rep_range);
if (!rep)
continue;
tmp = redis2kbitem (rep->element[i]->str, rep_range);
if (!tmp)
{
freeReplyObject (rep_range);
continue;
}
if (kbi)
{
struct kb_item *tmp2;
tmp2 = tmp;
while (tmp->next)
tmp = tmp->next;
tmp->next = kbi;
kbi = tmp2;
}
else
kbi = tmp;
freeReplyObject (rep_range);
}
freeReplyObject (rep);
return kbi;
}
static GSList *
redis_get_oids (kb_t kb)
{
struct kb_redis *kbr;
redisReply *rep;
GSList *list = NULL;
size_t i;
kbr = redis_kb (kb);
rep = redis_cmd (kbr, "KEYS nvt:*");
if (!rep)
return NULL;
if (rep->type != REDIS_REPLY_ARRAY)
{
freeReplyObject (rep);
return NULL;
}
/* Fetch OID values from key names nvt:OID. */
for (i = 0; i < rep->elements; i++)
list = g_slist_prepend (list, g_strdup (rep->element[i]->str + 4));
freeReplyObject (rep);
return list;
}
static size_t
redis_count (kb_t kb, const char *pattern)
{
struct kb_redis *kbr;
redisReply *rep;
size_t count;
kbr = redis_kb (kb);
rep = redis_cmd (kbr, "KEYS %s", pattern);
if (rep == NULL)
return 0;
if (rep->type != REDIS_REPLY_ARRAY)
{
freeReplyObject (rep);
return 0;
}
count = rep->elements;
freeReplyObject (rep);
return count;
}
static int
redis_del_items (kb_t kb, const char *name)
{
struct kb_redis *kbr;
redisReply *rep;
int rc = 0;
kbr = redis_kb (kb);
rep = redis_cmd (kbr, "DEL %s", name);
if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
rc = -1;
if (rep != NULL)
freeReplyObject (rep);
return rc;
}
static int
redis_add_str_unique_volatile (kb_t kb, const char *name, const char *str,
int expire, size_t len, int pos)
{
struct kb_redis *kbr;
redisReply *rep = NULL;
int rc = 0;
redisContext *ctx;
kbr = redis_kb (kb);
if (get_redis_ctx (kbr) < 0)
return -1;
ctx = kbr->rctx;
/* Some VTs still rely on values being unique (ie. a value inserted multiple
* times, will only be present once.)
* Once these are fixed, the LREM becomes redundant and should be removed.
*/
if (len == 0)
{
redisAppendCommand (ctx, "LREM %s 1 %s", name, str);
redisAppendCommand (ctx, "%s %s %s", pos ? "LPUSH" : "RPUSH", name, str);
redisAppendCommand (ctx, "EXPIRE %s %d", name, expire);
/* Check LREM reply. */
redisGetReply (ctx, (void **) &rep);
if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
g_debug ("Key '%s' already contained value '%s'", name, str);
freeReplyObject (rep);
/* Check PUSH reply. */
redisGetReply (ctx, (void **) &rep);
if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
{
rc = -1;
goto out;
}
/* Check EXPIRE reply. */
redisGetReply (ctx, (void **) &rep);
if (rep == NULL || rep->type == REDIS_REPLY_ERROR
|| (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer != 1))
{
g_warning ("%s: Not able to set expire", __func__);
rc = -1;
goto out;
}
}
else
{
redisAppendCommand (ctx, "LREM %s 1 %b", name, str, len);
redisAppendCommand (ctx, "%s %s %b", pos ? "LPUSH" : "RPUSH", name, str,
len);
redisAppendCommand (ctx, "EXPIRE %s %d", name, expire);
/* Check LREM reply. */
redisGetReply (ctx, (void **) &rep);
if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
g_debug ("Key '%s' already contained string '%s'", name, str);
freeReplyObject (rep);
/* Check PUSH reply. */
redisGetReply (ctx, (void **) &rep);
if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
{
rc = -1;
goto out;
}
/* Check EXPIRE reply. */
redisGetReply (ctx, (void **) &rep);
if (rep == NULL || rep->type == REDIS_REPLY_ERROR
|| (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer != 1))
{
g_warning ("%s: Not able to set expire", __func__);
rc = -1;
goto out;
}
}
out:
if (rep != NULL)
freeReplyObject (rep);
return rc;
}
static int
redis_add_str_unique (kb_t kb, const char *name, const char *str, size_t len,
int pos)
{
struct kb_redis *kbr;
redisReply *rep = NULL;
int rc = 0;
redisContext *ctx;
kbr = redis_kb (kb);
if (get_redis_ctx (kbr) < 0)
return -1;
ctx = kbr->rctx;
/* Some VTs still rely on values being unique (ie. a value inserted multiple
* times, will only be present once.)
* Once these are fixed, the LREM becomes redundant and should be removed.
*/
if (len == 0)
{
redisAppendCommand (ctx, "LREM %s 1 %s", name, str);
redisAppendCommand (ctx, "%s %s %s", pos ? "LPUSH" : "RPUSH", name, str);
redisGetReply (ctx, (void **) &rep);
if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
g_debug ("Key '%s' already contained value '%s'", name, str);
freeReplyObject (rep);
redisGetReply (ctx, (void **) &rep);
}
else
{
redisAppendCommand (ctx, "LREM %s 1 %b", name, str, len);
redisAppendCommand (ctx, "%s %s %b", pos ? "LPUSH" : "RPUSH", name, str,
len);
redisGetReply (ctx, (void **) &rep);
if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
g_debug ("Key '%s' already contained string '%s'", name, str);
freeReplyObject (rep);
redisGetReply (ctx, (void **) &rep);
}
if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
rc = -1;
if (rep != NULL)
freeReplyObject (rep);
return rc;
}
static int
redis_add_str (kb_t kb, const char *name, const char *str, size_t len)
{
struct kb_redis *kbr;
redisReply *rep;
int rc = 0;
kbr = redis_kb (kb);
if (len == 0)
rep = redis_cmd (kbr, "RPUSH %s %s", name, str);
else
rep = redis_cmd (kbr, "RPUSH %s %b", name, str, len);
if (!rep || rep->type == REDIS_REPLY_ERROR)
rc = -1;
if (rep)
freeReplyObject (rep);
return rc;
}
static int
redis_set_str (kb_t kb, const char *name, const char *val, size_t len)
{
struct kb_redis *kbr;
redisReply *rep = NULL;
redisContext *ctx;
int rc = 0, i = 4;
kbr = redis_kb (kb);
if (get_redis_ctx (kbr) < 0)
return -1;
ctx = kbr->rctx;
redisAppendCommand (ctx, "MULTI");
redisAppendCommand (ctx, "DEL %s", name);
if (len == 0)
redisAppendCommand (ctx, "RPUSH %s %s", name, val);
else
redisAppendCommand (ctx, "RPUSH %s %b", name, val, len);
redisAppendCommand (ctx, "EXEC");
while (i--)
{
redisGetReply (ctx, (void **) &rep);
if (!rep || rep->type == REDIS_REPLY_ERROR)
rc = -1;
if (rep)
freeReplyObject (rep);
}
return rc;
}
static int
redis_add_int_unique_volatile (kb_t kb, const char *name, int val, int expire)
{
struct kb_redis *kbr;
redisReply *rep;
int rc = 0;
redisContext *ctx;
kbr = redis_kb (kb);
if (get_redis_ctx (kbr) < 0)
return -1;
ctx = kbr->rctx;
redisAppendCommand (ctx, "LREM %s 1 %d", name, val);
redisAppendCommand (ctx, "RPUSH %s %d", name, val);
redisAppendCommand (ctx, "EXPIRE %s %d", name, expire);
/* Check LREM reply. */
redisGetReply (ctx, (void **) &rep);
if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
g_debug ("Key '%s' already contained integer '%d'", name, val);
freeReplyObject (rep);
/* Check PUSH reply. */
redisGetReply (ctx, (void **) &rep);
if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
{
rc = -1;
goto out;
}
/* Check EXPIRE reply. */
redisGetReply (ctx, (void **) &rep);
if (rep == NULL || rep->type == REDIS_REPLY_ERROR
|| (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer != 1))
{
g_warning ("%s: Not able to set expire", __func__);
rc = -1;
goto out;
}
out:
if (rep != NULL)
freeReplyObject (rep);
return rc;
}
static int
redis_add_int_unique (kb_t kb, const char *name, int val)
{
struct kb_redis *kbr;
redisReply *rep;
int rc = 0;
redisContext *ctx;
kbr = redis_kb (kb);
if (get_redis_ctx (kbr) < 0)
return -1;
ctx = kbr->rctx;
redisAppendCommand (ctx, "LREM %s 1 %d", name, val);
redisAppendCommand (ctx, "RPUSH %s %d", name, val);
redisGetReply (ctx, (void **) &rep);
if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
g_debug ("Key '%s' already contained integer '%d'", name, val);
freeReplyObject (rep);
redisGetReply (ctx, (void **) &rep);
if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
{
rc = -1;
goto out;
}
out:
if (rep != NULL)
freeReplyObject (rep);
return rc;
}
static int
redis_add_int (kb_t kb, const char *name, int val)
{
redisReply *rep;
int rc = 0;
rep = redis_cmd (redis_kb (kb), "RPUSH %s %d", name, val);
if (!rep || rep->type == REDIS_REPLY_ERROR)
rc = -1;
if (rep)
freeReplyObject (rep);
return rc;
}
static int
redis_set_int (kb_t kb, const char *name, int val)
{
struct kb_redis *kbr;
redisReply *rep = NULL;
redisContext *ctx;
int rc = 0, i = 4;
kbr = redis_kb (kb);
if (get_redis_ctx (redis_kb (kb)) < 0)
return -1;
ctx = kbr->rctx;
redisAppendCommand (ctx, "MULTI");
redisAppendCommand (ctx, "DEL %s", name);
redisAppendCommand (ctx, "RPUSH %s %d", name, val);
redisAppendCommand (ctx, "EXEC");
while (i--)
{
redisGetReply (ctx, (void **) &rep);
if (!rep || rep->type == REDIS_REPLY_ERROR)
rc = -1;
if (rep)
freeReplyObject (rep);
}
return rc;
}
static int
redis_add_nvt (kb_t kb, const nvti_t *nvt, const char *filename)
{
struct kb_redis *kbr;
redisReply *rep = NULL;
int rc = 0;
unsigned int i;
gchar *cves, *bids, *xrefs;
if (!nvt || !filename)
return -1;
cves = nvti_refs (nvt, "cve", "", 0);
bids = nvti_refs (nvt, "bid", "", 0);
xrefs = nvti_refs (nvt, NULL, "cve,bid", 1);
kbr = redis_kb (kb);
rep = redis_cmd (
kbr, "RPUSH nvt:%s %s %s %s %s %s %s %s %s %s %s %s %d %s %s",
nvti_oid (nvt), filename,
nvti_required_keys (nvt) ? nvti_required_keys (nvt) : "",
nvti_mandatory_keys (nvt) ? nvti_mandatory_keys (nvt) : "",
nvti_excluded_keys (nvt) ? nvti_excluded_keys (nvt) : "",
nvti_required_udp_ports (nvt) ? nvti_required_udp_ports (nvt) : "",
nvti_required_ports (nvt) ? nvti_required_ports (nvt) : "",
nvti_dependencies (nvt) ? nvti_dependencies (nvt) : "",
nvti_tag (nvt) ? nvti_tag (nvt) : "", cves ? cves : "", bids ? bids : "",
xrefs ? xrefs : "", nvti_category (nvt), nvti_family (nvt),
nvti_name (nvt));
g_free (cves);
g_free (bids);
g_free (xrefs);
if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
rc = -1;
if (rep != NULL)
freeReplyObject (rep);
if (nvti_pref_len (nvt))
redis_cmd (kbr, "DEL oid:%s:prefs", nvti_oid (nvt));
for (i = 0; i < nvti_pref_len (nvt); i++)
{
const nvtpref_t *pref = nvti_pref (nvt, i);
rep = redis_cmd (kbr, "RPUSH oid:%s:prefs %d|||%s|||%s|||%s",
nvti_oid (nvt), nvtpref_id (pref), nvtpref_name (pref),
nvtpref_type (pref), nvtpref_default (pref));
if (!rep || rep->type == REDIS_REPLY_ERROR)
rc = -1;
if (rep)
freeReplyObject (rep);
}
rep = redis_cmd (kbr, "RPUSH filename:%s %lu %s", filename, time (NULL),
nvti_oid (nvt));
if (!rep || rep->type == REDIS_REPLY_ERROR)
rc = -1;
if (rep)
freeReplyObject (rep);
return rc;
}
static int
redis_lnk_reset (kb_t kb)
{
struct kb_redis *kbr;
kbr = redis_kb (kb);
if (kbr->rctx != NULL)
{
redisFree (kbr->rctx);
kbr->rctx = NULL;
}
return 0;
}
static int
redis_flush_all (kb_t kb, const char *except)
{
unsigned int i = 1;
struct kb_redis *kbr;
kbr = redis_kb (kb);
if (kbr->rctx)
redisFree (kbr->rctx);
g_debug ("%s: deleting all DBs at %s except %s", __func__, kbr->path, except);
do
{
redisReply *rep;
kbr->rctx = connect_redis (kbr->path, strlen (kbr->path));
if (kbr->rctx == NULL || kbr->rctx->err)
{
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"%s: redis connection error to %s: %s", __func__, kbr->path,
kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
redisFree (kbr->rctx);
kbr->rctx = NULL;
return -1;
}
kbr->db = i;
rep = redisCommand (kbr->rctx, "HEXISTS %s %d", GLOBAL_DBINDEX_NAME, i);
if (rep == NULL || rep->type != REDIS_REPLY_INTEGER || rep->integer != 1)
{
freeReplyObject (rep);
redisFree (kbr->rctx);
i++;
continue;
}
freeReplyObject (rep);
rep = redisCommand (kbr->rctx, "SELECT %u", i);
if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
{
freeReplyObject (rep);
redisFree (kbr->rctx);
kbr->rctx = NULL;
}
else
{
freeReplyObject (rep);
/* Don't remove DB if it has "except" key. */
if (except)
{
char *tmp = kb_item_get_str (kb, except);
if (tmp)
{
g_free (tmp);
i++;
redisFree (kbr->rctx);
continue;
}
}
redis_delete_all (kbr);
redis_release_db (kbr);
redisFree (kbr->rctx);
}
i++;
}
while (i < kbr->max_db);
g_free (kbr->path);
g_free (kb);
return 0;
}
static int
redis_save (kb_t kb)
{
int rc;
redisReply *rep;
struct kb_redis *kbr;
kbr = redis_kb (kb);
g_debug ("%s: saving all elements from KB #%u", __func__, kbr->db);
rep = redis_cmd (kbr, "SAVE");
if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
{
rc = -1;
goto err_cleanup;
}
rc = 0;
err_cleanup:
if (rep != NULL)
freeReplyObject (rep);
return rc;
}
int
redis_delete_all (struct kb_redis *kbr)
{
int rc;
redisReply *rep;
struct sigaction new_action, original_action;
/* Ignore SIGPIPE, in case of a lost connection. */
new_action.sa_flags = 0;
if (sigemptyset (&new_action.sa_mask))
return -1;
new_action.sa_handler = SIG_IGN;
if (sigaction (SIGPIPE, &new_action, &original_action))
return -1;
if (kbr)
g_debug ("%s: deleting all elements from KB #%u", __func__, kbr->db);
rep = redis_cmd (kbr, "FLUSHDB");
if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
{
rc = -1;
goto err_cleanup;
}
rc = 0;
err_cleanup:
if (sigaction (SIGPIPE, &original_action, NULL))
return -1;
if (rep != NULL)
freeReplyObject (rep);
return rc;
}
static const struct kb_operations KBRedisOperations = {
.kb_new = redis_new,
.kb_find = redis_find,
.kb_delete = redis_delete,
.kb_get_single = redis_get_single,
.kb_get_str = redis_get_str,
.kb_get_int = redis_get_int,
.kb_get_nvt = redis_get_nvt,
.kb_get_nvt_all = redis_get_nvt_all,
.kb_get_nvt_oids = redis_get_oids,
.kb_push_str = redis_push_str,
.kb_pop_str = redis_pop_str,
.kb_get_all = redis_get_all,
.kb_get_pattern = redis_get_pattern,
.kb_count = redis_count,
.kb_add_str = redis_add_str,
.kb_add_str_unique = redis_add_str_unique,
.kb_add_str_unique_volatile = redis_add_str_unique_volatile,
.kb_set_str = redis_set_str,
.kb_add_int = redis_add_int,
.kb_add_int_unique = redis_add_int_unique,
.kb_add_int_unique_volatile = redis_add_int_unique_volatile,
.kb_set_int = redis_set_int,
.kb_add_nvt = redis_add_nvt,
.kb_del_items = redis_del_items,
.kb_lnk_reset = redis_lnk_reset,
.kb_save = redis_save,
.kb_flush = redis_flush_all,
.kb_direct_conn = redis_direct_conn,
.kb_get_kb_index = redis_get_kb_index};
const struct kb_operations *KBDefaultOperations = &KBRedisOperations;
G_LOG_DOMAIN
#define G_LOG_DOMAIN
GLib log domain.
Definition array.c:17
redis_lnk_reset
static int redis_lnk_reset(kb_t)
Reset connection to the KB. This is called after each fork() to make sure connections aren't shared b...
Definition kb.c:1676
KBRedisOperations
static const struct kb_operations KBRedisOperations
Default KB operations.
Definition kb.c:47
get_redis_ctx
static int get_redis_ctx(struct kb_redis *kbr)
Get redis context if it is already connected or do a a connection.
Definition kb.c:315
redis_push_str
static int redis_push_str(kb_t kb, const char *name, const char *value)
Push a new entry under a given key.
Definition kb.c:875
redis_memory_purge
static int redis_memory_purge(kb_t kb)
Attempt to purge dirty pages.
Definition kb.c:445
redis_test_connection
static int redis_test_connection(struct kb_redis *kbr)
Test redis connection.
Definition kb.c:354
redis_set_str
static int redis_set_str(kb_t kb, const char *name, const char *val, size_t len)
Set (replace) a new entry under a given name.
Definition kb.c:1412
redis_add_str_unique_volatile
static int redis_add_str_unique_volatile(kb_t kb, const char *name, const char *str, int expire, size_t len, int pos)
Insert (append) a new unique and volatile entry under a given name.
Definition kb.c:1231
parse_port_of_addr
static const char * parse_port_of_addr(const char *addr, int tcp_indicator_len)
Definition kb.c:250
redis_get_nvt
static char * redis_get_nvt(kb_t kb, const char *oid, enum kb_nvt_pos position)
Get field of a NVT.
Definition kb.c:957
redis2kbitem
static struct kb_item * redis2kbitem(const char *name, const redisReply *rep)
Fetch a KB item or list from a redis Reply.
Definition kb.c:712
redis_find
static kb_t redis_find(const char *kb_path, const char *key)
Find an existing Knowledge Base object with key.
Definition kb.c:565
redis_delete
static int redis_delete(kb_t kb)
Delete all entries and release ownership on the namespace.
Definition kb.c:395
redis_add_str
static int redis_add_str(kb_t kb, const char *name, const char *str, size_t len)
Insert (append) a new entry under a given name.
Definition kb.c:1382
select_database
static int select_database(struct kb_redis *kbr)
Select DB.
Definition kb.c:164
redis_delete_all
static int redis_delete_all(struct kb_redis *)
Delete all the KB's content.
Definition kb.c:1810
kb_item_free
void kb_item_free(struct kb_item *item)
Release a KB item (or a list).
Definition kb.c:643
redis_add_int_unique_volatile
static int redis_add_int_unique_volatile(kb_t kb, const char *name, int val, int expire)
Insert (append) a new unique entry under a given name.
Definition kb.c:1453
redis_get_all
static struct kb_item * redis_get_all(kb_t kb, const char *name)
Get all items stored under a given name.
Definition kb.c:1039
memdup
#define memdup
Definition kb.c:32
redis_add_int
static int redis_add_int(kb_t kb, const char *name, int val)
Insert (append) a new entry under a given name.
Definition kb.c:1547
redis_direct_conn
static kb_t redis_direct_conn(const char *kb_path, const int kb_index)
Connect to a Knowledge Base object with the given kb_index.
Definition kb.c:517
redis_add_str_unique
static int redis_add_str_unique(kb_t kb, const char *name, const char *str, size_t len, int pos)
Insert (append) a new unique entry under a given name.
Definition kb.c:1324
redis_get_str
static char * redis_get_str(kb_t kb, const char *name)
Get a single KB string item.
Definition kb.c:848
redis_get_pattern
static struct kb_item * redis_get_pattern(kb_t kb, const char *pattern)
Get all items stored under a given pattern.
Definition kb.c:1068
redis_get_oids
static GSList * redis_get_oids(kb_t kb)
Get all NVT OIDs.
Definition kb.c:1132
redis2kbitem_single
static struct kb_item * redis2kbitem_single(const char *name, const redisReply *elt, int force_int)
Give a single KB item.
Definition kb.c:667
redis_save
static int redis_save(kb_t kb)
Save all the elements from the KB.
Definition kb.c:1778
redis_get_int
static int redis_get_int(kb_t kb, const char *name)
Get a single KB integer item.
Definition kb.c:931
connect_redis
static redisContext * connect_redis(const char *addr, int len)
Definition kb.c:264
redis_pop_str
static char * redis_pop_str(kb_t kb, const char *name)
Pops a single KB string item.
Definition kb.c:904
redis_new
static int redis_new(kb_t *kb, const char *kb_path)
Initialize a new Knowledge Base object.
Definition kb.c:469
redis_get_kb_index
static int redis_get_kb_index(kb_t kb)
Return the kb index.
Definition kb.c:423
redis_add_int_unique
static int redis_add_int_unique(kb_t kb, const char *name, int val)
Insert (append) a new unique entry under a given name.
Definition kb.c:1506
redis_kb
#define redis_kb(__kb)
Definition kb.c:62
try_database_index
static int try_database_index(struct kb_redis *kbr, int index)
Attempt to atomically acquire ownership of a database.
Definition kb.c:78
GLOBAL_DBINDEX_NAME
#define GLOBAL_DBINDEX_NAME
Name of the namespace usage bitmap in redis.
Definition kb.c:45
KBDefaultOperations
const struct kb_operations * KBDefaultOperations
Default KB operations. No selection mechanism is provided yet since there's only one implementation (...
Definition kb.c:1881
redis_flush_all
static int redis_flush_all(kb_t, const char *)
Flush all the KB's content. Delete all namespaces.
Definition kb.c:1700
redis_count
static size_t redis_count(kb_t kb, const char *pattern)
Count all items stored under a given pattern.
Definition kb.c:1167
redis_release_db
static int redis_release_db(struct kb_redis *kbr)
Release DB.
Definition kb.c:216
redis_get_single
static struct kb_item * redis_get_single(kb_t kb, const char *name, enum kb_item_type type)
Get a single KB element.
Definition kb.c:813
redis_set_int
static int redis_set_int(kb_t kb, const char *name, int val)
Set (replace) a new entry under a given name.
Definition kb.c:1571
redis_add_nvt
static int redis_add_nvt(kb_t kb, const nvti_t *nvt, const char *filename)
Insert a new nvt.
Definition kb.c:1608
fetch_max_db_index
static int fetch_max_db_index(struct kb_redis *kbr)
Set the number of databases have been configured into kbr struct.
Definition kb.c:109
redis_cmd
static redisReply * redis_cmd(struct kb_redis *kbr, const char *fmt,...)
Execute a redis command and get a redis reply.
Definition kb.c:765
redis_get_nvt_all
static nvti_t * redis_get_nvt_all(kb_t kb, const char *oid)
Get a full NVT.
Definition kb.c:989
redis_del_items
static int redis_del_items(kb_t kb, const char *name)
Delete all entries under a given name.
Definition kb.c:1199
kb.h
Knowledge base management API - Redis backend.
kb_nvt_pos
kb_nvt_pos
Possible positions of nvt values in cache list.
Definition kb.h:45
NVT_FAMILY_POS
@ NVT_FAMILY_POS
Definition kb.h:58
NVT_CATEGORY_POS
@ NVT_CATEGORY_POS
Definition kb.h:57
NVT_TIMESTAMP_POS
@ NVT_TIMESTAMP_POS
Definition kb.h:60
NVT_NAME_POS
@ NVT_NAME_POS
Definition kb.h:59
NVT_TAGS_POS
@ NVT_TAGS_POS
Definition kb.h:53
NVT_BIDS_POS
@ NVT_BIDS_POS
Definition kb.h:55
NVT_EXCLUDED_KEYS_POS
@ NVT_EXCLUDED_KEYS_POS
Definition kb.h:49
NVT_REQUIRED_PORTS_POS
@ NVT_REQUIRED_PORTS_POS
Definition kb.h:51
NVT_REQUIRED_UDP_PORTS_POS
@ NVT_REQUIRED_UDP_PORTS_POS
Definition kb.h:50
NVT_FILENAME_POS
@ NVT_FILENAME_POS
Definition kb.h:46
NVT_DEPENDENCIES_POS
@ NVT_DEPENDENCIES_POS
Definition kb.h:52
NVT_CVES_POS
@ NVT_CVES_POS
Definition kb.h:54
NVT_REQUIRED_KEYS_POS
@ NVT_REQUIRED_KEYS_POS
Definition kb.h:47
NVT_XREFS_POS
@ NVT_XREFS_POS
Definition kb.h:56
NVT_MANDATORY_KEYS_POS
@ NVT_MANDATORY_KEYS_POS
Definition kb.h:48
kb_t
struct kb * kb_t
type abstraction to hide KB internals.
Definition kb.h:98
kb_item_type
kb_item_type
Possible type of a kb_item.
Definition kb.h:33
KB_TYPE_INT
@ KB_TYPE_INT
Definition kb.h:35
KB_TYPE_STR
@ KB_TYPE_STR
Definition kb.h:36
kb_item_get_str
static char * kb_item_get_str(kb_t kb, const char *name)
Get a single KB string item.
Definition kb.h:334
nvti_new
nvti_t * nvti_new(void)
Create a new (empty) nvti structure.
Definition nvti.c:559
nvti_dependencies
gchar * nvti_dependencies(const nvti_t *n)
Get the dependencies list.
Definition nvti.c:1032
nvti_pref_len
guint nvti_pref_len(const nvti_t *n)
Get the number of preferences of the NVT.
Definition nvti.c:1171
nvti_required_udp_ports
gchar * nvti_required_udp_ports(const nvti_t *n)
Get the required udp ports list.
Definition nvti.c:1102
nvti_required_ports
gchar * nvti_required_ports(const nvti_t *n)
Get the required ports list.
Definition nvti.c:1088
nvti_refs
gchar * nvti_refs(const nvti_t *n, const gchar *type, const gchar *exclude_types, guint use_types)
Get references as string.
Definition nvti.c:766
nvtpref_type
gchar * nvtpref_type(const nvtpref_t *np)
Get the Type of a NVT Preference.
Definition nvti.c:532
nvti_set_excluded_keys
int nvti_set_excluded_keys(nvti_t *n, const gchar *excluded_keys)
Set the excluded keys of a NVT.
Definition nvti.c:1744
nvti_t
struct nvti nvti_t
The structure of a information record that corresponds to a NVT.
nvti_set_dependencies
int nvti_set_dependencies(nvti_t *n, const gchar *dependencies)
Set the dependencies of a NVT.
Definition nvti.c:1672
nvti_set_required_ports
int nvti_set_required_ports(nvti_t *n, const gchar *required_ports)
Set the required ports of a NVT.
Definition nvti.c:1768
nvti_set_oid
int nvti_set_oid(nvti_t *n, const gchar *oid)
Set the OID of a NVT Info.
Definition nvti.c:1214
nvti_set_tag
int nvti_set_tag(nvti_t *n, const gchar *tag)
Set the tags of a NVT.
Definition nvti.c:1625
nvti_set_mandatory_keys
int nvti_set_mandatory_keys(nvti_t *n, const gchar *mandatory_keys)
Set the mandatory keys of a NVT.
Definition nvti.c:1720
nvti_category
gint nvti_category(const nvti_t *n)
Get the category for this NVT.
Definition nvti.c:1199
nvtpref_t
struct nvtpref nvtpref_t
The structure for a preference of a NVT.
nvti_family
gchar * nvti_family(const nvti_t *n)
Get the family name.
Definition nvti.c:1158
nvti_pref
const nvtpref_t * nvti_pref(const nvti_t *n, guint p)
Get the n'th preferences of the NVT.
Definition nvti.c:1186
nvti_excluded_keys
gchar * nvti_excluded_keys(const nvti_t *n)
Get the excluded keys list.
Definition nvti.c:1074
nvti_name
gchar * nvti_name(const nvti_t *n)
Get the name.
Definition nvti.c:625
nvti_oid
gchar * nvti_oid(const nvti_t *n)
Get the OID string.
Definition nvti.c:611
nvti_set_required_keys
int nvti_set_required_keys(nvti_t *n, const gchar *required_keys)
Set the required keys of a NVT.
Definition nvti.c:1696
nvtpref_id
int nvtpref_id(const nvtpref_t *np)
Get the ID of a NVT Preference.
Definition nvti.c:504
nvti_set_name
int nvti_set_name(nvti_t *n, const gchar *name)
Set the name of a NVT.
Definition nvti.c:1234
nvti_required_keys
gchar * nvti_required_keys(const nvti_t *n)
Get the required keys list.
Definition nvti.c:1046
nvti_add_refs
int nvti_add_refs(nvti_t *n, const gchar *type, const gchar *ref_ids, const gchar *ref_text)
Add many new vtref from a comma-separated list.
Definition nvti.c:1968
nvti_set_required_udp_ports
int nvti_set_required_udp_ports(nvti_t *n, const gchar *required_udp_ports)
Set the required udp ports of a NVT.
Definition nvti.c:1792
nvti_mandatory_keys
gchar * nvti_mandatory_keys(const nvti_t *n)
Get the mandatory keys list.
Definition nvti.c:1060
nvtpref_default
gchar * nvtpref_default(const nvtpref_t *np)
Get the Default of a NVT Preference.
Definition nvti.c:546
nvti_set_family
int nvti_set_family(nvti_t *n, const gchar *family)
Set the family of a NVT.
Definition nvti.c:1903
nvtpref_name
gchar * nvtpref_name(const nvtpref_t *np)
Get the Name of a NVT Preference.
Definition nvti.c:518
nvti_tag
gchar * nvti_tag(const nvti_t *n)
Get the tags.
Definition nvti.c:966
nvti_set_category
int nvti_set_category(nvti_t *n, const gint category)
Set the category type of a NVT Info.
Definition nvti.c:1943
kb_item
Knowledge base item (defined by name, type (int/char*) and value). Implemented as a singly linked lis...
Definition kb.h:69
kb_item::name
char name[]
Definition kb.h:82
kb_item::v_int
int v_int
Definition kb.h:75
kb_item::type
enum kb_item_type type
Definition kb.h:70
kb_item::v_str
char * v_str
Definition kb.h:74
kb_item::next
struct kb_item * next
Definition kb.h:79
kb_item::len
size_t len
Definition kb.h:78
kb_item::namelen
size_t namelen
Definition kb.h:81
kb_operations
KB interface. Functions provided by an implementation. All functions have to be provided,...
Definition kb.h:107
kb_redis
Subclass of struct kb, it contains the redis-specific fields, such as the redis context,...
Definition kb.c:55
kb_redis::path
char * path
Definition kb.c:60
kb_redis::max_db
unsigned int max_db
Definition kb.c:57
kb_redis::db
unsigned int db
Definition kb.c:58
kb_redis::kb
struct kb kb
Definition kb.c:56
kb_redis::rctx
redisContext * rctx
Definition kb.c:59
kb
Top-level KB. This is to be inherited by KB implementations.
Definition kb.h:91
kb::kb_ops
const struct kb_operations * kb_ops
Definition kb.h:92
nvti
The structure of a information record that corresponds to a NVT.
Definition nvti.c:358