OpenVAS Scanner 23.40.0
table_driven_lsc.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Greenbone AG
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
10
11#include "table_driven_lsc.h"
12
13#include "base/networking.h"
14#include "kb_cache.h"
15#include "plugutils.h"
16
17#include <ctype.h> // for tolower()
18#include <curl/curl.h>
19#include <gnutls/gnutls.h>
20#include <gvm/base/prefs.h>
21#include <gvm/util/mqtt.h> // for mqtt_reset
22#include <gvm/util/uuidutils.h> // for gvm_uuid_make
23#include <json-glib/json-glib.h>
24#include <stddef.h>
25
26#undef G_LOG_DOMAIN
30#define G_LOG_DOMAIN "lib misc"
31
35static int lsc_flag = 0;
36
39void
41{
42 lsc_flag = 1;
43}
44
47int
49{
50 return lsc_flag;
51}
52
64static JsonBuilder *
65add_packages_str_to_list (JsonBuilder *builder, const gchar *packages)
66{
67 gchar **package_list = NULL;
68
69 json_builder_set_member_name (builder, "package_list");
70 json_builder_begin_array (builder);
71
72 package_list = g_strsplit (packages, "\n", 0);
73 if (package_list && package_list[0])
74 {
75 int i;
76 for (i = 0; package_list[i]; i++)
77 json_builder_add_string_value (builder, package_list[i]);
78 }
79
80 json_builder_end_array (builder);
81 g_strfreev (package_list);
82
83 return builder;
84}
85
101static gchar *
102make_table_driven_lsc_info_json_str (const char *scan_id, const char *ip_str,
103 const char *hostname,
104 const char *os_release,
105 const char *package_list)
106{
107 JsonBuilder *builder;
108 JsonGenerator *gen;
109 JsonNode *root;
110 gchar *json_str;
111
112 /* Build the message in json format to be published. */
113 builder = json_builder_new ();
114
115 json_builder_begin_object (builder);
116
117 json_builder_set_member_name (builder, "message_id");
118 builder = json_builder_add_string_value (builder, gvm_uuid_make ());
119
120 json_builder_set_member_name (builder, "group_id");
121 builder = json_builder_add_string_value (builder, gvm_uuid_make ());
122
123 json_builder_set_member_name (builder, "message_type");
124 builder = json_builder_add_string_value (builder, "scan.start");
125
126 json_builder_set_member_name (builder, "created");
127 builder = json_builder_add_int_value (builder, time (NULL));
128
129 json_builder_set_member_name (builder, "scan_id");
130 builder = json_builder_add_string_value (builder, scan_id);
131
132 json_builder_set_member_name (builder, "host_ip");
133 json_builder_add_string_value (builder, ip_str);
134
135 json_builder_set_member_name (builder, "host_name");
136 json_builder_add_string_value (builder, hostname);
137
138 json_builder_set_member_name (builder, "os_release");
139 json_builder_add_string_value (builder, os_release);
140
141 add_packages_str_to_list (builder, package_list);
142
143 json_builder_end_object (builder);
144
145 gen = json_generator_new ();
146 root = json_builder_get_root (builder);
147 json_generator_set_root (gen, root);
148 json_str = json_generator_to_data (gen, NULL);
149
150 json_node_free (root);
151 g_object_unref (gen);
152 g_object_unref (builder);
153
154 if (json_str == NULL)
155 g_warning ("%s: Error while creating JSON.", __func__);
156
157 return json_str;
158}
159
174static gchar *
176 const char *host_ip, const char *json,
177 int len)
178{
179 JsonParser *parser;
180 JsonReader *reader = NULL;
181
182 GError *err = NULL;
183 gchar *ret = NULL;
184
185 parser = json_parser_new ();
186 if (!json_parser_load_from_data (parser, json, len, &err))
187 {
188 goto cleanup;
189 }
190
191 reader = json_reader_new (json_parser_get_root (parser));
192
193 // Check for Scan ID
194 if (!json_reader_read_member (reader, "scan_id"))
195 {
196 goto cleanup;
197 }
198 if (g_strcmp0 (json_reader_get_string_value (reader), scan_id))
199 {
200 goto cleanup;
201 }
202 json_reader_end_member (reader);
203
204 // Check Host IP
205 if (!json_reader_read_member (reader, "host_ip"))
206 {
207 goto cleanup;
208 }
209 if (g_strcmp0 (json_reader_get_string_value (reader), host_ip))
210 {
211 goto cleanup;
212 }
213 json_reader_end_member (reader);
214
215 // Check Status
216 if (!json_reader_read_member (reader, "status"))
217 {
218 goto cleanup;
219 }
220 ret = g_strdup (json_reader_get_string_value (reader));
221
222 json_reader_end_member (reader);
223
224cleanup:
225 if (reader)
226 g_object_unref (reader);
227 g_object_unref (parser);
228 if (err != NULL)
229 {
230 g_warning ("%s: Unable to parse json. Reason: %s", __func__,
231 err->message);
232 }
233 return ret;
234}
235
236#define RSNOTUS
237#ifdef RSNOTUS
242{
243 char *server; // original openvasd server URL
244 char *schema; // schema is http or https
245 char *host; // server hostname
246 char *alpn; // Application layer protocol negotiation: http/1.0, http/1.1, h2
247 char *http_version; // same version as in application layer
248 int port; // server port
249 int tls; // 0: TLS encapsulation disable. Otherwise enable
250};
251
252typedef struct notus_info *notus_info_t;
253
260static notus_info_t
262{
263 notus_info_t notusdata;
264 notusdata = g_malloc0 (sizeof (struct notus_info));
265 if (!notusdata)
266 return NULL;
267 notusdata->server = g_strdup (server);
268 return notusdata;
269}
270
275static void
277{
278 if (notusdata)
279 {
280 g_free (notusdata->server);
281 g_free (notusdata->schema);
282 g_free (notusdata->host);
283 g_free (notusdata->alpn);
284 g_free (notusdata->http_version);
285 }
286}
287
294static char *
296{
297 for (char *p = s; *p; p++)
298 *p = tolower (*p);
299 return s;
300}
301
311static gchar *
312make_package_list_as_json_str (const char *packages)
313{
314 JsonBuilder *builder;
315 JsonGenerator *gen;
316 JsonNode *root;
317 gchar *json_str = NULL;
318 gchar **package_list = NULL;
319 builder = json_builder_new ();
320
321 json_builder_begin_array (builder);
322
323 package_list = g_strsplit (packages, "\n", 0);
324 if (package_list && package_list[0])
325 {
326 int i;
327 for (i = 0; package_list[i]; i++)
328 json_builder_add_string_value (builder, package_list[i]);
329 }
330
331 json_builder_end_array (builder);
332 g_strfreev (package_list);
333
334 gen = json_generator_new ();
335 root = json_builder_get_root (builder);
336 json_generator_set_root (gen, root);
337 json_str = json_generator_to_data (gen, NULL);
338
339 json_node_free (root);
340 g_object_unref (gen);
341 g_object_unref (builder);
342
343 if (json_str == NULL)
344 g_warning ("%s: Error while creating JSON.", __func__);
345
346 return json_str;
347}
348
358static int
360{
361 CURLU *h = curl_url ();
362 char *schema = NULL;
363 char *host = NULL;
364 char *port = NULL;
365
366 if (!notusdata)
367 return -1;
368
369 if (curl_url_set (h, CURLUPART_URL, (*notusdata)->server, 0) > 0)
370 {
371 g_warning ("%s: Error parsing URL %s", __func__, (*notusdata)->server);
372 return -1;
373 }
374
375 curl_url_get (h, CURLUPART_SCHEME, &schema, 0);
376 curl_url_get (h, CURLUPART_HOST, &host, 0);
377 curl_url_get (h, CURLUPART_PORT, &port, 0);
378
379 if (!schema || !host)
380 {
381 g_warning ("%s: Invalid URL %s. It must be in format: "
382 "schema://host:port. E.g. http://localhost:8080",
383 __func__, (*notusdata)->server);
384 curl_url_cleanup (h);
385 curl_free (schema);
386 curl_free (host);
387 curl_free (port);
388 return -1;
389 }
390
391 (*notusdata)->host = g_strdup (host);
392 if (port)
393 (*notusdata)->port = atoi (port);
394 else if (g_strcmp0 (schema, "https"))
395 (*notusdata)->port = 443;
396 else
397 (*notusdata)->port = 80;
398
399 (*notusdata)->schema = g_strdup (help_tolower (schema));
400 if (g_strrstr ((*notusdata)->schema, "https"))
401 {
402 (*notusdata)->tls = 1;
403 (*notusdata)->http_version = g_strdup ("2");
404 (*notusdata)->alpn = g_strdup ("h2");
405 }
406 else if (g_strrstr ((*notusdata)->schema, "http"))
407 {
408 (*notusdata)->tls = 0;
409 (*notusdata)->http_version = g_strdup ("1.1");
410 (*notusdata)->alpn = g_strdup ("http/1.1");
411 }
412 else
413 {
414 g_warning ("%s: Invalid openvasd server schema", (*notusdata)->server);
415 curl_url_cleanup (h);
416 curl_free (schema);
417 curl_free (host);
418 curl_free (port);
419 return -1;
420 }
421
422 curl_url_cleanup (h);
423 curl_free (schema);
424 curl_free (host);
425 curl_free (port);
426
427 return 0;
428}
429
435static advisories_t *
437{
438 advisories_t *advisories_list = g_malloc0 (sizeof (advisories_t));
439 advisories_list->max_size = 100;
440 advisories_list->advisories =
441 g_malloc0_n (advisories_list->max_size, sizeof (advisory_t));
442 advisories_list->type = NOTUS;
443
444 return advisories_list;
445}
446
452static advisories_t *
454{
455 advisories_t *advisories_list = g_malloc0 (sizeof (advisories_t));
456 advisories_list->max_size = 100;
457 advisories_list->skiron_advisories =
458 g_malloc0_n (advisories_list->max_size, sizeof (skiron_advisory_t));
459 advisories_list->type = SKIRON;
460
461 return advisories_list;
462}
463
471static void
473{
474 // Reallocate more memory if the list is full
475 if (advisories_list->count == advisories_list->max_size)
476 {
477 advisories_list->max_size *= 2;
478 advisories_list->advisories =
479 g_realloc_n (advisories_list->advisories, advisories_list->max_size,
480 sizeof (advisory_t));
481 memset (advisories_list->advisories + advisories_list->count, '\0',
482 (advisories_list->max_size - advisories_list->count)
483 * sizeof (advisory_t *));
484 }
485 advisories_list->advisories[advisories_list->count] = notus_advisory;
486 advisories_list->count++;
487}
488
495static advisory_t *
497{
498 advisory_t *adv = NULL;
499 adv = g_malloc0 (sizeof (advisory_t));
500 adv->oid = g_strdup (oid);
501 adv->count = 0;
502 return adv;
503}
504
505static skiron_advisory_t *
506skiron_advisory_new (char *oid, char *message)
507{
508 skiron_advisory_t *adv = NULL;
509 adv = g_malloc0 (sizeof (skiron_advisory_t));
510 adv->oid = g_strdup (oid);
511 adv->message = g_strdup (message);
512 return adv;
513}
514
523static void
525{
526 if (adv->count == 100)
527 {
528 g_warning (
529 "%s: Failed adding new vulnerable package to the notus_advisory %s. "
530 "No more free slots",
531 __func__, adv->oid);
532 return;
533 }
534
535 adv->pkgs[adv->count] = vuln;
536 adv->count++;
537}
538
544static void
546{
547 if (notus_advisory == NULL)
548 return;
549
550 g_free (notus_advisory->oid);
551 for (size_t i = 0; i < notus_advisory->count; i++)
552 {
553 if (notus_advisory->pkgs[i] != NULL)
554 {
555 g_free (notus_advisory->pkgs[i]->pkg_name);
556 g_free (notus_advisory->pkgs[i]->install_version);
557 if (notus_advisory->pkgs[i]->type == RANGE)
558 {
559 g_free (notus_advisory->pkgs[i]->range->start);
560 g_free (notus_advisory->pkgs[i]->range->stop);
561 }
562 else if (notus_advisory->pkgs[i]->type == SINGLE)
563 {
564 g_free (notus_advisory->pkgs[i]->version->version);
565 g_free (notus_advisory->pkgs[i]->version->specifier);
566 }
567 }
568 }
569 notus_advisory = NULL;
570}
571
572static void
574{
575 if (skiron_advisory == NULL)
576 return;
577
578 g_free (skiron_advisory->oid);
579 g_free (skiron_advisory->message);
580 skiron_advisory = NULL;
581}
582
588void
590{
591 if (advisories == NULL)
592 return;
593 for (size_t i = 0; i < advisories->count; i++)
594 {
595 if (advisories->type == NOTUS)
597 else
599 }
600 advisories = NULL;
601}
602
617static vuln_pkg_t *
618vulnerable_pkg_new (const char *pkg_name, const char *install_version,
619 enum fixed_type type, char *item1, char *item2)
620{
621 vuln_pkg_t *vuln = NULL;
622 version_range_t *range = NULL;
623 fixed_version_t *fixed_ver = NULL;
624
625 vuln = g_malloc0 (sizeof (vuln_pkg_t));
626 vuln->pkg_name = g_strdup (pkg_name);
627 vuln->install_version = g_strdup (install_version);
628 vuln->type = type;
629 if (type == RANGE)
630 {
631 range = g_malloc0 (sizeof (range_t));
632 range->start = g_strdup (item1);
633 range->stop = g_strdup (item2);
634 vuln->range = range;
635 }
636 else
637 {
638 fixed_ver = g_malloc0 (sizeof (fixed_version_t));
639 fixed_ver->version = g_strdup (item1);
640 fixed_ver->specifier = g_strdup (item2);
641 vuln->version = fixed_ver;
642 }
643
644 return vuln;
645}
646
647static advisories_t *
648lsc_process_response_notus (JsonReader *reader)
649{
652 char **members = json_reader_list_members (reader);
653
654 if (!members || !members[0])
655 {
656 return advisories;
657 }
658
659 for (int i = 0; members[i]; i++)
660 {
662
663 if (!json_reader_read_member (reader, members[i]))
664 {
665 g_debug ("No member oid");
666 return NULL;
667 }
668 if (!json_reader_is_array (reader))
669 {
670 g_debug ("Is not an array");
671 return NULL;
672 }
673
674 notus_advisory = advisory_new (g_strdup (members[i]));
675
676 int count_pkgs = json_reader_count_elements (reader);
677 g_debug ("There are %d packages for notus_advisory %s", count_pkgs,
678 members[i]);
679 for (int j = 0; j < count_pkgs; j++)
680 {
681 vuln_pkg_t *pkg = NULL;
682 char *name = NULL;
683 char *installed_version = NULL;
684 char *start = NULL;
685 char *stop = NULL;
686 char *version = NULL;
687 char *specifier = NULL;
688 enum fixed_type type = UNKNOWN;
689
690 json_reader_read_element (reader, j);
691 if (!json_reader_is_object (reader))
692 {
693 g_warning ("%s: Package %d of notus_advisory %s is not an object",
694 __func__, j, members[i]);
696 return NULL;
697 }
698
699 json_reader_read_member (reader, "name");
700 name = g_strdup (json_reader_get_string_value (reader));
701 json_reader_end_member (reader);
702 g_debug ("name: %s", name);
703
704 json_reader_read_member (reader, "installed_version");
705 installed_version = g_strdup (json_reader_get_string_value (reader));
706 json_reader_end_member (reader);
707 g_debug ("installed_version: %s", installed_version);
708
709 json_reader_read_member (reader, "fixed_version");
710 g_debug ("Fixed_version has %d members",
711 json_reader_count_members (reader));
712
713 // Version Range
714 json_reader_read_member (reader, "start");
715 start = g_strdup (json_reader_get_string_value (reader));
716 json_reader_end_member (reader);
717 json_reader_read_member (reader, "end");
718 stop = g_strdup (json_reader_get_string_value (reader));
719 json_reader_end_member (reader);
720 g_debug ("start %s, end: %s", start, stop);
721
722 // version and specifier
723 json_reader_read_member (reader, "version");
724 version = g_strdup (json_reader_get_string_value (reader));
725 json_reader_end_member (reader);
726 json_reader_read_member (reader, "specifier");
727 specifier = g_strdup (json_reader_get_string_value (reader));
728 json_reader_end_member (reader);
729 g_debug ("version %s, specifier: %s", version, specifier);
730
731 // end read fixes version member
732 json_reader_end_member (reader);
733
734 // end package element
735 json_reader_end_element (reader);
736
737 char *item1 = NULL, *item2 = NULL;
738 if (start && stop)
739 {
740 type = RANGE;
741 item1 = start;
742 item2 = stop;
743 }
744 else if (version && specifier)
745 {
746 type = SINGLE;
747 item1 = version;
748 item2 = specifier;
749 }
750 else
751 {
752 g_warning ("%s: Error parsing json element", __func__);
753 g_free (name);
754 g_free (installed_version);
755 g_free (item1);
756 g_free (item2);
759 return NULL;
760 }
761
762 pkg =
763 vulnerable_pkg_new (name, installed_version, type, item1, item2);
764 g_free (name);
765 g_free (installed_version);
766 g_free (item1);
767 g_free (item2);
768
770 }
771 // end notus_advisory
772 json_reader_end_member (reader);
774 }
775 return advisories;
776}
777
778static advisories_t *
779lsc_process_response_skiron (JsonReader *reader)
780{
782
783 for (int i = 0; json_reader_read_element (reader, i); i++)
784 {
786 char *oid = NULL;
787 char *message = NULL;
788
789 json_reader_read_member (reader, "oid");
790 oid = (char *) json_reader_get_string_value (reader);
791 json_reader_end_member (reader);
792
793 json_reader_read_member (reader, "message");
794 message = (char *) json_reader_get_string_value (reader);
795 json_reader_end_member (reader);
796
798
800
801 // end element
802 json_reader_end_element (reader);
803 }
804
805 return advisories;
806}
807
821lsc_process_response (const gchar *resp, const size_t len)
822{
823 JsonParser *parser = NULL;
824 JsonReader *reader = NULL;
825 GError *err = NULL;
826
827 advisories_t *advisories = NULL;
828
829 parser = json_parser_new ();
830 if (!json_parser_load_from_data (parser, resp, len, &err))
831 {
832 g_message ("Error parsing");
833 }
834
835 reader = json_reader_new (json_parser_get_root (parser));
836
837 if (json_reader_is_object (reader))
838 {
840 }
841 else if (json_reader_is_array (reader))
842 {
844 }
845 else
846 {
847 g_debug ("Unknown JSON response format");
848 }
849
850 if (reader)
851 g_object_unref (reader);
852 g_object_unref (parser);
853
854 return advisories;
855}
856
859struct string
860{
861 char *ptr;
862 size_t len;
863};
864
869static void
870init_string (struct string *s)
871{
872 s->len = 0;
873 s->ptr = g_malloc0 (s->len + 1);
874 if (s->ptr == NULL)
875 {
876 g_warning ("%s: Error allocating memory for response", __func__);
877 return;
878 }
879 s->ptr[0] = '\0';
880}
881
887static size_t
888response_callback_fn (void *ptr, size_t size, size_t nmemb, void *struct_string)
889{
890 struct string *s = struct_string;
891 size_t new_len = s->len + size * nmemb;
892 char *ptr_aux = g_realloc (s->ptr, new_len + 1);
893 s->ptr = ptr_aux;
894 if (s->ptr == NULL)
895 {
896 g_warning ("%s: Error allocating memory for response", __func__);
897 return 0; // no memory left
898 }
899 memcpy (s->ptr + s->len, ptr, size * nmemb);
900 s->ptr[new_len] = '\0';
901 s->len = new_len;
902
903 return size * nmemb;
904}
905
916static long
917send_request (notus_info_t notusdata, const char *os, const char *pkg_list,
918 char **response)
919{
920 CURL *curl;
921 GString *url = NULL;
922 long http_code = -1;
923 struct string resp;
924 struct curl_slist *customheader = NULL;
925 char *os_aux;
926 GString *xapikey = NULL;
927
928 if ((curl = curl_easy_init ()) == NULL)
929 {
930 g_warning ("Not possible to initialize curl library");
931 return http_code;
932 }
933
934 url = g_string_new (notusdata->server);
935 g_string_append (url, "/notus/");
936
937 //
938 os_aux = help_tolower (g_strdup (os));
939 for (size_t i = 0; i < strlen (os_aux); i++)
940 {
941 if (os_aux[i] == ' ')
942 os_aux[i] = '_';
943 }
944
945 g_string_append (url, os_aux);
946 g_free (os_aux);
947
948 g_debug ("%s: URL: %s", __func__, url->str);
949 // Set URL
950 if (curl_easy_setopt (curl, CURLOPT_URL, g_strdup (url->str)) != CURLE_OK)
951 {
952 g_warning ("Not possible to set the URL");
953 curl_easy_cleanup (curl);
954 return http_code;
955 }
956 g_string_free (url, TRUE);
957
958 // Accept an insecure connection. Don't verify the server certificate
959 curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0L);
960 curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0L);
961
962 // Set API KEY
963 if (prefs_get ("x-apikey"))
964 {
965 xapikey = g_string_new ("X-APIKEY: ");
966 g_string_append (xapikey, prefs_get ("x-apikey"));
967 customheader = curl_slist_append (customheader, g_strdup (xapikey->str));
968 g_string_free (xapikey, TRUE);
969 }
970 // SET Content type
971 customheader =
972 curl_slist_append (customheader, "Content-Type: application/json");
973 curl_easy_setopt (curl, CURLOPT_HTTPHEADER, customheader);
974 // Set body
975 curl_easy_setopt (curl, CURLOPT_POSTFIELDS, pkg_list);
976 curl_easy_setopt (curl, CURLOPT_POSTFIELDSIZE, strlen (pkg_list));
977
978 // Init the struct where the response is stored and set the callback function
979 init_string (&resp);
980 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, response_callback_fn);
981 curl_easy_setopt (curl, CURLOPT_WRITEDATA, &resp);
982
983 int ret = CURLE_OK;
984 if ((ret = curl_easy_perform (curl)) != CURLE_OK)
985 {
986 g_warning ("%s: Error sending request: %d", __func__, ret);
987 curl_easy_cleanup (curl);
988 g_free (resp.ptr);
989 return http_code;
990 }
991
992 curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
993
994 curl_easy_cleanup (curl);
995 g_debug ("Server response %s", resp.ptr);
996 *response = g_strdup (resp.ptr);
997 g_free (resp.ptr);
998 // already free()'ed with curl_easy_cleanup().
999
1000 return http_code;
1001}
1002
1011char *
1012lsc_get_response (const char *pkg_list, const char *os)
1013{
1014 const char *server = NULL;
1015 char *json_pkglist;
1016 char *response = NULL;
1017 notus_info_t notusdata;
1018 long ret;
1019
1020 // Parse the server and get the port, host, schema
1021 // and necessary information to build the message
1022 server = prefs_get ("openvasd_server");
1023 notusdata = init_notus_info (server);
1024
1025 if (parse_server (&notusdata) < 0)
1026 {
1027 free_notus_info (notusdata);
1028 return NULL;
1029 }
1030
1031 // Convert the package list string into a string containing json
1032 // array of packages
1033 if ((json_pkglist = make_package_list_as_json_str (pkg_list)) == NULL)
1034 {
1035 free_notus_info (notusdata);
1036 return NULL;
1037 }
1038
1039 ret = send_request (notusdata, os, json_pkglist, &response);
1040 if (ret != 200)
1041 g_warning ("%ld: Error sending request to openvasd: %s", ret, response);
1042
1043 free_notus_info (notusdata);
1044 g_free (json_pkglist);
1045
1046 return response;
1047}
1048
1059static int
1060call_rs_notus (const char *ip_str, const char *hostname, const char *pkg_list,
1061 const char *os)
1062{
1063 char *body = NULL;
1064 advisories_t *advisories = NULL;
1065 int res_count = 0;
1066 if ((body = lsc_get_response (pkg_list, os)) == NULL)
1067 return -1;
1068
1069 advisories = lsc_process_response (body, strlen (body));
1070 g_free (body);
1071
1072 if (!advisories)
1073 {
1074 g_message ("%s: Unable to process response", __func__);
1075 return -1;
1076 }
1077
1078 // Process the advisories, generate results and store them in the kb
1079 for (size_t i = 0; i < advisories->count; i++)
1080 {
1082 gchar *buffer;
1083 GString *result = g_string_new (NULL);
1084
1085 if (!notus_advisory)
1086 {
1087 g_message ("%s: Unable to process response. No notus advisories",
1088 __func__);
1089 g_string_free (result, TRUE);
1091 return -1;
1092 }
1093 for (size_t j = 0; j < notus_advisory->count; j++)
1094 {
1095 vuln_pkg_t *pkg = notus_advisory->pkgs[j];
1096 GString *res = g_string_new (NULL);
1097
1098 if (pkg->type == RANGE)
1099 {
1100 g_string_printf (res,
1101 "\n"
1102 "Vulnerable package: %s\n"
1103 "Installed version: %s-%s\n"
1104 "Fixed version: < %s-%s\n"
1105 "Fixed version: >=%s-%s\n",
1106 pkg->pkg_name, pkg->pkg_name,
1107 pkg->install_version, pkg->pkg_name,
1108 pkg->range->start, pkg->pkg_name,
1109 pkg->range->stop);
1110 }
1111 else if (pkg->type == SINGLE)
1112 {
1113 g_string_printf (res,
1114 "\n"
1115 "Vulnerable package: %s\n"
1116 "Installed version: %s-%s\n"
1117 "Fixed version: %2s%s-%s\n",
1118 pkg->pkg_name, pkg->pkg_name,
1119 pkg->install_version, pkg->version->specifier,
1120 pkg->pkg_name, pkg->version->version);
1121 }
1122 else
1123 {
1124 g_warning ("%s: Unknown fixed version type for notus_advisory %s",
1125 __func__, notus_advisory->oid);
1126 g_string_free (result, TRUE);
1128 return -1;
1129 }
1130 g_string_append (result, res->str);
1131 g_string_free (res, TRUE);
1132 }
1133
1134 // type|||IP|||HOSTNAME|||package|||OID|||the result message|||URI
1135 buffer = g_strdup_printf ("%s|||%s|||%s|||%s|||%s|||%s|||%s", "ALARM",
1136 ip_str, hostname ? hostname : " ", "package",
1137 notus_advisory->oid, result->str, "");
1138 g_string_free (result, TRUE);
1139 kb_item_push_str_with_main_kb_check (get_main_kb (), "internal/results",
1140 buffer);
1141 res_count++;
1142 g_free (buffer);
1143 }
1144
1146 return res_count;
1147}
1148
1149#endif // End RSNOTUS
1150
1166int
1167run_table_driven_lsc (const char *scan_id, const char *ip_str,
1168 const char *hostname, const char *package_list,
1169 const char *os_release)
1170{
1171 int err = 0;
1172 if (!os_release || !package_list)
1173 return 0;
1174
1175 if (prefs_get ("openvasd_server"))
1176 {
1177 g_message ("Running Notus for %s via openvasd", ip_str);
1178 err = call_rs_notus (ip_str, hostname, package_list, os_release);
1179
1180 return err;
1181 }
1182 else
1183 {
1184 gchar *json_str;
1185 gchar *topic;
1186 gchar *payload;
1187 gchar *status = NULL;
1188 int topic_len;
1189 int payload_len;
1190
1191 // Subscribe to status topic
1192 err = mqtt_subscribe ("scanner/status");
1193 if (err)
1194 {
1195 g_warning ("%s: Error starting lsc. Unable to subscribe", __func__);
1196 return -1;
1197 }
1198 /* Get the OS release. TODO: have a list with supported OS. */
1199
1201 os_release, package_list);
1202
1203 // Run table driven lsc
1204 if (json_str == NULL)
1205 return -1;
1206
1207 g_message ("Running Notus for %s", ip_str);
1208 err = mqtt_publish ("scanner/package/cmd/notus", json_str);
1209 if (err)
1210 {
1211 g_warning ("%s: Error publishing message for Notus.", __func__);
1212 g_free (json_str);
1213 return -1;
1214 }
1215
1216 g_free (json_str);
1217
1218 // Wait for Notus scanner to start or interrupt
1219 while (!status)
1220 {
1221 err = mqtt_retrieve_message (&topic, &topic_len, &payload,
1222 &payload_len, 60000);
1223 if (err == -1 || err == 1)
1224 {
1225 g_warning ("%s: Unable to retrieve status message from notus. %s",
1226 __func__, err == 1 ? "Timeout after 60 s." : "");
1227 return -1;
1228 }
1229
1230 // Get status if it belongs to corresponding scan and host
1231 // Else wait for next status message
1233 scan_id, ip_str, payload, payload_len);
1234
1235 g_free (topic);
1236 g_free (payload);
1237 }
1238 // If started wait for it to finish or interrupt
1239 if (!g_strcmp0 (status, "running"))
1240 {
1241 g_debug ("%s: table driven LSC with scan id %s successfully started "
1242 "for host %s",
1243 __func__, scan_id, ip_str);
1244 g_free (status);
1245 status = NULL;
1246 while (!status)
1247 {
1248 err = mqtt_retrieve_message (&topic, &topic_len, &payload,
1249 &payload_len, 60000);
1250 if (err == -1)
1251 {
1252 g_warning (
1253 "%s: Unable to retrieve status message from notus.",
1254 __func__);
1255 return -1;
1256 }
1257 if (err == 1)
1258 {
1259 g_warning (
1260 "%s: Unable to retrieve message. Timeout after 60s.",
1261 __func__);
1262 return -1;
1263 }
1264
1266 scan_id, ip_str, payload, payload_len);
1267 g_free (topic);
1268 g_free (payload);
1269 }
1270 }
1271 else
1272 {
1273 g_warning ("%s: Unable to start lsc. Got status: %s", __func__,
1274 status);
1275 g_free (status);
1276 return -1;
1277 }
1278
1279 if (g_strcmp0 (status, "finished"))
1280 {
1281 g_warning (
1282 "%s: table driven lsc with scan id %s did not finish successfully "
1283 "for host %s. Last status was %s",
1284 __func__, scan_id, ip_str, status);
1285 err = -1;
1286 }
1287 else
1288 g_debug ("%s: table driven lsc with scan id %s successfully finished "
1289 "for host %s",
1290 __func__, scan_id, ip_str);
1291 g_free (status);
1292 }
1293 return err;
1294}
kb_t get_main_kb(void)
gets the main_kb. @description returns the previously set main_kb; when asserts are enabled it will a...
Definition kb_cache.c:41
Header file to cache main_kb.
const char * oid
Definition nasl_builtin_find_service.c:51
u_char * payload
Definition nasl_frame_forgery.c:1
const char * name
Definition nasl_init.c:440
uint8_t len
Definition nasl_packet_forgery.c:1
const char * hostname
Definition pluginlaunch.c:68
int kb_item_push_str_with_main_kb_check(kb_t kb, const char *name, const char *value)
Check if the current kb corresponds to the original scanid, if it matches it kb_item_push_str....
Definition plugutils.c:533
Header file for module plugutils.
const char * scan_id
Definition scan_id.c:10
Definition table_driven_lsc.h:90
size_t max_size
Definition table_driven_lsc.h:98
advisory_type_t type
Definition table_driven_lsc.h:96
advisory_t ** advisories
Definition table_driven_lsc.h:93
size_t count
Definition table_driven_lsc.h:97
skiron_advisory_t ** skiron_advisories
Definition table_driven_lsc.h:94
char * specifier
Definition table_driven_lsc.h:39
char * version
Definition table_driven_lsc.h:38
Host information, implemented as doubly linked list.
Definition hosts.c:37
Definition table_driven_lsc.h:71
vuln_pkg_t * pkgs[100]
Definition table_driven_lsc.h:73
char * oid
Definition table_driven_lsc.h:72
size_t count
Definition table_driven_lsc.h:75
Struct to hold necessary information to call and run notus.
Definition table_driven_lsc.c:242
int tls
Definition table_driven_lsc.c:249
int port
Definition table_driven_lsc.c:248
char * host
Definition table_driven_lsc.c:245
char * alpn
Definition table_driven_lsc.c:246
char * schema
Definition table_driven_lsc.c:244
char * server
Definition table_driven_lsc.c:243
char * http_version
Definition table_driven_lsc.c:247
Definition table_driven_lsc.h:80
char * oid
Definition table_driven_lsc.h:81
char * message
Definition table_driven_lsc.h:82
Define a string struct for storing the response.
Definition table_driven_lsc.c:860
size_t len
Definition table_driven_lsc.c:862
char * ptr
Definition table_driven_lsc.c:861
char * stop
Definition table_driven_lsc.h:48
char * start
Definition table_driven_lsc.h:47
fixed_version_t * version
Definition table_driven_lsc.h:62
enum fixed_type type
Definition table_driven_lsc.h:58
version_range_t * range
Definition table_driven_lsc.h:61
char * pkg_name
Definition table_driven_lsc.h:56
char * install_version
Definition table_driven_lsc.h:57
static gchar * make_table_driven_lsc_info_json_str(const char *scan_id, const char *ip_str, const char *hostname, const char *os_release, const char *package_list)
Build a json object with data necessary to start a table drive LSC.
Definition table_driven_lsc.c:102
static void advisory_free(advisory_t *notus_advisory)
Free()'s an notus_advisory.
Definition table_driven_lsc.c:545
static JsonBuilder * add_packages_str_to_list(JsonBuilder *builder, const gchar *packages)
Split the package list string and creates a json array.
Definition table_driven_lsc.c:65
static advisory_t * advisory_new(char *oid)
Initialize a new notus_advisory.
Definition table_driven_lsc.c:496
static notus_info_t init_notus_info(const char *server)
Initialize a notus info struct and stores the server URL.
Definition table_driven_lsc.c:261
static void free_notus_info(notus_info_t notusdata)
Free notus info structure.
Definition table_driven_lsc.c:276
int run_table_driven_lsc(const char *scan_id, const char *ip_str, const char *hostname, const char *package_list, const char *os_release)
Publish the necessary data to start a Table driven LSC scan.
Definition table_driven_lsc.c:1167
static long send_request(notus_info_t notusdata, const char *os, const char *pkg_list, char **response)
Send a request to the server.
Definition table_driven_lsc.c:917
char * lsc_get_response(const char *pkg_list, const char *os)
Sent the installed package list and OS to notus.
Definition table_driven_lsc.c:1012
static int parse_server(notus_info_t *notusdata)
Parse the server URL.
Definition table_driven_lsc.c:359
static advisories_t * advisories_new_notus()
Initialize a new advisories struct with 100 slots.
Definition table_driven_lsc.c:436
static void advisories_add(advisories_t *advisories_list, advisory_t *notus_advisory)
Initialize a new advisories struct with 100 slots.
Definition table_driven_lsc.c:472
static advisories_t * advisories_new_skiron()
Initialize a new advisories struct with 100 slots.
Definition table_driven_lsc.c:453
static gchar * make_package_list_as_json_str(const char *packages)
Build a json array from the package list to start a table drive LSC.
Definition table_driven_lsc.c:312
int lsc_has_run(void)
Get lsc_flag value.
Definition table_driven_lsc.c:48
static gchar * get_status_of_table_driven_lsc_from_json(const char *scan_id, const char *host_ip, const char *json, int len)
Get the status of table driven lsc from json object.
Definition table_driven_lsc.c:175
static size_t response_callback_fn(void *ptr, size_t size, size_t nmemb, void *struct_string)
Call back function to stored the response.
Definition table_driven_lsc.c:888
static vuln_pkg_t * vulnerable_pkg_new(const char *pkg_name, const char *install_version, enum fixed_type type, char *item1, char *item2)
Creates a new Vulnerable packages which belongs to an notus_advisory.
Definition table_driven_lsc.c:618
static int call_rs_notus(const char *ip_str, const char *hostname, const char *pkg_list, const char *os)
Call notus and stores the results.
Definition table_driven_lsc.c:1060
static advisories_t * lsc_process_response_skiron(JsonReader *reader)
Definition table_driven_lsc.c:779
static char * help_tolower(char *s)
helper function to lower case
Definition table_driven_lsc.c:295
struct notus_info * notus_info_t
Definition table_driven_lsc.c:252
static void skiron_advisory_free(skiron_advisory_t *skiron_advisory)
Definition table_driven_lsc.c:573
void set_lsc_flag(void)
Set lsc_flag to 1.
Definition table_driven_lsc.c:40
static skiron_advisory_t * skiron_advisory_new(char *oid, char *message)
Definition table_driven_lsc.c:506
void advisories_free(advisories_t *advisories)
Free()'s an advisories.
Definition table_driven_lsc.c:589
static int lsc_flag
LSC ran or didn't 0 didn't run. 1 ran.
Definition table_driven_lsc.c:35
static void init_string(struct string *s)
Initialize the string struct to hold the response.
Definition table_driven_lsc.c:870
static void advisory_add_vuln_pkg(advisory_t *adv, vuln_pkg_t *vuln)
Add a new vulnerability to the notus_advisory.
Definition table_driven_lsc.c:524
advisories_t * lsc_process_response(const gchar *resp, const size_t len)
Process a json object which contains advisories and vulnerable packages.
Definition table_driven_lsc.c:821
static advisories_t * lsc_process_response_notus(JsonReader *reader)
Definition table_driven_lsc.c:648
struct advisories advisories_t
Definition table_driven_lsc.h:100
fixed_type
Fixed version format.
Definition table_driven_lsc.h:20
@ SINGLE
Definition table_driven_lsc.h:23
@ RANGE
Definition table_driven_lsc.h:22
@ UNKNOWN
Definition table_driven_lsc.h:21
struct notus_advisory advisory_t
Definition table_driven_lsc.h:77
struct fixed_version fixed_version_t
Definition table_driven_lsc.h:41
struct skiron_advisory skiron_advisory_t
Definition table_driven_lsc.h:85
struct vulnerable_pkg vuln_pkg_t
Definition table_driven_lsc.h:66
struct version_range version_range_t
Definition table_driven_lsc.h:50
@ NOTUS
Definition table_driven_lsc.h:28
@ SKIRON
Definition table_driven_lsc.h:29