1 /* Copyright (C) 2009-2021 Greenbone Networks GmbH
2  *
3  * SPDX-License-Identifier: AGPL-3.0-or-later
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as
7  * published by the Free Software Foundation, either version 3 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /**
20  * @file manage_sql_nvts.c
21  * @brief GVM management layer: NVTs
22  *
23  * The NVT parts of the GVM management layer.
24  */
25 
26 /**
27  * @brief Enable extra GNU functions.
28  */
29 #define _GNU_SOURCE
30 
31 #include <assert.h>
32 #include <errno.h>
33 #include <math.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 
38 #include <gvm/base/cvss.h>
39 
40 #include "manage_sql_nvts.h"
41 #include "manage_preferences.h"
42 #include "manage_sql.h"
43 #include "manage_sql_configs.h"
44 #include "sql.h"
45 #include "utils.h"
46 
47 #undef G_LOG_DOMAIN
48 /**
49  * @brief GLib log domain.
50  */
51 #define G_LOG_DOMAIN "md manage"
52 
53 
54 /* NVT related global options */
55 
56 /**
57  * @brief File socket for OSP NVT update.
58  */
59 static gchar *osp_vt_update_socket = NULL;
60 
61 /**
62  * @brief Get the current file socket for OSP NVT update.
63  *
64  * @return The path of the file socket for OSP NVT update.
65  */
66 const gchar *
get_osp_vt_update_socket()67 get_osp_vt_update_socket ()
68 {
69   return osp_vt_update_socket;
70 }
71 
72 /**
73  * @brief Set the file socket for OSP NVT update.
74  *
75  * @param new_socket The new path of the file socket for OSP NVT update.
76  */
77 void
set_osp_vt_update_socket(const char * new_socket)78 set_osp_vt_update_socket (const char *new_socket)
79 {
80   if (new_socket)
81     {
82       g_free (osp_vt_update_socket);
83       osp_vt_update_socket = g_strdup (new_socket);
84     }
85 }
86 
87 /**
88  * @brief Check the files socket used for OSP NVT update.
89  *
90  * @return 0 success, 1 no socket found.
91  */
92 int
check_osp_vt_update_socket()93 check_osp_vt_update_socket ()
94 {
95   if (get_osp_vt_update_socket () == NULL)
96     {
97       char *default_socket;
98 
99       /* Try to get OSP VT update socket from default scanner. */
100 
101       default_socket = openvas_default_scanner_host ();
102       if (default_socket == NULL)
103         return 1;
104 
105       g_debug ("%s: Using OSP VT update socket from default OpenVAS"
106                " scanner: %s",
107                __func__,
108                default_socket);
109       set_osp_vt_update_socket (default_socket);
110       free (default_socket);
111     }
112 
113   return 0;
114 }
115 
116 
117 /* NVT's. */
118 
119 /**
120  * @brief Ensures the sanity of nvts cache in DB.
121  */
122 void
check_db_nvts()123 check_db_nvts ()
124 {
125   /* Ensure the nvti cache update flag exists and is clear. */
126   if (sql_int ("SELECT count(*) FROM %s.meta"
127                " WHERE name = 'update_nvti_cache';",
128                sql_schema ()))
129     sql ("UPDATE %s.meta SET value = 0 WHERE name = 'update_nvti_cache';",
130          sql_schema ());
131   else
132     sql ("INSERT INTO %s.meta (name, value)"
133          " VALUES ('update_nvti_cache', 0);",
134          sql_schema ());
135 }
136 
137 /**
138  * @brief Get the name of an NVT.
139  *
140  * @param[in]  nvt  NVT.
141  *
142  * @return Freshly allocated name of NVT if possible, else NULL.
143  */
144 char *
manage_nvt_name(nvt_t nvt)145 manage_nvt_name (nvt_t nvt)
146 {
147   return sql_string ("SELECT name FROM nvts WHERE id = %llu;", nvt);
148 }
149 
150 /**
151  * @brief Get the name of an NVT given its OID.
152  *
153  * @param[in]  oid  OID of NVT.
154  *
155  * @return Name of NVT if possible, else NULL.
156  */
157 char *
nvt_name(const char * oid)158 nvt_name (const char *oid)
159 {
160   gchar *quoted_oid = sql_quote (oid);
161   char *ret = sql_string ("SELECT name FROM nvts WHERE oid = '%s' LIMIT 1;",
162                           quoted_oid);
163   g_free (quoted_oid);
164   return ret;
165 }
166 
167 /**
168  * @brief Return feed version of the plugins in the plugin cache.
169  *
170  * @return Feed version of plugins if the plugins are cached, else NULL.
171  */
172 char*
nvts_feed_version()173 nvts_feed_version ()
174 {
175   return sql_string ("SELECT value FROM %s.meta"
176                      " WHERE name = 'nvts_feed_version';",
177                      sql_schema ());
178 }
179 
180 /**
181  * @brief Return feed version of the plugins as seconds since epoch.
182  *
183  * @return Feed version in seconds since epoch of plugins.
184  */
185 time_t
nvts_feed_version_epoch()186 nvts_feed_version_epoch ()
187 {
188   gchar *feed_version;
189   struct tm tm;
190 
191   feed_version = nvts_feed_version ();
192 
193   if (feed_version == NULL)
194     return 0;
195 
196   memset (&tm, 0, sizeof (struct tm));
197   strptime (feed_version, "%Y%m%d%H%M%S", &tm);
198 
199   g_free (feed_version);
200 
201   return mktime (&tm);
202 }
203 
204 /**
205  * @brief Set the feed version of the plugins in the plugin cache.
206  *
207  * @param[in]  feed_version  New feed version.
208  *
209  * Also queue an update to the nvti cache.
210  */
211 void
set_nvts_feed_version(const char * feed_version)212 set_nvts_feed_version (const char *feed_version)
213 {
214   gchar* quoted = sql_quote (feed_version);
215   sql ("DELETE FROM %s.meta WHERE name = 'nvts_feed_version';",
216        sql_schema ());
217   sql ("INSERT INTO %s.meta (name, value)"
218        " VALUES ('nvts_feed_version', '%s');",
219        sql_schema (),
220        quoted);
221   g_free (quoted);
222 }
223 
224 /**
225  * @brief Find an NVT given an identifier.
226  *
227  * @param[in]   oid  An NVT identifier.
228  * @param[out]  nvt  NVT return, 0 if successfully failed to find task.
229  *
230  * @return FALSE on success (including if failed to find NVT), TRUE on error.
231  */
232 gboolean
find_nvt(const char * oid,nvt_t * nvt)233 find_nvt (const char* oid, nvt_t* nvt)
234 {
235   gchar *quoted_oid;
236   int ret;
237 
238   quoted_oid = sql_quote (oid);
239   ret = sql_int64 (nvt,
240                    "SELECT id FROM nvts WHERE oid = '%s';",
241                    quoted_oid);
242   g_free (quoted_oid);
243   switch (ret)
244     {
245       case 0:
246         break;
247       case 1:        /* Too few rows in result of query. */
248         *nvt = 0;
249         break;
250       default:       /* Programming error. */
251         assert (0);
252       case -1:
253         return TRUE;
254         break;
255     }
256 
257   return FALSE;
258 }
259 
260 /**
261  * @brief Insert an NVT.
262  *
263  * @param[in]  nvti       NVT Information.
264  */
265 static void
insert_nvt(const nvti_t * nvti)266 insert_nvt (const nvti_t *nvti)
267 {
268   gchar *qod_str, *qod_type, *cve;
269   gchar *quoted_name, *quoted_summary, *quoted_insight, *quoted_affected;
270   gchar *quoted_impact, *quoted_detection, *quoted_cve, *quoted_tag;
271   gchar *quoted_cvss_base, *quoted_qod_type, *quoted_family;
272   gchar *quoted_solution, *quoted_solution_type, *quoted_solution_method;
273   int qod, i;
274   double highest;
275 
276   cve = nvti_refs (nvti, "cve", "", 0);
277 
278   quoted_name = sql_quote (nvti_name (nvti) ? nvti_name (nvti) : "");
279   quoted_summary = sql_quote (nvti_summary (nvti) ? nvti_summary (nvti) : "");
280   quoted_insight = sql_quote (nvti_insight (nvti) ? nvti_insight (nvti) : "");
281   quoted_affected = sql_quote (nvti_affected (nvti) ?
282                                nvti_affected (nvti) : "");
283   quoted_impact = sql_quote (nvti_impact (nvti) ? nvti_impact (nvti) : "");
284 
285   quoted_cve = sql_quote (cve ? cve : "");
286   g_free (cve);
287 
288   quoted_solution = sql_quote (nvti_solution (nvti) ?
289                                nvti_solution (nvti) : "");
290   quoted_solution_type = sql_quote (nvti_solution_type (nvti) ?
291                                     nvti_solution_type (nvti) : "");
292   quoted_solution_method = sql_quote (nvti_solution_method (nvti) ?
293                                       nvti_solution_method (nvti) : "");
294   quoted_detection = sql_quote (nvti_detection (nvti) ?
295                                 nvti_detection (nvti) : "");
296 
297   quoted_tag = sql_quote (nvti_tag (nvti) ?  nvti_tag (nvti) : "");
298 
299   quoted_cvss_base = sql_quote (nvti_cvss_base (nvti) ? nvti_cvss_base (nvti) : "");
300 
301   qod_str = nvti_qod (nvti);
302   qod_type = nvti_qod_type (nvti);
303 
304   if (qod_str == NULL || sscanf (qod_str, "%d", &qod) != 1)
305     qod = qod_from_type (qod_type);
306 
307   quoted_qod_type = sql_quote (qod_type ? qod_type : "");
308 
309   quoted_family = sql_quote (nvti_family (nvti) ? nvti_family (nvti) : "");
310 
311   if (sql_int ("SELECT EXISTS (SELECT * FROM nvts WHERE oid = '%s');",
312                nvti_oid (nvti)))
313     sql ("DELETE FROM nvts WHERE oid = '%s';", nvti_oid (nvti));
314 
315   sql ("INSERT into nvts (oid, name, summary, insight, affected,"
316        " impact, cve, tag, category, family, cvss_base,"
317        " creation_time, modification_time, uuid, solution_type,"
318        " solution_method, solution, detection, qod, qod_type)"
319        " VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s',"
320        " '%s', %i, '%s', '%s', %i, %i, '%s', '%s', '%s', '%s', '%s', %d, '%s');",
321        nvti_oid (nvti), quoted_name, quoted_summary, quoted_insight,
322        quoted_affected, quoted_impact, quoted_cve, quoted_tag,
323        nvti_category (nvti), quoted_family, quoted_cvss_base,
324        nvti_creation_time (nvti), nvti_modification_time (nvti),
325        nvti_oid (nvti), quoted_solution_type, quoted_solution_method,
326        quoted_solution, quoted_detection, qod, quoted_qod_type);
327 
328   sql ("DELETE FROM vt_refs where vt_oid = '%s';", nvti_oid (nvti));
329 
330   for (i = 0; i < nvti_vtref_len (nvti); i++)
331     {
332       vtref_t *ref;
333       gchar *quoted_type, *quoted_id, *quoted_text;
334 
335       ref = nvti_vtref (nvti, i);
336       quoted_type = sql_quote (vtref_type (ref));
337       quoted_id = sql_quote (vtref_id (ref));
338       quoted_text = sql_quote (vtref_text (ref) ? vtref_text (ref) : "");
339 
340       sql ("INSERT into vt_refs (vt_oid, type, ref_id, ref_text)"
341            " VALUES ('%s', '%s', '%s', '%s');",
342            nvti_oid (nvti), quoted_type, quoted_id, quoted_text);
343 
344       g_free (quoted_type);
345       g_free (quoted_id);
346       g_free (quoted_text);
347     }
348 
349   sql ("DELETE FROM vt_severities where vt_oid = '%s';", nvti_oid (nvti));
350 
351   highest = 0;
352 
353   for (i = 0; i < nvti_vtseverities_len (nvti); i++)
354     {
355       vtseverity_t *severity;
356       gchar *quoted_origin, *quoted_value;
357 
358       severity = nvti_vtseverity (nvti, i);
359       quoted_origin = sql_quote (vtseverity_origin (severity) ?
360                                  vtseverity_origin (severity) : "");
361       quoted_value = sql_quote (vtseverity_value (severity) ?
362                                  vtseverity_value (severity) : "");
363 
364       sql ("INSERT into vt_severities (vt_oid, type, origin, date, score,"
365            "                           value)"
366            " VALUES ('%s', '%s', '%s', %i, %0.1f, '%s');",
367            nvti_oid (nvti), vtseverity_type (severity),
368            quoted_origin, vtseverity_date (severity),
369            vtseverity_score (severity), quoted_value);
370       if (vtseverity_score (severity) > highest)
371         highest = vtseverity_score (severity);
372 
373       g_free (quoted_origin);
374       g_free (quoted_value);
375     }
376 
377   sql ("UPDATE nvts SET cvss_base = %0.1f WHERE oid = '%s';",
378        highest,
379        nvti_oid (nvti));
380 
381   g_free (quoted_name);
382   g_free (quoted_summary);
383   g_free (quoted_insight);
384   g_free (quoted_affected);
385   g_free (quoted_impact);
386   g_free (quoted_cve);
387   g_free (quoted_tag);
388   g_free (quoted_cvss_base);
389   g_free (quoted_family);
390   g_free (quoted_solution);
391   g_free (quoted_solution_type);
392   g_free (quoted_solution_method);
393   g_free (quoted_detection);
394   g_free (quoted_qod_type);
395 }
396 
397 /**
398  * @brief Initialise an NVT iterator.
399  *
400  * @param[in]  iterator    Iterator.
401  * @param[in]  get         GET data.
402  * @param[in]  name        Name of the info
403  *
404  * @return 0 success, 1 failed to find NVT, 2 failed to find filter,
405  *         -1 error.
406  */
407 int
init_nvt_info_iterator(iterator_t * iterator,get_data_t * get,const char * name)408 init_nvt_info_iterator (iterator_t* iterator, get_data_t *get, const char *name)
409 {
410   static const char *filter_columns[] = NVT_INFO_ITERATOR_FILTER_COLUMNS;
411   static column_t columns[] = NVT_ITERATOR_COLUMNS;
412   gchar *clause = NULL;
413   int ret;
414 
415   if (get->id)
416     {
417       gchar *quoted = sql_quote (get->id);
418       clause = g_strdup_printf (" AND uuid = '%s'", quoted);
419       g_free (quoted);
420     }
421   else if (name)
422     {
423       gchar *quoted = sql_quote (name);
424       clause = g_strdup_printf (" AND name = '%s'", quoted);
425       g_free (quoted);
426       /* The entry is specified by name, so filtering just gets in the way. */
427       g_free (get->filter);
428       get->filter = NULL;
429     }
430 
431   ret = init_get_iterator (iterator,
432                            "nvt",
433                            get,
434                            /* Columns. */
435                            columns,
436                            /* Columns for trashcan. */
437                            NULL,
438                            filter_columns,
439                            0,
440                            NULL,
441                            clause,
442                            0);
443 
444   g_free (clause);
445   return ret;
446 }
447 
448 /**
449  * @brief Get NVT iterator SELECT columns.
450  *
451  * @return SELECT columns
452  */
453 static gchar *
nvt_iterator_columns()454 nvt_iterator_columns ()
455 {
456   static column_t select_columns[] = NVT_ITERATOR_COLUMNS;
457   static gchar *columns = NULL;
458   if (columns == NULL)
459     columns = columns_build_select (select_columns);
460   return columns;
461 }
462 
463 /**
464  * @brief Get NVT iterator SELECT columns.
465  *
466  * @return SELECT columns
467  */
468 static gchar *
nvt_iterator_columns_nvts()469 nvt_iterator_columns_nvts ()
470 {
471   static column_t select_columns[] = NVT_ITERATOR_COLUMNS_NVTS;
472   static gchar *columns = NULL;
473   if (columns == NULL)
474     columns = columns_build_select (select_columns);
475   return columns;
476 }
477 
478 /**
479  * @brief Count number of nvt.
480  *
481  * @param[in]  get  GET params.
482  *
483  * @return Total number of cpes in filtered set.
484  */
485 int
nvt_info_count(const get_data_t * get)486 nvt_info_count (const get_data_t *get)
487 {
488   static const char *extra_columns[] = NVT_INFO_ITERATOR_FILTER_COLUMNS;
489   static column_t columns[] = NVT_ITERATOR_COLUMNS;
490   return count ("nvt", get, columns, NULL, extra_columns, 0, 0, 0,
491                 FALSE);
492 }
493 
494 /**
495  * @brief Count number of nvts created or modified after a given time.
496  *
497  * @param[in]  get            GET params.
498  * @param[in]  count_time     Time NVTs must be created or modified after.
499  * @param[in]  get_modified   Whether to get the modification time.
500  *
501  * @return Total number of nvts in filtered set.
502  */
503 int
nvt_info_count_after(const get_data_t * get,time_t count_time,gboolean get_modified)504 nvt_info_count_after (const get_data_t *get, time_t count_time,
505                       gboolean get_modified)
506 {
507   static const char *filter_columns[] = NVT_INFO_ITERATOR_FILTER_COLUMNS;
508   static column_t columns[] = NVT_ITERATOR_COLUMNS;
509   gchar *extra_where;
510   int ret;
511 
512   if (get_modified)
513     extra_where = g_strdup_printf (" AND modification_time > %ld"
514                                    " AND creation_time <= %ld",
515                                    count_time,
516                                    count_time);
517   else
518     extra_where = g_strdup_printf (" AND creation_time > %ld",
519                                    count_time);
520 
521   ret = count ("nvt", get, columns, NULL, filter_columns, 0, 0, extra_where,
522                FALSE);
523 
524   g_free (extra_where);
525   return ret;
526 }
527 
528 /**
529  * @brief Return SQL for selecting NVT's of a config from one family.
530  *
531  * @param[in]  config      Config.
532  * @param[in]  family      Family to limit selection to.
533  * @param[in]  ascending   Whether to sort ascending or descending.
534  * @param[in]  sort_field  Field to sort on, or NULL for "nvts.id".
535  *
536  * @return Freshly allocated SELECT statement on success, or NULL on error.
537  */
538 static gchar *
select_config_nvts(const config_t config,const char * family,int ascending,const char * sort_field)539 select_config_nvts (const config_t config, const char* family, int ascending,
540                     const char* sort_field)
541 {
542   gchar *quoted_selector, *quoted_family, *sql;
543   char *selector;
544 
545   selector = config_nvt_selector (config);
546   if (selector == NULL)
547     /* The config should always have a selector. */
548     return NULL;
549 
550   quoted_selector = sql_quote (selector);
551   free (selector);
552 
553   quoted_family = sql_quote (family);
554 
555   if (config_nvts_growing (config))
556     {
557       int constraining;
558 
559       /* The number of NVT's can increase. */
560 
561       constraining = config_families_growing (config);
562 
563       if (constraining)
564         {
565           /* Constraining the universe. */
566 
567           if (sql_int ("SELECT COUNT(*) FROM nvt_selectors WHERE name = '%s';",
568                        quoted_selector)
569               == 1)
570             /* There is one selector, it should be the all selector. */
571             sql = g_strdup_printf
572                    ("SELECT %s"
573                     " FROM nvts WHERE family = '%s'"
574                     " ORDER BY %s %s;",
575                     nvt_iterator_columns (),
576                     quoted_family,
577                     sort_field ? sort_field : "name",
578                     ascending ? "ASC" : "DESC");
579           else
580             {
581               /* There are multiple selectors. */
582 
583               if (sql_int ("SELECT COUNT(*) FROM nvt_selectors"
584                            " WHERE name = '%s' AND exclude = 1"
585                            " AND type = "
586                            G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
587                            " AND family_or_nvt = '%s'"
588                            ";",
589                            quoted_selector,
590                            quoted_family))
591                 /* The family is excluded, just iterate the NVT includes. */
592                 sql = g_strdup_printf
593                        ("SELECT %s"
594                         " FROM nvts, nvt_selectors"
595                         " WHERE"
596                         " nvts.family = '%s'"
597                         " AND nvt_selectors.name = '%s'"
598                         " AND nvt_selectors.family = '%s'"
599                         " AND nvt_selectors.type = "
600                         G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
601                         " AND nvt_selectors.exclude = 0"
602                         " AND nvts.oid = nvt_selectors.family_or_nvt"
603                         " ORDER BY %s %s;",
604                         nvt_iterator_columns_nvts (),
605                         quoted_family,
606                         quoted_selector,
607                         quoted_family,
608                         sort_field ? sort_field : "nvts.name",
609                         ascending ? "ASC" : "DESC");
610               else
611                 /* The family is included.
612                  *
613                  * Iterate all NVT's minus excluded NVT's. */
614                 sql = g_strdup_printf
615                        ("SELECT %s"
616                         " FROM nvts"
617                         " WHERE family = '%s'"
618                         " EXCEPT"
619                         " SELECT %s"
620                         " FROM nvt_selectors, nvts"
621                         " WHERE"
622                         " nvts.family = '%s'"
623                         " AND nvt_selectors.name = '%s'"
624                         " AND nvt_selectors.family = '%s'"
625                         " AND nvt_selectors.type = "
626                         G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
627                         " AND nvt_selectors.exclude = 1"
628                         " AND nvts.oid = nvt_selectors.family_or_nvt"
629                         " ORDER BY %s %s;",
630                         nvt_iterator_columns (),
631                         quoted_family,
632                         nvt_iterator_columns_nvts (),
633                         quoted_family,
634                         quoted_selector,
635                         quoted_family,
636                         /* This works around "ERROR: missing FROM-clause" from
637                          * Postgres when using nvts.name. */
638                         sort_field && strcmp (sort_field, "nvts.name")
639                          ? sort_field : "3", /* 3 is nvts.name. */
640                         ascending ? "ASC" : "DESC");
641             }
642         }
643       else
644         {
645           int all;
646 
647           /* Generating from empty. */
648 
649           all = sql_int ("SELECT COUNT(*) FROM nvt_selectors"
650                          " WHERE name = '%s' AND exclude = 0"
651                          " AND type = "
652                          G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
653                          " AND family_or_nvt = '%s';",
654                          quoted_selector,
655                          quoted_family);
656 
657           if (all)
658             /* There is a family include for this family. */
659             sql = g_strdup_printf
660                    ("SELECT %s"
661                     " FROM nvts"
662                     " WHERE family = '%s'"
663                     " EXCEPT"
664                     " SELECT %s"
665                     " FROM nvt_selectors, nvts"
666                     " WHERE"
667                     " nvts.family = '%s'"
668                     " AND nvt_selectors.name = '%s'"
669                     " AND nvt_selectors.family = '%s'"
670                     " AND nvt_selectors.type = "
671                     G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
672                     " AND nvt_selectors.exclude = 1"
673                     " AND nvts.oid = nvt_selectors.family_or_nvt"
674                     " ORDER BY %s %s;",
675                     nvt_iterator_columns (),
676                     quoted_family,
677                     nvt_iterator_columns_nvts (),
678                     quoted_family,
679                     quoted_selector,
680                     quoted_family,
681                     /* This works around "ERROR: missing FROM-clause" from
682                      * Postgres when using nvts.name. */
683                     sort_field && strcmp (sort_field, "nvts.name")
684                      ? sort_field : "3", /* 3 is nvts.name. */
685                     ascending ? "ASC" : "DESC");
686           else
687             sql = g_strdup_printf
688                    (" SELECT %s"
689                     " FROM nvt_selectors, nvts"
690                     " WHERE"
691                     " nvts.family = '%s'"
692                     " AND nvt_selectors.name = '%s'"
693                     " AND nvt_selectors.family = '%s'"
694                     " AND nvt_selectors.type = "
695                     G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
696                     " AND nvt_selectors.exclude = 0"
697                     " AND nvts.oid = nvt_selectors.family_or_nvt"
698                     " ORDER BY %s %s;",
699                     nvt_iterator_columns_nvts (),
700                     quoted_family,
701                     quoted_selector,
702                     quoted_family,
703                     sort_field ? sort_field : "nvts.name",
704                     ascending ? "ASC" : "DESC");
705         }
706     }
707   else
708     {
709       /* The number of NVT's is static.  Assume a simple list of NVT
710        * includes. */
711 
712       sql = g_strdup_printf
713              ("SELECT %s"
714               " FROM nvt_selectors, nvts"
715               " WHERE nvts.family = '%s'"
716               " AND nvt_selectors.exclude = 0"
717               " AND nvt_selectors.type = " G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
718               " AND nvt_selectors.name = '%s'"
719               " AND nvts.oid = nvt_selectors.family_or_nvt"
720               " ORDER BY %s %s;",
721               nvt_iterator_columns_nvts (),
722               quoted_family,
723               quoted_selector,
724               sort_field ? sort_field : "nvts.id",
725               ascending ? "ASC" : "DESC");
726     }
727 
728   g_free (quoted_selector);
729   g_free (quoted_family);
730 
731   return sql;
732 }
733 
734 /**
735  * @brief Initialise an NVT iterator.
736  *
737  * @param[in]  iterator    Iterator.
738  * @param[in]  nvt         NVT to iterate over, all if 0.
739  * @param[in]  config      Config to limit selection to.  NULL for all NVTs.
740  *                         Overridden by \arg nvt.
741  * @param[in]  family      Family to limit selection to.  NULL for all NVTs.
742  *                         Overridden by \arg config.
743  * @param[in]  category    Category to limit selection to.  NULL for all.
744  * @param[in]  ascending   Whether to sort ascending or descending.
745  * @param[in]  sort_field  Field to sort on, or NULL for "id".
746  */
747 void
init_nvt_iterator(iterator_t * iterator,nvt_t nvt,config_t config,const char * family,const char * category,int ascending,const char * sort_field)748 init_nvt_iterator (iterator_t* iterator, nvt_t nvt, config_t config,
749                    const char* family, const char *category, int ascending,
750                    const char* sort_field)
751 {
752   assert ((nvt && family) == 0);
753 
754   if (nvt)
755     {
756       gchar* sql;
757       sql = g_strdup_printf ("SELECT %s"
758                              " FROM nvts WHERE id = %llu;",
759                              nvt_iterator_columns (),
760                              nvt);
761       init_iterator (iterator, "%s", sql);
762       g_free (sql);
763     }
764   else if (config)
765     {
766       gchar* sql;
767       if (family == NULL) abort ();
768       sql = select_config_nvts (config, family, ascending, sort_field);
769       if (sql)
770         {
771           init_iterator (iterator, "%s", sql);
772           g_free (sql);
773         }
774       else
775         init_iterator (iterator,
776                        "SELECT %s"
777                        " FROM nvts LIMIT 0;",
778                        nvt_iterator_columns ());
779     }
780   else if (family)
781     {
782       gchar *quoted_family = sql_quote (family);
783       init_iterator (iterator,
784                      "SELECT %s"
785                      " FROM nvts"
786                      " WHERE family = '%s'"
787                      " ORDER BY %s %s;",
788                      nvt_iterator_columns (),
789                      quoted_family,
790                      sort_field ? sort_field : "name",
791                      ascending ? "ASC" : "DESC");
792       g_free (quoted_family);
793     }
794   else if (category)
795     {
796       gchar *quoted_category;
797       quoted_category = sql_quote (category);
798       init_iterator (iterator,
799                      "SELECT %s"
800                      " FROM nvts"
801                      " WHERE category = '%s'"
802                      " ORDER BY %s %s;",
803                      nvt_iterator_columns (),
804                      quoted_category,
805                      sort_field ? sort_field : "name",
806                      ascending ? "ASC" : "DESC");
807       g_free (quoted_category);
808     }
809   else
810     init_iterator (iterator,
811                    "SELECT %s"
812                    " FROM nvts"
813                    " ORDER BY %s %s;",
814                    nvt_iterator_columns (),
815                    sort_field ? sort_field : "name",
816                    ascending ? "ASC" : "DESC");
817 }
818 
819 /**
820  * @brief Initialise an NVT iterator, for NVTs of a certain CVE.
821  *
822  * @param[in]  iterator    Iterator.
823  * @param[in]  cve         CVE name.
824  * @param[in]  ascending   Whether to sort ascending or descending.
825  * @param[in]  sort_field  Field to sort on, or NULL for "id".
826  */
827 void
init_cve_nvt_iterator(iterator_t * iterator,const char * cve,int ascending,const char * sort_field)828 init_cve_nvt_iterator (iterator_t* iterator, const char *cve, int ascending,
829                        const char* sort_field)
830 {
831   init_iterator (iterator,
832                  "SELECT %s"
833                  " FROM nvts"
834                  " WHERE cve %s '%%%s, %%'"
835                  "    OR cve %s '%%%s'"
836                  " ORDER BY %s %s;",
837                  nvt_iterator_columns (),
838                  sql_ilike_op (),
839                  cve ? cve : "",
840                  sql_ilike_op (),
841                  cve ? cve : "",
842                  sort_field ? sort_field : "name",
843                  ascending ? "ASC" : "DESC");
844 }
845 
846 /**
847  * @brief Get the OID from an NVT iterator.
848  *
849  * @param[in]  iterator  Iterator.
850  *
851  * @return OID, or NULL if iteration is complete.  Freed by
852  *         cleanup_iterator.
853  */
854 DEF_ACCESS (nvt_iterator_oid, GET_ITERATOR_COLUMN_COUNT);
855 
856 /**
857  * @brief Get the name from an NVT iterator.
858  *
859  * @param[in]  iterator  Iterator.
860  *
861  * @return Name, or NULL if iteration is complete.  Freed by
862  *         cleanup_iterator.
863  */
864 DEF_ACCESS (nvt_iterator_name, GET_ITERATOR_COLUMN_COUNT + 2);
865 
866 /**
867  * @brief Get the tag from an NVT iterator.
868  *
869  * @param[in]  iterator  Iterator.
870  *
871  * @return Tag, or NULL if iteration is complete.  Freed by
872  *         cleanup_iterator.
873  */
874 DEF_ACCESS (nvt_iterator_tag, GET_ITERATOR_COLUMN_COUNT + 4);
875 
876 /**
877  * @brief Get the category from an NVT iterator.
878  *
879  * @param[in]  iterator  Iterator.
880  *
881  * @return Category.
882  */
883 int
nvt_iterator_category(iterator_t * iterator)884 nvt_iterator_category (iterator_t* iterator)
885 {
886   int ret;
887   if (iterator->done) return -1;
888   ret = iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 5);
889   return ret;
890 }
891 
892 /**
893  * @brief Get the family from an NVT iterator.
894  *
895  * @param[in]  iterator  Iterator.
896  *
897  * @return Family, or NULL if iteration is complete.  Freed by
898  *         cleanup_iterator.
899  */
900 DEF_ACCESS (nvt_iterator_family, GET_ITERATOR_COLUMN_COUNT + 6);
901 
902 /**
903  * @brief Get the cvss_base from an NVT iterator.
904  *
905  * @param[in]  iterator  Iterator.
906  *
907  * @return Cvss_base, or NULL if iteration is complete.  Freed by
908  *         cleanup_iterator.
909  */
910 DEF_ACCESS (nvt_iterator_cvss_base, GET_ITERATOR_COLUMN_COUNT + 7);
911 
912 /**
913  * @brief Get the qod from an NVT iterator.
914  *
915  * @param[in]  iterator  Iterator.
916  *
917  * @return QoD, or NULL if iteration is complete.  Freed by
918  *         cleanup_iterator.
919  */
920 DEF_ACCESS (nvt_iterator_qod, GET_ITERATOR_COLUMN_COUNT + 10);
921 
922 /**
923  * @brief Get the qod_type from an NVT iterator.
924  *
925  * @param[in]  iterator  Iterator.
926  *
927  * @return QoD type, or NULL if iteration is complete.  Freed by
928  *         cleanup_iterator.
929  */
930 DEF_ACCESS (nvt_iterator_qod_type, GET_ITERATOR_COLUMN_COUNT + 11);
931 
932 /**
933  * @brief Get the solution_type from an NVT iterator.
934  *
935  * @param[in]  iterator  Iterator.
936  *
937  * @return Solution Type, or NULL if iteration is complete.  Freed by
938  *         cleanup_iterator.
939  */
940 DEF_ACCESS (nvt_iterator_solution_type, GET_ITERATOR_COLUMN_COUNT + 12);
941 
942 /**
943  * @brief Get the solution from an NVT iterator.
944  *
945  * @param[in]  iterator  Iterator.
946  *
947  * @return Solution, or NULL if iteration is complete.  Freed by
948  *         cleanup_iterator.
949  */
950 DEF_ACCESS (nvt_iterator_solution, GET_ITERATOR_COLUMN_COUNT + 14);
951 
952 /**
953  * @brief Get the summary from an NVT iterator.
954  *
955  * @param[in]  iterator  Iterator.
956  *
957  * @return Summary, or NULL if iteration is complete.  Freed by
958  *         cleanup_iterator.
959  */
960 DEF_ACCESS (nvt_iterator_summary, GET_ITERATOR_COLUMN_COUNT + 15);
961 
962 /**
963  * @brief Get the insight from an NVT iterator.
964  *
965  * @param[in]  iterator  Iterator.
966  *
967  * @return Insight, or NULL if iteration is complete.  Freed by
968  *         cleanup_iterator.
969  */
970 DEF_ACCESS (nvt_iterator_insight, GET_ITERATOR_COLUMN_COUNT + 16);
971 
972 /**
973  * @brief Get the affected from an NVT iterator.
974  *
975  * @param[in]  iterator  Iterator.
976  *
977  * @return Affected, or NULL if iteration is complete.  Freed by
978  *         cleanup_iterator.
979  */
980 DEF_ACCESS (nvt_iterator_affected, GET_ITERATOR_COLUMN_COUNT + 17);
981 
982 /**
983  * @brief Get the impact from an NVT iterator.
984  *
985  * @param[in]  iterator  Iterator.
986  *
987  * @return Impact, or NULL if iteration is complete.  Freed by
988  *         cleanup_iterator.
989  */
990 DEF_ACCESS (nvt_iterator_impact, GET_ITERATOR_COLUMN_COUNT + 18);
991 
992 /**
993  * @brief Get the detection from an NVT iterator.
994  *
995  * @param[in]  iterator  Iterator.
996  *
997  * @return Detection, or NULL if iteration is complete.  Freed by
998  *         cleanup_iterator.
999  */
1000 DEF_ACCESS (nvt_iterator_detection, GET_ITERATOR_COLUMN_COUNT + 19);
1001 
1002 /**
1003  * @brief Get the solution method from an NVT iterator.
1004  *
1005  * @param[in]  iterator  Iterator.
1006  *
1007  * @return Solution method, or NULL if iteration is complete.  Freed by
1008  *         cleanup_iterator.
1009  */
1010 DEF_ACCESS (nvt_iterator_solution_method, GET_ITERATOR_COLUMN_COUNT + 20);
1011 
1012 /**
1013  * @brief Get the default timeout of an NVT.
1014  *
1015  * @param[in]  oid  The OID of the NVT to get the timeout of.
1016  *
1017  * @return  Newly allocated string of the timeout in seconds or NULL.
1018  */
1019 char *
nvt_default_timeout(const char * oid)1020 nvt_default_timeout (const char* oid)
1021 {
1022   return sql_string ("SELECT value FROM nvt_preferences"
1023                      " WHERE name = '%s:0:entry:Timeout'",
1024                      oid);
1025 }
1026 
1027 /**
1028  * @brief Get the family of an NVT.
1029  *
1030  * @param[in]  oid  The OID of the NVT.
1031  *
1032  * @return Newly allocated string of the family, or NULL.
1033  */
1034 char *
nvt_family(const char * oid)1035 nvt_family (const char *oid)
1036 {
1037   gchar *quoted_oid;
1038   char *ret;
1039 
1040   quoted_oid = sql_quote (oid);
1041   ret = sql_string ("SELECT family FROM nvts WHERE oid = '%s' LIMIT 1;",
1042                     quoted_oid);
1043   g_free (quoted_oid);
1044   return ret;
1045 }
1046 
1047 /**
1048  * @brief Get the number of NVTs in one or all families.
1049  *
1050  * @param[in]  family  Family name.  NULL for all families.
1051  *
1052  * @return Number of NVTs in family, or total number of nvts.
1053  */
1054 int
family_nvt_count(const char * family)1055 family_nvt_count (const char *family)
1056 {
1057   gchar *quoted_family;
1058 
1059   if (family == NULL)
1060     {
1061       static int nvt_count = -1;
1062       if (nvt_count == -1)
1063         nvt_count = sql_int ("SELECT COUNT(*) FROM nvts"
1064                              " WHERE family != 'Credentials';");
1065       return nvt_count;
1066     }
1067 
1068   quoted_family = sql_quote (family);
1069   int ret = sql_int ("SELECT COUNT(*) FROM nvts WHERE family = '%s';",
1070                      quoted_family);
1071   g_free (quoted_family);
1072   return ret;
1073 }
1074 
1075 /**
1076  * @brief Get the number of families.
1077  *
1078  * @return Total number of families.
1079  */
1080 int
family_count()1081 family_count ()
1082 {
1083   return sql_int ("SELECT COUNT(distinct family) FROM nvts"
1084                   " WHERE family != 'Credentials';");
1085 }
1086 
1087 /**
1088  * @brief Insert a NVT preferences.
1089  *
1090  * @param[in] nvt_preference  Preference.
1091  * @param[in] dummy           Dummy arg for g_list_foreach.
1092  *
1093  */
1094 static void
insert_nvt_preference(gpointer nvt_preference,gpointer dummy)1095 insert_nvt_preference (gpointer nvt_preference, gpointer dummy)
1096 {
1097   preference_t *preference;
1098 
1099   if (nvt_preference == NULL)
1100     return;
1101 
1102   preference = (preference_t*) nvt_preference;
1103   manage_nvt_preference_add (preference->name, preference->value);
1104 }
1105 
1106 /**
1107  * @brief Inserts NVT preferences in DB from a list of nvt_preference_t structures.
1108  *
1109  * @param[in]  nvt_preferences_list     List of nvts to be inserted.
1110  */
1111 static void
insert_nvt_preferences_list(GList * nvt_preferences_list)1112 insert_nvt_preferences_list (GList *nvt_preferences_list)
1113 {
1114   g_list_foreach (nvt_preferences_list, insert_nvt_preference, NULL);
1115 }
1116 
1117 /**
1118  * @brief Set the NVT update check time in the meta table.
1119  *
1120  * @param[in]  count_new       Number of new VTs with current update.
1121  * @param[in]  count_modified  Number of modified VTs with current update.
1122  */
1123 static void
set_nvts_check_time(int count_new,int count_modified)1124 set_nvts_check_time (int count_new, int count_modified)
1125 {
1126   if (sql_int ("SELECT NOT EXISTS (SELECT * FROM meta"
1127                "                   WHERE name = 'nvts_check_time')"))
1128     sql ("INSERT INTO meta (name, value)"
1129          " VALUES ('nvts_check_time', m_now ());");
1130   else if (sql_int ("SELECT value = '0' FROM meta"
1131                     " WHERE name = 'nvts_check_time';"))
1132     sql ("UPDATE meta SET value = m_now ()"
1133          " WHERE name = 'nvts_check_time';");
1134   else
1135     {
1136       if (count_new > 0)
1137         event (EVENT_NEW_SECINFO, "nvt", 0, 0);
1138 
1139       if (count_modified > 0)
1140         event (EVENT_UPDATED_SECINFO, "nvt", 0, 0);
1141 
1142       sql ("UPDATE meta SET value = m_now ()"
1143            " WHERE name = 'nvts_check_time';");
1144     }
1145 }
1146 
1147 /**
1148  * @brief Update NVT from VT XML.
1149  *
1150  * @param[in]  vt           OSP GET_VTS VT element.
1151  * @param[in]  oid          OID of NVT.
1152  * @param[in]  preferences  All NVT preferences.
1153  *
1154  * @return 0 success, -1 error.
1155  */
1156 static int
update_preferences_from_vt(entity_t vt,const gchar * oid,GList ** preferences)1157 update_preferences_from_vt (entity_t vt, const gchar *oid, GList **preferences)
1158 {
1159   entity_t params, param;
1160   entities_t children;
1161 
1162   assert (preferences);
1163 
1164   params = entity_child (vt, "params");
1165   if (params == NULL)
1166     return 0;
1167 
1168   children = params->entities;
1169   while ((param = first_entity (children)))
1170     {
1171       if (strcasecmp (entity_name (param), "param") == 0)
1172         {
1173           const gchar *type, *id;
1174           entity_t name, def;
1175 
1176           type = entity_attribute (param, "type");
1177           id = entity_attribute (param, "id");
1178           name = entity_child (param, "name");
1179           def = entity_child (param, "default");
1180 
1181           if (type == NULL)
1182             {
1183               GString *debug = g_string_new ("");
1184               g_warning ("%s: PARAM missing type attribute", __func__);
1185               print_entity_to_string (param, debug);
1186               g_warning ("%s: PARAM: %s", __func__, debug->str);
1187               g_string_free (debug, TRUE);
1188             }
1189           else if (id == NULL)
1190             {
1191               GString *debug = g_string_new ("");
1192               g_warning ("%s: PARAM missing id attribute", __func__);
1193               print_entity_to_string (param, debug);
1194               g_warning ("%s: PARAM: %s", __func__, debug->str);
1195               g_string_free (debug, TRUE);
1196             }
1197           else if (name == NULL)
1198             {
1199               GString *debug = g_string_new ("");
1200               g_warning ("%s: PARAM missing NAME", __func__);
1201               print_entity_to_string (param, debug);
1202               g_warning ("%s: PARAM: %s", __func__, debug->str);
1203               g_string_free (debug, TRUE);
1204             }
1205           else
1206             {
1207               gchar *full_name;
1208               preference_t *preference;
1209 
1210               full_name = g_strdup_printf ("%s:%s:%s:%s",
1211                                            oid,
1212                                            id,
1213                                            type,
1214                                            entity_text (name));
1215 
1216               blank_control_chars (full_name);
1217               preference = g_malloc0 (sizeof (preference_t));
1218               preference->name = full_name;
1219               if (def)
1220                 preference->value = g_strdup (entity_text (def));
1221               else
1222                 preference->value = g_strdup ("");
1223               *preferences = g_list_prepend (*preferences, preference);
1224             }
1225         }
1226 
1227       children = next_entities (children);
1228     }
1229 
1230   return 0;
1231 }
1232 
1233 /**
1234  * @brief Create NVTI structure from VT XML.
1235  *
1236  * @param[in]  vt           OSP GET_VTS VT element.
1237  *
1238  * @return The NVTI object on success (needs to be free'd), NULL on error.
1239  */
1240 static nvti_t *
nvti_from_vt(entity_t vt)1241 nvti_from_vt (entity_t vt)
1242 {
1243   nvti_t *nvti = nvti_new ();
1244   const char *id;
1245   entity_t name, summary, insight, affected, impact, detection, solution;
1246   entity_t creation_time, modification_time;
1247   entity_t refs, ref, custom, family, category, deprecated;
1248   entity_t severities, severity;
1249 
1250   entities_t children;
1251 
1252   id = entity_attribute (vt, "id");
1253   if (id == NULL)
1254     {
1255       g_warning ("%s: VT missing id attribute", __func__);
1256       nvti_free (nvti);
1257       return NULL;
1258     }
1259   nvti_set_oid (nvti, id);
1260 
1261   name = entity_child (vt, "name");
1262   if (name == NULL)
1263     {
1264       g_warning ("%s: VT missing NAME", __func__);
1265       nvti_free (nvti);
1266       return NULL;
1267     }
1268   nvti_set_name (nvti, entity_text (name));
1269 
1270   summary = entity_child (vt, "summary");
1271   if (summary)
1272     nvti_set_summary (nvti, entity_text (summary));
1273 
1274   insight = entity_child (vt, "insight");
1275   if (insight)
1276     nvti_set_insight (nvti, entity_text (insight));
1277 
1278   affected = entity_child (vt, "affected");
1279   if (affected)
1280     nvti_set_affected (nvti, entity_text (affected));
1281 
1282   impact = entity_child (vt, "impact");
1283   if (impact)
1284     nvti_set_impact (nvti, entity_text (impact));
1285 
1286   creation_time = entity_child (vt, "creation_time");
1287   if (creation_time)
1288     nvti_set_creation_time (nvti, strtol (entity_text (creation_time),
1289                                           NULL, 10));
1290 
1291   modification_time = entity_child (vt, "modification_time");
1292   if (modification_time)
1293     nvti_set_modification_time (nvti, strtol (entity_text (modification_time),
1294                                               NULL, 10));
1295 
1296   detection = entity_child (vt, "detection");
1297   if (detection)
1298     {
1299       const gchar *qod;
1300 
1301       nvti_set_detection (nvti, entity_text (detection));
1302 
1303       qod = entity_attribute (detection, "qod");
1304       if (qod == NULL)
1305         nvti_set_qod_type (nvti, entity_attribute (detection, "qod_type"));
1306       else
1307         nvti_set_qod (nvti, qod);
1308     }
1309 
1310   solution = entity_child (vt, "solution");
1311   if (solution)
1312     {
1313       const gchar *type, *method;
1314 
1315       nvti_set_solution (nvti, entity_text (solution));
1316 
1317       type = entity_attribute (solution, "type");
1318       if (type == NULL)
1319         g_debug ("%s: SOLUTION missing type", __func__);
1320       else
1321         nvti_set_solution_type (nvti, type);
1322 
1323       method = entity_attribute (solution, "method");
1324       if (method)
1325         nvti_set_solution_method (nvti, method);
1326     }
1327 
1328   severities = entity_child (vt, "severities");
1329   if (severities == NULL)
1330     {
1331       g_warning ("%s: VT missing SEVERITIES", __func__);
1332       nvti_free (nvti);
1333       return NULL;
1334     }
1335 
1336   children = severities->entities;
1337   while ((severity = first_entity (children)))
1338     {
1339       const gchar *severity_type;
1340 
1341       severity_type = entity_attribute (severity, "type");
1342 
1343       if (severity_type == NULL)
1344         {
1345           GString *debug = g_string_new ("");
1346           g_warning ("%s: SEVERITY missing type attribute", __func__);
1347           print_entity_to_string (severity, debug);
1348           g_warning ("%s: severity: %s", __func__, debug->str);
1349           g_string_free (debug, TRUE);
1350         }
1351       else
1352         {
1353           entity_t value;
1354 
1355           value = entity_child (severity, "value");
1356 
1357           if (!value)
1358             {
1359               GString *debug = g_string_new ("");
1360               g_warning ("%s: SEVERITY missing value element", __func__);
1361               print_entity_to_string (severity, debug);
1362               g_warning ("%s: severity: %s", __func__, debug->str);
1363               g_string_free (debug, TRUE);
1364             }
1365           else
1366             {
1367               entity_t origin, severity_date;
1368               double cvss_base_dbl;
1369               gchar * cvss_base;
1370               time_t parsed_severity_date;
1371 
1372               cvss_base_dbl
1373                 = get_cvss_score_from_base_metrics (entity_text (value));
1374 
1375               origin
1376                 = entity_child (severity, "origin");
1377               severity_date
1378                 = entity_child (severity, "date");
1379 
1380               if (severity_date)
1381                 parsed_severity_date = strtol (entity_text (severity_date),
1382                                                NULL, 10);
1383               else
1384                 parsed_severity_date = nvti_creation_time (nvti);
1385 
1386               nvti_add_vtseverity (nvti,
1387                 vtseverity_new (severity_type,
1388                                 origin ? entity_text (origin) : NULL,
1389                                 parsed_severity_date,
1390                                 cvss_base_dbl,
1391                                 entity_text (value)));
1392 
1393               nvti_add_tag (nvti, "cvss_base_vector", entity_text (value));
1394 
1395               cvss_base = g_strdup_printf ("%.1f",
1396                 get_cvss_score_from_base_metrics (entity_text (value)));
1397               nvti_set_cvss_base (nvti, cvss_base);
1398               g_free (cvss_base);
1399             }
1400         }
1401 
1402       children = next_entities (children);
1403     }
1404 
1405   refs = entity_child (vt, "refs");
1406   if (refs)
1407     {
1408       children = refs->entities;
1409       while ((ref = first_entity (children)))
1410         {
1411           const gchar *ref_type;
1412 
1413           ref_type = entity_attribute (ref, "type");
1414           if (ref_type == NULL)
1415             {
1416               GString *debug = g_string_new ("");
1417               g_warning ("%s: REF missing type attribute", __func__);
1418               print_entity_to_string (ref, debug);
1419               g_warning ("%s: ref: %s", __func__, debug->str);
1420               g_string_free (debug, TRUE);
1421             }
1422           else
1423             {
1424               const gchar *ref_id;
1425 
1426               ref_id = entity_attribute (ref, "id");
1427               if (ref_id == NULL)
1428                 {
1429                   GString *debug = g_string_new ("");
1430                   g_warning ("%s: REF missing id attribute", __func__);
1431                   print_entity_to_string (ref, debug);
1432                   g_warning ("%s: ref: %s", __func__, debug->str);
1433                   g_string_free (debug, TRUE);
1434                 }
1435               else
1436                 {
1437                   nvti_add_vtref (nvti, vtref_new (ref_type, ref_id, NULL));
1438                 }
1439             }
1440 
1441           children = next_entities (children);
1442         }
1443     }
1444 
1445   custom = entity_child (vt, "custom");
1446   if (custom == NULL)
1447     {
1448       g_warning ("%s: VT missing CUSTOM", __func__);
1449       nvti_free (nvti);
1450       return NULL;
1451     }
1452 
1453   family = entity_child (custom, "family");
1454   if (family == NULL)
1455     {
1456       g_warning ("%s: VT/CUSTOM missing FAMILY", __func__);
1457       nvti_free (nvti);
1458       return NULL;
1459     }
1460   nvti_set_family (nvti, entity_text (family));
1461 
1462   category = entity_child (custom, "category");
1463   if (category == NULL)
1464     {
1465       g_warning ("%s: VT/CUSTOM missing CATEGORY", __func__);
1466       nvti_free (nvti);
1467       return NULL;
1468     }
1469   nvti_set_category (nvti, atoi (entity_text (category)));
1470 
1471   deprecated = entity_child (custom, "deprecated");
1472   if (deprecated)
1473     {
1474       nvti_add_tag (nvti, "deprecated", entity_text (deprecated));
1475     }
1476 
1477   return nvti;
1478 }
1479 
1480 /**
1481  * @brief Update NVTs from VTs XML.
1482  *
1483  * @param[in]  get_vts_response      OSP GET_VTS response.
1484  * @param[in]  scanner_feed_version  Version of feed from scanner.
1485  *
1486  * @return 0 success, 1 VT integrity check failed, -1 error
1487  */
1488 static int
update_nvts_from_vts(entity_t * get_vts_response,const gchar * scanner_feed_version)1489 update_nvts_from_vts (entity_t *get_vts_response,
1490                       const gchar *scanner_feed_version)
1491 {
1492   entity_t vts, vt;
1493   entities_t children;
1494   GList *preferences;
1495   int count_modified_vts, count_new_vts;
1496   time_t feed_version_epoch;
1497   const char *osp_vt_hash;
1498 
1499   count_modified_vts = 0;
1500   count_new_vts = 0;
1501 
1502   feed_version_epoch = nvts_feed_version_epoch();
1503 
1504   vts = entity_child (*get_vts_response, "vts");
1505   if (vts == NULL)
1506     {
1507       g_warning ("%s: VTS missing", __func__);
1508       return -1;
1509     }
1510 
1511   osp_vt_hash = entity_attribute (vts, "sha256_hash");
1512 
1513   sql_begin_immediate ();
1514 
1515   if (sql_int ("SELECT coalesce ((SELECT CAST (value AS INTEGER)"
1516                "                  FROM meta"
1517                "                  WHERE name = 'checked_preferences'),"
1518                "                 0);")
1519       == 0)
1520     /* We're in the first NVT sync after migrating preference names.
1521      *
1522      * If a preference was removed from an NVT then the preference will be in
1523      * nvt_preferences in the old format, but we will not get a new version
1524      * of the preference name from the sync.  For example "Alle Dateien
1525      * Auflisten" was removed from 1.3.6.1.4.1.25623.1.0.94023.
1526      *
1527      * If a preference was not in the migrator then the new version of the
1528      * preference would be inserted alongside the old version, resulting in a
1529      * duplicate when the name of the old version was corrected.
1530      *
1531      * To solve both cases, we remove all nvt_preferences. */
1532     sql ("TRUNCATE nvt_preferences;");
1533 
1534   children = vts->entities;
1535   while ((vt = first_entity (children)))
1536     {
1537       nvti_t *nvti = nvti_from_vt (vt);
1538 
1539       if (nvti == NULL)
1540         continue;
1541 
1542       if (nvti_creation_time (nvti) > feed_version_epoch)
1543         count_new_vts += 1;
1544       else
1545         count_modified_vts += 1;
1546 
1547       insert_nvt (nvti);
1548 
1549       preferences = NULL;
1550       if (update_preferences_from_vt (vt, nvti_oid (nvti), &preferences))
1551         {
1552           sql_rollback ();
1553           return -1;
1554         }
1555       sql ("DELETE FROM nvt_preferences WHERE name LIKE '%s:%%';",
1556            nvti_oid (nvti));
1557       insert_nvt_preferences_list (preferences);
1558       g_list_free_full (preferences, g_free);
1559 
1560       nvti_free (nvti);
1561       children = next_entities (children);
1562     }
1563 
1564   set_nvts_check_time (count_new_vts, count_modified_vts);
1565 
1566   set_nvts_feed_version (scanner_feed_version);
1567 
1568   if (check_config_families ())
1569     g_warning ("%s: Error updating config families."
1570                "  One or more configs refer to an outdated family of an NVT.",
1571                __func__);
1572   update_all_config_caches ();
1573 
1574   g_info ("Updating VTs in database ... %i new VTs, %i changed VTs",
1575           count_new_vts, count_modified_vts);
1576 
1577   sql_commit ();
1578 
1579   if (osp_vt_hash && strcmp (osp_vt_hash, ""))
1580     {
1581       char *db_vts_hash;
1582 
1583       /*
1584        * The hashed string used for verifying the NVTs generated as follows:
1585        *
1586        * For each NVT, sorted by OID, concatenate:
1587        *   - the OID
1588        *   - the modification time as seconds since epoch
1589        *   - the preferences sorted as strings(!) and concatenated including:
1590        *     - the id
1591        *     - the name
1592        *     - the default value (including choices for the "radio" type)
1593        *
1594        * All values are concatenated without a separator.
1595        */
1596       db_vts_hash
1597         = sql_string ("SELECT encode ("
1598                       "  digest (vts_verification_str (), 'SHA256'),"
1599                       "  'hex'"
1600                       " );");
1601 
1602       if (strcmp (osp_vt_hash, db_vts_hash ? db_vts_hash : ""))
1603         {
1604           g_warning ("%s: SHA-256 hash of the VTs in the database (%s)"
1605                      " does not match the one from the scanner (%s).",
1606                      __func__, db_vts_hash, osp_vt_hash);
1607 
1608           g_free (db_vts_hash);
1609           return 1;
1610         }
1611 
1612       g_free (db_vts_hash);
1613     }
1614   else
1615     g_warning ("%s: No SHA-256 hash received from scanner, skipping check.",
1616                __func__);
1617 
1618   return 0;
1619 }
1620 
1621 /**
1622  * @brief Check that preference names are in the new format.
1623  *
1624  * @param[in]  table  Table name.
1625  */
1626 static void
check_old_preference_names(const gchar * table)1627 check_old_preference_names (const gchar *table)
1628 {
1629   /* 1.3.6.1.4.1.25623.1.0.14259:checkbox:Log nmap output
1630    * =>
1631    * 1.3.6.1.4.1.25623.1.0.14259:21:checkbox:Log nmap output */
1632 
1633   sql ("UPDATE %s"
1634        " SET name = nvt_preferences.name"
1635        " FROM nvt_preferences"
1636        " WHERE %s.name ~ '.*:.*:.*'"
1637        " AND nvt_preferences.name ~ '.*:.*:.*:.*'"
1638        " AND %s.name = regexp_replace (nvt_preferences.name,"
1639        "                               E'([^:]+):[^:]+:(.*)', '\\1:\\2');",
1640        table,
1641        table,
1642        table,
1643        table);
1644 }
1645 
1646 /**
1647  * @brief Update config preferences where the name has changed in the NVTs.
1648  *
1649  * @param[in]  trash              Whether to update the trash table.
1650  * @param[in]  modification_time  Time NVTs considered must be modified after.
1651  */
1652 static void
check_preference_names(int trash,time_t modification_time)1653 check_preference_names (int trash, time_t modification_time)
1654 {
1655   iterator_t prefs;
1656 
1657   sql_begin_immediate ();
1658 
1659   init_iterator (&prefs,
1660                  "WITH new_pref_matches AS"
1661                  " (SELECT substring (nvt_preferences.name,"
1662                  "                    '^([^:]*:[^:]*)') || ':%%' AS match,"
1663                  "          name AS new_name"
1664                  "     FROM nvt_preferences"
1665                  "    WHERE substr (name, 0, position (':' IN name))"
1666                  "          IN (SELECT oid FROM nvts"
1667                  "              WHERE modification_time > %ld))"
1668                  " SELECT c_prefs.id, c_prefs.name as old_name, new_name,"
1669                  "        configs%s.uuid AS config_id"
1670                  "  FROM config_preferences%s AS c_prefs"
1671                  "  JOIN new_pref_matches"
1672                  "    ON c_prefs.name LIKE new_pref_matches.match"
1673                  "  JOIN configs%s ON configs%s.id = c_prefs.config"
1674                  " WHERE c_prefs.name != new_name;",
1675                  modification_time,
1676                  trash ? "_trash" : "",
1677                  trash ? "_trash" : "",
1678                  trash ? "_trash" : "",
1679                  trash ? "_trash" : "");
1680 
1681   while (next (&prefs))
1682     {
1683       resource_t preference;
1684       const char *old_name, *new_name, *config_id;
1685       gchar *quoted_new_name;
1686 
1687       preference = iterator_int64 (&prefs, 0);
1688       old_name = iterator_string (&prefs, 1);
1689       new_name = iterator_string (&prefs, 2);
1690       config_id = iterator_string (&prefs, 3);
1691 
1692       g_message ("Preference '%s' of %sconfig %s changed to '%s'",
1693                  old_name,
1694                  trash ? "trash " : "",
1695                  config_id,
1696                  new_name);
1697 
1698       quoted_new_name = sql_quote (new_name);
1699 
1700       sql ("UPDATE config_preferences%s"
1701            " SET name = '%s'"
1702            " WHERE id = %llu",
1703            trash ? "_trash " : "",
1704            quoted_new_name,
1705            preference);
1706 
1707       g_free (quoted_new_name);
1708     }
1709 
1710   sql_commit ();
1711 
1712   cleanup_iterator (&prefs);
1713 }
1714 
1715 /**
1716  * @brief Initialise an NVT severity iterator.
1717  *
1718  * @param[in]  iterator  Iterator.
1719  * @param[in]  oid       OID of NVT.
1720  */
1721 void
init_nvt_severity_iterator(iterator_t * iterator,const char * oid)1722 init_nvt_severity_iterator (iterator_t* iterator, const char *oid)
1723 {
1724   gchar *quoted_oid;
1725   quoted_oid = sql_quote (oid ? oid : "");
1726 
1727   init_iterator (iterator,
1728                  "SELECT type, origin, iso_time(date), score, value"
1729                  " FROM vt_severities"
1730                  " WHERE vt_oid = '%s'",
1731                  quoted_oid);
1732 
1733   g_free (quoted_oid);
1734 }
1735 
1736 /**
1737  * @brief Gets the type from an NVT severity iterator.
1738  *
1739  * @param[in]  iterator  Iterator.
1740  *
1741  * @return The type of the severity.
1742  */
1743 DEF_ACCESS (nvt_severity_iterator_type, 0)
1744 
1745 /**
1746  * @brief Gets the origin from an NVT severity iterator.
1747  *
1748  * @param[in]  iterator  Iterator.
1749  *
1750  * @return The origin of the severity.
1751  */
1752 DEF_ACCESS (nvt_severity_iterator_origin, 1);
1753 
1754 /**
1755  * @brief Gets the date from an NVT severity iterator.
1756  *
1757  * @param[in]  iterator  Iterator.
1758  *
1759  * @return The date of the severity in ISO time format.
1760  */
1761 DEF_ACCESS (nvt_severity_iterator_date, 2);
1762 
1763 /**
1764  * @brief Gets the score from an NVT severity iterator.
1765  *
1766  * @param[in]  iterator  Iterator.
1767  *
1768  * @return The score of the severity.
1769  */
1770 double
nvt_severity_iterator_score(iterator_t * iterator)1771 nvt_severity_iterator_score (iterator_t *iterator)
1772 {
1773   return iterator_double (iterator, 3);
1774 }
1775 
1776 /**
1777  * @brief Gets the value from an NVT severity iterator.
1778  *
1779  * @param[in]  iterator  Iterator.
1780  *
1781  * @return The value of the severity in ISO time format.
1782  */
1783 DEF_ACCESS (nvt_severity_iterator_value, 4);
1784 
1785 /**
1786  * @brief Update VTs via OSP.
1787  *
1788  * @param[in]  update_socket         Socket to use to contact scanner.
1789  * @param[in]  db_feed_version       Feed version from meta table.
1790  * @param[in]  scanner_feed_version  Feed version from scanner.
1791  *
1792  * @return 0 success, 1 VT integrity check failed, -1 error.
1793  */
1794 static int
update_nvt_cache_osp(const gchar * update_socket,gchar * db_feed_version,gchar * scanner_feed_version)1795 update_nvt_cache_osp (const gchar *update_socket, gchar *db_feed_version,
1796                       gchar *scanner_feed_version)
1797 {
1798   osp_connection_t *connection;
1799   GSList *scanner_prefs;
1800   entity_t vts;
1801   osp_get_vts_opts_t get_vts_opts;
1802   time_t old_nvts_last_modified;
1803   int ret;
1804 
1805   if (db_feed_version == NULL
1806       || strcmp (db_feed_version, "") == 0
1807       || strcmp (db_feed_version, "0") == 0)
1808     old_nvts_last_modified = 0;
1809   else
1810     old_nvts_last_modified
1811       = (time_t) sql_int64_0 ("SELECT max(modification_time) FROM nvts");
1812 
1813   connection = osp_connection_new (update_socket, 0, NULL, NULL, NULL);
1814   if (!connection)
1815     {
1816       g_warning ("%s: failed to connect to %s (2)", __func__,
1817                  update_socket);
1818       return -1;
1819     }
1820 
1821   get_vts_opts = osp_get_vts_opts_default;
1822   if (db_feed_version)
1823     get_vts_opts.filter = g_strdup_printf ("modification_time>%s", db_feed_version);
1824   else
1825     get_vts_opts.filter = NULL;
1826   if (osp_get_vts_ext (connection, get_vts_opts, &vts))
1827     {
1828       g_warning ("%s: failed to get VTs", __func__);
1829       g_free (get_vts_opts.filter);
1830       return -1;
1831     }
1832   g_free (get_vts_opts.filter);
1833 
1834   osp_connection_close (connection);
1835   ret = update_nvts_from_vts (&vts, scanner_feed_version);
1836   free_entity (vts);
1837   if (ret)
1838     return ret;
1839 
1840   /* Update scanner preferences */
1841   connection = osp_connection_new (update_socket, 0, NULL, NULL, NULL);
1842   if (!connection)
1843     {
1844       g_warning ("%s: failed to connect to %s (3)",
1845                 __func__, update_socket);
1846       return -1;
1847     }
1848 
1849   scanner_prefs = NULL;
1850   if (osp_get_scanner_details (connection, NULL, &scanner_prefs))
1851     {
1852       g_warning ("%s: failed to get scanner preferences", __func__);
1853       osp_connection_close (connection);
1854       return -1;
1855     }
1856   else
1857     {
1858       GString *prefs_sql;
1859       GSList *point;
1860       int first;
1861 
1862       point = scanner_prefs;
1863       first = 1;
1864 
1865       osp_connection_close (connection);
1866       prefs_sql = g_string_new ("INSERT INTO nvt_preferences (name, value)"
1867                                 " VALUES");
1868       while (point)
1869         {
1870           osp_param_t *param;
1871           gchar *quoted_name, *quoted_value;
1872 
1873           param = point->data;
1874           quoted_name = sql_quote (osp_param_id (param));
1875           quoted_value = sql_quote (osp_param_default (param));
1876 
1877           g_string_append_printf (prefs_sql,
1878                                   "%s ('%s', '%s')",
1879                                   first ? "" : ",",
1880                                   quoted_name,
1881                                   quoted_value);
1882           first = 0;
1883           point = g_slist_next (point);
1884           g_free (quoted_name);
1885           g_free (quoted_value);
1886         }
1887       g_string_append (prefs_sql,
1888                        " ON CONFLICT (name)"
1889                        " DO UPDATE SET value = EXCLUDED.value;");
1890 
1891       if (first == 0)
1892         {
1893           sql ("%s", prefs_sql->str);
1894         }
1895 
1896       g_string_free (prefs_sql, TRUE);
1897     }
1898 
1899   /* Update the cache of report counts. */
1900 
1901   reports_clear_count_cache_dynamic ();
1902 
1903   /* Tell the main process to update its NVTi cache. */
1904   sql ("UPDATE %s.meta SET value = 1 WHERE name = 'update_nvti_cache';",
1905        sql_schema ());
1906 
1907   g_info ("Updating VTs in database ... done (%i VTs).",
1908           sql_int ("SELECT count (*) FROM nvts;"));
1909 
1910   if (sql_int ("SELECT coalesce ((SELECT CAST (value AS INTEGER)"
1911                "                  FROM meta"
1912                "                  WHERE name = 'checked_preferences'),"
1913                "                 0);")
1914       == 0)
1915     {
1916       check_old_preference_names ("config_preferences");
1917       check_old_preference_names ("config_preferences_trash");
1918 
1919       /* Force update of names in new format in case hard-coded names
1920        * used by migrators are outdated */
1921       old_nvts_last_modified = 0;
1922 
1923       sql ("INSERT INTO meta (name, value)"
1924            " VALUES ('checked_preferences', 1)"
1925            " ON CONFLICT (name) DO UPDATE SET value = EXCLUDED.value;");
1926     }
1927 
1928   check_preference_names (0, old_nvts_last_modified);
1929   check_preference_names (1, old_nvts_last_modified);
1930 
1931   check_whole_only_in_configs ();
1932 
1933   return 0;
1934 }
1935 
1936 /**
1937  * @brief Get the VTs feed version from an OSP scanner.
1938  *
1939  * @param[in]  update_socket  Socket to use to contact ospd-openvas scanner.
1940  *
1941  * @return The feed version or NULL on error.
1942  */
1943 static char *
osp_scanner_feed_version(const gchar * update_socket)1944 osp_scanner_feed_version (const gchar *update_socket)
1945 {
1946   osp_connection_t *connection;
1947   gchar *error;
1948   gchar *scanner_feed_version;
1949 
1950   scanner_feed_version = NULL;
1951 
1952   connection = osp_connection_new (update_socket, 0, NULL, NULL, NULL);
1953   if (!connection)
1954     {
1955       g_debug ("%s: failed to connect to %s", __func__, update_socket);
1956       return NULL;
1957     }
1958 
1959   error = NULL;
1960   if (osp_get_vts_version (connection, &scanner_feed_version, &error))
1961     {
1962       g_debug ("%s: failed to get scanner_feed_version. %s",
1963                __func__, error ? : "");
1964       g_free (error);
1965       osp_connection_close (connection);
1966       return NULL;
1967     }
1968 
1969   osp_connection_close (connection);
1970 
1971   return scanner_feed_version;
1972 }
1973 
1974 /**
1975  * @brief Check VTs feed version status via OSP, optionally get versions.
1976  *
1977  * @param[in]  update_socket  Socket to use to contact ospd-openvas scanner.
1978  * @param[out] db_feed_version_out       Output of database feed version.
1979  * @param[out] scanner_feed_version_out  Output of scanner feed version.
1980  *
1981  * @return 0 VTs feed current, -1 error, 1 VT update needed.
1982  */
1983 static int
nvts_feed_version_status_internal(const gchar * update_socket,gchar ** db_feed_version_out,gchar ** scanner_feed_version_out)1984 nvts_feed_version_status_internal (const gchar *update_socket,
1985                                    gchar **db_feed_version_out,
1986                                    gchar **scanner_feed_version_out)
1987 {
1988   gchar *db_feed_version, *scanner_feed_version;
1989 
1990   if (db_feed_version_out)
1991     *db_feed_version_out = NULL;
1992   if (scanner_feed_version_out)
1993     *scanner_feed_version_out = NULL;
1994 
1995   db_feed_version = nvts_feed_version ();
1996   g_debug ("%s: db_feed_version: %s", __func__, db_feed_version);
1997   if (db_feed_version_out && db_feed_version)
1998     *db_feed_version_out = g_strdup (db_feed_version);
1999 
2000   scanner_feed_version = osp_scanner_feed_version (update_socket);
2001   g_debug ("%s: scanner_feed_version: %s", __func__, scanner_feed_version);
2002   if (scanner_feed_version == NULL)
2003     return -1;
2004   if (scanner_feed_version_out && scanner_feed_version)
2005     *scanner_feed_version_out = g_strdup (scanner_feed_version);
2006 
2007   if ((db_feed_version == NULL)
2008       || strcmp (scanner_feed_version, db_feed_version))
2009     {
2010       g_free (db_feed_version);
2011       g_free (scanner_feed_version);
2012       return 1;
2013     }
2014 
2015   return 0;
2016 }
2017 
2018 /**
2019  * @brief Check VTs feed version status
2020  *
2021  * @return 0 VTs feed current, 1 VT update needed, -1 error.
2022  */
2023 int
nvts_feed_version_status()2024 nvts_feed_version_status ()
2025 {
2026   return nvts_feed_version_status_internal (get_osp_vt_update_socket (),
2027                                             NULL,
2028                                             NULL);
2029 }
2030 
2031 /**
2032  * @brief Update VTs via OSP.
2033  *
2034  * Expect to be called in the child after a fork.
2035  *
2036  * @param[in]  update_socket  Socket to use to contact ospd-openvas scanner.
2037  *
2038  * @return 0 success, -1 error, 1 VT integrity check failed.
2039  */
2040 int
manage_update_nvt_cache_osp(const gchar * update_socket)2041 manage_update_nvt_cache_osp (const gchar *update_socket)
2042 {
2043   gchar *db_feed_version, *scanner_feed_version;
2044   int ret;
2045 
2046   /* Re-open DB after fork. */
2047 
2048   reinit_manage_process ();
2049   manage_session_init (current_credentials.uuid);
2050 
2051   /* Try update VTs. */
2052 
2053   ret = nvts_feed_version_status_internal (update_socket,
2054                                            &db_feed_version,
2055                                            &scanner_feed_version);
2056   if (ret == 1)
2057     {
2058       g_info ("OSP service has different VT status (version %s)"
2059               " from database (version %s, %i VTs). Starting update ...",
2060               scanner_feed_version, db_feed_version,
2061               sql_int ("SELECT count (*) FROM nvts;"));
2062 
2063       ret = update_nvt_cache_osp (update_socket, db_feed_version,
2064                                   scanner_feed_version);
2065 
2066       g_free (db_feed_version);
2067       g_free (scanner_feed_version);
2068       return ret;
2069     }
2070 
2071   return ret;
2072 }
2073 
2074 /**
2075  * @brief Sync NVTs if newer NVTs are available.
2076  *
2077  * @param[in]  fork_update_nvt_cache  Function to do the update.
2078  */
2079 void
manage_sync_nvts(int (* fork_update_nvt_cache)())2080 manage_sync_nvts (int (*fork_update_nvt_cache) ())
2081 {
2082   fork_update_nvt_cache ();
2083 }
2084 
2085 /**
2086  * @brief Update or rebuild NVT db.
2087  *
2088  * Caller must get the lock.
2089  *
2090  * @param[in]  update  0 rebuild, else update.
2091  *
2092  * @return 0 success, -1 error, -4 no osp update socket.
2093  */
2094 int
update_or_rebuild_nvts(int update)2095 update_or_rebuild_nvts (int update)
2096 {
2097   const char *osp_update_socket;
2098   gchar *db_feed_version, *scanner_feed_version;
2099   osp_connection_t *connection;
2100   int ret;
2101   gchar *error;
2102 
2103   if (check_osp_vt_update_socket ())
2104     {
2105       printf ("No OSP VT update socket found."
2106               " Use --osp-vt-update or change the 'OpenVAS Default'"
2107               " scanner to use the main ospd-openvas socket.\n");
2108       return -4;
2109     }
2110 
2111   osp_update_socket = get_osp_vt_update_socket ();
2112   if (osp_update_socket == NULL)
2113     {
2114       printf ("No OSP VT update socket set.\n");
2115       return -4;
2116     }
2117 
2118   db_feed_version = nvts_feed_version ();
2119   g_debug ("%s: db_feed_version: %s", __func__, db_feed_version);
2120 
2121   connection = osp_connection_new (osp_update_socket, 0, NULL, NULL, NULL);
2122   if (!connection)
2123     {
2124       printf ("Failed to connect to %s.\n", osp_update_socket);
2125       return -1;
2126     }
2127 
2128   error = NULL;
2129   if (osp_get_vts_version (connection, &scanner_feed_version, &error))
2130     {
2131       printf ("Failed to get scanner_version. %s\n", error ? : "");
2132       g_free (error);
2133       return -1;
2134     }
2135   g_debug ("%s: scanner_feed_version: %s", __func__, scanner_feed_version);
2136 
2137   osp_connection_close (connection);
2138 
2139   if (update == 0)
2140     {
2141       sql ("TRUNCATE nvts;");
2142       sql ("TRUNCATE nvt_preferences;");
2143       set_nvts_feed_version ("0");
2144     }
2145 
2146   ret = update_nvt_cache_osp (osp_update_socket, NULL, scanner_feed_version);
2147   if (ret)
2148     {
2149       return -1;
2150     }
2151 
2152   return 0;
2153 }
2154 
2155 /**
2156  * @brief Rebuild NVT db.
2157  *
2158  * @param[in]  log_config  Log configuration.
2159  * @param[in]  database    Location of manage database.
2160  *
2161  * @return 0 success, 1 VT integrity check failed, -1 error,
2162  *         -2 database is wrong version,
2163  *         -3 database needs to be initialised from server, -5 sync active.
2164  */
2165 int
manage_rebuild(GSList * log_config,const db_conn_info_t * database)2166 manage_rebuild (GSList *log_config, const db_conn_info_t *database)
2167 {
2168   int ret;
2169   static lockfile_t lockfile;
2170 
2171   g_info ("   Rebuilding NVTs.");
2172 
2173   switch (feed_lockfile_lock_timeout (&lockfile))
2174     {
2175       case 1:
2176         printf ("A feed sync is already running.\n");
2177         return -5;
2178       case -1:
2179         printf ("Error getting sync lock.\n");
2180         return -1;
2181     }
2182 
2183   ret = manage_option_setup (log_config, database);
2184   if (ret)
2185     {
2186       feed_lockfile_unlock (&lockfile);
2187       return ret;
2188     }
2189 
2190   sql_begin_immediate ();
2191   ret = update_or_rebuild_nvts (0);
2192   if (ret)
2193     sql_rollback ();
2194   else
2195     sql_commit ();
2196 
2197   feed_lockfile_unlock (&lockfile);
2198   manage_option_cleanup ();
2199 
2200   return ret;
2201 }
2202 
2203 /**
2204  * @brief Dump the string used to calculate the VTs verification hash
2205  *  to stdout.
2206  *
2207  * @param[in]  log_config  Log configuration.
2208  * @param[in]  database    Location of manage database.
2209  *
2210  * @return 0 success, -1 error, -2 database is wrong version,
2211  *         -3 database needs to be initialised from server, -5 sync active.
2212  */
2213 int
manage_dump_vt_verification(GSList * log_config,const db_conn_info_t * database)2214 manage_dump_vt_verification (GSList *log_config,
2215                              const db_conn_info_t *database)
2216 {
2217   int ret;
2218   static lockfile_t lockfile;
2219   char *verification_str;
2220 
2221   switch (feed_lockfile_lock_timeout (&lockfile))
2222     {
2223       case 1:
2224         printf ("A feed sync is already running.\n");
2225         return -5;
2226       case -1:
2227         printf ("Error getting sync lock.\n");
2228         return -1;
2229     }
2230 
2231   ret = manage_option_setup (log_config, database);
2232   if (ret)
2233     {
2234       feed_lockfile_unlock (&lockfile);
2235       return ret;
2236     }
2237 
2238   verification_str = sql_string ("SELECT vts_verification_str ();");
2239   printf ("%s\n", verification_str);
2240 
2241   feed_lockfile_unlock (&lockfile);
2242   manage_option_cleanup ();
2243 
2244   return 0;
2245 }