31 #include <hiredis/hiredis.h> 39 #define G_LOG_DOMAIN "lib kb" 51 #define GLOBAL_DBINDEX_NAME "GVM.__GlobalDBIndex" 57 #define KB_RETRY_DELAY 60 74 #define redis_kb(__kb) ((struct kb_redis *) (__kb)) 91 redisContext *ctx = kbr->
rctx;
99 if (rep->type != REDIS_REPLY_INTEGER)
101 else if (rep->integer == 0)
106 freeReplyObject (rep);
120 #define MAX_DB_INDEX__24 1000 131 redisContext *ctx = kbr->
rctx;
143 current = min + ((max - min) / 2);
145 rep = redisCommand (ctx,
"SELECT %d", current);
149 "%s: redis command failed with '%s'", __func__, ctx->errstr);
155 case REDIS_REPLY_ERROR:
159 case REDIS_REPLY_STATUS:
165 "%s: unexpected reply of type %d", __func__, rep->type);
166 freeReplyObject (rep);
169 freeReplyObject (rep);
175 rep = redisCommand (ctx,
"SELECT 0");
179 "%s: DB selection failed with '%s'", __func__, ctx->errstr);
184 freeReplyObject (rep);
199 redisContext *ctx = kbr->
rctx;
200 redisReply *rep = NULL;
202 rep = redisCommand (ctx,
"CONFIG GET databases");
206 "%s: redis command failed with '%s'", __func__, ctx->errstr);
211 if (rep->type != REDIS_REPLY_ARRAY)
214 "%s: cannot retrieve max DB number: %s", __func__, rep->str);
219 if (rep->elements == 0)
224 else if (rep->elements == 2)
226 kbr->
max_db = (unsigned) atoi (rep->element[1]->str);
231 "%s: unexpected reply length (%zd)", __func__, rep->elements);
236 g_debug (
"%s: maximum DB number: %u", __func__, kbr->
max_db);
240 freeReplyObject (rep);
257 redisContext *ctx = kbr->
rctx;
258 redisReply *rep = NULL;
267 for (i = 1; i < kbr->
max_db; i++)
282 rep = redisCommand (ctx,
"SELECT %u", kbr->
db);
283 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
293 freeReplyObject (rep);
308 redisContext *ctx = kbr->
rctx;
314 rep = redisCommand (ctx,
"SELECT 0");
315 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
320 freeReplyObject (rep);
323 if (rep == NULL || rep->type != REDIS_REPLY_INTEGER)
333 freeReplyObject (rep);
345 static redisContext *
350 if (kbr->
rctx != NULL)
355 kbr->
rctx = redisConnectUnix (kbr->
path);
356 if (kbr->
rctx == NULL || kbr->
rctx->err)
359 "%s: redis connection error: %s", __func__,
360 kbr->
rctx ? kbr->
rctx->errstr : strerror (ENOMEM));
361 redisFree (kbr->
rctx);
369 g_debug (
"%s: No redis DB available, retrying in %ds...", __func__,
372 redisFree (kbr->
rctx);
378 g_debug (
"%s: connected to redis://%s/%d", __func__, kbr->
path, kbr->
db);
402 if (rep->type != REDIS_REPLY_STATUS)
408 if (g_ascii_strcasecmp (rep->str,
"PONG"))
416 freeReplyObject (rep);
436 if (kbr->
rctx != NULL)
438 redisFree (kbr->
rctx);
473 kbr = g_malloc0 (
sizeof (
struct kb_redis) + strlen (kb_path) + 1);
475 strncpy (kbr->
path, kb_path, strlen (kb_path));
481 "%s: cannot access redis at '%s'", __func__, kb_path);
503 kbr = g_malloc0 (
sizeof (
struct kb_redis) + strlen (kb_path) + 1);
505 strncpy (kbr->
path, kb_path, strlen (kb_path));
507 kbr->
rctx = redisConnectUnix (kbr->
path);
508 if (kbr->
rctx == NULL || kbr->
rctx->err)
511 "%s: redis connection error: %s", __func__,
512 kbr->
rctx ? kbr->
rctx->errstr : strerror (ENOMEM));
513 redisFree (kbr->
rctx);
518 rep = redisCommand (kbr->
rctx,
"SELECT %d", kb_index);
519 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
522 freeReplyObject (rep);
523 redisFree (kbr->
rctx);
527 freeReplyObject (rep);
543 kbr = g_malloc0 (
sizeof (
struct kb_redis) + strlen (kb_path) + 1);
545 strncpy (kbr->
path, kb_path, strlen (kb_path));
551 kbr->
rctx = redisConnectUnix (kbr->
path);
552 if (kbr->
rctx == NULL || kbr->
rctx->err)
555 "%s: redis connection error: %s", __func__,
556 kbr->
rctx ? kbr->
rctx->errstr : strerror (ENOMEM));
557 redisFree (kbr->
rctx);
567 if (rep == NULL || rep->type != REDIS_REPLY_INTEGER || rep->integer != 1)
570 freeReplyObject (rep);
574 freeReplyObject (rep);
575 rep = redisCommand (kbr->
rctx,
"SELECT %u", i);
576 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
583 freeReplyObject (rep);
594 redisFree (kbr->
rctx);
616 g_free (item->
v_str);
635 if (elt->type != REDIS_REPLY_STRING && elt->type != REDIS_REPLY_INTEGER)
641 if (elt->type == REDIS_REPLY_INTEGER)
644 item->
v_int = elt->integer;
649 item->
v_int = atoi (elt->str);
654 item->
v_str = g_memdup (elt->str, elt->len + 1);
655 item->
len = elt->len;
682 case REDIS_REPLY_STRING:
683 case REDIS_REPLY_INTEGER:
687 case REDIS_REPLY_ARRAY:
688 for (i = 0; i < rep->elements; i++)
706 case REDIS_REPLY_NIL:
707 case REDIS_REPLY_STATUS:
708 case REDIS_REPLY_ERROR:
744 rep = redisvCommand (ctx, fmt, aq);
750 freeReplyObject (rep);
783 rep =
redis_cmd (kbr,
"LINDEX %s -1", name);
784 if (rep == NULL || rep->type != REDIS_REPLY_STRING)
794 freeReplyObject (rep);
835 redisReply *rep = NULL;
839 rep =
redis_cmd (kbr,
"LPUSH %s %s", name, value);
840 if (!rep || rep->type == REDIS_REPLY_ERROR)
844 freeReplyObject (rep);
867 if (rep->type == REDIS_REPLY_STRING)
868 value = g_strdup (rep->str);
869 freeReplyObject (rep);
914 rep =
redis_cmd (kbr,
"LINDEX filename:%s %d", oid,
917 rep =
redis_cmd (kbr,
"LINDEX nvt:%s %d", oid, position);
920 if (rep->type == REDIS_REPLY_INTEGER)
921 res = g_strdup_printf (
"%lld", rep->integer);
922 else if (rep->type == REDIS_REPLY_STRING)
923 res = g_strdup (rep->str);
924 freeReplyObject (rep);
946 if (rep->type != REDIS_REPLY_ARRAY || rep->elements !=
NVT_NAME_POS + 1)
948 freeReplyObject (rep);
972 freeReplyObject (rep);
999 freeReplyObject (rep);
1021 rep =
redis_cmd (kbr,
"KEYS %s", pattern);
1024 if (rep->type != REDIS_REPLY_ARRAY)
1026 freeReplyObject (rep);
1031 for (i = 0; i < rep->elements; i++)
1032 redisAppendCommand (ctx,
"LRANGE %s 0 -1", rep->element[i]->str);
1034 for (i = 0; i < rep->elements; i++)
1037 redisReply *rep_range;
1039 redisGetReply (ctx, (
void **) &rep_range);
1045 freeReplyObject (rep_range);
1061 freeReplyObject (rep_range);
1064 freeReplyObject (rep);
1078 GSList *list = NULL;
1086 if (rep->type != REDIS_REPLY_ARRAY)
1088 freeReplyObject (rep);
1093 for (i = 0; i < rep->elements; i++)
1094 list = g_slist_prepend (list, g_strdup (rep->element[i]->str + 4));
1095 freeReplyObject (rep);
1117 rep =
redis_cmd (kbr,
"KEYS %s", pattern);
1121 if (rep->type != REDIS_REPLY_ARRAY)
1123 freeReplyObject (rep);
1127 count = rep->elements;
1128 freeReplyObject (rep);
1148 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1152 freeReplyObject (rep);
1169 redisReply *rep = NULL;
1182 redisAppendCommand (ctx,
"LREM %s 1 %s", name, str);
1183 redisAppendCommand (ctx,
"RPUSH %s %s", name, str);
1184 redisGetReply (ctx, (
void **) &rep);
1185 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1186 g_debug (
"Key '%s' already contained value '%s'", name, str);
1187 freeReplyObject (rep);
1188 redisGetReply (ctx, (
void **) &rep);
1192 redisAppendCommand (ctx,
"LREM %s 1 %b", name, str, len);
1193 redisAppendCommand (ctx,
"RPUSH %s %b", name, str, len);
1194 redisGetReply (ctx, (
void **) &rep);
1195 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1196 g_debug (
"Key '%s' already contained string '%s'", name, str);
1197 freeReplyObject (rep);
1198 redisGetReply (ctx, (
void **) &rep);
1200 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1204 freeReplyObject (rep);
1226 rep =
redis_cmd (kbr,
"RPUSH %s %s", name, str);
1228 rep =
redis_cmd (kbr,
"RPUSH %s %b", name, str, len);
1229 if (!rep || rep->type == REDIS_REPLY_ERROR)
1233 freeReplyObject (rep);
1249 redisReply *rep = NULL;
1255 redisAppendCommand (ctx,
"MULTI");
1256 redisAppendCommand (ctx,
"DEL %s", name);
1258 redisAppendCommand (ctx,
"RPUSH %s %s", name, val);
1260 redisAppendCommand (ctx,
"RPUSH %s %b", name, val, len);
1261 redisAppendCommand (ctx,
"EXEC");
1264 redisGetReply (ctx, (
void **) &rep);
1265 if (!rep || rep->type == REDIS_REPLY_ERROR)
1268 freeReplyObject (rep);
1291 redisAppendCommand (ctx,
"LREM %s 1 %d", name, val);
1292 redisAppendCommand (ctx,
"RPUSH %s %d", name, val);
1293 redisGetReply (ctx, (
void **) &rep);
1294 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1295 g_debug (
"Key '%s' already contained integer '%d'", name, val);
1296 freeReplyObject (rep);
1297 redisGetReply (ctx, (
void **) &rep);
1298 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1306 freeReplyObject (rep);
1325 if (!rep || rep->type == REDIS_REPLY_ERROR)
1328 freeReplyObject (rep);
1343 redisReply *rep = NULL;
1348 redisAppendCommand (ctx,
"MULTI");
1349 redisAppendCommand (ctx,
"DEL %s", name);
1350 redisAppendCommand (ctx,
"RPUSH %s %d", name, val);
1351 redisAppendCommand (ctx,
"EXEC");
1354 redisGetReply (ctx, (
void **) &rep);
1355 if (!rep || rep->type == REDIS_REPLY_ERROR)
1358 freeReplyObject (rep);
1375 redisReply *rep = NULL;
1379 if (!nvt || !filename)
1384 kbr,
"RPUSH nvt:%s %s %s %s %s %s %s %s %s %s %s %s %d %d %s %s",
1391 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1394 freeReplyObject (rep);
1396 element = nvt->
prefs;
1397 if (g_slist_length (element))
1405 if (!rep || rep->type == REDIS_REPLY_ERROR)
1408 freeReplyObject (rep);
1409 element = element->next;
1411 rep =
redis_cmd (kbr,
"RPUSH filename:%s %lu %s", filename, time (NULL),
1413 if (!rep || rep->type == REDIS_REPLY_ERROR)
1416 freeReplyObject (rep);
1433 if (kbr->
rctx != NULL)
1435 redisFree (kbr->
rctx);
1456 redisFree (kbr->
rctx);
1458 g_debug (
"%s: deleting all DBs at %s except %s", __func__, kbr->
path, except);
1463 kbr->
rctx = redisConnectUnix (kbr->
path);
1464 if (kbr->
rctx == NULL || kbr->
rctx->err)
1467 "%s: redis connection error: %s", __func__,
1468 kbr->
rctx ? kbr->
rctx->errstr : strerror (ENOMEM));
1469 redisFree (kbr->
rctx);
1476 if (rep == NULL || rep->type != REDIS_REPLY_INTEGER || rep->integer != 1)
1478 freeReplyObject (rep);
1479 redisFree (kbr->
rctx);
1483 freeReplyObject (rep);
1484 rep = redisCommand (kbr->
rctx,
"SELECT %u", i);
1485 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
1487 freeReplyObject (rep);
1489 redisFree (kbr->
rctx);
1494 freeReplyObject (rep);
1503 redisFree (kbr->
rctx);
1509 redisFree (kbr->
rctx);
1532 g_debug (
"%s: saving all elements from KB #%u", __func__, kbr->
db);
1534 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
1544 freeReplyObject (rep);
1559 struct sigaction new_action, original_action;
1562 new_action.sa_flags = 0;
1563 if (sigemptyset (&new_action.sa_mask))
1565 new_action.sa_handler = SIG_IGN;
1566 if (sigaction (SIGPIPE, &new_action, &original_action))
1569 g_debug (
"%s: deleting all elements from KB #%u", __func__, kbr->
db);
1571 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
1580 if (sigaction (SIGPIPE, &original_action, NULL))
1583 freeReplyObject (rep);
static int redis_push_str(kb_t kb, const char *name, const char *value)
Push a new entry under a given key.
int nvti_set_category(nvti_t *n, const gint category)
Set the category type of a NVT Info.
#define KB_RETRY_DELAY
Number of seconds to wait for between two attempts to acquire a KB namespace.
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.
kb_nvt_pos
Possible positions of nvt values in cache list.
gchar * nvti_xref(const nvti_t *n)
Get the xref's.
static int fetch_max_db_index_compat(struct kb_redis *kbr)
Set the number of databases have been configured into kbr struct. (For Redis 2.4.* compatibility).
static nvti_t * redis_get_nvt_all(kb_t kb, const char *oid)
Get a full NVT.
gchar * nvti_required_ports(const nvti_t *n)
Get the required ports list.
static int redis_test_connection(struct kb_redis *kbr)
Test redis connection.
static struct kb_item * redis_get_single(kb_t kb, const char *name, enum kb_item_type type)
Get a single KB element.
void kb_item_free(struct kb_item *item)
Release a KB item (or a list).
static int redis_delete_all(struct kb_redis *)
Delete all the KB's content.
nvti_t * nvti_new(void)
Create a new (empty) nvti structure.
int nvti_set_family(nvti_t *n, const gchar *family)
Set the family of a NVT.
int nvti_set_required_ports(nvti_t *n, const gchar *required_ports)
Set the required ports of a NVT.
static char * redis_pop_str(kb_t kb, const char *name)
Pops a single KB string item.
gchar * nvti_cve(const nvti_t *n)
Get the CVE references.
gchar * name
Name of the preference.
The structure of a information record that corresponds to a NVT.
static redisContext * get_redis_ctx(struct kb_redis *kbr)
Get redis context if it is already connected or do a a connection.
Knowledge base item (defined by name, type (int/char*) and value). Implemented as a singly linked lis...
static struct kb_item * redis_get_all(kb_t kb, const char *name)
Get all items stored under a given name.
KB interface. Functions provided by an implementation. All functions have to be provided,...
gint nvti_category(const nvti_t *n)
Get the category for this NVT.
int nvti_set_timeout(nvti_t *n, const gint timeout)
Set the timeout of a NVT Info.
int nvti_set_tag(nvti_t *n, const gchar *tag)
Set the tags of a NVT.
gint nvti_timeout(const nvti_t *n)
Get the timeout for this NVT.
int nvti_set_cve(nvti_t *n, const gchar *cve)
Set the CVE references of a NVT.
static int redis_add_nvt(kb_t kb, const nvti_t *nvt, const char *filename)
Insert a new nvt.
static int redis_release_db(struct kb_redis *kbr)
Release DB.
gchar * nvti_tag(const nvti_t *n)
Get the tag.
static GSList * redis_get_oids(kb_t kb)
Get all NVT OIDs.
gchar * nvti_family(const nvti_t *n)
Get the family name.
static int redis_flush_all(kb_t, const char *)
Flush all the KB's content. Delete all namespaces.
static struct kb_item * redis2kbitem_single(const char *name, const redisReply *elt, int force_int)
Give a single KB item.
gchar * type
Preference type.
gchar * nvti_dependencies(const nvti_t *n)
Get the dependencies list.
static int redis_set_int(kb_t kb, const char *name, int val)
Set (replace) a new entry under a given name.
gchar * nvti_excluded_keys(const nvti_t *n)
Get the excluded keys list.
static int select_database(struct kb_redis *kbr)
Select DB.
gchar * nvti_mandatory_keys(const nvti_t *n)
Get the mandatory keys list.
Top-level KB. This is to be inherited by KB implementations.
#define GLOBAL_DBINDEX_NAME
Name of the namespace usage bitmap in redis.
const struct kb_operations * kb_ops
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...
int nvti_set_oid(nvti_t *n, const gchar *oid)
Set the OID of a NVT Info.
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.
int nvti_set_mandatory_keys(nvti_t *n, const gchar *mandatory_keys)
Set the mandatory keys of a NVT.
int nvti_set_name(nvti_t *n, const gchar *name)
Set the name of a NVT.
int nvti_set_xref(nvti_t *n, const gchar *xref)
Set the xrefs of a NVT.
static int redis_add_str_unique(kb_t kb, const char *name, const char *str, size_t len)
Insert (append) a new unique entry under a given name.
Knowledge base management API - Redis backend.
static struct kb_item * redis2kbitem(const char *name, const redisReply *rep)
Fetch a KB item or list from a redis Reply.
static size_t redis_count(kb_t kb, const char *pattern)
Count all items stored under a given pattern.
int nvti_set_bid(nvti_t *n, const gchar *bid)
Set the bid references of a NVT.
gchar * nvti_required_udp_ports(const nvti_t *n)
Get the required udp ports list.
int nvti_set_required_udp_ports(nvti_t *n, const gchar *required_udp_ports)
Set the required udp ports of a NVT.
gchar * dflt
Default value of the preference.
static int try_database_index(struct kb_redis *kbr, int index)
Attempt to atomically acquire ownership of a database.
static redisReply * redis_cmd(struct kb_redis *kbr, const char *fmt,...)
Execute a redis command and get a redis reply.
kb_item_type
Possible type of a kb_item.
static char * kb_item_get_str(kb_t kb, const char *name)
Get a single KB string item.
static int redis_add_int(kb_t kb, const char *name, int val)
Insert (append) a new entry under a given name.
static char * redis_get_str(kb_t kb, const char *name)
Get a single KB string item.
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.
static int redis_add_int_unique(kb_t kb, const char *name, int val)
Insert (append) a new unique entry under a given name.
int redis_save(kb_t kb)
Save all the elements from the KB.
Subclass of struct kb, it contains the redis-specific fields, such as the redis context,...
static int redis_delete(kb_t kb)
Delete all entries and release ownership on the namespace.
static const struct kb_operations KBRedisOperations
Default KB operations. No selection mechanism is provided yet since there's only one implementation (...
int nvti_set_excluded_keys(nvti_t *n, const gchar *excluded_keys)
Set the excluded keys of a NVT.
The structure for a preference of a NVT.
struct kb * kb_t
type abstraction to hide KB internals.
int nvti_set_dependencies(nvti_t *n, const gchar *dependencies)
Set the dependencies of a NVT.
static char * redis_get_nvt(kb_t kb, const char *oid, enum kb_nvt_pos position)
Get field of a NVT.
gchar * nvti_required_keys(const nvti_t *n)
Get the required keys list.
#define MAX_DB_INDEX__24
Max number of configured DB.
static kb_t redis_find(const char *kb_path, const char *key)
Find an existing Knowledge Base object with key.
static int redis_new(kb_t *kb, const char *kb_path)
Initialize a new Knowledge Base object.
static int redis_get_int(kb_t kb, const char *name)
Get a single KB integer item.
gchar * nvti_oid(const nvti_t *n)
Get the OID string.
static int redis_get_kb_index(kb_t kb)
Return the kb index.
gchar * nvti_bid(const nvti_t *n)
Get the bid references.
const struct kb_operations * KBDefaultOperations
Default KB operations. No selection mechanism is provided yet since there's only one implementation (...
static int fetch_max_db_index(struct kb_redis *kbr)
Set the number of databases have been configured into kbr struct.
int nvti_set_required_keys(nvti_t *n, const gchar *required_keys)
Set the required keys of a NVT.
static struct kb_item * redis_get_pattern(kb_t kb, const char *pattern)
Get all items stored under a given pattern.
int(* kb_new)(kb_t *, const char *)
static int redis_del_items(kb_t kb, const char *name)
Delete all entries under a given name.
gchar * nvti_name(const nvti_t *n)
Get the name.
GSList * prefs
Collection of NVT preferences.