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