OpenVAS Scanner 23.32.3
table_driven_lsc.c File Reference
#include "table_driven_lsc.h"
#include "base/networking.h"
#include "kb_cache.h"
#include "plugutils.h"
#include <ctype.h>
#include <curl/curl.h>
#include <gnutls/gnutls.h>
#include <gvm/base/prefs.h>
#include <gvm/util/mqtt.h>
#include <gvm/util/uuidutils.h>
#include <json-glib/json-glib.h>
#include <stddef.h>
Include dependency graph for table_driven_lsc.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  notus_info
 Struct to hold necessary information to call and run notus. More...
struct  string
 Define a string struct for storing the response. More...

Macros

#define G_LOG_DOMAIN   "lib misc"
 GLib logging domain.
#define RSNOTUS

Typedefs

typedef struct notus_infonotus_info_t

Functions

void set_lsc_flag (void)
 Set lsc_flag to 1.
int lsc_has_run (void)
 Get lsc_flag value.
static JsonBuilder * add_packages_str_to_list (JsonBuilder *builder, const gchar *packages)
 Split the package list string and creates a json array.
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.
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.
static notus_info_t init_notus_info (const char *server)
 Initialize a notus info struct and stores the server URL.
static void free_notus_info (notus_info_t notusdata)
 Free notus info structure.
static char * help_tolower (char *s)
 helper function to lower case
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.
static int parse_server (notus_info_t *notusdata)
 Parse the server URL.
static advisories_tadvisories_new ()
 Initialize a new advisories struct with 100 slots.
static void advisories_add (advisories_t *advisories_list, advisory_t *advisory)
 Initialize a new advisories struct with 100 slots.
static advisory_tadvisory_new (char *oid)
 Initialize a new advisory.
static void advisory_add_vuln_pkg (advisory_t *adv, vuln_pkg_t *vuln)
 Add a new vulnerability to the advisory.
static void advisory_free (advisory_t *advisory)
 Free()'s an advisory.
void advisories_free (advisories_t *advisories)
 Free()'s an advisories.
static vuln_pkg_tvulnerable_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 advisory.
advisories_tprocess_notus_response (const gchar *resp, const size_t len)
 Process a json object which contains advisories and vulnerable packages.
static void init_string (struct string *s)
 Initialize the string struct to hold the response.
static size_t response_callback_fn (void *ptr, size_t size, size_t nmemb, void *struct_string)
 Call back function to stored the response.
static long send_request (notus_info_t notusdata, const char *os, const char *pkg_list, char **response)
 Send a request to the server.
char * notus_get_response (const char *pkg_list, const char *os)
 Sent the installed package list and OS to notus.
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.
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.

Variables

static int lsc_flag = 0
 LSC ran or didn't 0 didn't run. 1 ran.

Macro Definition Documentation

◆ G_LOG_DOMAIN

#define G_LOG_DOMAIN   "lib misc"

GLib logging domain.

Definition at line 30 of file table_driven_lsc.c.

◆ RSNOTUS

#define RSNOTUS

Definition at line 236 of file table_driven_lsc.c.

Typedef Documentation

◆ notus_info_t

typedef struct notus_info* notus_info_t

Definition at line 252 of file table_driven_lsc.c.

Function Documentation

◆ add_packages_str_to_list()

JsonBuilder * add_packages_str_to_list ( JsonBuilder * builder,
const gchar * packages )
static

Split the package list string and creates a json array.

JSON result consists of scan_id, message type, host ip, hostname, port together with proto, OID, result message and uri.

Parameters
[in/out]builder The Json builder to add the array to.
[in]packagesThe installed package list as string
Returns
JSON builder including the package list as array.

Definition at line 65 of file table_driven_lsc.c.

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}

Referenced by make_table_driven_lsc_info_json_str().

Here is the caller graph for this function:

◆ advisories_add()

void advisories_add ( advisories_t * advisories_list,
advisory_t * advisory )
static

Initialize a new advisories struct with 100 slots.

Parameters
advisories_list[in/out]An advisories holder to add new advisories into.
advisory[in]the new advisory to add in the list

Definition at line 454 of file table_driven_lsc.c.

455{
456 // Reallocate more memory if the list is full
457 if (advisories_list->count == advisories_list->max_size)
458 {
459 advisories_list->max_size *= 2;
460 advisories_list->advisories =
461 g_realloc_n (advisories_list->advisories, advisories_list->max_size,
462 sizeof (advisory_t));
463 memset (advisories_list->advisories + advisories_list->count, '\0',
464 (advisories_list->max_size - advisories_list->count)
465 * sizeof (advisory_t *));
466 }
467 advisories_list->advisories[advisories_list->count] = advisory;
468 advisories_list->count++;
469}
advisory_t ** advisories
struct advisory advisory_t

References advisories::advisories, advisories::count, and advisories::max_size.

Referenced by process_notus_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ advisories_free()

void advisories_free ( advisories_t * advisories)

Free()'s an advisories.

Parameters
advisoryThe advisories holder to be free()'ed. It free()'s all advisories members.

Definition at line 549 of file table_driven_lsc.c.

550{
551 if (advisories == NULL)
552 return;
553
554 for (size_t i = 0; i < advisories->count; i++)
556 advisories = NULL;
557}
static void advisory_free(advisory_t *advisory)
Free()'s an advisory.

References advisories::advisories, advisory_free(), and advisories::count.

Referenced by call_rs_notus(), Ensure(), nasl_notus(), and process_notus_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ advisories_new()

advisories_t * advisories_new ( )
static

Initialize a new advisories struct with 100 slots.

Returns
initialized advisories_t struct. It must be free by the caller with advisories_free()

Definition at line 436 of file table_driven_lsc.c.

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
443 return advisories_list;
444}
struct advisories advisories_t

References advisories::advisories, and advisories::max_size.

Referenced by process_notus_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ advisory_add_vuln_pkg()

void advisory_add_vuln_pkg ( advisory_t * adv,
vuln_pkg_t * vuln )
static

Add a new vulnerability to the advisory.

@description Each advisory can have multiple vulnerable packages This structure can hold up to 100 packages.

Parameters
adv[in/out]The advisory to add the vulnerable package into
vuln[in]The vulnerable package to add.

Definition at line 496 of file table_driven_lsc.c.

497{
498 if (adv->count == 100)
499 {
500 g_warning ("%s: Failed adding new vulnerable package to the advisory %s. "
501 "No more free slots",
502 __func__, adv->oid);
503 return;
504 }
505
506 adv->pkgs[adv->count] = vuln;
507 adv->count++;
508}
vuln_pkg_t * pkgs[100]

References advisory::count, advisory::oid, and advisory::pkgs.

Referenced by process_notus_response().

Here is the caller graph for this function:

◆ advisory_free()

void advisory_free ( advisory_t * advisory)
static

Free()'s an advisory.

Parameters
advisoryThe advisory to be free()'ed. It free()'s all vulnerable packages that belong to this advisory.

Definition at line 516 of file table_driven_lsc.c.

517{
518 if (advisory == NULL)
519 return;
520
521 g_free (advisory->oid);
522 for (size_t i = 0; i < advisory->count; i++)
523 {
524 if (advisory->pkgs[i] != NULL)
525 {
526 g_free (advisory->pkgs[i]->pkg_name);
527 g_free (advisory->pkgs[i]->install_version);
528 if (advisory->pkgs[i]->type == RANGE)
529 {
530 g_free (advisory->pkgs[i]->range->start);
531 g_free (advisory->pkgs[i]->range->stop);
532 }
533 else if (advisory->pkgs[i]->type == SINGLE)
534 {
535 g_free (advisory->pkgs[i]->version->version);
536 g_free (advisory->pkgs[i]->version->specifier);
537 }
538 }
539 }
540 advisory = NULL;
541}
fixed_version_t * version
enum fixed_type type
version_range_t * range
@ SINGLE
@ RANGE

References advisory::count, vulnerable_pkg::install_version, advisory::oid, vulnerable_pkg::pkg_name, advisory::pkgs, RANGE, vulnerable_pkg::range, SINGLE, fixed_version::specifier, version_range::start, version_range::stop, vulnerable_pkg::type, fixed_version::version, and vulnerable_pkg::version.

Referenced by advisories_free().

Here is the caller graph for this function:

◆ advisory_new()

advisory_t * advisory_new ( char * oid)
static

Initialize a new advisory.

Parameters
oidThe advisory's OID
Returns
initialized advisory_t struct

Definition at line 478 of file table_driven_lsc.c.

479{
480 advisory_t *adv = NULL;
481 adv = g_malloc0 (sizeof (advisory_t));
482 adv->oid = g_strdup (oid);
483 adv->count = 0;
484 return adv;
485}
const char * oid

References advisory::count, advisory::oid, and oid.

Referenced by process_notus_response().

Here is the caller graph for this function:

◆ call_rs_notus()

int call_rs_notus ( const char * ip_str,
const char * hostname,
const char * pkg_list,
const char * os )
static

Call notus and stores the results.

Parameters
ip_strTarget's IP address.
hostnameTarget's hostname.
pkg_listList of packages installed in the target. The packages are "\n" separated.
osName of the target's operating system.
Returns
Count of stored results. -1 on error.

Definition at line 966 of file table_driven_lsc.c.

968{
969 char *body = NULL;
970 advisories_t *advisories = NULL;
971 int res_count = 0;
972 if ((body = notus_get_response (pkg_list, os)) == NULL)
973 return -1;
974
975 advisories = process_notus_response (body, strlen (body));
976
977 // Process the advisories, generate results and store them in the kb
978 for (size_t i = 0; i < advisories->count; i++)
979 {
981 gchar *buffer;
982 GString *result = g_string_new (NULL);
983 for (size_t j = 0; j < advisory->count; j++)
984 {
985 vuln_pkg_t *pkg = advisory->pkgs[j];
986 GString *res = g_string_new (NULL);
987
988 if (pkg->type == RANGE)
989 {
990 g_string_printf (res,
991 "\n"
992 "Vulnerable package: %s\n"
993 "Installed version: %s-%s\n"
994 "Fixed version: < %s-%s\n"
995 "Fixed version: >=%s-%s\n",
996 pkg->pkg_name, pkg->pkg_name,
997 pkg->install_version, pkg->pkg_name,
998 pkg->range->start, pkg->pkg_name,
999 pkg->range->stop);
1000 }
1001 else if (pkg->type == SINGLE)
1002 {
1003 g_string_printf (res,
1004 "\n"
1005 "Vulnerable package: %s\n"
1006 "Installed version: %s-%s\n"
1007 "Fixed version: %2s%s-%s\n",
1008 pkg->pkg_name, pkg->pkg_name,
1009 pkg->install_version, pkg->version->specifier,
1010 pkg->pkg_name, pkg->version->version);
1011 }
1012 else
1013 {
1014 g_warning ("%s: Unknown fixed version type for advisory %s",
1015 __func__, advisory->oid);
1016 g_string_free (result, TRUE);
1018 return -1;
1019 }
1020 g_string_append (result, res->str);
1021 g_string_free (res, TRUE);
1022 }
1023
1024 // type|||IP|||HOSTNAME|||package|||OID|||the result message|||URI
1025 buffer = g_strdup_printf ("%s|||%s|||%s|||%s|||%s|||%s|||%s", "ALARM",
1026 ip_str, hostname ? hostname : " ", "package",
1027 advisory->oid, result->str, "");
1028 g_string_free (result, TRUE);
1029 kb_item_push_str_with_main_kb_check (get_main_kb (), "internal/results",
1030 buffer);
1031 res_count++;
1032 g_free (buffer);
1033 }
1034
1036 return res_count;
1037}
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
const char * hostname
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
char * notus_get_response(const char *pkg_list, const char *os)
Sent the installed package list and OS to notus.
advisories_t * process_notus_response(const gchar *resp, const size_t len)
Process a json object which contains advisories and vulnerable packages.
void advisories_free(advisories_t *advisories)
Free()'s an advisories.
struct vulnerable_pkg vuln_pkg_t

References advisories::advisories, advisories_free(), advisories::count, advisory::count, get_main_kb(), hostname, vulnerable_pkg::install_version, kb_item_push_str_with_main_kb_check(), notus_get_response(), advisory::oid, vulnerable_pkg::pkg_name, advisory::pkgs, process_notus_response(), RANGE, vulnerable_pkg::range, SINGLE, fixed_version::specifier, version_range::start, version_range::stop, vulnerable_pkg::type, fixed_version::version, and vulnerable_pkg::version.

Referenced by run_table_driven_lsc().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_notus_info()

void free_notus_info ( notus_info_t notusdata)
static

Free notus info structure.

Parameters
notusdataThe data to free()

Definition at line 276 of file table_driven_lsc.c.

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}

References notus_info::alpn, notus_info::host, notus_info::http_version, notus_info::schema, and notus_info::server.

Referenced by notus_get_response().

Here is the caller graph for this function:

◆ get_status_of_table_driven_lsc_from_json()

gchar * get_status_of_table_driven_lsc_from_json ( const char * scan_id,
const char * host_ip,
const char * json,
int len )
static

Get the status of table driven lsc from json object.

Checks for the corresponding status inside the JSON. If the status does not belong the the scan or host, NULL is returned instead. NULL is also returned if message JSON cannot be parsed correctly. Return value has to be freed by caller.

Parameters
scan_idid of scan
host_ipip of host
jsonjson to get information from
lenlength of json
Returns
gchar* Status of table driven lsc or NULL

Definition at line 175 of file table_driven_lsc.c.

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}
uint8_t len
const char * scan_id
Definition scan_id.c:10

References len, and scan_id.

Referenced by run_table_driven_lsc().

Here is the caller graph for this function:

◆ help_tolower()

char * help_tolower ( char * s)
static

helper function to lower case

Parameters
sthe string to lower case
Returns
pointer to the modified string.

Definition at line 295 of file table_driven_lsc.c.

296{
297 for (char *p = s; *p; p++)
298 *p = tolower (*p);
299 return s;
300}

Referenced by parse_server(), and send_request().

Here is the caller graph for this function:

◆ init_notus_info()

notus_info_t init_notus_info ( const char * server)
static

Initialize a notus info struct and stores the server URL.

Parameters
serverOriginal server to store and to get the info from
Returns
the initialized struct. NULL on error.

Definition at line 261 of file table_driven_lsc.c.

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}
Struct to hold necessary information to call and run notus.
struct notus_info * notus_info_t

References notus_info::server.

Referenced by notus_get_response().

Here is the caller graph for this function:

◆ init_string()

void init_string ( struct string * s)
static

Initialize the string struct to hold the response.

Parameters
s[in/out]The string struct to be initialized

Definition at line 776 of file table_driven_lsc.c.

777{
778 s->len = 0;
779 s->ptr = g_malloc0 (s->len + 1);
780 if (s->ptr == NULL)
781 {
782 g_warning ("%s: Error allocating memory for response", __func__);
783 return;
784 }
785 s->ptr[0] = '\0';
786}

References string::len, and string::ptr.

Referenced by send_request().

Here is the caller graph for this function:

◆ lsc_has_run()

int lsc_has_run ( void )

Get lsc_flag value.

Definition at line 48 of file table_driven_lsc.c.

49{
50 return lsc_flag;
51}
static int lsc_flag
LSC ran or didn't 0 didn't run. 1 ran.

References lsc_flag.

Referenced by attack_host().

Here is the caller graph for this function:

◆ make_package_list_as_json_str()

gchar * make_package_list_as_json_str ( const char * packages)
static

Build a json array from the package list to start a table drive LSC.

Parameters
packagesThe installed package list in the target system to be evaluated
Returns
String in json format on success. Must be freed by caller. NULL on error.

Definition at line 312 of file table_driven_lsc.c.

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}

Referenced by Ensure(), and notus_get_response().

Here is the caller graph for this function:

◆ make_table_driven_lsc_info_json_str()

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 )
static

Build a json object with data necessary to start a table drive LSC.

JSON result consists of scan_id, message type, host ip, hostname, port together with proto, OID, result message and uri.

Parameters
scan_idScan Id.
ip_strIP string of host.
hostnameName of host.
os_releaseOS release
package_listThe installed package list in the target system to be evaluated
Returns
JSON string on success. Must be freed by caller. NULL on error.

Definition at line 102 of file table_driven_lsc.c.

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}
static JsonBuilder * add_packages_str_to_list(JsonBuilder *builder, const gchar *packages)
Split the package list string and creates a json array.

References add_packages_str_to_list(), hostname, and scan_id.

Referenced by run_table_driven_lsc().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ notus_get_response()

char * notus_get_response ( const char * pkg_list,
const char * os )

Sent the installed package list and OS to notus.

Parameters
pkg_listInstalled package list
osThe target's OS
Returns
String containing the server response or NULL Must be free()'ed by the caller.

Definition at line 918 of file table_driven_lsc.c.

919{
920 const char *server = NULL;
921 char *json_pkglist;
922 char *response = NULL;
923 notus_info_t notusdata;
924 long ret;
925
926 // Parse the server and get the port, host, schema
927 // and necessary information to build the message
928 server = prefs_get ("openvasd_server");
929 notusdata = init_notus_info (server);
930
931 if (parse_server (&notusdata) < 0)
932 {
933 free_notus_info (notusdata);
934 return NULL;
935 }
936
937 // Convert the package list string into a string containing json
938 // array of packages
939 if ((json_pkglist = make_package_list_as_json_str (pkg_list)) == NULL)
940 {
941 free_notus_info (notusdata);
942 return NULL;
943 }
944
945 ret = send_request (notusdata, os, json_pkglist, &response);
946 if (ret != 200)
947 g_warning ("%ld: Error sending request to openvasd: %s", ret, response);
948
949 free_notus_info (notusdata);
950 g_free (json_pkglist);
951
952 return response;
953}
static notus_info_t init_notus_info(const char *server)
Initialize a notus info struct and stores the server URL.
static void free_notus_info(notus_info_t notusdata)
Free notus info structure.
static long send_request(notus_info_t notusdata, const char *os, const char *pkg_list, char **response)
Send a request to the server.
static int parse_server(notus_info_t *notusdata)
Parse the server URL.
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.

References free_notus_info(), init_notus_info(), make_package_list_as_json_str(), parse_server(), and send_request().

Referenced by call_rs_notus(), and nasl_notus().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_server()

int parse_server ( notus_info_t * notusdata)
static

Parse the server URL.

Parameters
[in]serverString containing the server URL Valid is http://example.com:1234 or https://example.com.1234. @notusdata[out] Structure to store information from the URL
Returns
0 on success, -1 on error.

Definition at line 359 of file table_driven_lsc.c.

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}
Host information, implemented as doubly linked list.
Definition hosts.c:37
static char * help_tolower(char *s)
helper function to lower case

References help_tolower(), notus_info::port, and notus_info::schema.

Referenced by notus_get_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_notus_response()

advisories_t * process_notus_response ( const gchar * resp,
const size_t len )

Process a json object which contains advisories and vulnerable packages.

@description This is the body string in response get from an openvasd server

Parameters
respString containing the json object to be processed.
lenString length.
Returns
a advisories_t struct containing all advisories and vulnerable packages. After usage must be free()'ed with advisories_free().

Definition at line 616 of file table_driven_lsc.c.

617{
618 JsonParser *parser = NULL;
619 JsonReader *reader = NULL;
620 GError *err = NULL;
621
623
624 parser = json_parser_new ();
625 if (!json_parser_load_from_data (parser, resp, len, &err))
626 {
627 g_message ("Error parsing");
628 }
629
630 reader = json_reader_new (json_parser_get_root (parser));
631
632 if (!json_reader_is_object (reader))
633 {
634 g_debug ("It is not an object");
635 goto cleanup_advisories;
636 }
637
638 char **members = json_reader_list_members (reader);
639
640 for (int i = 0; members[i]; i++)
641 {
643
644 if (!json_reader_read_member (reader, members[i]))
645 {
646 g_debug ("No member oid");
647 goto cleanup_advisories;
648 }
649 if (!json_reader_is_array (reader))
650 {
651 g_debug ("Is not an array");
652 goto cleanup_advisories;
653 }
654
655 advisory = advisory_new (g_strdup (members[i]));
656
657 int count_pkgs = json_reader_count_elements (reader);
658 g_debug ("There are %d packages for advisory %s", count_pkgs, members[i]);
659 for (int j = 0; j < count_pkgs; j++)
660 {
661 vuln_pkg_t *pkg = NULL;
662 char *name = NULL;
663 char *installed_version = NULL;
664 char *start = NULL;
665 char *stop = NULL;
666 char *version = NULL;
667 char *specifier = NULL;
668 enum fixed_type type = UNKNOWN;
669
670 json_reader_read_element (reader, j);
671 if (!json_reader_is_object (reader))
672 {
673 g_warning ("%s: Package %d of advisory %s is not an object",
674 __func__, j, members[i]);
676 goto cleanup_advisories;
677 }
678
679 json_reader_read_member (reader, "name");
680 name = g_strdup (json_reader_get_string_value (reader));
681 json_reader_end_member (reader);
682 g_debug ("name: %s", name);
683
684 json_reader_read_member (reader, "installed_version");
685 installed_version = g_strdup (json_reader_get_string_value (reader));
686 json_reader_end_member (reader);
687 g_debug ("installed_version: %s", installed_version);
688
689 json_reader_read_member (reader, "fixed_version");
690 g_debug ("Fixed_version has %d members",
691 json_reader_count_members (reader));
692
693 // Version Range
694 json_reader_read_member (reader, "start");
695 start = g_strdup (json_reader_get_string_value (reader));
696 json_reader_end_member (reader);
697 json_reader_read_member (reader, "end");
698 stop = g_strdup (json_reader_get_string_value (reader));
699 json_reader_end_member (reader);
700 g_debug ("start %s, end: %s", start, stop);
701
702 // version and specifier
703 json_reader_read_member (reader, "version");
704 version = g_strdup (json_reader_get_string_value (reader));
705 json_reader_end_member (reader);
706 json_reader_read_member (reader, "specifier");
707 specifier = g_strdup (json_reader_get_string_value (reader));
708 json_reader_end_member (reader);
709 g_debug ("version %s, specifier: %s", version, specifier);
710
711 // end read fixes version member
712 json_reader_end_member (reader);
713
714 // end package element
715 json_reader_end_element (reader);
716
717 char *item1 = NULL, *item2 = NULL;
718 if (start && stop)
719 {
720 type = RANGE;
721 item1 = start;
722 item2 = stop;
723 }
724 else if (version && specifier)
725 {
726 type = SINGLE;
727 item1 = version;
728 item2 = specifier;
729 }
730 else
731 {
732 g_warning ("%s: Error parsing json element", __func__);
733 g_free (name);
734 g_free (installed_version);
735 g_free (item1);
736 g_free (item2);
738 goto cleanup_advisories;
739 }
740
741 pkg =
742 vulnerable_pkg_new (name, installed_version, type, item1, item2);
743 g_free (name);
744 g_free (installed_version);
745 g_free (item1);
746 g_free (item2);
747
749 }
750 // end advisory
751 json_reader_end_member (reader);
753 }
754
755cleanup_advisories:
756 if (reader)
757 g_object_unref (reader);
758 g_object_unref (parser);
759
760 return advisories;
761}
const char * name
Definition nasl_init.c:439
static advisory_t * advisory_new(char *oid)
Initialize a new advisory.
static void advisories_add(advisories_t *advisories_list, advisory_t *advisory)
Initialize a new advisories struct with 100 slots.
static advisories_t * advisories_new()
Initialize a new advisories struct with 100 slots.
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 advisory.
static void advisory_add_vuln_pkg(advisory_t *adv, vuln_pkg_t *vuln)
Add a new vulnerability to the advisory.
fixed_type
Fixed version format.
@ UNKNOWN

References advisories_add(), advisories_free(), advisories_new(), advisory_add_vuln_pkg(), advisory_new(), len, name, RANGE, SINGLE, UNKNOWN, and vulnerable_pkg_new().

Referenced by call_rs_notus(), Ensure(), and nasl_notus().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ response_callback_fn()

size_t response_callback_fn ( void * ptr,
size_t size,
size_t nmemb,
void * struct_string )
static

Call back function to stored the response.

@description The function signature is the necessary to work with libcurl. It stores the response in s. It reallocate memory if necessary.

Definition at line 794 of file table_driven_lsc.c.

795{
796 struct string *s = struct_string;
797 size_t new_len = s->len + size * nmemb;
798 char *ptr_aux = g_realloc (s->ptr, new_len + 1);
799 s->ptr = ptr_aux;
800 if (s->ptr == NULL)
801 {
802 g_warning ("%s: Error allocating memory for response", __func__);
803 return 0; // no memory left
804 }
805 memcpy (s->ptr + s->len, ptr, size * nmemb);
806 s->ptr[new_len] = '\0';
807 s->len = new_len;
808
809 return size * nmemb;
810}
Define a string struct for storing the response.

References string::len, and string::ptr.

Referenced by _http2_req(), and send_request().

Here is the caller graph for this function:

◆ run_table_driven_lsc()

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.

If the gather-package-list.nasl plugin was launched, and it generated a valid package list for a supported OS, the table driven LSC scan which is subscribed to the topic will perform a scan an publish the the results to be handle by the sensor/client.

Parameters
scan_idScan Id.
kb
ip_strIP string of host.
hostnameName of host.
Returns
0 on success, less than 0 on error.

Definition at line 1057 of file table_driven_lsc.c.

1060{
1061 int err = 0;
1062 if (!os_release || !package_list)
1063 return 0;
1064
1065 if (prefs_get ("openvasd_server"))
1066 {
1067 g_message ("Running Notus for %s via openvasd", ip_str);
1068 err = call_rs_notus (ip_str, hostname, package_list, os_release);
1069
1070 return err;
1071 }
1072 else
1073 {
1074 gchar *json_str;
1075 gchar *topic;
1076 gchar *payload;
1077 gchar *status = NULL;
1078 int topic_len;
1079 int payload_len;
1080
1081 // Subscribe to status topic
1082 err = mqtt_subscribe ("scanner/status");
1083 if (err)
1084 {
1085 g_warning ("%s: Error starting lsc. Unable to subscribe", __func__);
1086 return -1;
1087 }
1088 /* Get the OS release. TODO: have a list with supported OS. */
1089
1091 os_release, package_list);
1092
1093 // Run table driven lsc
1094 if (json_str == NULL)
1095 return -1;
1096
1097 g_message ("Running Notus for %s", ip_str);
1098 err = mqtt_publish ("scanner/package/cmd/notus", json_str);
1099 if (err)
1100 {
1101 g_warning ("%s: Error publishing message for Notus.", __func__);
1102 g_free (json_str);
1103 return -1;
1104 }
1105
1106 g_free (json_str);
1107
1108 // Wait for Notus scanner to start or interrupt
1109 while (!status)
1110 {
1111 err = mqtt_retrieve_message (&topic, &topic_len, &payload,
1112 &payload_len, 60000);
1113 if (err == -1 || err == 1)
1114 {
1115 g_warning ("%s: Unable to retrieve status message from notus. %s",
1116 __func__, err == 1 ? "Timeout after 60 s." : "");
1117 return -1;
1118 }
1119
1120 // Get status if it belongs to corresponding scan and host
1121 // Else wait for next status message
1123 scan_id, ip_str, payload, payload_len);
1124
1125 g_free (topic);
1126 g_free (payload);
1127 }
1128 // If started wait for it to finish or interrupt
1129 if (!g_strcmp0 (status, "running"))
1130 {
1131 g_debug ("%s: table driven LSC with scan id %s successfully started "
1132 "for host %s",
1133 __func__, scan_id, ip_str);
1134 g_free (status);
1135 status = NULL;
1136 while (!status)
1137 {
1138 err = mqtt_retrieve_message (&topic, &topic_len, &payload,
1139 &payload_len, 60000);
1140 if (err == -1)
1141 {
1142 g_warning (
1143 "%s: Unable to retrieve status message from notus.",
1144 __func__);
1145 return -1;
1146 }
1147 if (err == 1)
1148 {
1149 g_warning (
1150 "%s: Unable to retrieve message. Timeout after 60s.",
1151 __func__);
1152 return -1;
1153 }
1154
1156 scan_id, ip_str, payload, payload_len);
1157 g_free (topic);
1158 g_free (payload);
1159 }
1160 }
1161 else
1162 {
1163 g_warning ("%s: Unable to start lsc. Got status: %s", __func__,
1164 status);
1165 g_free (status);
1166 return -1;
1167 }
1168
1169 if (g_strcmp0 (status, "finished"))
1170 {
1171 g_warning (
1172 "%s: table driven lsc with scan id %s did not finish successfully "
1173 "for host %s. Last status was %s",
1174 __func__, scan_id, ip_str, status);
1175 err = -1;
1176 }
1177 else
1178 g_debug ("%s: table driven lsc with scan id %s successfully finished "
1179 "for host %s",
1180 __func__, scan_id, ip_str);
1181 g_free (status);
1182 }
1183 return err;
1184}
u_char * payload
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.
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.
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.

References call_rs_notus(), get_status_of_table_driven_lsc_from_json(), hostname, make_table_driven_lsc_info_json_str(), payload, and scan_id.

Referenced by call_lsc().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_request()

long send_request ( notus_info_t notusdata,
const char * os,
const char * pkg_list,
char ** response )
static

Send a request to the server.

Parameters
[in]notusdataStructure containing information necessary for the request
[in]osTarget's operative system. Necessary for the URL path part.
[in]pkg_listThe package list installed in the target, to be checked
[out]responseThe string containing the results in json format.
Returns
the http code or -1 on error

Definition at line 823 of file table_driven_lsc.c.

825{
826 CURL *curl;
827 GString *url = NULL;
828 long http_code = -1;
829 struct string resp;
830 struct curl_slist *customheader = NULL;
831 char *os_aux;
832 GString *xapikey = NULL;
833
834 if ((curl = curl_easy_init ()) == NULL)
835 {
836 g_warning ("Not possible to initialize curl library");
837 return http_code;
838 }
839
840 url = g_string_new (notusdata->server);
841 g_string_append (url, "/notus/");
842
843 //
844 os_aux = help_tolower (g_strdup (os));
845 for (size_t i = 0; i < strlen (os_aux); i++)
846 {
847 if (os_aux[i] == ' ')
848 os_aux[i] = '_';
849 }
850
851 g_string_append (url, os_aux);
852 g_free (os_aux);
853
854 g_debug ("%s: URL: %s", __func__, url->str);
855 // Set URL
856 if (curl_easy_setopt (curl, CURLOPT_URL, g_strdup (url->str)) != CURLE_OK)
857 {
858 g_warning ("Not possible to set the URL");
859 curl_easy_cleanup (curl);
860 return http_code;
861 }
862 g_string_free (url, TRUE);
863
864 // Accept an insecure connection. Don't verify the server certificate
865 curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0L);
866 curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0L);
867
868 // Set API KEY
869 if (prefs_get ("x-apikey"))
870 {
871 xapikey = g_string_new ("X-APIKEY: ");
872 g_string_append (xapikey, prefs_get ("x-apikey"));
873 customheader = curl_slist_append (customheader, g_strdup (xapikey->str));
874 g_string_free (xapikey, TRUE);
875 }
876 // SET Content type
877 customheader =
878 curl_slist_append (customheader, "Content-Type: application/json");
879 curl_easy_setopt (curl, CURLOPT_HTTPHEADER, customheader);
880 // Set body
881 curl_easy_setopt (curl, CURLOPT_POSTFIELDS, pkg_list);
882 curl_easy_setopt (curl, CURLOPT_POSTFIELDSIZE, strlen (pkg_list));
883
884 // Init the struct where the response is stored and set the callback function
885 init_string (&resp);
886 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, response_callback_fn);
887 curl_easy_setopt (curl, CURLOPT_WRITEDATA, &resp);
888
889 int ret = CURLE_OK;
890 if ((ret = curl_easy_perform (curl)) != CURLE_OK)
891 {
892 g_warning ("%s: Error sending request: %d", __func__, ret);
893 curl_easy_cleanup (curl);
894 g_free (resp.ptr);
895 return http_code;
896 }
897
898 curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
899
900 curl_easy_cleanup (curl);
901 g_debug ("Server response %s", resp.ptr);
902 *response = g_strdup (resp.ptr);
903 g_free (resp.ptr);
904 // already free()'ed with curl_easy_cleanup().
905
906 return http_code;
907}
static size_t response_callback_fn(void *ptr, size_t size, size_t nmemb, void *struct_string)
Call back function to stored the response.
static void init_string(struct string *s)
Initialize the string struct to hold the response.

References help_tolower(), init_string(), string::ptr, response_callback_fn(), and notus_info::server.

Referenced by notus_get_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_lsc_flag()

void set_lsc_flag ( void )

Set lsc_flag to 1.

Definition at line 40 of file table_driven_lsc.c.

41{
42 lsc_flag = 1;
43}

References lsc_flag.

Referenced by process_ipc_data().

Here is the caller graph for this function:

◆ vulnerable_pkg_new()

vuln_pkg_t * vulnerable_pkg_new ( const char * pkg_name,
const char * install_version,
enum fixed_type type,
char * item1,
char * item2 )
static

Creates a new Vulnerable packages which belongs to an advisory.

Parameters
pkg_name
install_version
typeData type specifying how the fixed version is stored. Can be RANGE or SINGLE
item1Depending on the type is the "version" for SINGLE type, or the "less than" for RANGE type
item2Depending on the type is the "specifier" for SINGLE type, or the "greater than" for RANGE type
Returns
a vulnerable packages struct. Members are a copy of the passed parameters. They must be free separately.

Definition at line 574 of file table_driven_lsc.c.

576{
577 vuln_pkg_t *vuln = NULL;
578 version_range_t *range = NULL;
579 fixed_version_t *fixed_ver = NULL;
580
581 vuln = g_malloc0 (sizeof (vuln_pkg_t));
582 vuln->pkg_name = g_strdup (pkg_name);
583 vuln->install_version = g_strdup (install_version);
584 vuln->type = type;
585 if (type == RANGE)
586 {
587 range = g_malloc0 (sizeof (range_t));
588 range->start = g_strdup (item1);
589 range->stop = g_strdup (item2);
590 vuln->range = range;
591 }
592 else
593 {
594 fixed_ver = g_malloc0 (sizeof (fixed_version_t));
595 fixed_ver->version = g_strdup (item1);
596 fixed_ver->specifier = g_strdup (item2);
597 vuln->version = fixed_ver;
598 }
599
600 return vuln;
601}
struct fixed_version fixed_version_t
struct version_range version_range_t

References vulnerable_pkg::install_version, vulnerable_pkg::pkg_name, RANGE, vulnerable_pkg::range, fixed_version::specifier, version_range::start, version_range::stop, vulnerable_pkg::type, fixed_version::version, and vulnerable_pkg::version.

Referenced by process_notus_response().

Here is the caller graph for this function:

Variable Documentation

◆ lsc_flag

int lsc_flag = 0
static

LSC ran or didn't 0 didn't run. 1 ran.

Definition at line 35 of file table_driven_lsc.c.

Referenced by lsc_has_run(), and set_lsc_flag().