Greenbone Vulnerability Management Libraries 22.8.0
kb.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2014-2023 Greenbone AG
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
11#define _GNU_SOURCE
12
13#include "kb.h"
14
15#include <errno.h> /* for ENOMEM, EINVAL, EPROTO, EALREADY, ECONN... */
16#include <glib.h> /* for g_log, g_free */
17#include <hiredis/hiredis.h> /* for redisReply, freeReplyObject, redisCommand */
18#include <stdbool.h> /* for bool, true, false */
19#include <stdio.h>
20#include <stdlib.h> /* for atoi */
21#include <string.h> /* for strlen, strerror, strncpy, memset */
22
23#undef G_LOG_DOMAIN
27#define G_LOG_DOMAIN "libgvm util"
28
29#if GLIB_CHECK_VERSION(2, 67, 3)
30#define memdup g_memdup2
31#else
32#define memdup g_memdup
33#endif
34
45#define GLOBAL_DBINDEX_NAME "GVM.__GlobalDBIndex"
46
47static const struct kb_operations KBRedisOperations;
48
55{
56 struct kb kb;
57 unsigned int max_db;
58 unsigned int db;
59 redisContext *rctx;
60 char *path;
61};
62#define redis_kb(__kb) ((struct kb_redis *) (__kb))
63
64static int
65redis_delete_all (struct kb_redis *);
66static int redis_lnk_reset (kb_t);
67static int
68redis_flush_all (kb_t, const char *);
69static redisReply *
70redis_cmd (struct kb_redis *kbr, const char *fmt, ...);
71
77static int
78try_database_index (struct kb_redis *kbr, int index)
79{
80 redisContext *ctx = kbr->rctx;
81 redisReply *rep;
82 int rc = 0;
83
84 rep = redisCommand (ctx, "HSETNX %s %d 1", GLOBAL_DBINDEX_NAME, index);
85 if (rep == NULL)
86 return -ENOMEM;
87
88 if (rep->type != REDIS_REPLY_INTEGER)
89 rc = -EPROTO;
90 else if (rep->integer == 0)
91 rc = -EALREADY;
92 else
93 kbr->db = index;
94
95 freeReplyObject (rep);
96
97 return rc;
98}
99
108static int
110{
111 int rc = 0;
112 redisContext *ctx = kbr->rctx;
113 redisReply *rep = NULL;
114
115 rep = redisCommand (ctx, "CONFIG GET databases");
116 if (rep == NULL)
117 {
118 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
119 "%s: redis command failed with '%s'", __func__, ctx->errstr);
120 rc = -1;
121 goto err_cleanup;
122 }
123
124 if (rep->type != REDIS_REPLY_ARRAY)
125 {
126 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
127 "%s: cannot retrieve max DB number: %s", __func__, rep->str);
128 rc = -1;
129 goto err_cleanup;
130 }
131
132 if (rep->elements == 2)
133 {
134 kbr->max_db = (unsigned) atoi (rep->element[1]->str);
135 }
136 else
137 {
138 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
139 "%s: unexpected reply length (%zd)", __func__, rep->elements);
140 rc = -1;
141 goto err_cleanup;
142 }
143
144 g_debug ("%s: maximum DB number: %u", __func__, kbr->max_db);
145
146err_cleanup:
147 if (rep != NULL)
148 freeReplyObject (rep);
149
150 return rc;
151}
152
163static int
165{
166 int rc;
167 redisContext *ctx = kbr->rctx;
168 redisReply *rep = NULL;
169
170 if (kbr->db == 0)
171 {
172 unsigned i;
173
174 if (kbr->max_db == 0)
175 fetch_max_db_index (kbr);
176
177 for (i = 1; i < kbr->max_db; i++)
178 {
179 rc = try_database_index (kbr, i);
180 if (rc == 0)
181 break;
182 }
183 }
184
185 /* No DB available, give up. */
186 if (kbr->db == 0)
187 {
188 rc = -1;
189 goto err_cleanup;
190 }
191
192 rep = redisCommand (ctx, "SELECT %u", kbr->db);
193 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
194 {
195 rc = -1;
196 goto err_cleanup;
197 }
198
199 rc = 0;
200
201err_cleanup:
202 if (rep != NULL)
203 freeReplyObject (rep);
204
205 return rc;
206}
207
215static int
217{
218 int rc;
219 redisContext *ctx = kbr->rctx;
220 redisReply *rep;
221
222 if (ctx == NULL)
223 return -EINVAL;
224
225 rep = redisCommand (ctx, "SELECT 0"); /* Management database*/
226 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
227 {
228 rc = -1;
229 goto err_cleanup;
230 }
231 freeReplyObject (rep);
232
233 rep = redisCommand (ctx, "HDEL %s %d", GLOBAL_DBINDEX_NAME, kbr->db);
234 if (rep == NULL || rep->type != REDIS_REPLY_INTEGER)
235 {
236 rc = -1;
237 goto err_cleanup;
238 }
239
240 rc = 0;
241
242err_cleanup:
243 if (rep != NULL)
244 freeReplyObject (rep);
245
246 return rc;
247}
248
249static inline char *
250parse_port_of_addr (const char *addr, int tcp_indicator_len)
251{
252 char *tmp;
253 int is_ip_v6;
254 if ((tmp = rindex (addr + tcp_indicator_len, ':')) == NULL)
255 return NULL;
256 is_ip_v6 = addr[tcp_indicator_len] == '[';
257 if (is_ip_v6 && (tmp - 1)[0] != ']')
258 return NULL;
259 return tmp + 1;
260}
261
262static redisContext *
263connect_redis (const char *addr, int len)
264{
265 const char *tcp_indicator = "tcp://";
266 const int tcp_indicator_len = strlen (tcp_indicator);
267 const int redis_default_port = 6379;
268
269 int port, host_len;
270 char *tmp, *host;
271 redisContext *result;
272 static int warn_flag = 0;
273
274 if (len < tcp_indicator_len + 1)
275 goto unix_connect;
276 if (memcmp (addr, tcp_indicator, tcp_indicator_len) != 0)
277 goto unix_connect;
278 host_len = len - tcp_indicator_len;
279 if ((tmp = parse_port_of_addr (addr, tcp_indicator_len)) == NULL)
280 port = redis_default_port;
281 else
282 {
283 port = atoi (tmp);
284 host_len -= strlen (tmp) + 1;
285 }
286 host = calloc (1, host_len);
287 memmove (host, addr + tcp_indicator_len, host_len);
288 result = redisConnect (host, port);
289 if (warn_flag == 0)
290 {
291 g_warning ("A Redis TCP connection is being used. This feature is "
292 "experimental and insecure, since it is not an encrypted "
293 "channel. We discourage its usage in production environments");
294 warn_flag = 1;
295 }
296 free (host);
297 return result;
298unix_connect:
299 return redisConnectUnix (addr);
300}
301
311static int
313{
314 int rc;
315
316 if (kbr->rctx != NULL)
317 return 0;
318
319 kbr->rctx = connect_redis (kbr->path, strlen (kbr->path));
320 if (kbr->rctx == NULL || kbr->rctx->err)
321 {
322 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
323 "%s: redis connection error to %s: %s", __func__, kbr->path,
324 kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
325 redisFree (kbr->rctx);
326 kbr->rctx = NULL;
327 return -1;
328 }
329
330 rc = select_database (kbr);
331 if (rc)
332 {
333 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "No redis DB available");
334 redisFree (kbr->rctx);
335 kbr->rctx = NULL;
336 return -2;
337 }
338
339 g_debug ("%s: connected to redis://%s/%d", __func__, kbr->path, kbr->db);
340 return 0;
341}
342
350static int
352{
353 int rc = 0;
354 redisReply *rep;
355
356 rep = redis_cmd (kbr, "PING");
357 if (rep == NULL)
358 {
359 /* not 100% relevant but hiredis doesn't provide us with proper error
360 * codes. */
361 rc = -ECONNREFUSED;
362 goto out;
363 }
364
365 if (rep->type != REDIS_REPLY_STATUS)
366 {
367 rc = -EINVAL;
368 goto out;
369 }
370
371 if (g_ascii_strcasecmp (rep->str, "PONG"))
372 {
373 rc = -EPROTO;
374 goto out;
375 }
376
377out:
378 if (rep != NULL)
379 freeReplyObject (rep);
380
381 return rc;
382}
383
391static int
393{
394 struct kb_redis *kbr;
395
396 kbr = redis_kb (kb);
397
398 redis_delete_all (kbr);
399 redis_release_db (kbr);
400
401 if (kbr->rctx != NULL)
402 {
403 g_free (kbr->path);
404 redisFree (kbr->rctx);
405 kbr->rctx = NULL;
406 }
407
408 g_free (kb);
409 return 0;
410}
411
419static int
421{
422 int i;
423 i = ((struct kb_redis *) kb)->db;
424 if (i > 0)
425 return i;
426 return -1;
427}
428
441static int
443{
444 redisReply *rep;
445 int rc = 0;
446
447 rep = redis_cmd (redis_kb (kb), "MEMORY PURGE");
448 if (!rep || rep->type == REDIS_REPLY_ERROR)
449 rc = -1;
450 if (rep)
451 freeReplyObject (rep);
452
453 return rc;
454}
455
465static int
466redis_new (kb_t *kb, const char *kb_path)
467{
468 struct kb_redis *kbr;
469 int rc = 0;
470
471 if (kb_path == NULL)
472 return -3;
473
474 kbr = g_malloc0 (sizeof (struct kb_redis));
476 kbr->path = g_strdup (kb_path);
477
478 if ((rc = get_redis_ctx (kbr)) < 0)
479 {
480 redis_delete ((kb_t) kbr);
481 return rc;
482 }
483 if (redis_test_connection (kbr))
484 {
485 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
486 "%s: cannot access redis at '%s'", __func__, kb_path);
487 redis_delete ((kb_t) kbr);
488 kbr = NULL;
489 rc = -1;
490 }
491
492 /* Ensure that the new kb is clean */
493 redis_delete_all (kbr);
494
495 *kb = (kb_t) kbr;
496
497 /* Try to make unused memory available for the OS again. */
498 if (redis_memory_purge (*kb))
499 g_warning ("%s: Memory purge was not successful", __func__);
500
501 return rc;
502}
503
512static kb_t
513redis_direct_conn (const char *kb_path, const int kb_index)
514{
515 struct kb_redis *kbr;
516 redisReply *rep;
517
518 if (kb_path == NULL)
519 return NULL;
520
521 kbr = g_malloc0 (sizeof (struct kb_redis));
523 kbr->path = g_strdup (kb_path);
524
525 kbr->rctx = connect_redis (kbr->path, strlen (kbr->path));
526 if (kbr->rctx == NULL || kbr->rctx->err)
527 {
528 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
529 "%s: redis connection error to %s: %s", __func__, kbr->path,
530 kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
531 redisFree (kbr->rctx);
532 g_free (kbr->path);
533 g_free (kbr);
534 return NULL;
535 }
536 kbr->db = kb_index;
537 rep = redisCommand (kbr->rctx, "SELECT %d", kb_index);
538 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
539 {
540 if (rep != NULL)
541 freeReplyObject (rep);
542 redisFree (kbr->rctx);
543 kbr->rctx = NULL;
544 g_free (kbr->path);
545 g_free (kbr);
546 return NULL;
547 }
548 freeReplyObject (rep);
549 return (kb_t) kbr;
550}
551
560static kb_t
561redis_find (const char *kb_path, const char *key)
562{
563 struct kb_redis *kbr;
564 unsigned int i = 1;
565
566 if (kb_path == NULL)
567 return NULL;
568
569 kbr = g_malloc0 (sizeof (struct kb_redis));
571 kbr->path = g_strdup (kb_path);
572
573 do
574 {
575 redisReply *rep;
576
577 kbr->rctx = connect_redis (kbr->path, strlen (kbr->path));
578 if (kbr->rctx == NULL || kbr->rctx->err)
579 {
580 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
581 "%s: redis connection error to %s: %s", __func__, kbr->path,
582 kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
583 redisFree (kbr->rctx);
584 g_free (kbr->path);
585 g_free (kbr);
586 return NULL;
587 }
588
589 if (kbr->max_db == 0)
590 fetch_max_db_index (kbr);
591
592 kbr->db = i;
593 rep = redisCommand (kbr->rctx, "HEXISTS %s %d", GLOBAL_DBINDEX_NAME, i);
594 if (rep == NULL || rep->type != REDIS_REPLY_INTEGER || rep->integer != 1)
595 {
596 if (rep != NULL)
597 freeReplyObject (rep);
598 i++;
599 redisFree (kbr->rctx);
600 kbr->rctx = NULL;
601 continue;
602 }
603 freeReplyObject (rep);
604 rep = redisCommand (kbr->rctx, "SELECT %u", i);
605 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
606 {
607 redisFree (kbr->rctx);
608 kbr->rctx = NULL;
609 }
610 else
611 {
612 freeReplyObject (rep);
613 if (key)
614 {
615 char *tmp = kb_item_get_str (&kbr->kb, key);
616 if (tmp)
617 {
618 g_free (tmp);
619 return (kb_t) kbr;
620 }
621 }
622 redisFree (kbr->rctx);
623 }
624 i++;
625 }
626 while (i < kbr->max_db);
627
628 g_free (kbr->path);
629 g_free (kbr);
630 return NULL;
631}
632
638void
639kb_item_free (struct kb_item *item)
640{
641 while (item != NULL)
642 {
643 struct kb_item *next;
644
645 next = item->next;
646 if (item->type == KB_TYPE_STR && item->v_str != NULL)
647 g_free (item->v_str);
648 g_free (item);
649 item = next;
650 }
651}
652
662static struct kb_item *
663redis2kbitem_single (const char *name, const redisReply *elt, int force_int)
664{
665 struct kb_item *item;
666 size_t namelen;
667
668 if (elt->type != REDIS_REPLY_STRING && elt->type != REDIS_REPLY_INTEGER)
669 return NULL;
670
671 namelen = strlen (name) + 1;
672
673 item = g_malloc0 (sizeof (struct kb_item) + namelen);
674 if (elt->type == REDIS_REPLY_INTEGER)
675 {
676 item->type = KB_TYPE_INT;
677 item->v_int = elt->integer;
678 }
679 else if (force_int)
680 {
681 item->type = KB_TYPE_INT;
682 item->v_int = atoi (elt->str);
683 }
684 else
685 {
686 item->type = KB_TYPE_STR;
687 item->v_str = memdup (elt->str, elt->len + 1);
688 item->len = elt->len;
689 }
690
691 item->next = NULL;
692 item->namelen = namelen;
693 memset (item->name, 0, namelen);
694 memcpy (item->name, name, namelen);
695
696 return item;
697}
698
707static struct kb_item *
708redis2kbitem (const char *name, const redisReply *rep)
709{
710 struct kb_item *kbi;
711
712 kbi = NULL;
713
714 switch (rep->type)
715 {
716 unsigned int i;
717
718 case REDIS_REPLY_STRING:
719 case REDIS_REPLY_INTEGER:
720 kbi = redis2kbitem_single (name, rep, 0);
721 break;
722
723 case REDIS_REPLY_ARRAY:
724 for (i = 0; i < rep->elements; i++)
725 {
726 struct kb_item *tmpitem;
727
728 tmpitem = redis2kbitem_single (name, rep->element[i], 0);
729 if (tmpitem == NULL)
730 break;
731
732 if (kbi != NULL)
733 {
734 tmpitem->next = kbi;
735 kbi = tmpitem;
736 }
737 else
738 kbi = tmpitem;
739 }
740 break;
741
742 case REDIS_REPLY_NIL:
743 case REDIS_REPLY_STATUS:
744 case REDIS_REPLY_ERROR:
745 default:
746 break;
747 }
748
749 return kbi;
750}
751
760static redisReply *
761redis_cmd (struct kb_redis *kbr, const char *fmt, ...)
762{
763 redisReply *rep;
764 va_list ap, aq;
765 int retry = 0;
766
767 va_start (ap, fmt);
768 do
769 {
770 if (get_redis_ctx (kbr) < 0)
771 {
772 va_end (ap);
773 return NULL;
774 }
775
776 va_copy (aq, ap);
777 rep = redisvCommand (kbr->rctx, fmt, aq);
778 va_end (aq);
779
780 if (kbr->rctx->err)
781 {
782 if (rep != NULL)
783 freeReplyObject (rep);
784
785 redis_lnk_reset ((kb_t) kbr);
786 retry = !retry;
787 }
788 else
789 retry = 0;
790 }
791 while (retry);
792
793 va_end (ap);
794
795 return rep;
796}
797
808static struct kb_item *
810{
811 struct kb_item *kbi;
812 struct kb_redis *kbr;
813 redisReply *rep;
814
815 kbr = redis_kb (kb);
816 kbi = NULL;
817
818 rep = redis_cmd (kbr, "LINDEX %s -1", name);
819 if (rep == NULL || rep->type != REDIS_REPLY_STRING)
820 {
821 kbi = NULL;
822 goto out;
823 }
824
825 kbi = redis2kbitem_single (name, rep, type == KB_TYPE_INT);
826
827out:
828 if (rep != NULL)
829 freeReplyObject (rep);
830
831 return kbi;
832}
833
843static char *
844redis_get_str (kb_t kb, const char *name)
845{
846 struct kb_item *kbi;
847
849 if (kbi != NULL)
850 {
851 char *res;
852
853 res = kbi->v_str;
854 kbi->v_str = NULL;
855 kb_item_free (kbi);
856 return res;
857 }
858 return NULL;
859}
860
870static int
871redis_push_str (kb_t kb, const char *name, const char *value)
872{
873 struct kb_redis *kbr;
874 redisReply *rep = NULL;
875 int rc = 0;
876
877 if (!value)
878 return -1;
879
880 kbr = redis_kb (kb);
881 rep = redis_cmd (kbr, "LPUSH %s %s", name, value);
882 if (!rep || rep->type == REDIS_REPLY_ERROR)
883 rc = -1;
884
885 if (rep)
886 freeReplyObject (rep);
887
888 return rc;
889}
890
899static char *
900redis_pop_str (kb_t kb, const char *name)
901{
902 struct kb_redis *kbr;
903 redisReply *rep;
904 char *value = NULL;
905
906 kbr = redis_kb (kb);
907 rep = redis_cmd (kbr, "RPOP %s", name);
908 if (!rep)
909 return NULL;
910
911 if (rep->type == REDIS_REPLY_STRING)
912 value = g_strdup (rep->str);
913 freeReplyObject (rep);
914
915 return value;
916}
917
926static int
927redis_get_int (kb_t kb, const char *name)
928{
929 struct kb_item *kbi;
930
932 if (kbi != NULL)
933 {
934 int res;
935
936 res = kbi->v_int;
937 kb_item_free (kbi);
938 return res;
939 }
940 return -1;
941}
942
952static char *
953redis_get_nvt (kb_t kb, const char *oid, enum kb_nvt_pos position)
954{
955 struct kb_redis *kbr;
956 redisReply *rep;
957 char *res = NULL;
958
959 kbr = redis_kb (kb);
960 if (position >= NVT_TIMESTAMP_POS)
961 rep = redis_cmd (kbr, "LINDEX filename:%s %d", oid,
962 position - NVT_TIMESTAMP_POS);
963 else
964 rep = redis_cmd (kbr, "LINDEX nvt:%s %d", oid, position);
965 if (!rep)
966 return NULL;
967 if (rep->type == REDIS_REPLY_INTEGER)
968 res = g_strdup_printf ("%lld", rep->integer);
969 else if (rep->type == REDIS_REPLY_STRING)
970 res = g_strdup (rep->str);
971 freeReplyObject (rep);
972
973 return res;
974}
975
984static nvti_t *
985redis_get_nvt_all (kb_t kb, const char *oid)
986{
987 struct kb_redis *kbr;
988 redisReply *rep;
989
990 kbr = redis_kb (kb);
991 rep =
992 redis_cmd (kbr, "LRANGE nvt:%s %d %d", oid, NVT_FILENAME_POS, NVT_NAME_POS);
993 if (!rep)
994 return NULL;
995 if (rep->type != REDIS_REPLY_ARRAY || rep->elements != NVT_NAME_POS + 1)
996 {
997 freeReplyObject (rep);
998 return NULL;
999 }
1000 else
1001 {
1002 nvti_t *nvti = nvti_new ();
1003
1004 nvti_set_oid (nvti, oid);
1009 nvti, rep->element[NVT_REQUIRED_UDP_PORTS_POS]->str);
1011 nvti_set_dependencies (nvti, rep->element[NVT_DEPENDENCIES_POS]->str);
1012 nvti_set_tag (nvti, rep->element[NVT_TAGS_POS]->str);
1013 nvti_add_refs (nvti, "cve", rep->element[NVT_CVES_POS]->str, "");
1014 nvti_add_refs (nvti, "bid", rep->element[NVT_BIDS_POS]->str, "");
1015 nvti_add_refs (nvti, NULL, rep->element[NVT_XREFS_POS]->str, "");
1016 nvti_set_category (nvti, atoi (rep->element[NVT_CATEGORY_POS]->str));
1017 nvti_set_family (nvti, rep->element[NVT_FAMILY_POS]->str);
1018 nvti_set_name (nvti, rep->element[NVT_NAME_POS]->str);
1019
1020 freeReplyObject (rep);
1021 return nvti;
1022 }
1023}
1024
1034static struct kb_item *
1036{
1037 struct kb_redis *kbr;
1038 struct kb_item *kbi;
1039 redisReply *rep;
1040
1041 kbr = redis_kb (kb);
1042
1043 rep = redis_cmd (kbr, "LRANGE %s 0 -1", name);
1044 if (rep == NULL)
1045 return NULL;
1046
1047 kbi = redis2kbitem (name, rep);
1048
1049 freeReplyObject (rep);
1050
1051 return kbi;
1052}
1053
1063static struct kb_item *
1064redis_get_pattern (kb_t kb, const char *pattern)
1065{
1066 struct kb_redis *kbr;
1067 struct kb_item *kbi = NULL;
1068 redisReply *rep;
1069 unsigned int i;
1070
1071 kbr = redis_kb (kb);
1072 rep = redis_cmd (kbr, "KEYS %s", pattern);
1073 if (!rep)
1074 return NULL;
1075 if (rep->type != REDIS_REPLY_ARRAY)
1076 {
1077 freeReplyObject (rep);
1078 return NULL;
1079 }
1080
1081 if (get_redis_ctx (kbr) < 0)
1082 return NULL;
1083 for (i = 0; i < rep->elements; i++)
1084 redisAppendCommand (kbr->rctx, "LRANGE %s 0 -1", rep->element[i]->str);
1085
1086 for (i = 0; i < rep->elements; i++)
1087 {
1088 struct kb_item *tmp;
1089 redisReply *rep_range;
1090
1091 redisGetReply (kbr->rctx, (void **) &rep_range);
1092 if (!rep)
1093 continue;
1094 tmp = redis2kbitem (rep->element[i]->str, rep_range);
1095 if (!tmp)
1096 {
1097 freeReplyObject (rep_range);
1098 continue;
1099 }
1100
1101 if (kbi)
1102 {
1103 struct kb_item *tmp2;
1104
1105 tmp2 = tmp;
1106 while (tmp->next)
1107 tmp = tmp->next;
1108 tmp->next = kbi;
1109 kbi = tmp2;
1110 }
1111 else
1112 kbi = tmp;
1113 freeReplyObject (rep_range);
1114 }
1115
1116 freeReplyObject (rep);
1117 return kbi;
1118}
1119
1127static GSList *
1129{
1130 struct kb_redis *kbr;
1131 redisReply *rep;
1132 GSList *list = NULL;
1133 size_t i;
1134
1135 kbr = redis_kb (kb);
1136 rep = redis_cmd (kbr, "KEYS nvt:*");
1137 if (!rep)
1138 return NULL;
1139
1140 if (rep->type != REDIS_REPLY_ARRAY)
1141 {
1142 freeReplyObject (rep);
1143 return NULL;
1144 }
1145
1146 /* Fetch OID values from key names nvt:OID. */
1147 for (i = 0; i < rep->elements; i++)
1148 list = g_slist_prepend (list, g_strdup (rep->element[i]->str + 4));
1149 freeReplyObject (rep);
1150
1151 return list;
1152}
1153
1162static size_t
1163redis_count (kb_t kb, const char *pattern)
1164{
1165 struct kb_redis *kbr;
1166 redisReply *rep;
1167 size_t count;
1168
1169 kbr = redis_kb (kb);
1170
1171 rep = redis_cmd (kbr, "KEYS %s", pattern);
1172 if (rep == NULL)
1173 return 0;
1174
1175 if (rep->type != REDIS_REPLY_ARRAY)
1176 {
1177 freeReplyObject (rep);
1178 return 0;
1179 }
1180
1181 count = rep->elements;
1182 freeReplyObject (rep);
1183 return count;
1184}
1185
1194static int
1195redis_del_items (kb_t kb, const char *name)
1196{
1197 struct kb_redis *kbr;
1198 redisReply *rep;
1199 int rc = 0;
1200
1201 kbr = redis_kb (kb);
1202
1203 rep = redis_cmd (kbr, "DEL %s", name);
1204 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1205 rc = -1;
1206
1207 if (rep != NULL)
1208 freeReplyObject (rep);
1209
1210 return rc;
1211}
1212
1226static int
1227redis_add_str_unique_volatile (kb_t kb, const char *name, const char *str,
1228 int expire, size_t len, int pos)
1229{
1230 struct kb_redis *kbr;
1231 redisReply *rep = NULL;
1232 int rc = 0;
1233 redisContext *ctx;
1234
1235 kbr = redis_kb (kb);
1236 if (get_redis_ctx (kbr) < 0)
1237 return -1;
1238 ctx = kbr->rctx;
1239
1240 /* Some VTs still rely on values being unique (ie. a value inserted multiple
1241 * times, will only be present once.)
1242 * Once these are fixed, the LREM becomes redundant and should be removed.
1243 */
1244 if (len == 0)
1245 {
1246 redisAppendCommand (ctx, "LREM %s 1 %s", name, str);
1247 redisAppendCommand (ctx, "%s %s %s", pos ? "LPUSH" : "RPUSH", name, str);
1248 redisAppendCommand (ctx, "EXPIRE %s %d", name, expire);
1249 /* Check LREM reply. */
1250 redisGetReply (ctx, (void **) &rep);
1251 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1252 g_debug ("Key '%s' already contained value '%s'", name, str);
1253 freeReplyObject (rep);
1254 /* Check PUSH reply. */
1255 redisGetReply (ctx, (void **) &rep);
1256 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1257 {
1258 rc = -1;
1259 goto out;
1260 }
1261 /* Check EXPIRE reply. */
1262 redisGetReply (ctx, (void **) &rep);
1263 if (rep == NULL || rep->type == REDIS_REPLY_ERROR
1264 || (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer != 1))
1265 {
1266 g_warning ("%s: Not able to set expire", __func__);
1267 rc = -1;
1268 goto out;
1269 }
1270 }
1271 else
1272 {
1273 redisAppendCommand (ctx, "LREM %s 1 %b", name, str, len);
1274 redisAppendCommand (ctx, "%s %s %b", pos ? "LPUSH" : "RPUSH", name, str,
1275 len);
1276 redisAppendCommand (ctx, "EXPIRE %s %d", name, expire);
1277 /* Check LREM reply. */
1278 redisGetReply (ctx, (void **) &rep);
1279 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1280 g_debug ("Key '%s' already contained string '%s'", name, str);
1281 freeReplyObject (rep);
1282 /* Check PUSH reply. */
1283 redisGetReply (ctx, (void **) &rep);
1284 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1285 {
1286 rc = -1;
1287 goto out;
1288 }
1289 /* Check EXPIRE reply. */
1290 redisGetReply (ctx, (void **) &rep);
1291 if (rep == NULL || rep->type == REDIS_REPLY_ERROR
1292 || (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer != 1))
1293 {
1294 g_warning ("%s: Not able to set expire", __func__);
1295 rc = -1;
1296 goto out;
1297 }
1298 }
1299
1300out:
1301 if (rep != NULL)
1302 freeReplyObject (rep);
1303
1304 return rc;
1305}
1306
1319static int
1320redis_add_str_unique (kb_t kb, const char *name, const char *str, size_t len,
1321 int pos)
1322{
1323 struct kb_redis *kbr;
1324 redisReply *rep = NULL;
1325 int rc = 0;
1326 redisContext *ctx;
1327
1328 kbr = redis_kb (kb);
1329 if (get_redis_ctx (kbr) < 0)
1330 return -1;
1331 ctx = kbr->rctx;
1332
1333 /* Some VTs still rely on values being unique (ie. a value inserted multiple
1334 * times, will only be present once.)
1335 * Once these are fixed, the LREM becomes redundant and should be removed.
1336 */
1337 if (len == 0)
1338 {
1339 redisAppendCommand (ctx, "LREM %s 1 %s", name, str);
1340 redisAppendCommand (ctx, "%s %s %s", pos ? "LPUSH" : "RPUSH", name, str);
1341 redisGetReply (ctx, (void **) &rep);
1342 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1343 g_debug ("Key '%s' already contained value '%s'", name, str);
1344 freeReplyObject (rep);
1345 redisGetReply (ctx, (void **) &rep);
1346 }
1347 else
1348 {
1349 redisAppendCommand (ctx, "LREM %s 1 %b", name, str, len);
1350 redisAppendCommand (ctx, "%s %s %b", pos ? "LPUSH" : "RPUSH", name, str,
1351 len);
1352 redisGetReply (ctx, (void **) &rep);
1353 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1354 g_debug ("Key '%s' already contained string '%s'", name, str);
1355 freeReplyObject (rep);
1356 redisGetReply (ctx, (void **) &rep);
1357 }
1358 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1359 rc = -1;
1360
1361 if (rep != NULL)
1362 freeReplyObject (rep);
1363
1364 return rc;
1365}
1366
1377static int
1378redis_add_str (kb_t kb, const char *name, const char *str, size_t len)
1379{
1380 struct kb_redis *kbr;
1381 redisReply *rep;
1382 int rc = 0;
1383
1384 kbr = redis_kb (kb);
1385 if (len == 0)
1386 rep = redis_cmd (kbr, "RPUSH %s %s", name, str);
1387 else
1388 rep = redis_cmd (kbr, "RPUSH %s %b", name, str, len);
1389 if (!rep || rep->type == REDIS_REPLY_ERROR)
1390 rc = -1;
1391
1392 if (rep)
1393 freeReplyObject (rep);
1394 return rc;
1395}
1396
1407static int
1408redis_set_str (kb_t kb, const char *name, const char *val, size_t len)
1409{
1410 struct kb_redis *kbr;
1411 redisReply *rep = NULL;
1412 redisContext *ctx;
1413 int rc = 0, i = 4;
1414
1415 kbr = redis_kb (kb);
1416 if (get_redis_ctx (kbr) < 0)
1417 return -1;
1418 ctx = kbr->rctx;
1419 redisAppendCommand (ctx, "MULTI");
1420 redisAppendCommand (ctx, "DEL %s", name);
1421 if (len == 0)
1422 redisAppendCommand (ctx, "RPUSH %s %s", name, val);
1423 else
1424 redisAppendCommand (ctx, "RPUSH %s %b", name, val, len);
1425 redisAppendCommand (ctx, "EXEC");
1426 while (i--)
1427 {
1428 redisGetReply (ctx, (void **) &rep);
1429 if (!rep || rep->type == REDIS_REPLY_ERROR)
1430 rc = -1;
1431 if (rep)
1432 freeReplyObject (rep);
1433 }
1434
1435 return rc;
1436}
1437
1448static int
1449redis_add_int_unique_volatile (kb_t kb, const char *name, int val, int expire)
1450{
1451 struct kb_redis *kbr;
1452 redisReply *rep;
1453 int rc = 0;
1454 redisContext *ctx;
1455
1456 kbr = redis_kb (kb);
1457 if (get_redis_ctx (kbr) < 0)
1458 return -1;
1459 ctx = kbr->rctx;
1460 redisAppendCommand (ctx, "LREM %s 1 %d", name, val);
1461 redisAppendCommand (ctx, "RPUSH %s %d", name, val);
1462 redisAppendCommand (ctx, "EXPIRE %s %d", name, expire);
1463 /* Check LREM reply. */
1464 redisGetReply (ctx, (void **) &rep);
1465 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1466 g_debug ("Key '%s' already contained integer '%d'", name, val);
1467 freeReplyObject (rep);
1468 /* Check PUSH reply. */
1469 redisGetReply (ctx, (void **) &rep);
1470 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1471 {
1472 rc = -1;
1473 goto out;
1474 }
1475 /* Check EXPIRE reply. */
1476 redisGetReply (ctx, (void **) &rep);
1477 if (rep == NULL || rep->type == REDIS_REPLY_ERROR
1478 || (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer != 1))
1479 {
1480 g_warning ("%s: Not able to set expire", __func__);
1481 rc = -1;
1482 goto out;
1483 }
1484
1485out:
1486 if (rep != NULL)
1487 freeReplyObject (rep);
1488
1489 return rc;
1490}
1491
1501static int
1502redis_add_int_unique (kb_t kb, const char *name, int val)
1503{
1504 struct kb_redis *kbr;
1505 redisReply *rep;
1506 int rc = 0;
1507 redisContext *ctx;
1508
1509 kbr = redis_kb (kb);
1510 if (get_redis_ctx (kbr) < 0)
1511 return -1;
1512 ctx = kbr->rctx;
1513 redisAppendCommand (ctx, "LREM %s 1 %d", name, val);
1514 redisAppendCommand (ctx, "RPUSH %s %d", name, val);
1515 redisGetReply (ctx, (void **) &rep);
1516 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1517 g_debug ("Key '%s' already contained integer '%d'", name, val);
1518 freeReplyObject (rep);
1519 redisGetReply (ctx, (void **) &rep);
1520 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1521 {
1522 rc = -1;
1523 goto out;
1524 }
1525
1526out:
1527 if (rep != NULL)
1528 freeReplyObject (rep);
1529
1530 return rc;
1531}
1532
1542static int
1543redis_add_int (kb_t kb, const char *name, int val)
1544{
1545 redisReply *rep;
1546 int rc = 0;
1547
1548 rep = redis_cmd (redis_kb (kb), "RPUSH %s %d", name, val);
1549 if (!rep || rep->type == REDIS_REPLY_ERROR)
1550 rc = -1;
1551 if (rep)
1552 freeReplyObject (rep);
1553
1554 return rc;
1555}
1556
1566static int
1567redis_set_int (kb_t kb, const char *name, int val)
1568{
1569 struct kb_redis *kbr;
1570 redisReply *rep = NULL;
1571 redisContext *ctx;
1572 int rc = 0, i = 4;
1573
1574 kbr = redis_kb (kb);
1575 if (get_redis_ctx (redis_kb (kb)) < 0)
1576 return -1;
1577 ctx = kbr->rctx;
1578 redisAppendCommand (ctx, "MULTI");
1579 redisAppendCommand (ctx, "DEL %s", name);
1580 redisAppendCommand (ctx, "RPUSH %s %d", name, val);
1581 redisAppendCommand (ctx, "EXEC");
1582 while (i--)
1583 {
1584 redisGetReply (ctx, (void **) &rep);
1585 if (!rep || rep->type == REDIS_REPLY_ERROR)
1586 rc = -1;
1587 if (rep)
1588 freeReplyObject (rep);
1589 }
1590
1591 return rc;
1592}
1593
1603static int
1604redis_add_nvt (kb_t kb, const nvti_t *nvt, const char *filename)
1605{
1606 struct kb_redis *kbr;
1607 redisReply *rep = NULL;
1608 int rc = 0;
1609 unsigned int i;
1610 gchar *cves, *bids, *xrefs;
1611
1612 if (!nvt || !filename)
1613 return -1;
1614
1615 cves = nvti_refs (nvt, "cve", "", 0);
1616 bids = nvti_refs (nvt, "bid", "", 0);
1617 xrefs = nvti_refs (nvt, NULL, "cve,bid", 1);
1618
1619 kbr = redis_kb (kb);
1620 rep = redis_cmd (
1621 kbr, "RPUSH nvt:%s %s %s %s %s %s %s %s %s %s %s %s %d %s %s",
1622 nvti_oid (nvt), filename,
1623 nvti_required_keys (nvt) ? nvti_required_keys (nvt) : "",
1624 nvti_mandatory_keys (nvt) ? nvti_mandatory_keys (nvt) : "",
1625 nvti_excluded_keys (nvt) ? nvti_excluded_keys (nvt) : "",
1627 nvti_required_ports (nvt) ? nvti_required_ports (nvt) : "",
1628 nvti_dependencies (nvt) ? nvti_dependencies (nvt) : "",
1629 nvti_tag (nvt) ? nvti_tag (nvt) : "", cves ? cves : "", bids ? bids : "",
1630 xrefs ? xrefs : "", nvti_category (nvt), nvti_family (nvt),
1631 nvti_name (nvt));
1632 g_free (cves);
1633 g_free (bids);
1634 g_free (xrefs);
1635 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1636 rc = -1;
1637 if (rep != NULL)
1638 freeReplyObject (rep);
1639
1640 if (nvti_pref_len (nvt))
1641 redis_cmd (kbr, "DEL oid:%s:prefs", nvti_oid (nvt));
1642 for (i = 0; i < nvti_pref_len (nvt); i++)
1643 {
1644 const nvtpref_t *pref = nvti_pref (nvt, i);
1645
1646 rep = redis_cmd (kbr, "RPUSH oid:%s:prefs %d|||%s|||%s|||%s",
1647 nvti_oid (nvt), nvtpref_id (pref), nvtpref_name (pref),
1648 nvtpref_type (pref), nvtpref_default (pref));
1649 if (!rep || rep->type == REDIS_REPLY_ERROR)
1650 rc = -1;
1651 if (rep)
1652 freeReplyObject (rep);
1653 }
1654 rep = redis_cmd (kbr, "RPUSH filename:%s %lu %s", filename, time (NULL),
1655 nvti_oid (nvt));
1656 if (!rep || rep->type == REDIS_REPLY_ERROR)
1657 rc = -1;
1658 if (rep)
1659 freeReplyObject (rep);
1660 return rc;
1661}
1662
1671static int
1673{
1674 struct kb_redis *kbr;
1675
1676 kbr = redis_kb (kb);
1677
1678 if (kbr->rctx != NULL)
1679 {
1680 redisFree (kbr->rctx);
1681 kbr->rctx = NULL;
1682 }
1683
1684 return 0;
1685}
1686
1695static int
1696redis_flush_all (kb_t kb, const char *except)
1697{
1698 unsigned int i = 1;
1699 struct kb_redis *kbr;
1700
1701 kbr = redis_kb (kb);
1702 if (kbr->rctx)
1703 redisFree (kbr->rctx);
1704
1705 g_debug ("%s: deleting all DBs at %s except %s", __func__, kbr->path, except);
1706 do
1707 {
1708 redisReply *rep;
1709
1710 kbr->rctx = connect_redis (kbr->path, strlen (kbr->path));
1711 if (kbr->rctx == NULL || kbr->rctx->err)
1712 {
1713 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1714 "%s: redis connection error to %s: %s", __func__, kbr->path,
1715 kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
1716 redisFree (kbr->rctx);
1717 kbr->rctx = NULL;
1718 return -1;
1719 }
1720
1721 kbr->db = i;
1722 rep = redisCommand (kbr->rctx, "HEXISTS %s %d", GLOBAL_DBINDEX_NAME, i);
1723 if (rep == NULL || rep->type != REDIS_REPLY_INTEGER || rep->integer != 1)
1724 {
1725 freeReplyObject (rep);
1726 redisFree (kbr->rctx);
1727 i++;
1728 continue;
1729 }
1730 freeReplyObject (rep);
1731 rep = redisCommand (kbr->rctx, "SELECT %u", i);
1732 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
1733 {
1734 freeReplyObject (rep);
1735 redisFree (kbr->rctx);
1736 kbr->rctx = NULL;
1737 }
1738 else
1739 {
1740 freeReplyObject (rep);
1741 /* Don't remove DB if it has "except" key. */
1742 if (except)
1743 {
1744 char *tmp = kb_item_get_str (kb, except);
1745 if (tmp)
1746 {
1747 g_free (tmp);
1748 i++;
1749 redisFree (kbr->rctx);
1750 continue;
1751 }
1752 }
1753 redis_delete_all (kbr);
1754 redis_release_db (kbr);
1755 redisFree (kbr->rctx);
1756 }
1757 i++;
1758 }
1759 while (i < kbr->max_db);
1760
1761 g_free (kbr->path);
1762 g_free (kb);
1763 return 0;
1764}
1765
1773static int
1775{
1776 int rc;
1777 redisReply *rep;
1778 struct kb_redis *kbr;
1779
1780 kbr = redis_kb (kb);
1781 g_debug ("%s: saving all elements from KB #%u", __func__, kbr->db);
1782 rep = redis_cmd (kbr, "SAVE");
1783 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
1784 {
1785 rc = -1;
1786 goto err_cleanup;
1787 }
1788
1789 rc = 0;
1790
1791err_cleanup:
1792 if (rep != NULL)
1793 freeReplyObject (rep);
1794
1795 return rc;
1796}
1797
1805int
1807{
1808 int rc;
1809 redisReply *rep;
1810 struct sigaction new_action, original_action;
1811
1812 /* Ignore SIGPIPE, in case of a lost connection. */
1813 new_action.sa_flags = 0;
1814 if (sigemptyset (&new_action.sa_mask))
1815 return -1;
1816 new_action.sa_handler = SIG_IGN;
1817 if (sigaction (SIGPIPE, &new_action, &original_action))
1818 return -1;
1819
1820 if (kbr)
1821 g_debug ("%s: deleting all elements from KB #%u", __func__, kbr->db);
1822 rep = redis_cmd (kbr, "FLUSHDB");
1823 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
1824 {
1825 rc = -1;
1826 goto err_cleanup;
1827 }
1828
1829 rc = 0;
1830
1831err_cleanup:
1832 if (sigaction (SIGPIPE, &original_action, NULL))
1833 return -1;
1834 if (rep != NULL)
1835 freeReplyObject (rep);
1836
1837 return rc;
1838}
1839
1846static const struct kb_operations KBRedisOperations = {
1847 .kb_new = redis_new,
1848 .kb_find = redis_find,
1849 .kb_delete = redis_delete,
1850 .kb_get_single = redis_get_single,
1851 .kb_get_str = redis_get_str,
1852 .kb_get_int = redis_get_int,
1853 .kb_get_nvt = redis_get_nvt,
1854 .kb_get_nvt_all = redis_get_nvt_all,
1855 .kb_get_nvt_oids = redis_get_oids,
1856 .kb_push_str = redis_push_str,
1857 .kb_pop_str = redis_pop_str,
1858 .kb_get_all = redis_get_all,
1859 .kb_get_pattern = redis_get_pattern,
1860 .kb_count = redis_count,
1861 .kb_add_str = redis_add_str,
1862 .kb_add_str_unique = redis_add_str_unique,
1863 .kb_add_str_unique_volatile = redis_add_str_unique_volatile,
1864 .kb_set_str = redis_set_str,
1865 .kb_add_int = redis_add_int,
1866 .kb_add_int_unique = redis_add_int_unique,
1867 .kb_add_int_unique_volatile = redis_add_int_unique_volatile,
1868 .kb_set_int = redis_set_int,
1869 .kb_add_nvt = redis_add_nvt,
1870 .kb_del_items = redis_del_items,
1871 .kb_lnk_reset = redis_lnk_reset,
1872 .kb_save = redis_save,
1873 .kb_flush = redis_flush_all,
1874 .kb_direct_conn = redis_direct_conn,
1875 .kb_get_kb_index = redis_get_kb_index};
1876
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:1672
static const struct kb_operations KBRedisOperations
Default KB operations.
Definition: kb.c:47
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:312
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:871
static int redis_memory_purge(kb_t kb)
Attempt to purge dirty pages.
Definition: kb.c:442
#define G_LOG_DOMAIN
GLib logging domain.
Definition: kb.c:27
static int redis_test_connection(struct kb_redis *kbr)
Test redis connection.
Definition: kb.c:351
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:1408
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:1227
static char * redis_get_nvt(kb_t kb, const char *oid, enum kb_nvt_pos position)
Get field of a NVT.
Definition: kb.c:953
static struct kb_item * redis2kbitem(const char *name, const redisReply *rep)
Fetch a KB item or list from a redis Reply.
Definition: kb.c:708
static kb_t redis_find(const char *kb_path, const char *key)
Find an existing Knowledge Base object with key.
Definition: kb.c:561
static int redis_delete(kb_t kb)
Delete all entries and release ownership on the namespace.
Definition: kb.c:392
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:1378
static int select_database(struct kb_redis *kbr)
Select DB.
Definition: kb.c:164
static int redis_delete_all(struct kb_redis *)
Delete all the KB's content.
Definition: kb.c:1806
void kb_item_free(struct kb_item *item)
Release a KB item (or a list).
Definition: kb.c:639
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:1449
static char * parse_port_of_addr(const char *addr, int tcp_indicator_len)
Definition: kb.c:250
static struct kb_item * redis_get_all(kb_t kb, const char *name)
Get all items stored under a given name.
Definition: kb.c:1035
#define memdup
Definition: kb.c:32
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:1543
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:513
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:1320
static char * redis_get_str(kb_t kb, const char *name)
Get a single KB string item.
Definition: kb.c:844
static struct kb_item * redis_get_pattern(kb_t kb, const char *pattern)
Get all items stored under a given pattern.
Definition: kb.c:1064
static GSList * redis_get_oids(kb_t kb)
Get all NVT OIDs.
Definition: kb.c:1128
static struct kb_item * redis2kbitem_single(const char *name, const redisReply *elt, int force_int)
Give a single KB item.
Definition: kb.c:663
static int redis_save(kb_t kb)
Save all the elements from the KB.
Definition: kb.c:1774
static int redis_get_int(kb_t kb, const char *name)
Get a single KB integer item.
Definition: kb.c:927
static redisContext * connect_redis(const char *addr, int len)
Definition: kb.c:263
static char * redis_pop_str(kb_t kb, const char *name)
Pops a single KB string item.
Definition: kb.c:900
static int redis_new(kb_t *kb, const char *kb_path)
Initialize a new Knowledge Base object.
Definition: kb.c:466
static int redis_get_kb_index(kb_t kb)
Return the kb index.
Definition: kb.c:420
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:1502
#define redis_kb(__kb)
Definition: kb.c:62
static int try_database_index(struct kb_redis *kbr, int index)
Attempt to atomically acquire ownership of a database.
Definition: kb.c:78
#define GLOBAL_DBINDEX_NAME
Name of the namespace usage bitmap in redis.
Definition: kb.c:45
const struct kb_operations * KBDefaultOperations
Default KB operations. No selection mechanism is provided yet since there's only one implementation (...
Definition: kb.c:1877
static int redis_flush_all(kb_t, const char *)
Flush all the KB's content. Delete all namespaces.
Definition: kb.c:1696
static size_t redis_count(kb_t kb, const char *pattern)
Count all items stored under a given pattern.
Definition: kb.c:1163
static int redis_release_db(struct kb_redis *kbr)
Release DB.
Definition: kb.c:216
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:809
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:1567
static int redis_add_nvt(kb_t kb, const nvti_t *nvt, const char *filename)
Insert a new nvt.
Definition: kb.c:1604
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
static redisReply * redis_cmd(struct kb_redis *kbr, const char *fmt,...)
Execute a redis command and get a redis reply.
Definition: kb.c:761
static nvti_t * redis_get_nvt_all(kb_t kb, const char *oid)
Get a full NVT.
Definition: kb.c:985
static int redis_del_items(kb_t kb, const char *name)
Delete all entries under a given name.
Definition: kb.c:1195
Knowledge base management API - Redis backend.
kb_nvt_pos
Possible positions of nvt values in cache list.
Definition: kb.h:45
@ NVT_FAMILY_POS
Definition: kb.h:58
@ NVT_CATEGORY_POS
Definition: kb.h:57
@ NVT_TIMESTAMP_POS
Definition: kb.h:60
@ NVT_NAME_POS
Definition: kb.h:59
@ NVT_TAGS_POS
Definition: kb.h:53
@ NVT_BIDS_POS
Definition: kb.h:55
@ NVT_EXCLUDED_KEYS_POS
Definition: kb.h:49
@ NVT_REQUIRED_PORTS_POS
Definition: kb.h:51
@ NVT_REQUIRED_UDP_PORTS_POS
Definition: kb.h:50
@ NVT_FILENAME_POS
Definition: kb.h:46
@ NVT_DEPENDENCIES_POS
Definition: kb.h:52
@ NVT_CVES_POS
Definition: kb.h:54
@ NVT_REQUIRED_KEYS_POS
Definition: kb.h:47
@ NVT_XREFS_POS
Definition: kb.h:56
@ NVT_MANDATORY_KEYS_POS
Definition: kb.h:48
struct kb * kb_t
type abstraction to hide KB internals.
Definition: kb.h:98
kb_item_type
Possible type of a kb_item.
Definition: kb.h:33
@ KB_TYPE_INT
Definition: kb.h:35
@ KB_TYPE_STR
Definition: kb.h:36
static char * kb_item_get_str(kb_t kb, const char *name)
Get a single KB string item.
Definition: kb.h:334
nvti_t * nvti_new(void)
Create a new (empty) nvti structure.
Definition: nvti.c:597
gchar * nvti_dependencies(const nvti_t *n)
Get the dependencies list.
Definition: nvti.c:1070
guint nvti_pref_len(const nvti_t *n)
Get the number of preferences of the NVT.
Definition: nvti.c:1209
gchar * nvti_required_udp_ports(const nvti_t *n)
Get the required udp ports list.
Definition: nvti.c:1140
gchar * nvti_required_ports(const nvti_t *n)
Get the required ports list.
Definition: nvti.c:1126
gchar * nvti_refs(const nvti_t *n, const gchar *type, const gchar *exclude_types, guint use_types)
Get references as string.
Definition: nvti.c:804
gchar * nvtpref_type(const nvtpref_t *np)
Get the Type of a NVT Preference.
Definition: nvti.c:569
int nvti_set_excluded_keys(nvti_t *n, const gchar *excluded_keys)
Set the excluded keys of a NVT.
Definition: nvti.c:1782
int nvti_set_dependencies(nvti_t *n, const gchar *dependencies)
Set the dependencies of a NVT.
Definition: nvti.c:1710
int nvti_set_required_ports(nvti_t *n, const gchar *required_ports)
Set the required ports of a NVT.
Definition: nvti.c:1806
int nvti_set_oid(nvti_t *n, const gchar *oid)
Set the OID of a NVT Info.
Definition: nvti.c:1252
int nvti_set_tag(nvti_t *n, const gchar *tag)
Set the tags of a NVT.
Definition: nvti.c:1663
int nvti_set_mandatory_keys(nvti_t *n, const gchar *mandatory_keys)
Set the mandatory keys of a NVT.
Definition: nvti.c:1758
gint nvti_category(const nvti_t *n)
Get the category for this NVT.
Definition: nvti.c:1237
gchar * nvti_family(const nvti_t *n)
Get the family name.
Definition: nvti.c:1196
const nvtpref_t * nvti_pref(const nvti_t *n, guint p)
Get the n'th preferences of the NVT.
Definition: nvti.c:1224
gchar * nvti_excluded_keys(const nvti_t *n)
Get the excluded keys list.
Definition: nvti.c:1112
gchar * nvti_name(const nvti_t *n)
Get the name.
Definition: nvti.c:663
gchar * nvti_oid(const nvti_t *n)
Get the OID string.
Definition: nvti.c:649
int nvti_set_required_keys(nvti_t *n, const gchar *required_keys)
Set the required keys of a NVT.
Definition: nvti.c:1734
int nvtpref_id(const nvtpref_t *np)
Get the ID of a NVT Preference.
Definition: nvti.c:541
int nvti_set_name(nvti_t *n, const gchar *name)
Set the name of a NVT.
Definition: nvti.c:1272
gchar * nvti_required_keys(const nvti_t *n)
Get the required keys list.
Definition: nvti.c:1084
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:2006
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:1830
gchar * nvti_mandatory_keys(const nvti_t *n)
Get the mandatory keys list.
Definition: nvti.c:1098
gchar * nvtpref_default(const nvtpref_t *np)
Get the Default of a NVT Preference.
Definition: nvti.c:583
int nvti_set_family(nvti_t *n, const gchar *family)
Set the family of a NVT.
Definition: nvti.c:1941
gchar * nvtpref_name(const nvtpref_t *np)
Get the Name of a NVT Preference.
Definition: nvti.c:555
gchar * nvti_tag(const nvti_t *n)
Get the tags.
Definition: nvti.c:1004
int nvti_set_category(nvti_t *n, const gint category)
Set the category type of a NVT Info.
Definition: nvti.c:1981
Knowledge base item (defined by name, type (int/char*) and value). Implemented as a singly linked lis...
Definition: kb.h:69
char name[]
Definition: kb.h:82
int v_int
Definition: kb.h:75
enum kb_item_type type
Definition: kb.h:70
char * v_str
Definition: kb.h:74
struct kb_item * next
Definition: kb.h:79
size_t len
Definition: kb.h:78
size_t namelen
Definition: kb.h:81
KB interface. Functions provided by an implementation. All functions have to be provided,...
Definition: kb.h:107
int(* kb_new)(kb_t *, const char *)
Definition: kb.h:109
Subclass of struct kb, it contains the redis-specific fields, such as the redis context,...
Definition: kb.c:55
char * path
Definition: kb.c:60
unsigned int max_db
Definition: kb.c:57
unsigned int db
Definition: kb.c:58
struct kb kb
Definition: kb.c:56
redisContext * rctx
Definition: kb.c:59
Top-level KB. This is to be inherited by KB implementations.
Definition: kb.h:91
const struct kb_operations * kb_ops
Definition: kb.h:92
The structure of a information record that corresponds to a NVT.
Definition: nvti.c:394
The structure for a preference of a NVT.
Definition: nvti.c:477