Greenbone Vulnerability Management Libraries: util/kb.c Source File

Greenbone Vulnerability Management Libraries 23.1.2

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