Greenbone Vulnerability Management Libraries 22.18.1
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
10
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
41
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 tmp = strrchr (addr + tcp_indicator_len, ':');
255 if (tmp == NULL)
256 return NULL;
257 is_ip_v6 = addr[tcp_indicator_len] == '[';
258 if (is_ip_v6 && (tmp - 1)[0] != ']')
259 return NULL;
260 return tmp + 1;
261}
262
263static redisContext *
264connect_redis (const char *addr, int len)
265{
266 const char *tcp_indicator = "tcp://";
267 const int tcp_indicator_len = strlen (tcp_indicator);
268 const int redis_default_port = 6379;
269
270 int port, host_len;
271 char *tmp, *host;
272 redisContext *result;
273 static int warn_flag = 0;
274
275 if (len < tcp_indicator_len + 1)
276 goto unix_connect;
277 if (memcmp (addr, tcp_indicator, tcp_indicator_len) != 0)
278 goto unix_connect;
279 host_len = len - tcp_indicator_len;
280 tmp = parse_port_of_addr (addr, tcp_indicator_len);
281 if (tmp == NULL)
282 port = redis_default_port;
283 else
284 {
285 port = atoi (tmp);
286 host_len -= strlen (tmp) + 1;
287 }
288 host = calloc (1, host_len);
289 memmove (host, addr + tcp_indicator_len, host_len);
290 result = redisConnect (host, port);
291 if (warn_flag == 0)
292 {
293 g_warning ("A Redis TCP connection is being used. This feature is "
294 "experimental and insecure, since it is not an encrypted "
295 "channel. We discourage its usage in production environments");
296 warn_flag = 1;
297 }
298 free (host);
299 return result;
300unix_connect:
301 return redisConnectUnix (addr);
302}
303
313static int
315{
316 int rc;
317
318 if (kbr->rctx != NULL)
319 return 0;
320
321 kbr->rctx = connect_redis (kbr->path, strlen (kbr->path));
322 if (kbr->rctx == NULL || kbr->rctx->err)
323 {
324 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
325 "%s: redis connection error to %s: %s", __func__, kbr->path,
326 kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
327 redisFree (kbr->rctx);
328 kbr->rctx = NULL;
329 return -1;
330 }
331
332 rc = select_database (kbr);
333 if (rc)
334 {
335 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "No redis DB available");
336 redisFree (kbr->rctx);
337 kbr->rctx = NULL;
338 return -2;
339 }
340
341 g_debug ("%s: connected to redis://%s/%d", __func__, kbr->path, kbr->db);
342 return 0;
343}
344
352static int
354{
355 int rc = 0;
356 redisReply *rep;
357
358 rep = redis_cmd (kbr, "PING");
359 if (rep == NULL)
360 {
361 /* not 100% relevant but hiredis doesn't provide us with proper error
362 * codes. */
363 rc = -ECONNREFUSED;
364 goto out;
365 }
366
367 if (rep->type != REDIS_REPLY_STATUS)
368 {
369 rc = -EINVAL;
370 goto out;
371 }
372
373 if (g_ascii_strcasecmp (rep->str, "PONG"))
374 {
375 rc = -EPROTO;
376 goto out;
377 }
378
379out:
380 if (rep != NULL)
381 freeReplyObject (rep);
382
383 return rc;
384}
385
393static int
395{
396 struct kb_redis *kbr;
397
398 kbr = redis_kb (kb);
399
400 redis_delete_all (kbr);
401 redis_release_db (kbr);
402
403 if (kbr->rctx != NULL)
404 {
405 g_free (kbr->path);
406 redisFree (kbr->rctx);
407 kbr->rctx = NULL;
408 }
409
410 g_free (kb);
411 return 0;
412}
413
421static int
423{
424 int i;
425 i = ((struct kb_redis *) kb)->db;
426 if (i > 0)
427 return i;
428 return -1;
429}
430
443static int
445{
446 redisReply *rep;
447 int rc = 0;
448
449 rep = redis_cmd (redis_kb (kb), "MEMORY PURGE");
450 if (!rep || rep->type == REDIS_REPLY_ERROR)
451 rc = -1;
452 if (rep)
453 freeReplyObject (rep);
454
455 return rc;
456}
457
467static int
468redis_new (kb_t *kb, const char *kb_path)
469{
470 struct kb_redis *kbr;
471 int rc = 0;
472
473 if (kb_path == NULL)
474 return -3;
475
476 kbr = g_malloc0 (sizeof (struct kb_redis));
478 kbr->path = g_strdup (kb_path);
479
480 rc = get_redis_ctx (kbr);
481 if (rc < 0)
482 {
483 redis_delete ((kb_t) kbr);
484 return rc;
485 }
486 if (redis_test_connection (kbr))
487 {
488 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
489 "%s: cannot access redis at '%s'", __func__, kb_path);
490 redis_delete ((kb_t) kbr);
491 kbr = NULL;
492 rc = -1;
493 }
494
495 /* Ensure that the new kb is clean */
496 redis_delete_all (kbr);
497
498 *kb = (kb_t) kbr;
499
500 /* Try to make unused memory available for the OS again. */
501 if (redis_memory_purge (*kb))
502 g_warning ("%s: Memory purge was not successful", __func__);
503
504 return rc;
505}
506
515static kb_t
516redis_direct_conn (const char *kb_path, const int kb_index)
517{
518 struct kb_redis *kbr;
519 redisReply *rep;
520
521 if (kb_path == NULL)
522 return NULL;
523
524 kbr = g_malloc0 (sizeof (struct kb_redis));
526 kbr->path = g_strdup (kb_path);
527
528 kbr->rctx = connect_redis (kbr->path, strlen (kbr->path));
529 if (kbr->rctx == NULL || kbr->rctx->err)
530 {
531 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
532 "%s: redis connection error to %s: %s", __func__, kbr->path,
533 kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
534 redisFree (kbr->rctx);
535 g_free (kbr->path);
536 g_free (kbr);
537 return NULL;
538 }
539 kbr->db = kb_index;
540 rep = redisCommand (kbr->rctx, "SELECT %d", kb_index);
541 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
542 {
543 if (rep != NULL)
544 freeReplyObject (rep);
545 redisFree (kbr->rctx);
546 kbr->rctx = NULL;
547 g_free (kbr->path);
548 g_free (kbr);
549 return NULL;
550 }
551 freeReplyObject (rep);
552 return (kb_t) kbr;
553}
554
563static kb_t
564redis_find (const char *kb_path, const char *key)
565{
566 struct kb_redis *kbr;
567 unsigned int i = 1;
568
569 if (kb_path == NULL)
570 return NULL;
571
572 kbr = g_malloc0 (sizeof (struct kb_redis));
574 kbr->path = g_strdup (kb_path);
575
576 do
577 {
578 redisReply *rep;
579
580 kbr->rctx = connect_redis (kbr->path, strlen (kbr->path));
581 if (kbr->rctx == NULL || kbr->rctx->err)
582 {
583 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
584 "%s: redis connection error to %s: %s", __func__, kbr->path,
585 kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
586 redisFree (kbr->rctx);
587 g_free (kbr->path);
588 g_free (kbr);
589 return NULL;
590 }
591
592 if (kbr->max_db == 0)
593 fetch_max_db_index (kbr);
594
595 kbr->db = i;
596 rep = redisCommand (kbr->rctx, "HEXISTS %s %d", GLOBAL_DBINDEX_NAME, i);
597 if (rep == NULL || rep->type != REDIS_REPLY_INTEGER || rep->integer != 1)
598 {
599 if (rep != NULL)
600 freeReplyObject (rep);
601 i++;
602 redisFree (kbr->rctx);
603 kbr->rctx = NULL;
604 continue;
605 }
606 freeReplyObject (rep);
607 rep = redisCommand (kbr->rctx, "SELECT %u", i);
608 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
609 {
610 redisFree (kbr->rctx);
611 kbr->rctx = NULL;
612 }
613 else
614 {
615 freeReplyObject (rep);
616 if (key)
617 {
618 char *tmp = kb_item_get_str (&kbr->kb, key);
619 if (tmp)
620 {
621 g_free (tmp);
622 return (kb_t) kbr;
623 }
624 }
625 redisFree (kbr->rctx);
626 }
627 i++;
628 }
629 while (i < kbr->max_db);
630
631 g_free (kbr->path);
632 g_free (kbr);
633 return NULL;
634}
635
641void
642kb_item_free (struct kb_item *item)
643{
644 while (item != NULL)
645 {
646 struct kb_item *next;
647
648 next = item->next;
649 if (item->type == KB_TYPE_STR && item->v_str != NULL)
650 g_free (item->v_str);
651 g_free (item);
652 item = next;
653 }
654}
655
665static struct kb_item *
666redis2kbitem_single (const char *name, const redisReply *elt, int force_int)
667{
668 struct kb_item *item;
669 size_t namelen;
670
671 if (elt->type != REDIS_REPLY_STRING && elt->type != REDIS_REPLY_INTEGER)
672 return NULL;
673
674 namelen = strlen (name) + 1;
675
676 item = g_malloc0 (sizeof (struct kb_item) + namelen);
677 if (elt->type == REDIS_REPLY_INTEGER)
678 {
679 item->type = KB_TYPE_INT;
680 item->v_int = elt->integer;
681 }
682 else if (force_int)
683 {
684 item->type = KB_TYPE_INT;
685 item->v_int = atoi (elt->str);
686 }
687 else
688 {
689 item->type = KB_TYPE_STR;
690 item->v_str = memdup (elt->str, elt->len + 1);
691 item->len = elt->len;
692 }
693
694 item->next = NULL;
695 item->namelen = namelen;
696 memset (item->name, 0, namelen);
697 memcpy (item->name, name, namelen);
698
699 return item;
700}
701
710static struct kb_item *
711redis2kbitem (const char *name, const redisReply *rep)
712{
713 struct kb_item *kbi;
714
715 kbi = NULL;
716
717 switch (rep->type)
718 {
719 unsigned int i;
720
721 case REDIS_REPLY_STRING:
722 case REDIS_REPLY_INTEGER:
723 kbi = redis2kbitem_single (name, rep, 0);
724 break;
725
726 case REDIS_REPLY_ARRAY:
727 for (i = 0; i < rep->elements; i++)
728 {
729 struct kb_item *tmpitem;
730
731 tmpitem = redis2kbitem_single (name, rep->element[i], 0);
732 if (tmpitem == NULL)
733 break;
734
735 if (kbi != NULL)
736 {
737 tmpitem->next = kbi;
738 kbi = tmpitem;
739 }
740 else
741 kbi = tmpitem;
742 }
743 break;
744
745 case REDIS_REPLY_NIL:
746 case REDIS_REPLY_STATUS:
747 case REDIS_REPLY_ERROR:
748 default:
749 break;
750 }
751
752 return kbi;
753}
754
763static redisReply *
764redis_cmd (struct kb_redis *kbr, const char *fmt, ...)
765{
766 redisReply *rep;
767 va_list ap, aq;
768 int retry = 0;
769
770 va_start (ap, fmt);
771 do
772 {
773 if (get_redis_ctx (kbr) < 0)
774 {
775 va_end (ap);
776 return NULL;
777 }
778
779 va_copy (aq, ap);
780 rep = redisvCommand (kbr->rctx, fmt, aq);
781 va_end (aq);
782
783 if (kbr->rctx->err)
784 {
785 if (rep != NULL)
786 freeReplyObject (rep);
787
788 redis_lnk_reset ((kb_t) kbr);
789 retry = !retry;
790 }
791 else
792 retry = 0;
793 }
794 while (retry);
795
796 va_end (ap);
797
798 return rep;
799}
800
811static struct kb_item *
813{
814 struct kb_item *kbi;
815 struct kb_redis *kbr;
816 redisReply *rep;
817
818 kbr = redis_kb (kb);
819 kbi = NULL;
820
821 rep = redis_cmd (kbr, "LINDEX %s -1", name);
822 if (rep == NULL || rep->type != REDIS_REPLY_STRING)
823 {
824 kbi = NULL;
825 goto out;
826 }
827
828 kbi = redis2kbitem_single (name, rep, type == KB_TYPE_INT);
829
830out:
831 if (rep != NULL)
832 freeReplyObject (rep);
833
834 return kbi;
835}
836
846static char *
847redis_get_str (kb_t kb, const char *name)
848{
849 struct kb_item *kbi;
850
852 if (kbi != NULL)
853 {
854 char *res;
855
856 res = kbi->v_str;
857 kbi->v_str = NULL;
858 kb_item_free (kbi);
859 return res;
860 }
861 return NULL;
862}
863
873static int
874redis_push_str (kb_t kb, const char *name, const char *value)
875{
876 struct kb_redis *kbr;
877 redisReply *rep = NULL;
878 int rc = 0;
879
880 if (!value)
881 return -1;
882
883 kbr = redis_kb (kb);
884 rep = redis_cmd (kbr, "LPUSH %s %s", name, value);
885 if (!rep || rep->type == REDIS_REPLY_ERROR)
886 rc = -1;
887
888 if (rep)
889 freeReplyObject (rep);
890
891 return rc;
892}
893
902static char *
903redis_pop_str (kb_t kb, const char *name)
904{
905 struct kb_redis *kbr;
906 redisReply *rep;
907 char *value = NULL;
908
909 kbr = redis_kb (kb);
910 rep = redis_cmd (kbr, "RPOP %s", name);
911 if (!rep)
912 return NULL;
913
914 if (rep->type == REDIS_REPLY_STRING)
915 value = g_strdup (rep->str);
916 freeReplyObject (rep);
917
918 return value;
919}
920
929static int
930redis_get_int (kb_t kb, const char *name)
931{
932 struct kb_item *kbi;
933
935 if (kbi != NULL)
936 {
937 int res;
938
939 res = kbi->v_int;
940 kb_item_free (kbi);
941 return res;
942 }
943 return -1;
944}
945
955static char *
956redis_get_nvt (kb_t kb, const char *oid, enum kb_nvt_pos position)
957{
958 struct kb_redis *kbr;
959 redisReply *rep;
960 char *res = NULL;
961
962 kbr = redis_kb (kb);
963 if (position >= NVT_TIMESTAMP_POS)
964 rep = redis_cmd (kbr, "LINDEX filename:%s %d", oid,
965 position - NVT_TIMESTAMP_POS);
966 else
967 rep = redis_cmd (kbr, "LINDEX nvt:%s %d", oid, position);
968 if (!rep)
969 return NULL;
970 if (rep->type == REDIS_REPLY_INTEGER)
971 res = g_strdup_printf ("%lld", rep->integer);
972 else if (rep->type == REDIS_REPLY_STRING)
973 res = g_strdup (rep->str);
974 freeReplyObject (rep);
975
976 return res;
977}
978
987static nvti_t *
988redis_get_nvt_all (kb_t kb, const char *oid)
989{
990 struct kb_redis *kbr;
991 redisReply *rep;
992
993 kbr = redis_kb (kb);
994 rep =
995 redis_cmd (kbr, "LRANGE nvt:%s %d %d", oid, NVT_FILENAME_POS, NVT_NAME_POS);
996 if (!rep)
997 return NULL;
998 if (rep->type != REDIS_REPLY_ARRAY || rep->elements != NVT_NAME_POS + 1)
999 {
1000 freeReplyObject (rep);
1001 return NULL;
1002 }
1003 else
1004 {
1005 nvti_t *nvti = nvti_new ();
1006
1007 nvti_set_oid (nvti, oid);
1012 nvti, rep->element[NVT_REQUIRED_UDP_PORTS_POS]->str);
1014 nvti_set_dependencies (nvti, rep->element[NVT_DEPENDENCIES_POS]->str);
1015 nvti_set_tag (nvti, rep->element[NVT_TAGS_POS]->str);
1016 nvti_add_refs (nvti, "cve", rep->element[NVT_CVES_POS]->str, "");
1017 nvti_add_refs (nvti, "bid", rep->element[NVT_BIDS_POS]->str, "");
1018 nvti_add_refs (nvti, NULL, rep->element[NVT_XREFS_POS]->str, "");
1019 nvti_set_category (nvti, atoi (rep->element[NVT_CATEGORY_POS]->str));
1020 nvti_set_family (nvti, rep->element[NVT_FAMILY_POS]->str);
1021 nvti_set_name (nvti, rep->element[NVT_NAME_POS]->str);
1022
1023 freeReplyObject (rep);
1024 return nvti;
1025 }
1026}
1027
1037static struct kb_item *
1039{
1040 struct kb_redis *kbr;
1041 struct kb_item *kbi;
1042 redisReply *rep;
1043
1044 kbr = redis_kb (kb);
1045
1046 rep = redis_cmd (kbr, "LRANGE %s 0 -1", name);
1047 if (rep == NULL)
1048 return NULL;
1049
1050 kbi = redis2kbitem (name, rep);
1051
1052 freeReplyObject (rep);
1053
1054 return kbi;
1055}
1056
1066static struct kb_item *
1067redis_get_pattern (kb_t kb, const char *pattern)
1068{
1069 struct kb_redis *kbr;
1070 struct kb_item *kbi = NULL;
1071 redisReply *rep;
1072 unsigned int i;
1073
1074 kbr = redis_kb (kb);
1075 rep = redis_cmd (kbr, "KEYS %s", pattern);
1076 if (!rep)
1077 return NULL;
1078 if (rep->type != REDIS_REPLY_ARRAY)
1079 {
1080 freeReplyObject (rep);
1081 return NULL;
1082 }
1083
1084 if (get_redis_ctx (kbr) < 0)
1085 return NULL;
1086 for (i = 0; i < rep->elements; i++)
1087 redisAppendCommand (kbr->rctx, "LRANGE %s 0 -1", rep->element[i]->str);
1088
1089 for (i = 0; i < rep->elements; i++)
1090 {
1091 struct kb_item *tmp;
1092 redisReply *rep_range;
1093
1094 redisGetReply (kbr->rctx, (void **) &rep_range);
1095 if (!rep)
1096 continue;
1097 tmp = redis2kbitem (rep->element[i]->str, rep_range);
1098 if (!tmp)
1099 {
1100 freeReplyObject (rep_range);
1101 continue;
1102 }
1103
1104 if (kbi)
1105 {
1106 struct kb_item *tmp2;
1107
1108 tmp2 = tmp;
1109 while (tmp->next)
1110 tmp = tmp->next;
1111 tmp->next = kbi;
1112 kbi = tmp2;
1113 }
1114 else
1115 kbi = tmp;
1116 freeReplyObject (rep_range);
1117 }
1118
1119 freeReplyObject (rep);
1120 return kbi;
1121}
1122
1130static GSList *
1132{
1133 struct kb_redis *kbr;
1134 redisReply *rep;
1135 GSList *list = NULL;
1136 size_t i;
1137
1138 kbr = redis_kb (kb);
1139 rep = redis_cmd (kbr, "KEYS nvt:*");
1140 if (!rep)
1141 return NULL;
1142
1143 if (rep->type != REDIS_REPLY_ARRAY)
1144 {
1145 freeReplyObject (rep);
1146 return NULL;
1147 }
1148
1149 /* Fetch OID values from key names nvt:OID. */
1150 for (i = 0; i < rep->elements; i++)
1151 list = g_slist_prepend (list, g_strdup (rep->element[i]->str + 4));
1152 freeReplyObject (rep);
1153
1154 return list;
1155}
1156
1165static size_t
1166redis_count (kb_t kb, const char *pattern)
1167{
1168 struct kb_redis *kbr;
1169 redisReply *rep;
1170 size_t count;
1171
1172 kbr = redis_kb (kb);
1173
1174 rep = redis_cmd (kbr, "KEYS %s", pattern);
1175 if (rep == NULL)
1176 return 0;
1177
1178 if (rep->type != REDIS_REPLY_ARRAY)
1179 {
1180 freeReplyObject (rep);
1181 return 0;
1182 }
1183
1184 count = rep->elements;
1185 freeReplyObject (rep);
1186 return count;
1187}
1188
1197static int
1198redis_del_items (kb_t kb, const char *name)
1199{
1200 struct kb_redis *kbr;
1201 redisReply *rep;
1202 int rc = 0;
1203
1204 kbr = redis_kb (kb);
1205
1206 rep = redis_cmd (kbr, "DEL %s", name);
1207 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1208 rc = -1;
1209
1210 if (rep != NULL)
1211 freeReplyObject (rep);
1212
1213 return rc;
1214}
1215
1229static int
1230redis_add_str_unique_volatile (kb_t kb, const char *name, const char *str,
1231 int expire, size_t len, int pos)
1232{
1233 struct kb_redis *kbr;
1234 redisReply *rep = NULL;
1235 int rc = 0;
1236 redisContext *ctx;
1237
1238 kbr = redis_kb (kb);
1239 if (get_redis_ctx (kbr) < 0)
1240 return -1;
1241 ctx = kbr->rctx;
1242
1243 /* Some VTs still rely on values being unique (ie. a value inserted multiple
1244 * times, will only be present once.)
1245 * Once these are fixed, the LREM becomes redundant and should be removed.
1246 */
1247 if (len == 0)
1248 {
1249 redisAppendCommand (ctx, "LREM %s 1 %s", name, str);
1250 redisAppendCommand (ctx, "%s %s %s", pos ? "LPUSH" : "RPUSH", name, str);
1251 redisAppendCommand (ctx, "EXPIRE %s %d", name, expire);
1252 /* Check LREM reply. */
1253 redisGetReply (ctx, (void **) &rep);
1254 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1255 g_debug ("Key '%s' already contained value '%s'", name, str);
1256 freeReplyObject (rep);
1257 /* Check PUSH reply. */
1258 redisGetReply (ctx, (void **) &rep);
1259 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1260 {
1261 rc = -1;
1262 goto out;
1263 }
1264 /* Check EXPIRE reply. */
1265 redisGetReply (ctx, (void **) &rep);
1266 if (rep == NULL || rep->type == REDIS_REPLY_ERROR
1267 || (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer != 1))
1268 {
1269 g_warning ("%s: Not able to set expire", __func__);
1270 rc = -1;
1271 goto out;
1272 }
1273 }
1274 else
1275 {
1276 redisAppendCommand (ctx, "LREM %s 1 %b", name, str, len);
1277 redisAppendCommand (ctx, "%s %s %b", pos ? "LPUSH" : "RPUSH", name, str,
1278 len);
1279 redisAppendCommand (ctx, "EXPIRE %s %d", name, expire);
1280 /* Check LREM reply. */
1281 redisGetReply (ctx, (void **) &rep);
1282 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1283 g_debug ("Key '%s' already contained string '%s'", name, str);
1284 freeReplyObject (rep);
1285 /* Check PUSH reply. */
1286 redisGetReply (ctx, (void **) &rep);
1287 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1288 {
1289 rc = -1;
1290 goto out;
1291 }
1292 /* Check EXPIRE reply. */
1293 redisGetReply (ctx, (void **) &rep);
1294 if (rep == NULL || rep->type == REDIS_REPLY_ERROR
1295 || (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer != 1))
1296 {
1297 g_warning ("%s: Not able to set expire", __func__);
1298 rc = -1;
1299 goto out;
1300 }
1301 }
1302
1303out:
1304 if (rep != NULL)
1305 freeReplyObject (rep);
1306
1307 return rc;
1308}
1309
1322static int
1323redis_add_str_unique (kb_t kb, const char *name, const char *str, size_t len,
1324 int pos)
1325{
1326 struct kb_redis *kbr;
1327 redisReply *rep = NULL;
1328 int rc = 0;
1329 redisContext *ctx;
1330
1331 kbr = redis_kb (kb);
1332 if (get_redis_ctx (kbr) < 0)
1333 return -1;
1334 ctx = kbr->rctx;
1335
1336 /* Some VTs still rely on values being unique (ie. a value inserted multiple
1337 * times, will only be present once.)
1338 * Once these are fixed, the LREM becomes redundant and should be removed.
1339 */
1340 if (len == 0)
1341 {
1342 redisAppendCommand (ctx, "LREM %s 1 %s", name, str);
1343 redisAppendCommand (ctx, "%s %s %s", pos ? "LPUSH" : "RPUSH", name, str);
1344 redisGetReply (ctx, (void **) &rep);
1345 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1346 g_debug ("Key '%s' already contained value '%s'", name, str);
1347 freeReplyObject (rep);
1348 redisGetReply (ctx, (void **) &rep);
1349 }
1350 else
1351 {
1352 redisAppendCommand (ctx, "LREM %s 1 %b", name, str, len);
1353 redisAppendCommand (ctx, "%s %s %b", pos ? "LPUSH" : "RPUSH", name, str,
1354 len);
1355 redisGetReply (ctx, (void **) &rep);
1356 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1357 g_debug ("Key '%s' already contained string '%s'", name, str);
1358 freeReplyObject (rep);
1359 redisGetReply (ctx, (void **) &rep);
1360 }
1361 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1362 rc = -1;
1363
1364 if (rep != NULL)
1365 freeReplyObject (rep);
1366
1367 return rc;
1368}
1369
1380static int
1381redis_add_str (kb_t kb, const char *name, const char *str, size_t len)
1382{
1383 struct kb_redis *kbr;
1384 redisReply *rep;
1385 int rc = 0;
1386
1387 kbr = redis_kb (kb);
1388 if (len == 0)
1389 rep = redis_cmd (kbr, "RPUSH %s %s", name, str);
1390 else
1391 rep = redis_cmd (kbr, "RPUSH %s %b", name, str, len);
1392 if (!rep || rep->type == REDIS_REPLY_ERROR)
1393 rc = -1;
1394
1395 if (rep)
1396 freeReplyObject (rep);
1397 return rc;
1398}
1399
1410static int
1411redis_set_str (kb_t kb, const char *name, const char *val, size_t len)
1412{
1413 struct kb_redis *kbr;
1414 redisReply *rep = NULL;
1415 redisContext *ctx;
1416 int rc = 0, i = 4;
1417
1418 kbr = redis_kb (kb);
1419 if (get_redis_ctx (kbr) < 0)
1420 return -1;
1421 ctx = kbr->rctx;
1422 redisAppendCommand (ctx, "MULTI");
1423 redisAppendCommand (ctx, "DEL %s", name);
1424 if (len == 0)
1425 redisAppendCommand (ctx, "RPUSH %s %s", name, val);
1426 else
1427 redisAppendCommand (ctx, "RPUSH %s %b", name, val, len);
1428 redisAppendCommand (ctx, "EXEC");
1429 while (i--)
1430 {
1431 redisGetReply (ctx, (void **) &rep);
1432 if (!rep || rep->type == REDIS_REPLY_ERROR)
1433 rc = -1;
1434 if (rep)
1435 freeReplyObject (rep);
1436 }
1437
1438 return rc;
1439}
1440
1451static int
1452redis_add_int_unique_volatile (kb_t kb, const char *name, int val, int expire)
1453{
1454 struct kb_redis *kbr;
1455 redisReply *rep;
1456 int rc = 0;
1457 redisContext *ctx;
1458
1459 kbr = redis_kb (kb);
1460 if (get_redis_ctx (kbr) < 0)
1461 return -1;
1462 ctx = kbr->rctx;
1463 redisAppendCommand (ctx, "LREM %s 1 %d", name, val);
1464 redisAppendCommand (ctx, "RPUSH %s %d", name, val);
1465 redisAppendCommand (ctx, "EXPIRE %s %d", name, expire);
1466 /* Check LREM reply. */
1467 redisGetReply (ctx, (void **) &rep);
1468 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1469 g_debug ("Key '%s' already contained integer '%d'", name, val);
1470 freeReplyObject (rep);
1471 /* Check PUSH reply. */
1472 redisGetReply (ctx, (void **) &rep);
1473 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1474 {
1475 rc = -1;
1476 goto out;
1477 }
1478 /* Check EXPIRE reply. */
1479 redisGetReply (ctx, (void **) &rep);
1480 if (rep == NULL || rep->type == REDIS_REPLY_ERROR
1481 || (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer != 1))
1482 {
1483 g_warning ("%s: Not able to set expire", __func__);
1484 rc = -1;
1485 goto out;
1486 }
1487
1488out:
1489 if (rep != NULL)
1490 freeReplyObject (rep);
1491
1492 return rc;
1493}
1494
1504static int
1505redis_add_int_unique (kb_t kb, const char *name, int val)
1506{
1507 struct kb_redis *kbr;
1508 redisReply *rep;
1509 int rc = 0;
1510 redisContext *ctx;
1511
1512 kbr = redis_kb (kb);
1513 if (get_redis_ctx (kbr) < 0)
1514 return -1;
1515 ctx = kbr->rctx;
1516 redisAppendCommand (ctx, "LREM %s 1 %d", name, val);
1517 redisAppendCommand (ctx, "RPUSH %s %d", name, val);
1518 redisGetReply (ctx, (void **) &rep);
1519 if (rep && rep->type == REDIS_REPLY_INTEGER && rep->integer == 1)
1520 g_debug ("Key '%s' already contained integer '%d'", name, val);
1521 freeReplyObject (rep);
1522 redisGetReply (ctx, (void **) &rep);
1523 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1524 {
1525 rc = -1;
1526 goto out;
1527 }
1528
1529out:
1530 if (rep != NULL)
1531 freeReplyObject (rep);
1532
1533 return rc;
1534}
1535
1545static int
1546redis_add_int (kb_t kb, const char *name, int val)
1547{
1548 redisReply *rep;
1549 int rc = 0;
1550
1551 rep = redis_cmd (redis_kb (kb), "RPUSH %s %d", name, val);
1552 if (!rep || rep->type == REDIS_REPLY_ERROR)
1553 rc = -1;
1554 if (rep)
1555 freeReplyObject (rep);
1556
1557 return rc;
1558}
1559
1569static int
1570redis_set_int (kb_t kb, const char *name, int val)
1571{
1572 struct kb_redis *kbr;
1573 redisReply *rep = NULL;
1574 redisContext *ctx;
1575 int rc = 0, i = 4;
1576
1577 kbr = redis_kb (kb);
1578 if (get_redis_ctx (redis_kb (kb)) < 0)
1579 return -1;
1580 ctx = kbr->rctx;
1581 redisAppendCommand (ctx, "MULTI");
1582 redisAppendCommand (ctx, "DEL %s", name);
1583 redisAppendCommand (ctx, "RPUSH %s %d", name, val);
1584 redisAppendCommand (ctx, "EXEC");
1585 while (i--)
1586 {
1587 redisGetReply (ctx, (void **) &rep);
1588 if (!rep || rep->type == REDIS_REPLY_ERROR)
1589 rc = -1;
1590 if (rep)
1591 freeReplyObject (rep);
1592 }
1593
1594 return rc;
1595}
1596
1606static int
1607redis_add_nvt (kb_t kb, const nvti_t *nvt, const char *filename)
1608{
1609 struct kb_redis *kbr;
1610 redisReply *rep = NULL;
1611 int rc = 0;
1612 unsigned int i;
1613 gchar *cves, *bids, *xrefs;
1614
1615 if (!nvt || !filename)
1616 return -1;
1617
1618 cves = nvti_refs (nvt, "cve", "", 0);
1619 bids = nvti_refs (nvt, "bid", "", 0);
1620 xrefs = nvti_refs (nvt, NULL, "cve,bid", 1);
1621
1622 kbr = redis_kb (kb);
1623 rep = redis_cmd (
1624 kbr, "RPUSH nvt:%s %s %s %s %s %s %s %s %s %s %s %s %d %s %s",
1625 nvti_oid (nvt), filename,
1626 nvti_required_keys (nvt) ? nvti_required_keys (nvt) : "",
1627 nvti_mandatory_keys (nvt) ? nvti_mandatory_keys (nvt) : "",
1628 nvti_excluded_keys (nvt) ? nvti_excluded_keys (nvt) : "",
1630 nvti_required_ports (nvt) ? nvti_required_ports (nvt) : "",
1631 nvti_dependencies (nvt) ? nvti_dependencies (nvt) : "",
1632 nvti_tag (nvt) ? nvti_tag (nvt) : "", cves ? cves : "", bids ? bids : "",
1633 xrefs ? xrefs : "", nvti_category (nvt), nvti_family (nvt),
1634 nvti_name (nvt));
1635 g_free (cves);
1636 g_free (bids);
1637 g_free (xrefs);
1638 if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
1639 rc = -1;
1640 if (rep != NULL)
1641 freeReplyObject (rep);
1642
1643 if (nvti_pref_len (nvt))
1644 redis_cmd (kbr, "DEL oid:%s:prefs", nvti_oid (nvt));
1645 for (i = 0; i < nvti_pref_len (nvt); i++)
1646 {
1647 const nvtpref_t *pref = nvti_pref (nvt, i);
1648
1649 rep = redis_cmd (kbr, "RPUSH oid:%s:prefs %d|||%s|||%s|||%s",
1650 nvti_oid (nvt), nvtpref_id (pref), nvtpref_name (pref),
1651 nvtpref_type (pref), nvtpref_default (pref));
1652 if (!rep || rep->type == REDIS_REPLY_ERROR)
1653 rc = -1;
1654 if (rep)
1655 freeReplyObject (rep);
1656 }
1657 rep = redis_cmd (kbr, "RPUSH filename:%s %lu %s", filename, time (NULL),
1658 nvti_oid (nvt));
1659 if (!rep || rep->type == REDIS_REPLY_ERROR)
1660 rc = -1;
1661 if (rep)
1662 freeReplyObject (rep);
1663 return rc;
1664}
1665
1674static int
1676{
1677 struct kb_redis *kbr;
1678
1679 kbr = redis_kb (kb);
1680
1681 if (kbr->rctx != NULL)
1682 {
1683 redisFree (kbr->rctx);
1684 kbr->rctx = NULL;
1685 }
1686
1687 return 0;
1688}
1689
1698static int
1699redis_flush_all (kb_t kb, const char *except)
1700{
1701 unsigned int i = 1;
1702 struct kb_redis *kbr;
1703
1704 kbr = redis_kb (kb);
1705 if (kbr->rctx)
1706 redisFree (kbr->rctx);
1707
1708 g_debug ("%s: deleting all DBs at %s except %s", __func__, kbr->path, except);
1709 do
1710 {
1711 redisReply *rep;
1712
1713 kbr->rctx = connect_redis (kbr->path, strlen (kbr->path));
1714 if (kbr->rctx == NULL || kbr->rctx->err)
1715 {
1716 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1717 "%s: redis connection error to %s: %s", __func__, kbr->path,
1718 kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
1719 redisFree (kbr->rctx);
1720 kbr->rctx = NULL;
1721 return -1;
1722 }
1723
1724 kbr->db = i;
1725 rep = redisCommand (kbr->rctx, "HEXISTS %s %d", GLOBAL_DBINDEX_NAME, i);
1726 if (rep == NULL || rep->type != REDIS_REPLY_INTEGER || rep->integer != 1)
1727 {
1728 freeReplyObject (rep);
1729 redisFree (kbr->rctx);
1730 i++;
1731 continue;
1732 }
1733 freeReplyObject (rep);
1734 rep = redisCommand (kbr->rctx, "SELECT %u", i);
1735 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
1736 {
1737 freeReplyObject (rep);
1738 redisFree (kbr->rctx);
1739 kbr->rctx = NULL;
1740 }
1741 else
1742 {
1743 freeReplyObject (rep);
1744 /* Don't remove DB if it has "except" key. */
1745 if (except)
1746 {
1747 char *tmp = kb_item_get_str (kb, except);
1748 if (tmp)
1749 {
1750 g_free (tmp);
1751 i++;
1752 redisFree (kbr->rctx);
1753 continue;
1754 }
1755 }
1756 redis_delete_all (kbr);
1757 redis_release_db (kbr);
1758 redisFree (kbr->rctx);
1759 }
1760 i++;
1761 }
1762 while (i < kbr->max_db);
1763
1764 g_free (kbr->path);
1765 g_free (kb);
1766 return 0;
1767}
1768
1776static int
1778{
1779 int rc;
1780 redisReply *rep;
1781 struct kb_redis *kbr;
1782
1783 kbr = redis_kb (kb);
1784 g_debug ("%s: saving all elements from KB #%u", __func__, kbr->db);
1785 rep = redis_cmd (kbr, "SAVE");
1786 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
1787 {
1788 rc = -1;
1789 goto err_cleanup;
1790 }
1791
1792 rc = 0;
1793
1794err_cleanup:
1795 if (rep != NULL)
1796 freeReplyObject (rep);
1797
1798 return rc;
1799}
1800
1808int
1810{
1811 int rc;
1812 redisReply *rep;
1813 struct sigaction new_action, original_action;
1814
1815 /* Ignore SIGPIPE, in case of a lost connection. */
1816 new_action.sa_flags = 0;
1817 if (sigemptyset (&new_action.sa_mask))
1818 return -1;
1819 new_action.sa_handler = SIG_IGN;
1820 if (sigaction (SIGPIPE, &new_action, &original_action))
1821 return -1;
1822
1823 if (kbr)
1824 g_debug ("%s: deleting all elements from KB #%u", __func__, kbr->db);
1825 rep = redis_cmd (kbr, "FLUSHDB");
1826 if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
1827 {
1828 rc = -1;
1829 goto err_cleanup;
1830 }
1831
1832 rc = 0;
1833
1834err_cleanup:
1835 if (sigaction (SIGPIPE, &original_action, NULL))
1836 return -1;
1837 if (rep != NULL)
1838 freeReplyObject (rep);
1839
1840 return rc;
1841}
1842
1849static const struct kb_operations KBRedisOperations = {
1850 .kb_new = redis_new,
1851 .kb_find = redis_find,
1852 .kb_delete = redis_delete,
1853 .kb_get_single = redis_get_single,
1854 .kb_get_str = redis_get_str,
1855 .kb_get_int = redis_get_int,
1856 .kb_get_nvt = redis_get_nvt,
1857 .kb_get_nvt_all = redis_get_nvt_all,
1858 .kb_get_nvt_oids = redis_get_oids,
1859 .kb_push_str = redis_push_str,
1860 .kb_pop_str = redis_pop_str,
1861 .kb_get_all = redis_get_all,
1862 .kb_get_pattern = redis_get_pattern,
1863 .kb_count = redis_count,
1864 .kb_add_str = redis_add_str,
1865 .kb_add_str_unique = redis_add_str_unique,
1866 .kb_add_str_unique_volatile = redis_add_str_unique_volatile,
1867 .kb_set_str = redis_set_str,
1868 .kb_add_int = redis_add_int,
1869 .kb_add_int_unique = redis_add_int_unique,
1870 .kb_add_int_unique_volatile = redis_add_int_unique_volatile,
1871 .kb_set_int = redis_set_int,
1872 .kb_add_nvt = redis_add_nvt,
1873 .kb_del_items = redis_del_items,
1874 .kb_lnk_reset = redis_lnk_reset,
1875 .kb_save = redis_save,
1876 .kb_flush = redis_flush_all,
1877 .kb_direct_conn = redis_direct_conn,
1878 .kb_get_kb_index = redis_get_kb_index};
1879
#define G_LOG_DOMAIN
GLib log domain.
Definition array.c:17
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:1675
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:314
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:874
static int redis_memory_purge(kb_t kb)
Attempt to purge dirty pages.
Definition kb.c:444
static int redis_test_connection(struct kb_redis *kbr)
Test redis connection.
Definition kb.c:353
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:1411
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:1230
static char * redis_get_nvt(kb_t kb, const char *oid, enum kb_nvt_pos position)
Get field of a NVT.
Definition kb.c:956
static struct kb_item * redis2kbitem(const char *name, const redisReply *rep)
Fetch a KB item or list from a redis Reply.
Definition kb.c:711
static kb_t redis_find(const char *kb_path, const char *key)
Find an existing Knowledge Base object with key.
Definition kb.c:564
static int redis_delete(kb_t kb)
Delete all entries and release ownership on the namespace.
Definition kb.c:394
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:1381
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:1809
void kb_item_free(struct kb_item *item)
Release a KB item (or a list).
Definition kb.c:642
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:1452
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:1038
#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:1546
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:516
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:1323
static char * redis_get_str(kb_t kb, const char *name)
Get a single KB string item.
Definition kb.c:847
static struct kb_item * redis_get_pattern(kb_t kb, const char *pattern)
Get all items stored under a given pattern.
Definition kb.c:1067
static GSList * redis_get_oids(kb_t kb)
Get all NVT OIDs.
Definition kb.c:1131
static struct kb_item * redis2kbitem_single(const char *name, const redisReply *elt, int force_int)
Give a single KB item.
Definition kb.c:666
static int redis_save(kb_t kb)
Save all the elements from the KB.
Definition kb.c:1777
static int redis_get_int(kb_t kb, const char *name)
Get a single KB integer item.
Definition kb.c:930
static redisContext * connect_redis(const char *addr, int len)
Definition kb.c:264
static char * redis_pop_str(kb_t kb, const char *name)
Pops a single KB string item.
Definition kb.c:903
static int redis_new(kb_t *kb, const char *kb_path)
Initialize a new Knowledge Base object.
Definition kb.c:468
static int redis_get_kb_index(kb_t kb)
Return the kb index.
Definition kb.c:422
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:1505
#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:1880
static int redis_flush_all(kb_t, const char *)
Flush all the KB's content. Delete all namespaces.
Definition kb.c:1699
static size_t redis_count(kb_t kb, const char *pattern)
Count all items stored under a given pattern.
Definition kb.c:1166
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:812
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:1570
static int redis_add_nvt(kb_t kb, const nvti_t *nvt, const char *filename)
Insert a new nvt.
Definition kb.c:1607
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:764
static nvti_t * redis_get_nvt_all(kb_t kb, const char *oid)
Get a full NVT.
Definition kb.c:988
static int redis_del_items(kb_t kb, const char *name)
Delete all entries under a given name.
Definition kb.c:1198
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:559
gchar * nvti_dependencies(const nvti_t *n)
Get the dependencies list.
Definition nvti.c:1032
guint nvti_pref_len(const nvti_t *n)
Get the number of preferences of the NVT.
Definition nvti.c:1171
gchar * nvti_required_udp_ports(const nvti_t *n)
Get the required udp ports list.
Definition nvti.c:1102
gchar * nvti_required_ports(const nvti_t *n)
Get the required ports list.
Definition nvti.c:1088
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
gchar * nvtpref_type(const nvtpref_t *np)
Get the Type of a NVT Preference.
Definition nvti.c:532
int nvti_set_excluded_keys(nvti_t *n, const gchar *excluded_keys)
Set the excluded keys of a NVT.
Definition nvti.c:1744
struct nvti nvti_t
The structure of a information record that corresponds to a NVT.
int nvti_set_dependencies(nvti_t *n, const gchar *dependencies)
Set the dependencies of a NVT.
Definition nvti.c:1672
int nvti_set_required_ports(nvti_t *n, const gchar *required_ports)
Set the required ports of a NVT.
Definition nvti.c:1768
int nvti_set_oid(nvti_t *n, const gchar *oid)
Set the OID of a NVT Info.
Definition nvti.c:1214
int nvti_set_tag(nvti_t *n, const gchar *tag)
Set the tags of a NVT.
Definition nvti.c:1625
int nvti_set_mandatory_keys(nvti_t *n, const gchar *mandatory_keys)
Set the mandatory keys of a NVT.
Definition nvti.c:1720
gint nvti_category(const nvti_t *n)
Get the category for this NVT.
Definition nvti.c:1199
struct nvtpref nvtpref_t
The structure for a preference of a NVT.
gchar * nvti_family(const nvti_t *n)
Get the family name.
Definition nvti.c:1158
const nvtpref_t * nvti_pref(const nvti_t *n, guint p)
Get the n'th preferences of the NVT.
Definition nvti.c:1186
gchar * nvti_excluded_keys(const nvti_t *n)
Get the excluded keys list.
Definition nvti.c:1074
gchar * nvti_name(const nvti_t *n)
Get the name.
Definition nvti.c:625
gchar * nvti_oid(const nvti_t *n)
Get the OID string.
Definition nvti.c:611
int nvti_set_required_keys(nvti_t *n, const gchar *required_keys)
Set the required keys of a NVT.
Definition nvti.c:1696
int nvtpref_id(const nvtpref_t *np)
Get the ID of a NVT Preference.
Definition nvti.c:504
int nvti_set_name(nvti_t *n, const gchar *name)
Set the name of a NVT.
Definition nvti.c:1234
gchar * nvti_required_keys(const nvti_t *n)
Get the required keys list.
Definition nvti.c:1046
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
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
gchar * nvti_mandatory_keys(const nvti_t *n)
Get the mandatory keys list.
Definition nvti.c:1060
gchar * nvtpref_default(const nvtpref_t *np)
Get the Default of a NVT Preference.
Definition nvti.c:546
int nvti_set_family(nvti_t *n, const gchar *family)
Set the family of a NVT.
Definition nvti.c:1903
gchar * nvtpref_name(const nvtpref_t *np)
Get the Name of a NVT Preference.
Definition nvti.c:518
gchar * nvti_tag(const nvti_t *n)
Get the tags.
Definition nvti.c:966
int nvti_set_category(nvti_t *n, const gint category)
Set the category type of a NVT Info.
Definition nvti.c:1943
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
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:358