1 /* Copyright (C) 2019-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_configs.c
21 * @brief GVM management layer: Config SQL
22 *
23 * The Config SQL for the GVM management layer.
24 */
25
26 #include "manage_configs.h"
27 #include "manage_acl.h"
28 #include "manage_sql.h"
29 #include "manage_sql_configs.h"
30 #include "manage_sql_nvts.h"
31 #include "sql.h"
32
33 #include <assert.h>
34 #include <errno.h>
35 #include <glib/gstdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include <gvm/util/uuidutils.h>
40
41 #undef G_LOG_DOMAIN
42 /**
43 * @brief GLib log domain.
44 */
45 #define G_LOG_DOMAIN "md manage"
46
47
48 /* Static headers for internal non-SQL functions. */
49
50 int
51 sync_configs_with_feed (gboolean);
52
53
54 /* Static headers. */
55
56 static int
57 switch_representation (config_t, int);
58
59 static void
60 update_config_caches (config_t);
61
62
63 /* Helpers. */
64
65 /**
66 * @brief Test whether a string equal to a given string exists in an array.
67 *
68 * @param[in] array Array of gchar* pointers.
69 * @param[in] string String.
70 *
71 * @return 1 if a string equal to \arg string exists in \arg array, else 0.
72 */
73 static int
member(GPtrArray * array,const char * string)74 member (GPtrArray *array, const char *string)
75 {
76 const gchar *item;
77 int index = 0;
78 while ((item = (gchar*) g_ptr_array_index (array, index++)))
79 if (strcmp (item, string) == 0) return 1;
80 return 0;
81 }
82
83
84 /* NVT selectors. This is part of Configs.
85 *
86 * An NVT selector is a named selection of NVT's from the cache of all
87 * NVT's.
88 *
89 * An NVT selector is made up of zero or more selectors. The selectors
90 * combine in id order to make a selection. Depending on the choice
91 * of selectors the selection can be static or growing. A growing
92 * selection can grow when new NVT's enter the NVT cache, either because it
93 * selects new families or because it selects new NVT's within existing
94 * families.
95 *
96 * There are three types of selectors that an NVT selector can contain.
97 *
98 * 1) The "all selector", which selects all families and all NVT's in
99 * those families. The only way to construct the NVT selector so
100 * that it grows to includes new families, is to add this selector.
101 *
102 * 2) A "family" selector, which designates an entire family.
103 *
104 * 3) An "NVT" selector, which designates a single NVT.
105 *
106 * The naming overlaps here. It's a selector of type NVT, which is
107 * part of an "NVT selector" (a named collection of selectors).
108 *
109 * The family and NVT type selectors can either include or exclude the
110 * designated NVT's.
111 *
112 * While the all selector provides a way to select every single NVT, the
113 * empty NVT selector corresponds to an empty NVT set.
114 *
115 * The selectors provide a mechanism to select a wide range of NVT
116 * combinations. The mechanism allows for complex selections involving
117 * redundant selectors. The Manager, however, only implements a simple
118 * subset of the possible combinations of selectors. This simple subset
119 * is split into two cases.
120 *
121 * 1) Constraining the universe.
122 *
123 * The all selector and an optional exclude for each family,
124 * optional NVT includes in the excluded families, and optional NVT
125 * excludes in all other families.
126 *
127 * This allows a growing collection of families, while any family
128 * can still have a static NVT selection.
129 *
130 * 2) Generating from empty.
131 *
132 * An empty set of selectors with an optional include for each family,
133 * optional NVT excludes in the included families, and optional NVT
134 * includes in all other families.
135 *
136 * This allows a static collection of families, while any family
137 * can still grow when new NVT's enter the family.
138 *
139 * Either case allows one or more NVT's to be excluded from the family, both
140 * when the family is growing and when the family is static.
141 */
142
143 /* These could handle strange cases, like when a family is
144 * included then excluded, or all is included then later excluded.
145 * However, GMP prevents those cases from occurring. */
146
147 /**
148 * @brief Get the number of families selected by an NVT selector.
149 *
150 * A growing family which has all current NVT's excluded is still
151 * considered as selected by the NVT selector.
152 *
153 * @param[in] quoted_selector SQL-quoted selector name.
154 * @param[in] families_growing 1 if families are growing, else 0.
155 *
156 * @return The number of families selected by an NVT selector.
157 */
158 int
nvt_selector_family_count(const char * quoted_selector,int families_growing)159 nvt_selector_family_count (const char* quoted_selector, int families_growing)
160 {
161 if (families_growing)
162 /* Assume the only family selectors are excludes. */
163 return family_count ()
164 - sql_int ("SELECT COUNT(distinct family_or_nvt) FROM nvt_selectors"
165 " WHERE name = '%s'"
166 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
167 " AND exclude = 0"
168 " LIMIT 1;",
169 quoted_selector);
170
171 /* Assume that the only family selectors are includes, and that if a
172 * selection has any NVT includes then it only has NVT includes. */
173 return sql_int ("SELECT COUNT (DISTINCT family)"
174 " FROM (SELECT DISTINCT family FROM nvt_selectors"
175 " WHERE name = '%s'"
176 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
177 " AND exclude = 0"
178 " UNION SELECT family FROM nvt_selectors"
179 " WHERE name = '%s'"
180 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
181 " AND exclude = 0"
182 " AND family IS NOT NULL) AS subquery;",
183 quoted_selector,
184 quoted_selector);
185 }
186
187 /**
188 * @brief Get the family growth status of an NVT selector.
189 *
190 * @param[in] selector NVT selector.
191 *
192 * @return 1 growing, 0 static.
193 */
194 static int
nvt_selector_families_growing(const char * selector)195 nvt_selector_families_growing (const char* selector)
196 {
197 gchar *quoted_selector;
198 char *string;
199
200 /* The number of families can only grow if there is selector that includes
201 * all. */
202
203 quoted_selector = sql_quote (selector);
204 string = sql_string ("SELECT name FROM nvt_selectors"
205 " WHERE name = '%s'"
206 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_ALL)
207 " AND exclude = 0"
208 " LIMIT 1;",
209 quoted_selector);
210 g_free (quoted_selector);
211 if (string == NULL) return 0;
212 free (string);
213 return 1;
214 }
215
216 /**
217 * @brief Get the NVT growth status of an NVT selector.
218 *
219 * @param[in] quoted_selector SQL-quoted selector name.
220 * @param[in] families_growing 1 if families are growing, else 0.
221 *
222 * @return 1 growing, 0 static.
223 */
224 static int
nvt_selector_nvts_growing_2(const char * quoted_selector,int families_growing)225 nvt_selector_nvts_growing_2 (const char* quoted_selector, int families_growing)
226 {
227 if (families_growing)
228 /* Assume the only family selectors are excludes. */
229 return (family_count ()
230 - sql_int ("SELECT COUNT(distinct family_or_nvt) FROM nvt_selectors"
231 " WHERE name = '%s'"
232 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
233 " AND exclude = 0"
234 " LIMIT 1;",
235 quoted_selector))
236 > 0;
237
238 /* Assume the only family selectors are includes. */
239 return sql_int ("SELECT COUNT(*) FROM nvt_selectors"
240 " WHERE name = '%s'"
241 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
242 " AND exclude = 0"
243 " LIMIT 1;",
244 quoted_selector)
245 > 0;
246 }
247
248 /** @todo Move these config functions to the config section. */
249
250 /**
251 * @brief Get the NVT growth status of a config.
252 *
253 * @param[in] config Config.
254 *
255 * @return 1 growing, 0 static.
256 */
257 int
config_nvts_growing(config_t config)258 config_nvts_growing (config_t config)
259 {
260 return sql_int ("SELECT nvts_growing FROM configs"
261 " WHERE id = %llu;",
262 config);
263 }
264
265 /**
266 * @brief Get the family growth status of a config.
267 *
268 * @param[in] config Config.
269 *
270 * @return 1 growing, 0 static.
271 */
272 int
config_families_growing(config_t config)273 config_families_growing (config_t config)
274 {
275 return sql_int ("SELECT families_growing FROM configs"
276 " WHERE id = %llu;",
277 config);
278 }
279
280 /**
281 * @brief Initialise an NVT selector iterator.
282 *
283 * @param[in] iterator Iterator.
284 * @param[in] selector Name of single selector to iterate over, NULL for all.
285 * @param[in] config Config to limit iteration to, 0 for all.
286 * @param[in] type Type of selector. All if config is given.
287 */
288 void
init_nvt_selector_iterator(iterator_t * iterator,const char * selector,config_t config,int type)289 init_nvt_selector_iterator (iterator_t* iterator, const char* selector,
290 config_t config, int type)
291 {
292 gchar *sql;
293
294 assert (selector ? config == 0 : (config ? selector == NULL : 1));
295 assert (config ? type == NVT_SELECTOR_TYPE_ANY : (type >= 0 && type <= 2));
296
297 if (selector)
298 {
299 gchar *quoted_selector = sql_quote (selector);
300 sql = g_strdup_printf ("SELECT exclude, family_or_nvt, name, type"
301 " FROM nvt_selectors"
302 " WHERE name = '%s' AND type = %i;",
303 quoted_selector,
304 type);
305 g_free (quoted_selector);
306 }
307 else if (config)
308 sql = g_strdup_printf ("SELECT exclude, family_or_nvt, name, type"
309 " FROM nvt_selectors"
310 " WHERE name ="
311 " (SELECT nvt_selector FROM configs"
312 " WHERE configs.id = %llu);",
313 config);
314 else
315 sql = g_strdup_printf ("SELECT exclude, family_or_nvt, name, type"
316 " FROM nvt_selectors"
317 " WHERE type = %i;",
318 type);
319 init_iterator (iterator, "%s", sql);
320 g_free (sql);
321 }
322
323 /**
324 * @brief Get whether the selector rule is an include rule.
325 *
326 * @param[in] iterator Iterator.
327 *
328 * @return -1 if iteration is complete, 1 if include, else 0.
329 */
330 int
nvt_selector_iterator_include(iterator_t * iterator)331 nvt_selector_iterator_include (iterator_t* iterator)
332 {
333 int ret;
334 if (iterator->done) return -1;
335 ret = iterator_int (iterator, 0);
336 return ret == 0;
337 }
338
339 /**
340 * @brief Get the NVT or family from an NVT selector iterator.
341 *
342 * @param[in] iterator Iterator.
343 *
344 * @return NVT selector, or NULL if iteration is complete.
345 */
346 DEF_ACCESS (nvt_selector_iterator_nvt, 1);
347
348 /**
349 * @brief Get the name from an NVT selector iterator.
350 *
351 * @param[in] iterator Iterator.
352 *
353 * @return NVT selector, or NULL if iteration is complete.
354 */
355 DEF_ACCESS (nvt_selector_iterator_name, 2);
356
357 /**
358 * @brief Get the type from an NVT selector.
359 *
360 * @param[in] iterator Iterator.
361 *
362 * @return -1 if iteration is complete, 1 if include, else 0.
363 */
364 int
nvt_selector_iterator_type(iterator_t * iterator)365 nvt_selector_iterator_type (iterator_t* iterator)
366 {
367 int ret;
368 if (iterator->done) return -1;
369 ret = iterator_int (iterator, 3);
370 return ret;
371 }
372
373 /**
374 * @brief Initialise an NVT selector family iterator.
375 *
376 * @param[in] iterator Iterator.
377 * @param[in] all True if families are growing in the selector, else 0.
378 * Only considered with a selector.
379 * @param[in] selector Name of NVT selector. NULL for all families.
380 * @param[in] ascending Whether to sort ascending or descending.
381 */
382 void
init_family_iterator(iterator_t * iterator,int all,const char * selector,int ascending)383 init_family_iterator (iterator_t* iterator, int all, const char* selector,
384 int ascending)
385 {
386 gchar *quoted_selector;
387
388 if (selector == NULL)
389 {
390 init_iterator (iterator,
391 "SELECT distinct family FROM nvts"
392 " WHERE family != 'Credentials'"
393 " ORDER BY family %s;",
394 ascending ? "ASC" : "DESC");
395 return;
396 }
397
398 quoted_selector = sql_quote (selector);
399 if (all)
400 /* Constraining the universe. Presume there is a family exclude for
401 * every NVT include. */
402 init_iterator (iterator,
403 "SELECT distinct family FROM nvts"
404 " WHERE family != 'Credentials'"
405 " EXCEPT"
406 " SELECT distinct family FROM nvt_selectors"
407 " WHERE type = " G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
408 " AND exclude = 1"
409 " AND name = '%s'"
410 " UNION"
411 " SELECT distinct family FROM nvt_selectors"
412 " WHERE type = " G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
413 " AND exclude = 0"
414 " AND name = '%s'"
415 " ORDER BY 1 %s;", /* 1 is family. */
416 quoted_selector,
417 quoted_selector,
418 ascending ? "ASC" : "DESC");
419 else
420 /* Generating from empty. Presume any exclude is covered by an include. */
421 init_iterator (iterator,
422 "SELECT distinct family FROM nvt_selectors"
423 " WHERE (type = 1 OR type = 2) AND name = '%s'"
424 " AND family != 'Credentials'"
425 " ORDER BY 1 %s;", /* 1 is family. */
426 quoted_selector,
427 ascending ? "ASC" : "DESC");
428 g_free (quoted_selector);
429 }
430
431 /**
432 * @brief Get the name from a family iterator.
433 *
434 * @param[in] iterator Iterator.
435 *
436 * @return Name, or NULL if iteration is complete. Freed by
437 * cleanup_iterator.
438 */
439 DEF_ACCESS (family_iterator_name, 0);
440
441 /**
442 * @brief Get whether an NVT selector selects every NVT in a family.
443 *
444 * @param[in] selector NVT selector.
445 * @param[in] family Family name.
446 * @param[in] all True if selector is an "all" selector, else 0.
447 *
448 * @return 1 yes, 0 no.
449 */
450 static int
nvt_selector_entire_and_growing(const char * selector,const char * family,int all)451 nvt_selector_entire_and_growing (const char *selector,
452 const char *family,
453 int all)
454 {
455 int ret;
456 gchar *quoted_family;
457 gchar *quoted_selector;
458
459 quoted_selector = sql_quote (selector);
460 quoted_family = sql_quote (family);
461
462 if (all)
463 {
464 /* Constraining the universe. */
465
466 ret = sql_int ("SELECT COUNT(*) FROM nvt_selectors"
467 " WHERE name = '%s'"
468 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
469 " AND family_or_nvt = '%s'"
470 " AND exclude = 1"
471 " LIMIT 1;",
472 quoted_selector,
473 quoted_family);
474
475 if (ret)
476 /* There's an exclude for the family, so family is static. */
477 ret = 0;
478 else
479 {
480 ret = sql_int ("SELECT COUNT(*) FROM nvt_selectors"
481 " WHERE name = '%s'"
482 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
483 " AND exclude = 1"
484 /* And NVT is in family. */
485 " AND EXISTS (SELECT * FROM nvts"
486 " WHERE oid = family_or_nvt"
487 " AND family = '%s')"
488 " LIMIT 1;",
489 quoted_selector,
490 quoted_family);
491 if (ret)
492 /* Growing, but some NVTs excluded. */
493 ret = 0;
494 else
495 /* Growing, every NVT included. */
496 ret = 1;
497 }
498
499 g_free (quoted_selector);
500 g_free (quoted_family);
501
502 return ret;
503 }
504
505 /* Generating from empty. */
506
507 ret = sql_int ("SELECT COUNT(*) FROM nvt_selectors"
508 " WHERE name = '%s'"
509 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
510 " AND family_or_nvt = '%s'"
511 " AND exclude = 0"
512 " LIMIT 1;",
513 quoted_selector,
514 quoted_family);
515
516 if (ret)
517 {
518 if (sql_int ("SELECT COUNT(*) FROM nvt_selectors"
519 " WHERE name = '%s'"
520 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
521 " AND exclude = 1"
522 /* And NVT is in family. */
523 " AND EXISTS (SELECT * FROM nvts"
524 " WHERE oid = family_or_nvt"
525 " AND family = '%s')"
526 " LIMIT 1;",
527 quoted_selector,
528 quoted_family))
529 /* Growing, but some NVTs excluded. */
530 ret = 0;
531 else
532 /* Growing, every NVT included. */
533 ret = 1;
534 }
535 else
536 /* Family is not included, so family is static. */
537 ret = 0;
538
539 g_free (quoted_selector);
540 g_free (quoted_family);
541
542 return ret;
543 }
544
545 /**
546 * @brief Get whether an NVT selector family is growing.
547 *
548 * @param[in] selector NVT selector.
549 * @param[in] family Family name.
550 * @param[in] all True if selector is an "all" selector, else 0.
551 *
552 * @return 1 growing, 0 static.
553 */
554 int
nvt_selector_family_growing(const char * selector,const char * family,int all)555 nvt_selector_family_growing (const char *selector,
556 const char *family,
557 int all)
558 {
559 int ret;
560 gchar *quoted_family;
561 gchar *quoted_selector;
562
563 quoted_selector = sql_quote (selector);
564 quoted_family = sql_quote (family);
565
566 if (all)
567 {
568 /* Constraining the universe. It's static if there is a family
569 * exclude. */
570
571 ret = sql_int ("SELECT COUNT(*) FROM nvt_selectors"
572 " WHERE name = '%s'"
573 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
574 " AND family_or_nvt = '%s'"
575 " AND exclude = 1"
576 " LIMIT 1;",
577 quoted_selector,
578 quoted_family);
579
580 g_free (quoted_selector);
581 g_free (quoted_family);
582
583 return ret ? 0 : 1;
584 }
585
586 /* Generating from empty. It's growing if there is a family include. */
587
588 ret = sql_int ("SELECT COUNT(*) FROM nvt_selectors"
589 " WHERE name = '%s'"
590 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
591 " AND family_or_nvt = '%s'"
592 " AND exclude = 0"
593 " LIMIT 1;",
594 quoted_selector,
595 quoted_family);
596
597 g_free (quoted_selector);
598 g_free (quoted_family);
599
600 return ret ? 1 : 0;
601 }
602
603 /**
604 * @brief Get the number of NVTs selected by an NVT selector.
605 *
606 * @param[in] selector NVT selector.
607 * @param[in] family Family name. NULL for all.
608 * @param[in] growing True if the given family is growing, else 0.
609 * If family is NULL, true if the the families
610 * are growing, else 0.
611 *
612 * @return Number of NVTs selected in one or all families.
613 */
614 int
nvt_selector_nvt_count(const char * selector,const char * family,int growing)615 nvt_selector_nvt_count (const char *selector,
616 const char *family,
617 int growing)
618 {
619 if (family)
620 {
621 int ret;
622
623 /* Count in a single family. */
624
625 if (growing)
626 {
627 gchar *quoted_family = sql_quote (family);
628 gchar *quoted_selector = sql_quote (selector);
629 ret = sql_int ("SELECT COUNT(*) FROM nvts WHERE family = '%s';",
630 quoted_family);
631 ret -= sql_int ("SELECT COUNT(*) FROM nvt_selectors"
632 " WHERE exclude = 1 AND type = 2"
633 " AND name = '%s' AND family = '%s';",
634 quoted_selector,
635 quoted_family);
636 g_free (quoted_family);
637 g_free (quoted_selector);
638 }
639 else
640 {
641 gchar *quoted_selector = sql_quote (selector);
642 gchar *quoted_family = sql_quote (family);
643 ret = sql_int ("SELECT COUNT(*) FROM nvt_selectors"
644 " WHERE exclude = 0 AND type = 2"
645 " AND name = '%s' AND family = '%s';",
646 quoted_selector,
647 quoted_family);
648 g_free (quoted_family);
649 g_free (quoted_selector);
650 }
651
652 return ret;
653 }
654 else
655 {
656 int count;
657 iterator_t families;
658
659 /* Count in each family. */
660
661 count = 0;
662 init_family_iterator (&families, 0, NULL, 1);
663 while (next (&families))
664 {
665 const char *name = family_iterator_name (&families);
666 if (name)
667 count += nvt_selector_nvt_count (selector,
668 name,
669 nvt_selector_family_growing
670 (selector, name, growing));
671 }
672 cleanup_iterator (&families);
673
674 return count;
675 }
676 }
677
678 /**
679 * @brief Remove all selectors of a certain family from an NVT selector.
680 *
681 * @param[in] quoted_selector SQL-quoted selector name.
682 * @param[in] quoted_family SQL-quoted family name.
683 * @param[in] type Selector type to remove.
684 */
685 static void
nvt_selector_remove(const char * quoted_selector,const char * quoted_family,int type)686 nvt_selector_remove (const char* quoted_selector,
687 const char* quoted_family,
688 int type)
689 {
690 if (strcmp (quoted_selector, MANAGE_NVT_SELECTOR_UUID_ALL) == 0)
691 return;
692 if (type == NVT_SELECTOR_TYPE_ANY)
693 sql ("DELETE FROM nvt_selectors"
694 " WHERE name = '%s'"
695 " AND"
696 " ((type = " G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
697 " AND family = '%s')"
698 " OR (type = " G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
699 " AND family_or_nvt = '%s'));",
700 quoted_selector,
701 quoted_family,
702 quoted_family);
703 else if (type == NVT_SELECTOR_TYPE_NVT)
704 sql ("DELETE FROM nvt_selectors"
705 " WHERE name = '%s'"
706 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
707 " AND family = '%s';",
708 quoted_selector,
709 quoted_family);
710 else if (type == NVT_SELECTOR_TYPE_FAMILY)
711 sql ("DELETE FROM nvt_selectors"
712 " WHERE name = '%s'"
713 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
714 " AND family_or_nvt = '%s';",
715 quoted_selector,
716 quoted_family);
717 }
718
719 /**
720 * @brief Remove all selectors of a certain type from an NVT selector.
721 *
722 * @param[in] quoted_selector SQL-quoted selector name.
723 * @param[in] family_or_nvt SQL-quoted family name or NVT UUID.
724 * @param[in] type Selector type to remove.
725 */
726 static void
nvt_selector_remove_selector(const char * quoted_selector,const char * family_or_nvt,int type)727 nvt_selector_remove_selector (const char* quoted_selector,
728 const char* family_or_nvt,
729 int type)
730 {
731 if (strcmp (quoted_selector, MANAGE_NVT_SELECTOR_UUID_ALL) == 0)
732 return;
733 if (type == NVT_SELECTOR_TYPE_ANY)
734 sql ("DELETE FROM nvt_selectors"
735 " WHERE name = '%s' AND family_or_nvt = '%s');",
736 quoted_selector,
737 family_or_nvt);
738 else if (type == NVT_SELECTOR_TYPE_ALL)
739 sql ("DELETE FROM nvt_selectors"
740 " WHERE name = '%s'"
741 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_ALL) ";",
742 quoted_selector);
743 else
744 sql ("DELETE FROM nvt_selectors"
745 " WHERE name = '%s'"
746 " AND type = %i"
747 " AND family_or_nvt = '%s';",
748 quoted_selector,
749 type,
750 family_or_nvt);
751 }
752
753 /**
754 * @brief Add a selector to an NVT selector.
755 *
756 * @param[in] quoted_selector SQL-quoted selector name.
757 * @param[in] quoted_family_or_nvt SQL-quoted family or NVT name.
758 * @param[in] quoted_family SQL-quoted family name (NULL for families).
759 * @param[in] exclude 1 exclude selector, 0 include selector.
760 */
761 static void
nvt_selector_add(const char * quoted_selector,const char * quoted_family_or_nvt,const char * quoted_family,int exclude)762 nvt_selector_add (const char* quoted_selector,
763 const char* quoted_family_or_nvt,
764 const char* quoted_family,
765 int exclude)
766 {
767 if (quoted_family == NULL)
768 sql ("INSERT INTO nvt_selectors"
769 " (name, exclude, type, family_or_nvt, family)"
770 " VALUES ('%s', %i, "
771 G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
772 ", '%s', '%s');",
773 quoted_selector,
774 exclude,
775 quoted_family_or_nvt,
776 quoted_family_or_nvt);
777 else
778 sql ("INSERT INTO nvt_selectors"
779 " (name, exclude, type, family_or_nvt, family)"
780 " VALUES ('%s', %i, "
781 G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
782 ", '%s', '%s');",
783 quoted_selector,
784 exclude,
785 quoted_family_or_nvt,
786 quoted_family);
787 }
788
789 /**
790 * @brief Set the family of an NVT selector.
791 *
792 * @param[in] quoted_selector SQL-quoted selector name.
793 * @param[in] family_or_nvt Family name or NVT OID of selector.
794 * @param[in] type Selector type to remove.
795 * @param[in] family New family.
796 */
797 static void
nvt_selector_set_family(const char * quoted_selector,const char * family_or_nvt,int type,const char * family)798 nvt_selector_set_family (const char* quoted_selector,
799 const char* family_or_nvt,
800 int type,
801 const char *family)
802 {
803 gchar *quoted_family_or_nvt, *quoted_family;
804
805 quoted_family_or_nvt = sql_quote (family_or_nvt);
806 quoted_family = sql_quote (family);
807 sql ("UPDATE nvt_selectors SET family = '%s'"
808 " WHERE name = '%s'"
809 " AND family_or_nvt = '%s'"
810 " AND type = %i;",
811 quoted_family,
812 quoted_selector,
813 quoted_family_or_nvt,
814 type);
815 g_free (quoted_family);
816 g_free (quoted_family_or_nvt);
817 }
818
819 /**
820 * @brief Check whether a family is selected.
821 *
822 * Only works for "generating from empty" selection.
823 *
824 * @param[in] quoted_selector SQL-quoted selector name.
825 * @param[in] quoted_family SQL-quoted family name (NULL for families).
826 *
827 * @return 1 if selected, else 0.
828 */
829 static int
family_is_selected(const char * quoted_selector,const char * quoted_family)830 family_is_selected (const char* quoted_selector, const char* quoted_family)
831 {
832 return sql_int ("SELECT count(*) FROM nvt_selectors"
833 " WHERE name = '%s'"
834 " AND (type = " G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
835 " AND family = '%s')"
836 " OR (type = " G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY)
837 " AND family_or_nvt = '%s');",
838 quoted_selector,
839 quoted_family,
840 quoted_family);
841 }
842
843 /**
844 * @brief Check whether an NVT selector has a particular selector.
845 *
846 * @param[in] quoted_selector SQL-quoted selector name.
847 * @param[in] family_or_nvt SQL-quoted UUID of NVT, or family name.
848 * @param[in] type Selector type.
849 * @param[in] exclude 1 exclude, 0 include.
850 *
851 * @return 1 if contains include/exclude, else 0.
852 */
853 static int
nvt_selector_has(const char * quoted_selector,const char * family_or_nvt,int type,int exclude)854 nvt_selector_has (const char* quoted_selector, const char* family_or_nvt,
855 int type, int exclude)
856 {
857 return sql_int ("SELECT count(*) FROM nvt_selectors"
858 " WHERE name = '%s'"
859 " AND type = %i"
860 " AND exclude = %i"
861 " AND family_or_nvt = '%s'"
862 " LIMIT 1;",
863 quoted_selector,
864 type,
865 exclude,
866 family_or_nvt);
867 }
868
869 /**
870 * @brief Starts the SQL transaction for modify_config and finds the config.
871 *
872 * @param[in] config_id UUID of the config to find.
873 * @param[out] config_out Row ID of the config or 0 if not found.
874 *
875 * @return 0 success, 1 config not found, -1 error.
876 */
877 int
manage_modify_config_start(const char * config_id,config_t * config_out)878 manage_modify_config_start (const char *config_id, config_t *config_out)
879 {
880 sql_begin_immediate ();
881
882 if (find_config_with_permission (config_id, config_out, "modify_config"))
883 {
884 sql_rollback ();
885 return -1;
886 }
887 if (*config_out == 0)
888 {
889 sql_rollback ();
890 return 1;
891 }
892
893 return 0;
894 }
895
896 /**
897 * @brief Cancels a manage_config command and rolls back the changes.
898 */
899 void
manage_modify_config_cancel()900 manage_modify_config_cancel ()
901 {
902 sql_rollback ();
903 }
904
905 /**
906 * @brief Commits the changes of a manage_config command.
907 */
908 void
manage_modify_config_commit()909 manage_modify_config_commit ()
910 {
911 sql_commit ();
912 }
913
914 /**
915 * @brief Refresh NVT selection of a config from given families.
916 *
917 * @param[in] config Config to modify.
918 * @param[in] growing_all_families Growing families with all selection.
919 * @param[in] static_all_families Static families with all selection.
920 * @param[in] growing_families The rest of the growing families.
921 * @param[in] grow_families 1 if families should grow, else 0.
922 * @param[out] rejected_family Return of family if one was rejected.
923 *
924 * @return 0 success, 1 config in use, 2 whole-only families must be growing
925 * and include entire family, -1 error.
926 */
927 int
manage_set_config_families(config_t config,GPtrArray * growing_all_families,GPtrArray * static_all_families,GPtrArray * growing_families,int grow_families,gchar ** rejected_family)928 manage_set_config_families (config_t config,
929 GPtrArray* growing_all_families,
930 GPtrArray* static_all_families,
931 GPtrArray* growing_families,
932 int grow_families,
933 gchar **rejected_family)
934 {
935 static const gchar *wholes[] = FAMILIES_WHOLE_ONLY;
936 iterator_t families;
937 gchar *quoted_selector;
938 int constraining;
939 char *selector;
940
941 /* Ensure that whole-only families include all NVTs and are growing. */
942
943 if (rejected_family)
944 *rejected_family = NULL;
945
946 for (const gchar **whole = wholes; *whole; whole++)
947 {
948 if (member (static_all_families, *whole)
949 || member (growing_families, *whole))
950 {
951 if (member (static_all_families, *whole))
952 g_debug ("%s rejected static/all whole-only family %s",
953 __func__, *whole);
954 else if (member (growing_families, *whole))
955 g_debug ("%s rejected growing/empty whole-only family %s",
956 __func__, *whole);
957
958 if (rejected_family)
959 *rejected_family = g_strdup (*whole);
960 return 2;
961 }
962 }
963
964 /* Check the args. */
965
966 if (sql_int ("SELECT count(*) FROM tasks"
967 " WHERE config = %llu AND hidden = 0;",
968 config))
969 {
970 return 1;
971 }
972
973 if (config_type (config) > 0)
974 {
975 return 0;
976 }
977 constraining = config_families_growing (config);
978
979 if (constraining + grow_families == 1)
980 {
981 if (switch_representation (config, constraining))
982 {
983 return -1;
984 }
985 constraining = constraining == 0;
986 }
987
988 selector = config_nvt_selector (config);
989 if (selector == NULL)
990 {
991 /* The config should always have a selector. */
992 return -1;
993 }
994 quoted_selector = sql_quote (selector);
995
996 /* Loop through all the known families. */
997
998 init_family_iterator (&families, 1, NULL, 1);
999 while (next (&families))
1000 {
1001 const char *family;
1002
1003 family = family_iterator_name (&families);
1004 if (family)
1005 {
1006 int old_nvt_count, new_nvt_count = 0, was_selected, max_nvt_count;
1007 int family_growing;
1008 int growing_all = member (growing_all_families, family);
1009 int static_all = member (static_all_families, family);
1010 gchar *quoted_family = sql_quote (family);
1011
1012 assert ((growing_all && static_all) == 0);
1013
1014 family_growing = nvt_selector_family_growing (selector,
1015 family,
1016 constraining);
1017
1018 old_nvt_count
1019 = nvt_selector_nvt_count (selector, family, family_growing);
1020
1021 max_nvt_count = family_nvt_count (family);
1022
1023 if (growing_all || static_all)
1024 {
1025 if (old_nvt_count == max_nvt_count
1026 && ((growing_all && family_growing)
1027 || (static_all && family_growing == 0)))
1028 {
1029 /* Already in required state. */
1030 g_free (quoted_family);
1031 continue;
1032 }
1033
1034 was_selected = family_is_selected (quoted_selector,
1035 quoted_family);
1036
1037 /* Flush all selectors in the family from the config. */
1038
1039 nvt_selector_remove (quoted_selector,
1040 quoted_family,
1041 NVT_SELECTOR_TYPE_ANY);
1042
1043 if (static_all)
1044 {
1045 iterator_t nvts;
1046
1047 /* Static selection of all the NVT's currently in the
1048 * family. */
1049
1050 if (constraining)
1051 {
1052 /* Constraining the universe. */
1053
1054 /* Add an exclude for the family. */
1055
1056 nvt_selector_add (quoted_selector,
1057 quoted_family,
1058 NULL,
1059 1);
1060 }
1061 else
1062 {
1063 /* Generating from empty. */
1064 }
1065
1066 /* Add an include for every NVT in the family. */
1067
1068 init_nvt_iterator (&nvts, (nvt_t) 0, (config_t) 0, family,
1069 NULL, 1, NULL);
1070 while (next (&nvts))
1071 {
1072 nvt_selector_add (quoted_selector,
1073 nvt_iterator_oid (&nvts),
1074 quoted_family,
1075 0);
1076 new_nvt_count++;
1077 }
1078 cleanup_iterator (&nvts);
1079 }
1080 else if (growing_all)
1081 {
1082 /* Selection of an entire family, which grows with the family. */
1083
1084 if (constraining)
1085 {
1086 /* Constraining the universe. */
1087 }
1088 else
1089 {
1090 /* Generating from empty. Add an include for the
1091 * family. */
1092
1093 nvt_selector_add (quoted_selector,
1094 quoted_family,
1095 NULL,
1096 0);
1097
1098 }
1099
1100 new_nvt_count = max_nvt_count;
1101 }
1102
1103 /* Update the cached config info. */
1104
1105 sql ("UPDATE configs SET nvt_count = nvt_count - %i + %i,"
1106 " nvts_growing = %i, family_count = family_count + %i,"
1107 " modification_time = m_now ()"
1108 " WHERE id = %llu;",
1109 old_nvt_count,
1110 new_nvt_count,
1111 growing_all
1112 ? 1
1113 /* Recalculate the NVT growing state. */
1114 : nvt_selector_nvts_growing_2 (quoted_selector,
1115 constraining),
1116 was_selected ? 0 : 1,
1117 config);
1118 }
1119 else
1120 {
1121 int must_grow = member (growing_families, family);
1122
1123 if (must_grow)
1124 {
1125 /* The resulting family must be growing. If currently
1126 * growing, leave as is, otherwise switch family to
1127 * growing. */
1128
1129 if (old_nvt_count == max_nvt_count)
1130 {
1131 iterator_t nvts;
1132
1133 /* All were selected. Clear selection, ensuring that
1134 * the family is growing in the process. */
1135
1136 nvt_selector_remove (quoted_selector,
1137 quoted_family,
1138 NVT_SELECTOR_TYPE_ANY);
1139
1140 if (constraining == 0)
1141 /* Generating. */
1142 nvt_selector_add (quoted_selector,
1143 quoted_family,
1144 NULL,
1145 0);
1146
1147 /* Add an exclude for every NVT in the family. */
1148
1149 init_nvt_iterator (&nvts, (nvt_t) 0, (config_t) 0,
1150 family, NULL, 1, NULL);
1151 while (next (&nvts))
1152 nvt_selector_add (quoted_selector,
1153 nvt_iterator_oid (&nvts),
1154 quoted_family,
1155 1);
1156 cleanup_iterator (&nvts);
1157
1158 /* Update the cached config info. */
1159
1160 sql ("UPDATE configs SET nvt_count = nvt_count - %i,"
1161 " nvts_growing = 1, modification_time = m_now ()"
1162 " WHERE id = %llu;",
1163 old_nvt_count,
1164 config);
1165 }
1166 else if (family_growing == 0)
1167 {
1168 iterator_t nvts;
1169
1170 if (constraining == 0)
1171 nvt_selector_add (quoted_selector,
1172 quoted_family,
1173 NULL,
1174 0);
1175
1176 /* Remove any included NVT, add excludes for all
1177 * other NVT's. */
1178
1179 init_nvt_iterator (&nvts, (nvt_t) 0, (config_t) 0,
1180 family, NULL, 1, NULL);
1181 while (next (&nvts))
1182 if (nvt_selector_has (quoted_selector,
1183 nvt_iterator_oid (&nvts),
1184 NVT_SELECTOR_TYPE_NVT,
1185 0))
1186 nvt_selector_remove_selector
1187 (quoted_selector,
1188 nvt_iterator_oid (&nvts),
1189 NVT_SELECTOR_TYPE_NVT);
1190 else
1191 nvt_selector_add (quoted_selector,
1192 nvt_iterator_oid (&nvts),
1193 quoted_family,
1194 1);
1195 cleanup_iterator (&nvts);
1196
1197 /* Update the cached config info. */
1198
1199 sql ("UPDATE configs SET nvts_growing = 1,"
1200 " modification_time = m_now ()"
1201 " WHERE id = %llu;",
1202 config);
1203 }
1204 }
1205 else
1206 {
1207 /* The resulting family must be static. If currently
1208 * static, leave as is, otherwise switch family to
1209 * static. */
1210
1211 if (old_nvt_count == max_nvt_count)
1212 {
1213 /* All were selected, clear selection, ensuring the
1214 * family is static in the process. */
1215
1216 nvt_selector_remove (quoted_selector,
1217 quoted_family,
1218 NVT_SELECTOR_TYPE_ANY);
1219 if (constraining)
1220 nvt_selector_add (quoted_selector,
1221 quoted_family,
1222 NULL,
1223 1);
1224
1225 /* Update the cached config info. */
1226
1227 sql ("UPDATE configs SET nvts_growing = %i,"
1228 " nvt_count = nvt_count - %i,"
1229 " family_count = family_count - 1,"
1230 " modification_time = m_now ()"
1231 " WHERE id = %llu;",
1232 /* Recalculate the NVT growing state. */
1233 nvt_selector_nvts_growing_2 (quoted_selector,
1234 constraining),
1235 old_nvt_count,
1236 config);
1237 }
1238 else if (family_growing)
1239 {
1240 iterator_t nvts;
1241
1242 if (constraining)
1243 nvt_selector_add (quoted_selector,
1244 quoted_family,
1245 NULL,
1246 1);
1247 else
1248 nvt_selector_remove (quoted_selector,
1249 quoted_family,
1250 NVT_SELECTOR_TYPE_FAMILY);
1251
1252 /* Remove any excluded NVT; add includes for all
1253 * other NVT's. */
1254
1255 init_nvt_iterator (&nvts, (nvt_t) 0, (config_t) 0,
1256 family, NULL, 1, NULL);
1257 while (next (&nvts))
1258 if (nvt_selector_has (quoted_selector,
1259 nvt_iterator_oid (&nvts),
1260 NVT_SELECTOR_TYPE_NVT,
1261 1))
1262 nvt_selector_remove_selector
1263 (quoted_selector,
1264 nvt_iterator_oid (&nvts),
1265 NVT_SELECTOR_TYPE_NVT);
1266 else
1267 nvt_selector_add (quoted_selector,
1268 nvt_iterator_oid (&nvts),
1269 quoted_family,
1270 0);
1271 cleanup_iterator (&nvts);
1272
1273 /* Update the cached config info. */
1274
1275 sql ("UPDATE configs SET nvts_growing = %i,"
1276 " modification_time = m_now ()"
1277 " WHERE id = %llu;",
1278 /* Recalculate the NVT growing state. */
1279 nvt_selector_nvts_growing_2 (quoted_selector,
1280 constraining),
1281 config);
1282 }
1283 }
1284 }
1285
1286 g_free (quoted_family);
1287 }
1288 }
1289 cleanup_iterator (&families);
1290
1291 g_free (quoted_selector);
1292 free (selector);
1293 return 0;
1294 }
1295
1296 /**
1297 * @brief Insert NVT selectors.
1298 *
1299 * @param[in] quoted_name Name of NVT selector.
1300 * @param[in] selectors NVT selectors.
1301 * @param[in] allow_errors Whether certain errors are allowed.
1302 *
1303 * @return 0 success, -1 error, -3 input error.
1304 */
1305 static int
insert_nvt_selectors(const char * quoted_name,const array_t * selectors,int allow_errors)1306 insert_nvt_selectors (const char *quoted_name,
1307 const array_t* selectors, /* nvt_selector_t. */
1308 int allow_errors)
1309 {
1310 int index = 0;
1311 const nvt_selector_t *selector;
1312 if (selectors == NULL) return -3;
1313 while ((selector = (nvt_selector_t*) g_ptr_array_index (selectors, index++)))
1314 {
1315 int type;
1316
1317 if (selector->type == NULL) return -3;
1318
1319 /** @todo Check that selector->type is actually an integer. */
1320 type = atoi (selector->type);
1321
1322 if ((selector->family_or_nvt != NULL)
1323 && (type == NVT_SELECTOR_TYPE_NVT))
1324 {
1325 gchar *quoted_family_or_nvt, *quoted_family, *family = NULL;
1326
1327 /* An NVT selector. */
1328
1329 family = nvt_family (selector->family_or_nvt);
1330 if (family == NULL)
1331 g_debug ("%s: NVT '%s' in config '%s' does not have a family",
1332 __func__,
1333 selector->family_or_nvt,
1334 quoted_name);
1335
1336 quoted_family_or_nvt = sql_quote (selector->family_or_nvt);
1337 quoted_family = sql_quote (family ? family : "");
1338 sql ("INSERT into nvt_selectors (name, exclude, type, family_or_nvt,"
1339 " family)"
1340 " VALUES ('%s', %i, %i, '%s', '%s');",
1341 quoted_name,
1342 selector->include ? 0 : 1,
1343 type,
1344 quoted_family_or_nvt,
1345 quoted_family);
1346 g_free (quoted_family_or_nvt);
1347 g_free (quoted_family);
1348 }
1349 else if (selector->family_or_nvt)
1350 {
1351 gchar *quoted_family_or_nvt;
1352
1353 /* A family selector. */
1354
1355 if (type != NVT_SELECTOR_TYPE_FAMILY)
1356 {
1357 g_warning ("%s: skipping NVT '%s' from import of config '%s'"
1358 " because the type is wrong (expected family)",
1359 __func__,
1360 selector->family_or_nvt,
1361 quoted_name);
1362 if (allow_errors)
1363 continue;
1364 return -1;
1365 }
1366
1367 quoted_family_or_nvt = sql_quote (selector->family_or_nvt);
1368
1369 sql ("INSERT into nvt_selectors (name, exclude, type, family_or_nvt,"
1370 " family)"
1371 " VALUES ('%s', %i, %i, '%s', '%s');",
1372 quoted_name,
1373 selector->include ? 0 : 1,
1374 type,
1375 quoted_family_or_nvt,
1376 quoted_family_or_nvt);
1377 g_free (quoted_family_or_nvt);
1378 }
1379 else
1380 {
1381 /* An "all" selector. */
1382
1383 if (type != NVT_SELECTOR_TYPE_ALL)
1384 {
1385 g_warning ("%s: skipping NVT from import of config '%s'"
1386 " because the type is wrong (expected all)",
1387 __func__,
1388 quoted_name);
1389 if (allow_errors)
1390 continue;
1391 return -1;
1392 }
1393
1394 sql ("INSERT into nvt_selectors (name, exclude, type, family_or_nvt,"
1395 " family)"
1396 " VALUES ('%s', %i, %i, NULL, NULL);",
1397 quoted_name,
1398 selector->include ? 0 : 1,
1399 type);
1400 }
1401 }
1402 return 0;
1403 }
1404
1405 /**
1406 * @brief Change the family of an NVT in a config.
1407 *
1408 * @param[in] config Config.
1409 * @param[in] oid NVT OID.
1410 * @param[in] old_family Name of old family.
1411 * @param[in] new_family Name of new family.
1412 *
1413 * @return 0 success, -1 error.
1414 */
1415 static int
config_update_nvt_family(resource_t config,const char * oid,const char * old_family,const char * new_family)1416 config_update_nvt_family (resource_t config, const char *oid,
1417 const char *old_family, const char *new_family)
1418 {
1419 int constraining;
1420 char* selector;
1421 gchar *quoted_selector;
1422
1423 selector = config_nvt_selector (config);
1424 if (selector == NULL)
1425 {
1426 g_warning ("%s: Failed to get config selector", __func__);
1427 return -1;
1428 }
1429 quoted_selector = sql_quote (selector);
1430
1431 constraining = config_families_growing (config);
1432
1433 g_debug ("%s: Updating NVT family for selector '%s'", __func__, selector);
1434
1435 if (constraining)
1436 {
1437 /* Constraining the universe. */
1438
1439 g_debug ("%s: Selector constrains universe", __func__);
1440
1441 if (nvt_selector_family_growing (selector, old_family, constraining))
1442 {
1443 /* Old family is growing. */
1444
1445 g_debug ("%s: Old family is growing", __func__);
1446
1447 if (nvt_selector_has (quoted_selector, oid, NVT_SELECTOR_TYPE_NVT,
1448 0 /* Included. */))
1449 {
1450 /* NVT explicitly included in old family, which is redundant, so
1451 * drop selector. */
1452 g_debug ("%s: Drop selector", __func__);
1453 nvt_selector_remove_selector (quoted_selector,
1454 oid,
1455 NVT_SELECTOR_TYPE_NVT);
1456 }
1457 else if (nvt_selector_has (quoted_selector, oid,
1458 NVT_SELECTOR_TYPE_NVT,
1459 1 /* Excluded. */))
1460 {
1461 /* NVT explicitly excluded from old family. */
1462
1463 g_debug ("%s: NVT excluded from old family", __func__);
1464
1465 if (nvt_selector_family_growing (selector, new_family,
1466 constraining))
1467 {
1468 /* New family is growing, change NVT to new family. */
1469 g_debug ("%s: Change family", __func__);
1470 nvt_selector_set_family (quoted_selector,
1471 oid,
1472 NVT_SELECTOR_TYPE_NVT,
1473 new_family);
1474 }
1475 else
1476 {
1477 /* New family static, NVT excluded already, so drop NVT
1478 * selector. */
1479 g_debug ("%s: Remove selector", __func__);
1480 nvt_selector_remove_selector (quoted_selector,
1481 oid,
1482 NVT_SELECTOR_TYPE_NVT);
1483 }
1484 }
1485 }
1486 else
1487 {
1488 /* Old family is static. */
1489
1490 g_debug ("%s: Old family is static", __func__);
1491
1492 if (nvt_selector_has (quoted_selector, oid, NVT_SELECTOR_TYPE_NVT,
1493 0 /* Included. */))
1494 {
1495 /* NVT explicitly included in old family. */
1496
1497 g_debug ("%s: NVT included in old family", __func__);
1498
1499 if (nvt_selector_family_growing (selector, new_family,
1500 constraining))
1501 {
1502 /* New family is growing so it already includes the NVT.
1503 * Remove the NVT selector. */
1504 g_debug ("%s: Remove selector", __func__);
1505 nvt_selector_remove_selector (quoted_selector,
1506 oid,
1507 NVT_SELECTOR_TYPE_NVT);
1508 }
1509 else
1510 {
1511 /* New family static, change NVT to new family. */
1512 g_debug ("%s: Change family", __func__);
1513 nvt_selector_set_family (quoted_selector,
1514 oid,
1515 NVT_SELECTOR_TYPE_NVT,
1516 new_family);
1517 }
1518 }
1519 else if (nvt_selector_has (quoted_selector, oid,
1520 NVT_SELECTOR_TYPE_NVT,
1521 1 /* Excluded. */))
1522 {
1523 /* NVT explicitly excluded from old family, which is redundant, so
1524 * remove NVT selector. */
1525 g_debug ("%s: Remove selector", __func__);
1526 nvt_selector_remove_selector (quoted_selector,
1527 oid,
1528 NVT_SELECTOR_TYPE_NVT);
1529 }
1530 }
1531 }
1532 else
1533 {
1534 /* Generating from empty. */
1535
1536 g_debug ("%s: Selector generates from empty", __func__);
1537
1538 if (nvt_selector_family_growing (selector, old_family, constraining))
1539 {
1540 /* Old family is growing. */
1541
1542 g_debug ("%s: Old family is growing", __func__);
1543
1544 if (nvt_selector_has (quoted_selector, oid, NVT_SELECTOR_TYPE_NVT,
1545 0 /* Included. */))
1546 {
1547 /* NVT explicitly included in old family. This is redundant, so
1548 * just remove the NVT selector. */
1549 g_debug ("%s: Remove selector", __func__);
1550 nvt_selector_remove_selector (quoted_selector,
1551 oid,
1552 NVT_SELECTOR_TYPE_NVT);
1553 }
1554 else if (nvt_selector_has (quoted_selector, oid,
1555 NVT_SELECTOR_TYPE_NVT,
1556 1 /* Excluded. */))
1557 {
1558 /* NVT explicitly excluded from old family. */
1559
1560 g_debug ("%s: NVT excluded from old family", __func__);
1561
1562 if (nvt_selector_family_growing (selector, new_family,
1563 constraining))
1564 {
1565 /* New family is growing, change NVT to new family. */
1566 g_debug ("%s: Change family", __func__);
1567 nvt_selector_set_family (quoted_selector,
1568 oid,
1569 NVT_SELECTOR_TYPE_NVT,
1570 new_family);
1571 }
1572 else
1573 {
1574 /* New family static, so the NVT is already excluded from the
1575 * new family. Remove the NVT selector. */
1576 g_debug ("%s: Remove selector", __func__);
1577 nvt_selector_remove_selector (quoted_selector,
1578 oid,
1579 NVT_SELECTOR_TYPE_NVT);
1580 }
1581 }
1582 }
1583 else
1584 {
1585 /* Old family is static. */
1586
1587 g_debug ("%s: Old family is static", __func__);
1588
1589 if (nvt_selector_has (quoted_selector, oid, NVT_SELECTOR_TYPE_NVT,
1590 0 /* Included. */))
1591 {
1592 /* NVT explicitly included in old family. */
1593
1594 g_debug ("%s: NVT included in old family", __func__);
1595
1596 if (nvt_selector_family_growing (selector, new_family,
1597 constraining))
1598 {
1599 /* New family growing, so the NVT is already in there. Remove
1600 * the NVT selector. */
1601 g_debug ("%s: Remove selector", __func__);
1602 nvt_selector_remove_selector (quoted_selector,
1603 oid,
1604 NVT_SELECTOR_TYPE_NVT);
1605 }
1606 else
1607 {
1608 /* New family is static, change NVT to new family. */
1609 g_debug ("%s: Change family", __func__);
1610 nvt_selector_set_family (quoted_selector,
1611 oid,
1612 NVT_SELECTOR_TYPE_NVT,
1613 new_family);
1614 }
1615 }
1616 else if (nvt_selector_has (quoted_selector, oid,
1617 NVT_SELECTOR_TYPE_NVT,
1618 1 /* Excluded. */))
1619 {
1620 /* NVT explicitly excluded from old family. This is redundant,
1621 * so just remove the NVT selector. */
1622 g_debug ("%s: NVT exclude from old family, remove selector",
1623 __func__);
1624 nvt_selector_remove_selector (quoted_selector,
1625 oid,
1626 NVT_SELECTOR_TYPE_NVT);
1627 }
1628 }
1629 }
1630
1631 g_free (quoted_selector);
1632 free (selector);
1633 return 0;
1634 }
1635
1636 /**
1637 * @brief Change the family of an NVT in all configs.
1638 *
1639 * @param[in] oid NVT OID.
1640 * @param[in] old_family Name of old family.
1641 * @param[in] new_family Name of new family.
1642 *
1643 * @return 0 success, -1 error.
1644 */
1645 static int
update_nvt_family(const char * oid,const char * old_family,const char * new_family)1646 update_nvt_family (const char *oid, const char *old_family,
1647 const char *new_family)
1648 {
1649 int ret;
1650 iterator_t rows;
1651
1652 ret = 0;
1653 init_iterator (&rows, "SELECT id FROM configs WHERE type = 0;");
1654 while (next (&rows))
1655 if (config_update_nvt_family (iterator_int64 (&rows, 0), oid, old_family,
1656 new_family))
1657 ret = -1;
1658 cleanup_iterator (&rows);
1659 return ret;
1660 }
1661
1662 /**
1663 * @brief Ensure that all configs refer to the right NVT families.
1664 *
1665 * When the family of an NVT is changed in the feed, then the config
1666 * refers to the wrong family.
1667 *
1668 * @return 0 success, -1 error.
1669 */
1670 int
check_config_families()1671 check_config_families ()
1672 {
1673 int ret;
1674 iterator_t selectors;
1675
1676 ret = 0;
1677 /* Get all NVT selectors that have the wrong family. */
1678 init_iterator (&selectors,
1679 "SELECT DISTINCT family_or_nvt, family,"
1680 " (SELECT family FROM nvts WHERE oid = family_or_nvt)"
1681 " FROM nvt_selectors"
1682 " WHERE type = 2"
1683 " AND family != (SELECT family FROM nvts"
1684 " WHERE oid = family_or_nvt);");
1685 while (next (&selectors))
1686 /* Update the family of the NVT selector. */
1687 if (update_nvt_family (iterator_string (&selectors, 0),
1688 iterator_string (&selectors, 1),
1689 iterator_string (&selectors, 2)))
1690 ret = -1;
1691 cleanup_iterator (&selectors);
1692 return ret;
1693 }
1694
1695
1696 /* NVT preferences. This is part of Configs. */
1697
1698 /**
1699 * @brief Add/replace an NVT preference.
1700 *
1701 * @param[in] name The name of the preference.
1702 * @param[in] value The value of the preference.
1703 */
1704 void
manage_nvt_preference_add(const char * name,const char * value)1705 manage_nvt_preference_add (const char* name, const char* value)
1706 {
1707 gchar* quoted_name = sql_quote (name);
1708 gchar* quoted_value = sql_quote (value);
1709
1710 if (strcmp (name, "port_range"))
1711 {
1712 if (sql_int ("SELECT EXISTS"
1713 " (SELECT * FROM nvt_preferences"
1714 " WHERE name = '%s')",
1715 quoted_name))
1716 sql ("DELETE FROM nvt_preferences WHERE name = '%s';", quoted_name);
1717
1718 sql ("INSERT into nvt_preferences (name, value)"
1719 " VALUES ('%s', '%s');",
1720 quoted_name, quoted_value);
1721 }
1722
1723 g_free (quoted_name);
1724 g_free (quoted_value);
1725 }
1726
1727 /**
1728 * @brief Initialise an NVT preference iterator.
1729 *
1730 * @param[in] iterator Iterator.
1731 * @param[in] oid OID of NVT, NULL for all preferences.
1732 */
1733 void
init_nvt_preference_iterator(iterator_t * iterator,const char * oid)1734 init_nvt_preference_iterator (iterator_t* iterator, const char *oid)
1735 {
1736 if (oid)
1737 {
1738 gchar *quoted_oid = sql_quote (oid);
1739 init_iterator (iterator,
1740 "SELECT name, value FROM nvt_preferences"
1741 " WHERE name %s '%s:%%'"
1742 " AND name != 'cache_folder'"
1743 " AND name != 'include_folders'"
1744 " AND name != 'nasl_no_signature_check'"
1745 " AND name != 'network_targets'"
1746 " AND name != 'ntp_save_sessions'"
1747 " AND name != '%s:0:entry:Timeout'"
1748 " AND name NOT %s 'server_info_%%'"
1749 /* Task preferences. */
1750 " AND name != 'max_checks'"
1751 " AND name != 'max_hosts'"
1752 " ORDER BY name ASC",
1753 sql_ilike_op (),
1754 quoted_oid,
1755 quoted_oid,
1756 sql_ilike_op ());
1757 g_free (quoted_oid);
1758 }
1759 else
1760 init_iterator (iterator,
1761 "SELECT name, value FROM nvt_preferences"
1762 " WHERE name != 'cache_folder'"
1763 " AND name != 'include_folders'"
1764 " AND name != 'nasl_no_signature_check'"
1765 " AND name != 'network_targets'"
1766 " AND name != 'ntp_save_sessions'"
1767 " AND name NOT %s '%%:0:entry:Timeout'"
1768 " AND name NOT %s 'server_info_%%'"
1769 /* Task preferences. */
1770 " AND name != 'max_checks'"
1771 " AND name != 'max_hosts'"
1772 " ORDER BY name ASC",
1773 sql_ilike_op (),
1774 sql_ilike_op ());
1775 }
1776
1777 /**
1778 * @brief Get the name from an NVT preference iterator.
1779 *
1780 * @param[in] iterator Iterator.
1781 *
1782 * @return Name, or NULL if iteration is complete. Freed by
1783 * cleanup_iterator.
1784 */
1785 DEF_ACCESS (nvt_preference_iterator_name, 0);
1786
1787 /**
1788 * @brief Get the value from an NVT preference iterator.
1789 *
1790 * @param[in] iterator Iterator.
1791 *
1792 * @return Value, or NULL if iteration is complete. Freed by
1793 * cleanup_iterator.
1794 */
1795 DEF_ACCESS (nvt_preference_iterator_value, 1);
1796
1797 /**
1798 * @brief Get the real name from an NVT preference iterator.
1799 *
1800 * @param[in] iterator Iterator.
1801 *
1802 * @return Real name.
1803 */
1804 char*
nvt_preference_iterator_real_name(iterator_t * iterator)1805 nvt_preference_iterator_real_name (iterator_t* iterator)
1806 {
1807 const char *ret;
1808 char *real_name = NULL;
1809 if (iterator->done) return NULL;
1810 ret = iterator_string (iterator, 0);
1811 if (ret)
1812 {
1813 char **splits = g_strsplit (ret, ":", 4);
1814 if (splits && g_strv_length (splits) == 4)
1815 real_name = g_strdup (splits[3]);
1816 g_strfreev (splits);
1817 return real_name ?: g_strdup (ret);
1818 }
1819 return NULL;
1820 }
1821
1822 /**
1823 * @brief Get the type from an NVT preference iterator.
1824 *
1825 * @param[in] iterator Iterator.
1826 *
1827 * @return Type.
1828 */
1829 char*
nvt_preference_iterator_type(iterator_t * iterator)1830 nvt_preference_iterator_type (iterator_t* iterator)
1831 {
1832 const char *ret;
1833 char *type = NULL;
1834 if (iterator->done)
1835 return NULL;
1836 ret = iterator_string (iterator, 0);
1837 if (ret)
1838 {
1839 char **splits = g_strsplit (ret, ":", 4);
1840 if (splits && g_strv_length (splits) == 4)
1841 type = g_strdup (splits[2]);
1842 g_strfreev (splits);
1843 }
1844 return type;
1845 }
1846
1847 /**
1848 * @brief Get the NVT from an NVT preference iterator.
1849 *
1850 * @param[in] iterator Iterator.
1851 *
1852 * @return NVT.
1853 */
1854 char*
nvt_preference_iterator_oid(iterator_t * iterator)1855 nvt_preference_iterator_oid (iterator_t* iterator)
1856 {
1857 const char *ret;
1858 char *oid = NULL;
1859 if (iterator->done)
1860 return NULL;
1861 ret = iterator_string (iterator, 0);
1862 if (ret)
1863 {
1864 char **splits = g_strsplit (ret, ":", 4);
1865 if (splits && g_strv_length (splits) == 4)
1866 oid = g_strdup (splits[0]);
1867 g_strfreev (splits);
1868 }
1869 return oid;
1870 }
1871
1872 /**
1873 * @brief Get the ID from an NVT preference iterator.
1874 *
1875 * @param[in] iterator Iterator.
1876 *
1877 * @return NVT.
1878 */
1879 char*
nvt_preference_iterator_id(iterator_t * iterator)1880 nvt_preference_iterator_id (iterator_t* iterator)
1881 {
1882 const char *ret;
1883 char *id = NULL;
1884
1885 if (iterator->done)
1886 return NULL;
1887 ret = iterator_string (iterator, 0);
1888 if (ret)
1889 {
1890 char **splits = g_strsplit (ret, ":", 4);
1891 if (splits && g_strv_length (splits) == 4)
1892 id = g_strdup (splits[1]);
1893 g_strfreev (splits);
1894 }
1895 return id;
1896 }
1897
1898 /**
1899 * @brief Get the config value from an NVT preference iterator.
1900 *
1901 * @param[in] iterator Iterator.
1902 * @param[in] config Config.
1903 *
1904 * @return Freshly allocated config value.
1905 */
1906 char*
nvt_preference_iterator_config_value(iterator_t * iterator,config_t config)1907 nvt_preference_iterator_config_value (iterator_t* iterator, config_t config)
1908 {
1909 gchar *quoted_name, *value;
1910 const char *ret;
1911 if (iterator->done) return NULL;
1912
1913 quoted_name = sql_quote (iterator_string (iterator, 0));
1914 value = sql_string ("SELECT value FROM config_preferences"
1915 " WHERE config = %llu"
1916 " AND name = '%s'"
1917 /* Ensure that the NVT pref comes first, in case an
1918 * error in the GSA added the NVT pref as a Scanner
1919 * pref. */
1920 " ORDER BY type",
1921 config,
1922 quoted_name);
1923 g_free (quoted_name);
1924 if (value) return value;
1925
1926 ret = iterator_string (iterator, 1);
1927 if (ret) return g_strdup (ret);
1928 return NULL;
1929 }
1930
1931 /**
1932 * @brief Get the number preferences available for an NVT.
1933 *
1934 * @param[in] oid OID of NVT.
1935 *
1936 * @return Number of possible preferences on NVT.
1937 */
1938 int
nvt_preference_count(const char * oid)1939 nvt_preference_count (const char *oid)
1940 {
1941 gchar *quoted_oid = sql_quote (oid);
1942 int ret = sql_int ("SELECT COUNT(*) FROM nvt_preferences"
1943 " WHERE name != '%s:0:entry:Timeout'"
1944 " AND name %s '%s:%%';",
1945 quoted_oid,
1946 sql_ilike_op (),
1947 quoted_oid);
1948 g_free (quoted_oid);
1949 return ret;
1950 }
1951
1952 /**
1953 * @brief Get the value of a task preference.
1954 *
1955 * @param[in] task Task.
1956 * @param[in] name Preference name.
1957 *
1958 * @return Freshly allocated task preference value or NULL if pref missing.
1959 */
1960 char*
task_preference_value(task_t task,const char * name)1961 task_preference_value (task_t task, const char *name)
1962 {
1963 gchar *quoted_name, *value;
1964
1965 quoted_name = sql_quote (name);
1966 value = sql_string ("SELECT value FROM task_preferences"
1967 " WHERE task = %llu"
1968 " AND name = '%s';",
1969 task,
1970 quoted_name);
1971 if (value)
1972 {
1973 g_free (quoted_name);
1974 return value;
1975 }
1976
1977 value = sql_string ("SELECT value FROM nvt_preferences"
1978 " WHERE name = '%s';",
1979 quoted_name);
1980 g_free (quoted_name);
1981 return value;
1982 }
1983
1984 /**
1985 * @brief Set the preferences of a task.
1986 *
1987 * Only the given preferences are affected. A NULL value means to remove
1988 * the preference (reverts to using scanner value).
1989 *
1990 * @param[in] task Task.
1991 * @param[in] preferences Preferences.
1992 *
1993 * @return 0 success, 1 invalid auto_delete value, 2 auto_delete_data out of
1994 * range.
1995 */
1996 int
set_task_preferences(task_t task,array_t * preferences)1997 set_task_preferences (task_t task, array_t *preferences)
1998 {
1999 if (preferences)
2000 {
2001 guint index;
2002 for (index = 0; index < preferences->len; index++)
2003 {
2004 name_value_t *pair;
2005 pair = (name_value_t*) g_ptr_array_index (preferences, index);
2006 if (pair && pair->name)
2007 {
2008 gchar *quoted_name;
2009 quoted_name = sql_quote (pair->name);
2010 if (pair->value)
2011 {
2012 gchar *quoted_value;
2013
2014 if ((strcmp (pair->name, "auto_delete") == 0)
2015 && (strcmp (pair->value, "keep"))
2016 && (strcmp (pair->value, "no")))
2017 {
2018 return 1;
2019 }
2020
2021 if (strcmp (pair->name, "auto_delete_data") == 0)
2022 {
2023 int keep;
2024 keep = atoi (pair->value);
2025 if (keep < AUTO_DELETE_KEEP_MIN
2026 || keep > AUTO_DELETE_KEEP_MAX)
2027 return 2;
2028 }
2029
2030 if ((strcmp (pair->name, "in_assets") == 0)
2031 && scanner_type (task_scanner (task)) == SCANNER_TYPE_CVE)
2032 quoted_value = g_strdup ("no");
2033 else
2034 quoted_value = sql_quote (pair->value);
2035 sql_begin_immediate ();
2036 if (sql_int ("SELECT COUNT(*) FROM task_preferences"
2037 " WHERE task = %llu AND name = '%s';",
2038 task,
2039 quoted_name))
2040 sql ("UPDATE task_preferences"
2041 " SET value = '%s'"
2042 " WHERE task = %llu AND name = '%s';",
2043 quoted_value,
2044 task,
2045 quoted_name);
2046 else
2047 sql ("INSERT INTO task_preferences"
2048 " (task, name, value)"
2049 " VALUES"
2050 " (%llu, '%s', '%s');",
2051 task,
2052 quoted_name,
2053 quoted_value);
2054 sql_commit ();
2055 g_free (quoted_value);
2056 }
2057 else
2058 sql ("DELETE FROM task_preferences"
2059 " WHERE task = %llu AND name = '%s';",
2060 task, quoted_name);
2061 g_free (quoted_name);
2062 sql ("UPDATE tasks SET modification_time = m_now ()"
2063 " WHERE id = %llu;",
2064 task);
2065 }
2066 }
2067 }
2068 return 0;
2069 }
2070
2071
2072 /* Configs. */
2073
2074 /**
2075 * @brief Find a config for a set of permissions, given a UUID.
2076 *
2077 * @param[in] uuid UUID of config.
2078 * @param[out] config Config return, 0 if successfully failed to find
2079 * config.
2080 * @param[in] permission Permission.
2081 *
2082 * @return FALSE on success (including if failed to find config), TRUE on error.
2083 */
2084 gboolean
find_config_with_permission(const char * uuid,config_t * config,const char * permission)2085 find_config_with_permission (const char* uuid, config_t* config,
2086 const char *permission)
2087 {
2088 return find_resource_with_permission ("config", uuid, config, permission, 0);
2089 }
2090
2091 /**
2092 * @brief Find a config given a UUID.
2093 *
2094 * This does not do any permission checks.
2095 *
2096 * @param[in] uuid UUID of resource.
2097 * @param[out] config Config return, 0 if no such config.
2098 *
2099 * @return FALSE on success (including if no such config), TRUE on error.
2100 */
2101 gboolean
find_config_no_acl(const char * uuid,config_t * config)2102 find_config_no_acl (const char *uuid, config_t *config)
2103 {
2104 gchar *quoted_uuid;
2105
2106 quoted_uuid = sql_quote (uuid);
2107 switch (sql_int64 (config,
2108 "SELECT id FROM configs WHERE uuid = '%s';",
2109 quoted_uuid))
2110 {
2111 case 0:
2112 break;
2113 case 1: /* Too few rows in result of query. */
2114 *config = 0;
2115 break;
2116 default: /* Programming error. */
2117 assert (0);
2118 case -1:
2119 g_free (quoted_uuid);
2120 return TRUE;
2121 break;
2122 }
2123
2124 g_free (quoted_uuid);
2125 return FALSE;
2126 }
2127
2128 /**
2129 * @brief Find a trash config given a UUID.
2130 *
2131 * This does not do any permission checks.
2132 *
2133 * @param[in] uuid UUID of resource.
2134 * @param[out] config Config return, 0 if no such config.
2135 *
2136 * @return FALSE on success (including if no such config), TRUE on error.
2137 */
2138 gboolean
find_trash_config_no_acl(const char * uuid,config_t * config)2139 find_trash_config_no_acl (const char *uuid, config_t *config)
2140 {
2141 gchar *quoted_uuid;
2142
2143 quoted_uuid = sql_quote (uuid);
2144 switch (sql_int64 (config,
2145 "SELECT id FROM configs_trash WHERE uuid = '%s';",
2146 quoted_uuid))
2147 {
2148 case 0:
2149 break;
2150 case 1: /* Too few rows in result of query. */
2151 *config = 0;
2152 break;
2153 default: /* Programming error. */
2154 assert (0);
2155 case -1:
2156 g_free (quoted_uuid);
2157 return TRUE;
2158 break;
2159 }
2160
2161 g_free (quoted_uuid);
2162 return FALSE;
2163 }
2164
2165 /**
2166 * @brief Gets an NVT preference by id or by name.
2167 *
2168 * Note: This currently only gets the fields needed by create_config.
2169 *
2170 * @param[in] nvt_oid OID of the NVT the preference belongs to.
2171 * @param[in] find_id Preference id to find, or NULL.
2172 * @param[in] check_name Preference name to check.
2173 * @param[in] check_type Preference name to check.
2174 * @param[in] value Value to assign to the preference.
2175 *
2176 * @return Newly allocated preference, freed with preference_free,
2177 * or NULL (on error or if not found).
2178 */
2179 preference_t *
get_nvt_preference_by_id(const char * nvt_oid,const char * find_id,const char * check_name,const char * check_type,const char * value)2180 get_nvt_preference_by_id (const char *nvt_oid,
2181 const char *find_id,
2182 const char *check_name,
2183 const char *check_type,
2184 const char *value)
2185 {
2186 preference_t *new_pref;
2187 char *full_name, *id, *name, *type, *nvt_name, *default_value, *hr_name;
2188 array_t *alts;
2189 gchar *quoted_oid, *quoted_id;
2190
2191 full_name = name = type = nvt_name = default_value = hr_name = NULL;
2192
2193 /* Check parameters */
2194 if (nvt_oid == NULL)
2195 {
2196 g_warning ("%s: Missing nvt_oid", __func__);
2197 return NULL;
2198 }
2199 if (find_id == NULL || strcmp (find_id, "") == 0)
2200 {
2201 g_warning ("%s: Missing or empty find_id", __func__);
2202 return NULL;
2203 }
2204 if (value == NULL)
2205 {
2206 g_warning ("%s: Missing value", __func__);
2207 return NULL;
2208 }
2209
2210 /* Try to get by id first */
2211 quoted_oid = sql_quote (nvt_oid);
2212 quoted_id = find_id ? sql_quote (find_id) : NULL;
2213
2214 full_name = sql_string ("SELECT name FROM nvt_preferences"
2215 " WHERE name LIKE '%s:%s:%%:%%'",
2216 quoted_oid,
2217 quoted_id);
2218
2219 g_free (quoted_oid);
2220 g_free (quoted_id);
2221
2222 if (full_name == NULL)
2223 {
2224 if (check_name == NULL || strcmp (check_name, "") == 0)
2225 {
2226 g_warning ("%s: Preference not found and given name is missing/empty",
2227 __func__);
2228 return NULL;
2229 }
2230 if (check_type == NULL || strcmp (check_type, "") == 0)
2231 {
2232 g_warning ("%s: Preference not found and given name is missing/empty",
2233 __func__);
2234 return NULL;
2235 }
2236 id = strdup (find_id);
2237 type = strdup (check_type);
2238 name = strdup (check_name);
2239 }
2240 else
2241 {
2242 char **full_name_split;
2243
2244 /* Try to get components of the full name */
2245 full_name_split = g_strsplit (full_name, ":", 4);
2246
2247 if (g_strv_length (full_name_split) != 4)
2248 {
2249 g_warning ("%s: Preference name %s does not have 4 parts",
2250 __func__, full_name);
2251 g_strfreev (full_name_split);
2252 free (full_name);
2253 return NULL;
2254 }
2255 free (full_name);
2256
2257 id = strdup (full_name_split[1]);
2258 type = strdup (full_name_split[2]);
2259 name = strdup (full_name_split[3]);
2260 g_strfreev (full_name_split);
2261
2262 if (check_type && strcmp (check_type, "") && strcmp (check_type, type))
2263 g_warning ("%s: type of preference %s:%s (%s) has changed from %s to %s.",
2264 __func__, nvt_oid, find_id, name, check_type, type);
2265
2266 if (check_name && strcmp (check_name, "") && strcmp (check_name, name))
2267 g_message ("%s: name of preference %s:%s has changed from '%s' to '%s'.",
2268 __func__, nvt_oid, find_id, check_name, name);
2269 }
2270
2271 alts = make_array ();
2272 array_terminate (alts);
2273
2274 new_pref = preference_new (id,
2275 name,
2276 type,
2277 strdup (value),
2278 nvt_name,
2279 strdup (nvt_oid),
2280 alts,
2281 default_value,
2282 hr_name,
2283 1);
2284
2285 return new_pref;
2286 }
2287
2288 /**
2289 * @brief Insert preferences into a config.
2290 *
2291 * @param[in] config Config.
2292 * @param[in] preferences Preferences.
2293 * @param[in] config_type Config type.
2294 *
2295 * @return 0 success, -1 error, -4 input error.
2296 */
2297 static int
config_insert_preferences(config_t config,const array_t * preferences,const char * config_type)2298 config_insert_preferences (config_t config,
2299 const array_t* preferences /* preference_t. */,
2300 const char* config_type)
2301 {
2302 int index = 0;
2303 const preference_t *preference;
2304 if (preferences == NULL) return -4;
2305 while ((preference = (preference_t*) g_ptr_array_index (preferences, index++)))
2306 /* Simply skip the preference if the value is NULL, for exports
2307 * where sensitive information is left out. */
2308 if (preference->value)
2309 {
2310 GString *value;
2311 int alt_index = 0;
2312 const gchar *alt;
2313 gchar *quoted_value;
2314
2315 if (preference->name == NULL) return -4;
2316 if (strcmp (preference->name, "Timeout") == 0)
2317 {
2318 gchar *quoted_nvt_oid;
2319
2320 /* Special Timeout preference. */
2321
2322 if (preference->nvt_oid == NULL
2323 && (config_type == NULL || strcmp (config_type, "0") == 0))
2324 return -4;
2325
2326 quoted_nvt_oid = sql_quote (preference->nvt_oid);
2327 quoted_value = sql_quote (preference->value);
2328
2329 sql ("INSERT into config_preferences (config, type, name, value)"
2330 " VALUES (%llu, 'SERVER_PREFS', 'timeout.%s', '%s');",
2331 config,
2332 quoted_nvt_oid,
2333 quoted_value);
2334
2335 g_free (quoted_nvt_oid);
2336 g_free (quoted_value);
2337 }
2338 else if (preference->type)
2339 {
2340 gchar *quoted_type, *quoted_nvt_oid, *quoted_preference_name;
2341 gchar *quoted_default, *quoted_preference_hr_name;
2342 gchar *quoted_preference_id;
2343
2344 /* Presume NVT or OSP preference. */
2345
2346 if (preference->nvt_oid == NULL
2347 && (config_type == NULL || strcmp (config_type, "0") == 0))
2348 return -4;
2349
2350 value = g_string_new (preference->value);
2351 while ((alt = (gchar*) g_ptr_array_index (preference->alts,
2352 alt_index++)))
2353 {
2354 g_string_append_printf (value, ";%s", alt);
2355 }
2356
2357 quoted_nvt_oid = sql_quote (preference->nvt_oid ?: "");
2358 quoted_preference_id = sql_quote (preference->id ?: "");
2359 quoted_preference_name = sql_quote (preference->name);
2360 quoted_preference_hr_name
2361 = preference->hr_name
2362 ? sql_quote (preference->hr_name)
2363 : NULL;
2364 quoted_type
2365 = g_str_has_prefix (preference->type, "osp_")
2366 ? sql_quote (preference->type + strlen ("osp_"))
2367 : sql_quote (preference->type);
2368 quoted_value = sql_quote (value->str);
2369 g_string_free (value, TRUE);
2370 quoted_default = preference->default_value
2371 ? sql_quote (preference->default_value)
2372 : NULL;
2373
2374 if (config_type == NULL || strcmp (config_type, "0") == 0)
2375 {
2376 /* NVT preference */
2377 /* OID:PrefID:PrefType:PrefName value */
2378 sql ("INSERT INTO config_preferences"
2379 " (config, type, name, value)"
2380 " VALUES (%llu, 'PLUGINS_PREFS', '%s:%s:%s:%s', '%s');",
2381 config,
2382 quoted_nvt_oid,
2383 quoted_preference_id,
2384 quoted_type,
2385 quoted_preference_name,
2386 quoted_value);
2387 }
2388 else
2389 {
2390 /* OSP preference */
2391 sql ("INSERT into config_preferences"
2392 " (config, type, name, value, default_value, hr_name)"
2393 " VALUES (%llu, '%s', '%s', '%s', '%s', '%s');",
2394 config,
2395 quoted_type,
2396 quoted_preference_name,
2397 quoted_value,
2398 quoted_default,
2399 quoted_preference_hr_name
2400 ? quoted_preference_name : quoted_preference_hr_name);
2401 }
2402 g_free (quoted_nvt_oid);
2403 g_free (quoted_preference_name);
2404 g_free (quoted_type);
2405 g_free (quoted_value);
2406 g_free (quoted_default);
2407 g_free (quoted_preference_hr_name);
2408 g_free (quoted_preference_id);
2409 }
2410 else
2411 {
2412 gchar *quoted_name;
2413
2414 /* Presume scanner preference. */
2415
2416 quoted_name = sql_quote (preference->name);
2417 quoted_value = sql_quote (preference->value);
2418 sql ("INSERT into config_preferences (config, type, name, value)"
2419 " VALUES (%llu, 'SERVER_PREFS', '%s', '%s');",
2420 config,
2421 quoted_name,
2422 quoted_value);
2423 g_free (quoted_name);
2424 g_free (quoted_value);
2425 }
2426 }
2427 return 0;
2428 }
2429
2430 /**
2431 * @brief Create a config.
2432 *
2433 * If a config with the same name exists already then add a unique integer
2434 * suffix onto the name.
2435 *
2436 * @param[in] check_access Whether to check for create_config permission.
2437 * @param[in] config_id ID if one is required, else NULL.
2438 * @param[in] proposed_name Proposed name of config.
2439 * @param[in] make_name_unique Whether to make name unique.
2440 * @param[in] comment Comment on config.
2441 * @param[in] all_selector Whether to use "all" selector instead of selectors.
2442 * @param[in] selectors NVT selectors.
2443 * @param[in] preferences Preferences.
2444 * @param[in] config_type Config type.
2445 * @param[in] usage_type The usage type ("scan" or "policy")
2446 * @param[in] allow_errors Whether certain errors are allowed.
2447 * @param[in] predefined Whether config is predefined.
2448 * @param[out] config On success the config.
2449 * @param[out] name On success the name of the config.
2450 *
2451 * @return 0 success, 1 config exists already, 99 permission denied, -1 error,
2452 * -2 name empty, -3 input error in selectors, -4 input error in
2453 * preferences, -5 error in config_id.
2454 */
2455 static int
create_config_internal(int check_access,const char * config_id,const char * proposed_name,int make_name_unique,const char * comment,int all_selector,const array_t * selectors,const array_t * preferences,const char * config_type,const char * usage_type,int allow_errors,int predefined,config_t * config,char ** name)2456 create_config_internal (int check_access, const char *config_id,
2457 const char *proposed_name,
2458 int make_name_unique, const char *comment,
2459 int all_selector,
2460 const array_t *selectors /* nvt_selector_t. */,
2461 const array_t *preferences /* preference_t. */,
2462 const char *config_type, const char *usage_type,
2463 int allow_errors, int predefined, config_t *config,
2464 char **name)
2465 {
2466 int ret;
2467 gchar *quoted_comment, *candidate_name, *quoted_candidate_name;
2468 gchar *quoted_type;
2469 const char *actual_usage_type;
2470 char *selector_uuid;
2471 unsigned int num = 1;
2472
2473 assert (current_credentials.uuid);
2474
2475 if (config_id
2476 && (g_regex_match_simple ("^[-0123456789abcdef]{36}$",
2477 config_id, 0, 0)
2478 == FALSE))
2479 return -5;
2480
2481 if (proposed_name == NULL || strlen (proposed_name) == 0) return -2;
2482
2483 if (all_selector)
2484 selector_uuid = NULL;
2485 else
2486 {
2487 selector_uuid = gvm_uuid_make ();
2488 if (selector_uuid == NULL)
2489 return -1;
2490 }
2491
2492 sql_begin_immediate ();
2493
2494 if (check_access && (acl_user_may ("create_config") == 0))
2495 {
2496 sql_rollback ();
2497 free (selector_uuid);
2498 return 99;
2499 }
2500
2501 candidate_name = g_strdup (proposed_name);
2502 quoted_candidate_name = sql_quote (candidate_name);
2503 quoted_type = config_type ? sql_quote (config_type) : g_strdup ("0");
2504 if (usage_type && strcasecmp (usage_type, "policy") == 0)
2505 actual_usage_type = "policy";
2506 else
2507 actual_usage_type = "scan";
2508
2509 while (make_name_unique)
2510 {
2511 if (!resource_with_name_exists (quoted_candidate_name, "config", 0))
2512 break;
2513 g_free (candidate_name);
2514 g_free (quoted_candidate_name);
2515 candidate_name = g_strdup_printf ("%s %u", proposed_name, ++num);
2516 quoted_candidate_name = sql_quote (candidate_name);
2517 }
2518
2519 if (comment)
2520 {
2521 quoted_comment = sql_nquote (comment, strlen (comment));
2522 sql ("INSERT INTO configs (uuid, name, owner, nvt_selector, comment,"
2523 " type, creation_time, modification_time, usage_type, predefined)"
2524 " VALUES (%s%s%s, '%s',"
2525 " (SELECT id FROM users WHERE users.uuid = '%s'),"
2526 " '%s', '%s', '%s', m_now (), m_now (), '%s', %i);",
2527 config_id ? "'" : "",
2528 config_id ? config_id : "make_uuid ()",
2529 config_id ? "'" : "",
2530 quoted_candidate_name,
2531 current_credentials.uuid,
2532 selector_uuid ? selector_uuid : MANAGE_NVT_SELECTOR_UUID_ALL,
2533 quoted_comment,
2534 quoted_type,
2535 actual_usage_type,
2536 predefined);
2537 g_free (quoted_comment);
2538 }
2539 else
2540 sql ("INSERT INTO configs (uuid, name, owner, nvt_selector, comment,"
2541 " type, creation_time, modification_time, usage_type, predefined)"
2542 " VALUES (%s%s%s, '%s',"
2543 " (SELECT id FROM users WHERE users.uuid = '%s'),"
2544 " '%s', '', '%s', m_now (), m_now (), '%s', %i);",
2545 config_id ? "'" : "",
2546 config_id ? config_id : "make_uuid ()",
2547 config_id ? "'" : "",
2548 quoted_candidate_name,
2549 current_credentials.uuid,
2550 selector_uuid ? selector_uuid : MANAGE_NVT_SELECTOR_UUID_ALL,
2551 quoted_type,
2552 actual_usage_type,
2553 predefined);
2554 g_free (quoted_candidate_name);
2555 g_free (quoted_type);
2556
2557 /* Insert the selectors into the nvt_selectors table. */
2558
2559 *config = sql_last_insert_id ();
2560
2561 if (selector_uuid && (config_type == NULL || strcmp (config_type, "0") == 0))
2562 {
2563 if ((ret = insert_nvt_selectors (selector_uuid, selectors, allow_errors)))
2564 {
2565 sql_rollback ();
2566 free (selector_uuid);
2567 return ret;
2568 }
2569 }
2570 free (selector_uuid);
2571
2572 /* Insert the preferences into the config_preferences table. */
2573
2574 if ((ret = config_insert_preferences (*config, preferences, config_type)))
2575 {
2576 sql_rollback ();
2577 return ret;
2578 }
2579
2580 /* Update family and NVT count caches. */
2581
2582 update_config_caches (*config);
2583
2584 sql_commit ();
2585 *name = candidate_name;
2586 return 0;
2587 }
2588
2589 /**
2590 * @brief Create a config.
2591 *
2592 * If a config with the same name exists already then add a unique integer
2593 * suffix onto the name.
2594 *
2595 * @param[in] config_id ID if one is required, else NULL.
2596 * @param[in] proposed_name Proposed name of config.
2597 * @param[in] make_name_unique Whether to make name unique.
2598 * @param[in] comment Comment on config.
2599 * @param[in] all_selector Whether to use "all" selector instead of selectors.
2600 * @param[in] selectors NVT selectors.
2601 * @param[in] preferences Preferences.
2602 * @param[in] config_type Config type.
2603 * @param[in] usage_type The usage type ("scan" or "policy")
2604 * @param[out] config On success the config.
2605 * @param[out] name On success the name of the config.
2606 *
2607 * @return 0 success, 1 config exists already, 99 permission denied, -1 error,
2608 * -2 name empty, -3 input error in selectors, -4 input error in
2609 * preferences, -5 error in config_id.
2610 */
2611 int
create_config(const char * config_id,const char * proposed_name,int make_name_unique,const char * comment,int all_selector,const array_t * selectors,const array_t * preferences,const char * config_type,const char * usage_type,config_t * config,char ** name)2612 create_config (const char *config_id, const char *proposed_name,
2613 int make_name_unique, const char *comment, int all_selector,
2614 const array_t *selectors /* nvt_selector_t. */,
2615 const array_t *preferences /* preference_t. */,
2616 const char *config_type, const char *usage_type,
2617 config_t *config, char **name)
2618 {
2619 return create_config_internal (1, config_id, proposed_name, make_name_unique,
2620 comment, all_selector, selectors, preferences,
2621 config_type, usage_type, 1,
2622 0, /* Predefined. */
2623 config, name);
2624 }
2625
2626 /**
2627 * @brief Create a config.
2628 *
2629 * If a config with the same name exists already then add a unique integer
2630 * suffix onto the name.
2631 *
2632 * @param[in] config_id ID if one is required, else NULL.
2633 * @param[in] proposed_name Proposed name of config.
2634 * @param[in] make_name_unique Whether to make name unique.
2635 * @param[in] comment Comment on config.
2636 * @param[in] all_selector Whether to use "all" selector instead of selectors.
2637 * @param[in] selectors NVT selectors.
2638 * @param[in] preferences Preferences.
2639 * @param[in] config_type Config type.
2640 * @param[in] usage_type The usage type ("scan" or "policy")
2641 * @param[out] config On success the config.
2642 * @param[out] name On success the name of the config.
2643 *
2644 * @return 0 success, 1 config exists already, 99 permission denied, -1 error,
2645 * -2 name empty, -3 input error in selectors, -4 input error in
2646 * preferences, -5 error in config_id.
2647 */
2648 int
create_config_no_acl(const char * config_id,const char * proposed_name,int make_name_unique,const char * comment,int all_selector,const array_t * selectors,const array_t * preferences,const char * config_type,const char * usage_type,config_t * config,char ** name)2649 create_config_no_acl (const char *config_id, const char *proposed_name,
2650 int make_name_unique, const char *comment,
2651 int all_selector,
2652 const array_t *selectors /* nvt_selector_t. */,
2653 const array_t *preferences /* preference_t. */,
2654 const char *config_type, const char *usage_type,
2655 config_t *config, char **name)
2656 {
2657 return create_config_internal (0, config_id, proposed_name, make_name_unique,
2658 comment, all_selector, selectors, preferences,
2659 config_type, usage_type, 0,
2660 1, /* Predefined. */
2661 config, name);
2662 }
2663
2664 /**
2665 * @brief Get list of OSP Scanner parameters.
2666 *
2667 * @param[in] scanner Scanner.
2668 *
2669 * @return List of scanner parameters, NULL if error.
2670 */
2671 static GSList *
get_scanner_params(scanner_t scanner)2672 get_scanner_params (scanner_t scanner)
2673 {
2674 GSList *list = NULL;
2675 osp_connection_t *connection;
2676
2677 connection = osp_scanner_connect (scanner);
2678 if (!connection)
2679 return NULL;
2680
2681 osp_get_scanner_details (connection, NULL, &list);
2682 osp_connection_close (connection);
2683 return list;
2684 }
2685
2686 /**
2687 * @brief Insert an OSP parameter into a config if not already present.
2688 *
2689 * @param[in] param OSP parameter to insert.
2690 * @param[in] config Config to insert parameter into.
2691 *
2692 * @return 1 if added, 0 otherwise.
2693 */
2694 static int
insert_osp_parameter(osp_param_t * param,config_t config)2695 insert_osp_parameter (osp_param_t *param, config_t config)
2696 {
2697 char *param_id, *param_name, *param_type, *param_def, *param_value = NULL;
2698 int ret = 0;
2699
2700 if (!param)
2701 return ret;
2702 param_id = sql_quote (osp_param_id (param));
2703 param_name = sql_quote (osp_param_name (param));
2704 param_type = sql_quote (osp_param_type_str (param));
2705 if (!strcmp (param_type, "selection"))
2706 {
2707 char **strarray = g_strsplit (osp_param_default (param), "|", 2);
2708
2709 param_value = sql_quote (strarray[0] ?: "");
2710 param_def = sql_quote (strarray[1] ?: param_value);
2711 g_strfreev (strarray);
2712 }
2713 else
2714 param_def = sql_quote (osp_param_default (param));
2715 if (sql_int ("SELECT count(*) FROM config_preferences"
2716 " WHERE config = %llu AND name = '%s' AND type = '%s'"
2717 " AND default_value = '%s';",
2718 config, param_id, param_type, param_def) == 0)
2719 {
2720 sql ("INSERT INTO config_preferences (config, name, type, value,"
2721 " default_value, hr_name)"
2722 " VALUES (%llu, '%s', '%s', '%s', '%s', '%s')",
2723 config , param_id, param_type, param_value ?: param_def,
2724 param_def, param_name);
2725 ret = 1;
2726 }
2727 g_free (param_name);
2728 g_free (param_id);
2729 g_free (param_type);
2730 g_free (param_def);
2731 g_free (param_value);
2732 return ret;
2733 }
2734
2735 /**
2736 * @brief Generate an extra WHERE clause for selecting configs
2737 *
2738 * @param[in] usage_type The usage type to limit the selection to.
2739 *
2740 * @return Newly allocated where clause string.
2741 */
2742 gchar *
configs_extra_where(const char * usage_type)2743 configs_extra_where (const char *usage_type)
2744 {
2745 gchar *extra_where = NULL;
2746 if (usage_type && strcmp (usage_type, ""))
2747 {
2748 gchar *quoted_usage_type;
2749 quoted_usage_type = sql_quote (usage_type);
2750 extra_where = g_strdup_printf (" AND usage_type = '%s'",
2751 quoted_usage_type);
2752 g_free (quoted_usage_type);
2753 }
2754 return extra_where;
2755 }
2756
2757 /**
2758 * @brief Create a config from an OSP scanner.
2759 *
2760 * @param[in] scanner_id UUID of scanner to create config from.
2761 * @param[in] name Name for config.
2762 * @param[in] comment Comment for config.
2763 * @param[in] usage_type The usage type ("scan" or "policy")
2764 * @param[out] uuid Config UUID, on success.
2765 *
2766 * @return 0 success, 1 couldn't find scanner, 2 scanner not of OSP type,
2767 * 3 config name exists already, 4 couldn't get params from scanner,
2768 * 99 permission denied, -1 error.
2769 */
2770 int
create_config_from_scanner(const char * scanner_id,const char * name,const char * comment,const char * usage_type,char ** uuid)2771 create_config_from_scanner (const char *scanner_id, const char *name,
2772 const char *comment, const char *usage_type,
2773 char **uuid)
2774 {
2775 scanner_t scanner;
2776 config_t config;
2777 GSList *params, *element;
2778 char *quoted_name, *quoted_comment;
2779 const char *actual_usage_type;
2780
2781 assert (current_credentials.uuid);
2782 assert (scanner_id);
2783 sql_begin_immediate ();
2784
2785 if (acl_user_may ("create_config") == 0)
2786 {
2787 sql_rollback ();
2788 return 99;
2789 }
2790 if (find_scanner_with_permission (scanner_id, &scanner, "get_scanners"))
2791 {
2792 sql_rollback ();
2793 return -1;
2794 }
2795 if (scanner == 0)
2796 {
2797 sql_rollback ();
2798 return 1;
2799 }
2800 if (scanner_type (scanner) != SCANNER_TYPE_OSP)
2801 {
2802 sql_rollback ();
2803 return 2;
2804 }
2805 if (resource_with_name_exists (name, "config", 0))
2806 {
2807 sql_rollback ();
2808 return 3;
2809 }
2810
2811 params = get_scanner_params (scanner);
2812 if (!params)
2813 {
2814 sql_rollback ();
2815 return 4;
2816 }
2817 quoted_name = sql_quote (name ?: "");
2818 quoted_comment = sql_quote (comment ?: "");
2819 if (usage_type && strcasecmp (usage_type, "policy") == 0)
2820 actual_usage_type = "policy";
2821 else
2822 actual_usage_type = "scan";
2823
2824 /* Create new OSP config. */
2825 sql ("INSERT INTO configs (uuid, name, owner, nvt_selector, comment,"
2826 " type, scanner, creation_time, modification_time, usage_type)"
2827 " VALUES (make_uuid (), '%s',"
2828 " (SELECT id FROM users WHERE users.uuid = '%s'),"
2829 " '', '%s', 1, %llu, m_now (), m_now (), '%s');",
2830 quoted_name, current_credentials.uuid, quoted_comment, scanner,
2831 actual_usage_type);
2832 g_free (quoted_name);
2833 g_free (quoted_comment);
2834 config = sql_last_insert_id ();
2835 *uuid = config_uuid (config);
2836
2837 element = params;
2838 while (element)
2839 {
2840 insert_osp_parameter (element->data, config);
2841 osp_param_free (element->data);
2842 element = element->next;
2843 }
2844 g_slist_free (params);
2845 sql_commit ();
2846 return 0;
2847 }
2848
2849 /**
2850 * @brief Return the UUID of a config.
2851 *
2852 * @param[in] config Config.
2853 *
2854 * @return Newly allocated config uuid pointer.
2855 */
2856 char *
config_uuid(config_t config)2857 config_uuid (config_t config)
2858 {
2859 return sql_string ("SELECT uuid FROM configs WHERE id = %llu;", config);
2860 }
2861
2862 /**
2863 * @brief Return the type of a config.
2864 *
2865 * @param[in] config Config.
2866 *
2867 * @return Config type, -1 if not found.
2868 */
2869 int
config_type(config_t config)2870 config_type (config_t config)
2871 {
2872 int type;
2873 char *str;
2874 str = sql_string ("SELECT type FROM configs WHERE id = %llu;", config);
2875 if (!str)
2876 return -1;
2877 type = atoi (str);
2878 g_free (str);
2879 return type;
2880 }
2881
2882 /**
2883 * @brief Return the scanner associated with a config, if any.
2884 *
2885 * @param[in] config Config.
2886 *
2887 * @return Scanner ID if found, 0 otherwise.
2888 */
2889 static scanner_t
config_scanner(config_t config)2890 config_scanner (config_t config)
2891 {
2892 scanner_t scanner;
2893
2894 switch (sql_int64 (&scanner,
2895 "SELECT scanner FROM configs WHERE id = %llu;", config))
2896 {
2897 case 0:
2898 break;
2899 case 1: /* Too few rows in result of query. */
2900 return 0;
2901 case -1:
2902 return 0;
2903 default: /* Programming error. */
2904 assert (0);
2905 }
2906 return scanner;
2907 }
2908
2909 /**
2910 * @brief Return whether a config is predefined.
2911 *
2912 * @param[in] config Config.
2913 *
2914 * @return 1 if predefined, else 0.
2915 */
2916 int
config_predefined(config_t config)2917 config_predefined (config_t config)
2918 {
2919 return sql_int ("SELECT predefined FROM configs"
2920 " WHERE id = %llu;",
2921 config);
2922 }
2923
2924 /**
2925 * @brief Return whether a trash config is predefined.
2926 *
2927 * @param[in] config Config.
2928 *
2929 * @return 1 if predefined, else 0.
2930 */
2931 int
trash_config_predefined(config_t config)2932 trash_config_predefined (config_t config)
2933 {
2934 return sql_int ("SELECT predefined FROM configs_trash"
2935 " WHERE id = %llu;",
2936 config);
2937 }
2938
2939 /**
2940 * @brief Get the timeout value for an NVT in a config.
2941 *
2942 * @param[in] config Config.
2943 * @param[in] oid ID of NVT.
2944 *
2945 * @return Newly allocated timeout if set for the NVT, else NULL.
2946 */
2947 char *
config_nvt_timeout(config_t config,const char * oid)2948 config_nvt_timeout (config_t config, const char *oid)
2949 {
2950 return sql_string ("SELECT value FROM config_preferences"
2951 " WHERE config = %llu"
2952 " AND type = 'SERVER_PREFS'"
2953 " AND name = 'timeout.%s';",
2954 config,
2955 oid);
2956 }
2957
2958 /**
2959 * @brief Check scanner and config values match for a task.
2960 *
2961 * @param[in] config Scan Config.
2962 * @param[in] scanner Scanner.
2963 *
2964 * @return 1 if config and scanner types match, 0 otherwise.
2965 */
2966 int
create_task_check_config_scanner(config_t config,scanner_t scanner)2967 create_task_check_config_scanner (config_t config, scanner_t scanner)
2968 {
2969 int ctype, stype;
2970
2971 assert (config);
2972 assert (scanner);
2973
2974 ctype = config_type (config);
2975 stype = scanner_type (scanner);
2976
2977 if (ctype == 0 && stype == SCANNER_TYPE_OPENVAS)
2978 return 1;
2979 if (ctype == 0 && stype == SCANNER_TYPE_OSP_SENSOR)
2980 return 1;
2981 if (ctype == 1 && stype == SCANNER_TYPE_OSP)
2982 return 1;
2983
2984 return 0;
2985 }
2986
2987 /**
2988 * @brief Check scanner and config values match for a task.
2989 *
2990 * @param[in] task Task.
2991 * @param[in] config_id ID of config. "0" to use task's config.
2992 * @param[in] scanner_id ID of scanner.
2993 *
2994 * @return 0 if config and scanner types match, 1 do not match, 2 failed to
2995 * find config, 3 failed to find scanner, -1 error.
2996 */
2997 int
modify_task_check_config_scanner(task_t task,const char * config_id,const char * scanner_id)2998 modify_task_check_config_scanner (task_t task, const char *config_id,
2999 const char *scanner_id)
3000 {
3001 config_t config = 0;
3002 scanner_t scanner = 0;
3003 int ctype, stype;
3004
3005 if (config_id == NULL)
3006 config_id = "0";
3007 if (scanner_id == NULL)
3008 scanner_id = "0";
3009
3010 if (!strcmp (config_id, "0") && !strcmp (scanner_id, "0"))
3011 return 0;
3012
3013 if (strcmp (config_id, "0"))
3014 {
3015 if (find_config_with_permission (config_id, &config, "get_configs"))
3016 return -1;
3017 if (config == 0)
3018 return 2;
3019 }
3020 else
3021 config = task_config (task);
3022
3023 if (strcmp (scanner_id, "0"))
3024 {
3025 if (find_scanner_with_permission (scanner_id, &scanner, "get_scanners"))
3026 return -1;
3027 if (scanner == 0)
3028 return 3;
3029 }
3030 else
3031 scanner = task_scanner (task);
3032
3033 stype = scanner_type (scanner);
3034
3035 /* CVE Scanner. */
3036 if (stype == SCANNER_TYPE_CVE)
3037 return strcmp (scanner_id, "0")
3038 /* Selecting the CVE Scanner will clear the config. */
3039 ? 0
3040 /* CVE Scanner is currently selected, so the only option is to
3041 * leave the config alone. */
3042 : (config ? 1 : 0);
3043
3044 ctype = config_type (config);
3045 /* OSP Scanner with OSP config. */
3046 if (stype == SCANNER_TYPE_OSP && ctype == 1)
3047 return 0;
3048
3049 /* OpenVAS Scanner with OpenVAS config. */
3050 if ((stype == SCANNER_TYPE_OPENVAS)
3051 && ctype == 0)
3052 return 0;
3053
3054 /* OSP Sensor with OpenVAS config. */
3055 if (stype == SCANNER_TYPE_OSP_SENSOR && ctype == 0)
3056 return 0;
3057
3058 /* Default Scanner with OpenVAS Config. */
3059 if (scanner == 0 && ctype == 0)
3060 return 0;
3061
3062 return 1;
3063 }
3064
3065 /**
3066 * @brief Create a config from an existing config.
3067 *
3068 * @param[in] name Name of new config and NVT selector.
3069 * @param[in] comment Comment on new config.
3070 * @param[in] config_id UUID of existing config.
3071 * @param[in] usage_type Optional new usage type for the new config.
3072 * @param[out] new_config New config.
3073 *
3074 * @return 0 success, 1 config exists already, 2 failed to find existing
3075 * config, 99 permission denied, -1 error.
3076 */
3077 int
copy_config(const char * name,const char * comment,const char * config_id,const char * usage_type,config_t * new_config)3078 copy_config (const char* name, const char* comment, const char *config_id,
3079 const char* usage_type, config_t* new_config)
3080 {
3081 int ret, type;
3082 char *config_selector;
3083 gchar *quoted_config_selector;
3084 config_t new, old;
3085
3086 assert (current_credentials.uuid);
3087
3088 sql_begin_immediate ();
3089
3090 /* Copy the existing config. */
3091
3092 ret = copy_resource_lock ("config", name, comment, config_id,
3093 " family_count, nvt_count, families_growing,"
3094 " nvts_growing, type, scanner, usage_type",
3095 1, &new, &old);
3096 if (ret)
3097 {
3098 sql_rollback ();
3099 return ret;
3100 }
3101
3102 sql ("UPDATE configs SET predefined = 0 WHERE id = %llu;", new);
3103
3104 sql ("INSERT INTO config_preferences (config, type, name, value,"
3105 " default_value, hr_name)"
3106 " SELECT %llu, type, name, value, default_value, hr_name"
3107 " FROM config_preferences"
3108 " WHERE config = %llu;", new, old);
3109
3110 type = config_type (new);
3111 if (type > 0)
3112 {
3113 /* Don't create nvt_selector etc,. for non-standard configs
3114 * (eg. OSP config.) Only config preferences are copied.
3115 */
3116 sql_commit ();
3117 if (new_config) *new_config = new;
3118 return 0;
3119 }
3120
3121 sql ("UPDATE configs SET nvt_selector = make_uuid () WHERE id = %llu;",
3122 new);
3123
3124 if (usage_type && strcmp (usage_type, ""))
3125 {
3126 const char *actual_usage_type;
3127
3128 if (strcasecmp (usage_type, "policy") == 0)
3129 actual_usage_type = "policy";
3130 else
3131 actual_usage_type = "scan";
3132
3133 sql ("UPDATE configs SET usage_type = '%s' WHERE id = %llu;",
3134 actual_usage_type,
3135 new);
3136 }
3137
3138 config_selector = config_nvt_selector (old);
3139 if (config_selector == NULL)
3140 {
3141 sql_rollback ();
3142 return -1;
3143 }
3144 quoted_config_selector = sql_quote (config_selector);
3145 free (config_selector);
3146
3147 sql ("INSERT INTO nvt_selectors (name, exclude, type, family_or_nvt, family)"
3148 " SELECT (SELECT nvt_selector FROM configs WHERE id = %llu),"
3149 " exclude, type, family_or_nvt, family"
3150 " FROM nvt_selectors"
3151 " WHERE name = '%s';",
3152 new,
3153 quoted_config_selector);
3154 g_free (quoted_config_selector);
3155
3156 sql_commit ();
3157 if (new_config) *new_config = new;
3158 return 0;
3159 }
3160
3161 /**
3162 * @brief Delete a config.
3163 *
3164 * @param[in] config_id UUID of config.
3165 * @param[in] ultimate Whether to remove entirely, or to trashcan.
3166 *
3167 * @return 0 success, 1 fail because a task refers to the config, 2 failed to
3168 * find config, 99 permission denied, -1 error.
3169 */
3170 int
delete_config(const char * config_id,int ultimate)3171 delete_config (const char *config_id, int ultimate)
3172 {
3173 config_t config = 0;
3174
3175 sql_begin_immediate ();
3176
3177 if (acl_user_may ("delete_config") == 0)
3178 {
3179 sql_rollback ();
3180 return 99;
3181 }
3182
3183 if (find_config_with_permission (config_id, &config, "delete_config"))
3184 {
3185 sql_rollback ();
3186 return -1;
3187 }
3188
3189 if (config == 0)
3190 {
3191 if (find_trash ("config", config_id, &config))
3192 {
3193 sql_rollback ();
3194 return -1;
3195 }
3196 if (config == 0)
3197 {
3198 sql_rollback ();
3199 return 2;
3200 }
3201 if (ultimate == 0)
3202 {
3203 /* It's already in the trashcan. */
3204 sql_commit ();
3205 return 0;
3206 }
3207
3208 /* Check if it's in use by a task in the trashcan. */
3209 if (sql_int ("SELECT count(*) FROM tasks"
3210 " WHERE config = %llu"
3211 " AND config_location = " G_STRINGIFY (LOCATION_TRASH) ";",
3212 config))
3213 {
3214 sql_rollback ();
3215 return 1;
3216 }
3217
3218 permissions_set_orphans ("config", config, LOCATION_TRASH);
3219 tags_remove_resource ("config", config, LOCATION_TRASH);
3220
3221 sql ("DELETE FROM nvt_selectors"
3222 " WHERE name != '" MANAGE_NVT_SELECTOR_UUID_ALL "'"
3223 " AND name = (SELECT nvt_selector FROM configs_trash"
3224 " WHERE id = %llu);",
3225 config);
3226 sql ("DELETE FROM config_preferences_trash WHERE config = %llu;",
3227 config);
3228 sql ("DELETE FROM configs_trash WHERE id = %llu;",
3229 config);
3230 sql_commit ();
3231 return 0;
3232 }
3233
3234 if (ultimate)
3235 {
3236 if (sql_int ("SELECT count(*) FROM tasks"
3237 " WHERE config = %llu"
3238 " AND config_location = " G_STRINGIFY (LOCATION_TABLE),
3239 config))
3240 {
3241 sql_rollback ();
3242 return 1;
3243 }
3244
3245 sql ("DELETE FROM nvt_selectors"
3246 " WHERE name != '" MANAGE_NVT_SELECTOR_UUID_ALL "'"
3247 " AND name = (SELECT nvt_selector FROM configs_trash"
3248 " WHERE id = %llu);",
3249 config);
3250
3251 permissions_set_orphans ("config", config, LOCATION_TABLE);
3252 tags_remove_resource ("config", config, LOCATION_TABLE);
3253 }
3254 else
3255 {
3256 config_t trash_config;
3257
3258 if (sql_int ("SELECT count(*) FROM tasks"
3259 " WHERE config = %llu"
3260 " AND config_location = " G_STRINGIFY (LOCATION_TABLE)
3261 " AND hidden = 0;",
3262 config))
3263 {
3264 sql_rollback ();
3265 return 1;
3266 }
3267
3268 sql ("INSERT INTO configs_trash"
3269 " (uuid, owner, name, nvt_selector, comment, family_count,"
3270 " nvt_count, families_growing, nvts_growing, type, scanner,"
3271 " predefined, creation_time, modification_time,"
3272 " scanner_location, usage_type)"
3273 " SELECT uuid, owner, name, nvt_selector, comment, family_count,"
3274 " nvt_count, families_growing, nvts_growing, type, scanner,"
3275 " predefined, creation_time, modification_time,"
3276 " " G_STRINGIFY (LOCATION_TABLE) ", usage_type"
3277 " FROM configs WHERE id = %llu;",
3278 config);
3279
3280 trash_config = sql_last_insert_id ();
3281
3282 sql ("INSERT INTO config_preferences_trash"
3283 " (config, type, name, value, default_value, hr_name)"
3284 " SELECT %llu, type, name, value, default_value, hr_name"
3285 " FROM config_preferences WHERE config = %llu;",
3286 trash_config,
3287 config);
3288
3289 /* Update the location of the config in any trashcan tasks. */
3290 sql ("UPDATE tasks"
3291 " SET config = %llu,"
3292 " config_location = " G_STRINGIFY (LOCATION_TRASH)
3293 " WHERE config = %llu"
3294 " AND config_location = " G_STRINGIFY (LOCATION_TABLE) ";",
3295 trash_config,
3296 config);
3297
3298 permissions_set_locations ("config", config, trash_config,
3299 LOCATION_TRASH);
3300 tags_set_locations ("config", config, trash_config,
3301 LOCATION_TRASH);
3302 }
3303
3304 sql ("DELETE FROM config_preferences WHERE config = %llu;", config);
3305 sql ("DELETE FROM configs WHERE id = %llu;", config);
3306
3307 sql_commit ();
3308 return 0;
3309 }
3310
3311 /**
3312 * @brief Update a config with a list of parameters.
3313 *
3314 * @param[in] config Config ID.
3315 * @param[in] config_id Config UUID.
3316 * @param[in] params List of new config parameters.
3317 *
3318 */
3319 static void
update_config_params(config_t config,const char * config_id,GSList * params)3320 update_config_params (config_t config, const char *config_id, GSList *params)
3321 {
3322 GSList *element;
3323 iterator_t iterator;
3324
3325 /* Remove parameters not used anymore. */
3326 init_iterator (&iterator,
3327 "SELECT id, name, type, default_value, hr_name"
3328 " FROM config_preferences"
3329 " WHERE config = %llu;", config);
3330 while (next (&iterator))
3331 {
3332 int found = 0;
3333
3334 element = params;
3335 while (element)
3336 {
3337 const char *name, *type, *def;
3338
3339 name = osp_param_id (element->data);
3340 type = osp_param_type_str (element->data);
3341 def = osp_param_default (element->data);
3342 if (!strcmp (name, iterator_string (&iterator, 1))
3343 && !strcmp (type, iterator_string (&iterator, 2)))
3344 {
3345 const char *iter_def = iterator_string (&iterator, 3);
3346
3347 if (!strcmp (type, "selection")
3348 && !strcmp (strchr (def, '|') + 1, iter_def))
3349 found = 1;
3350 else if (strcmp (type, "selection") && !strcmp (def, iter_def))
3351 found = 1;
3352 if (found)
3353 break;
3354 }
3355 element = element->next;
3356 }
3357 if (!found)
3358 {
3359 g_message ("Removing config preference %s from config '%s'",
3360 iterator_string (&iterator, 1), config_id);
3361 sql ("DELETE FROM config_preferences WHERE id = %llu;",
3362 iterator_int64 (&iterator, 0));
3363 }
3364 else if (strcmp (osp_param_name (element->data),
3365 iterator_string (&iterator, 4)))
3366 {
3367 // Update hr_name (= OSP name)
3368 gchar *quoted_name;
3369 quoted_name = sql_quote (osp_param_name (element->data));
3370 g_message ("Updating name of config preference %s in config '%s'",
3371 iterator_string (&iterator, 1), config_id);
3372 sql ("UPDATE config_preferences SET hr_name='%s' WHERE id = %llu;",
3373 quoted_name,
3374 iterator_int64 (&iterator, 0));
3375 g_free (quoted_name);
3376 }
3377 }
3378 cleanup_iterator (&iterator);
3379 /* Insert new parameters. */
3380 element = params;
3381 while (element)
3382 {
3383 if (insert_osp_parameter (element->data, config))
3384 g_message ("Adding config preference %s to config '%s'",
3385 osp_param_id (element->data), config_id);
3386 element = element->next;
3387 }
3388 }
3389
3390 /**
3391 * @brief Synchronize a config.
3392 *
3393 * @param[in] config_id UUID of config.
3394 *
3395 * @return 0 success, 1 failed to find config, 2 config not of OSP type,
3396 * 3 config has no scanner, 4 couldn't get params from scanner,
3397 * 99 permission denied, -1 error.
3398 */
3399 int
sync_config(const char * config_id)3400 sync_config (const char *config_id)
3401 {
3402 config_t config = 0;
3403 GSList *params;
3404 scanner_t scanner;
3405
3406 assert (config_id);
3407 assert (current_credentials.uuid);
3408
3409 sql_begin_immediate ();
3410
3411 if (acl_user_may ("modify_config") == 0)
3412 {
3413 sql_rollback ();
3414 return 99;
3415 }
3416 if (find_config_with_permission (config_id, &config, "modify_config"))
3417 {
3418 sql_rollback ();
3419 return -1;
3420 }
3421 if (config == 0)
3422 {
3423 sql_rollback ();
3424 return 1;
3425 }
3426 if (config_type (config) != SCANNER_TYPE_OSP)
3427 {
3428 sql_rollback ();
3429 return 2;
3430 }
3431 scanner = config_scanner (config);
3432 if (!scanner)
3433 {
3434 sql_rollback ();
3435 return 3;
3436 }
3437 params = get_scanner_params (scanner);
3438 if (!params)
3439 {
3440 sql_rollback ();
3441 return 4;
3442 }
3443 update_config_params (config, config_id, params);
3444
3445 sql_commit ();
3446 while (params)
3447 {
3448 osp_param_free (params->data);
3449 params = g_slist_remove_link (params, params);
3450 }
3451 return 0;
3452 }
3453
3454 /**
3455 * @brief Count the number of scan configs.
3456 *
3457 * @param[in] get GET params.
3458 *
3459 * @return Total number of scan configs filtered set.
3460 */
3461 int
config_count(const get_data_t * get)3462 config_count (const get_data_t *get)
3463 {
3464 int rc;
3465 static const char *filter_columns[] = CONFIG_ITERATOR_FILTER_COLUMNS;
3466 static column_t columns[] = CONFIG_ITERATOR_COLUMNS;
3467 static column_t trash_columns[] = CONFIG_ITERATOR_TRASH_COLUMNS;
3468 const char *usage_type = get_data_get_extra (get, "usage_type");
3469 gchar *extra_where = configs_extra_where (usage_type);
3470
3471 rc = count ("config", get, columns, trash_columns, filter_columns,
3472 0, 0, extra_where, TRUE);
3473
3474 g_free (extra_where);
3475 return rc;
3476 }
3477
3478 /**
3479 * @brief Initialise a config iterator, limited to user's configs.
3480 *
3481 * @param[in] iterator Iterator.
3482 * @param[in] config Config. 0 for all.
3483 * @param[in] trash Whether to iterate over trashcan configs.
3484 * @param[in] ascending Whether to sort ascending or descending.
3485 * @param[in] sort_field Field to sort on, or NULL for "id".
3486 */
3487 void
init_user_config_iterator(iterator_t * iterator,config_t config,int trash,int ascending,const char * sort_field)3488 init_user_config_iterator (iterator_t* iterator, config_t config, int trash,
3489 int ascending, const char* sort_field)
3490 {
3491 static column_t select_columns[] = CONFIG_ITERATOR_COLUMNS;
3492 gchar *columns;
3493 gchar *sql;
3494
3495 assert (current_credentials.uuid);
3496
3497 columns = columns_build_select (select_columns);
3498 if (config)
3499 sql = g_strdup_printf ("SELECT %s"
3500 " FROM configs%s"
3501 " WHERE id = %llu"
3502 " AND " ACL_USER_OWNS ()
3503 " ORDER BY %s %s;",
3504 columns,
3505 trash ? "_trash" : "",
3506 config,
3507 current_credentials.uuid,
3508 sort_field ? sort_field : "id",
3509 ascending ? "ASC" : "DESC");
3510 else
3511 sql = g_strdup_printf ("SELECT %s"
3512 " FROM configs%s"
3513 " WHERE " ACL_USER_OWNS ()
3514 " ORDER BY %s %s;",
3515 columns,
3516 trash ? "_trash" : "",
3517 current_credentials.uuid,
3518 sort_field ? sort_field : "id",
3519 ascending ? "ASC" : "DESC");
3520 g_free (columns);
3521 init_iterator (iterator, "%s", sql);
3522 g_free (sql);
3523 }
3524
3525 /**
3526 * @brief Initialise a scan config iterator.
3527 *
3528 * @param[in] iterator Iterator.
3529 * @param[in] get GET data.
3530 *
3531 * @return 0 success, 1 failed to find scan config, 2 failed to find filter,
3532 * -1 error.
3533 */
3534 int
init_config_iterator(iterator_t * iterator,const get_data_t * get)3535 init_config_iterator (iterator_t* iterator, const get_data_t *get)
3536 {
3537 int rc;
3538 static const char *filter_columns[] = CONFIG_ITERATOR_FILTER_COLUMNS;
3539 static column_t columns[] = CONFIG_ITERATOR_COLUMNS;
3540 static column_t trash_columns[] = CONFIG_ITERATOR_TRASH_COLUMNS;
3541 const char *usage_type = get_data_get_extra (get, "usage_type");
3542 gchar *extra_where = configs_extra_where (usage_type);
3543
3544 rc = init_get_iterator (iterator,
3545 "config",
3546 get,
3547 columns,
3548 trash_columns,
3549 filter_columns,
3550 0,
3551 NULL,
3552 extra_where,
3553 TRUE);
3554 g_free (extra_where);
3555 return rc;
3556 }
3557
3558 /**
3559 * @brief Get the nvt_selector from a config iterator.
3560 *
3561 * @param[in] iterator Iterator.
3562 *
3563 * @return The nvt_selector of the config, or NULL if iteration is complete.
3564 * Freed by cleanup_iterator.
3565 */
3566 DEF_ACCESS (config_iterator_nvt_selector, GET_ITERATOR_COLUMN_COUNT);
3567
3568 /**
3569 * @brief Get the family count from a config iterator.
3570 *
3571 * @param[in] iterator Iterator.
3572 *
3573 * @return Family count if known, -1 else.
3574 */
3575 int
config_iterator_family_count(iterator_t * iterator)3576 config_iterator_family_count (iterator_t* iterator)
3577 {
3578 int ret;
3579 if (iterator->done) return -1;
3580 ret = iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 1);
3581 return ret;
3582 }
3583
3584 /**
3585 * @brief Get the nvt count from a config iterator.
3586 *
3587 * @param[in] iterator Iterator.
3588 *
3589 * @return Nvt count if known, -1 else.
3590 */
3591 int
config_iterator_nvt_count(iterator_t * iterator)3592 config_iterator_nvt_count (iterator_t* iterator)
3593 {
3594 int ret;
3595 if (iterator->done) return -1;
3596 ret = iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 2);
3597 return ret;
3598 }
3599
3600 /**
3601 * @brief Get the families growing state from a config iterator.
3602 *
3603 * @param[in] iterator Iterator.
3604 *
3605 * @return Families growing flag.
3606 */
3607 int
config_iterator_families_growing(iterator_t * iterator)3608 config_iterator_families_growing (iterator_t* iterator)
3609 {
3610 int ret;
3611 if (iterator->done) return -1;
3612 ret = iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT +3);
3613 return ret;
3614 }
3615
3616 /**
3617 * @brief Get the NVTs growing state from a config iterator.
3618 *
3619 * @param[in] iterator Iterator.
3620 *
3621 * @return NVTs growing flag.
3622 */
3623 int
config_iterator_nvts_growing(iterator_t * iterator)3624 config_iterator_nvts_growing (iterator_t* iterator)
3625 {
3626 int ret;
3627 if (iterator->done) return -1;
3628 ret = iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 4);
3629 return ret;
3630 }
3631
3632 /**
3633 * @brief Get the type from a config iterator.
3634 *
3635 * @param[in] iterator Iterator.
3636 *
3637 * @return Config type.
3638 */
3639 int
config_iterator_type(iterator_t * iterator)3640 config_iterator_type (iterator_t* iterator)
3641 {
3642 int ret;
3643 if (iterator->done) return -1;
3644 ret = iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 5);
3645 return ret;
3646 }
3647
3648 /**
3649 * @brief Get the scanner from a config iterator.
3650 *
3651 * @param[in] iterator Iterator.
3652 *
3653 * @return Scanner.
3654 */
3655 scanner_t
config_iterator_scanner(iterator_t * iterator)3656 config_iterator_scanner (iterator_t* iterator)
3657 {
3658 scanner_t ret = 0;
3659 if (iterator->done) return 0;
3660 ret = iterator_int64 (iterator, GET_ITERATOR_COLUMN_COUNT + 6);
3661 return ret;
3662 }
3663
3664 /**
3665 * @brief Get whether scanner is in trash from a config iterator.
3666 *
3667 * @param[in] iterator Iterator.
3668 *
3669 * @return Whether Scanner is in trash.
3670 */
3671 int
config_iterator_scanner_trash(iterator_t * iterator)3672 config_iterator_scanner_trash (iterator_t* iterator)
3673 {
3674 int ret = 0;
3675 if (iterator->done) return 0;
3676 ret = iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 7);
3677 return ret;
3678 }
3679
3680 /**
3681 * @brief Get the usage type from a config iterator.
3682 *
3683 * @param[in] iterator Iterator.
3684 *
3685 * @return The usage type of the config, or NULL if iteration is complete.
3686 * Freed by cleanup_iterator.
3687 */
3688 DEF_ACCESS (config_iterator_usage_type, GET_ITERATOR_COLUMN_COUNT + 8);
3689
3690 /**
3691 * @brief Get predefined status from a config iterator.
3692 *
3693 * @param[in] iterator Iterator.
3694 *
3695 * @return 1 if predefined, else 0.
3696 */
3697 int
config_iterator_predefined(iterator_t * iterator)3698 config_iterator_predefined (iterator_t* iterator)
3699 {
3700 int ret = 0;
3701 if (iterator->done) return 0;
3702 ret = iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 9);
3703 return ret;
3704 }
3705
3706 /**
3707 * @brief Return whether a config is referenced by a task.
3708 *
3709 * @param[in] config Config.
3710 *
3711 * @return 1 if in use, else 0.
3712 */
3713 int
config_in_use(config_t config)3714 config_in_use (config_t config)
3715 {
3716 return !!sql_int ("SELECT count(*) FROM tasks"
3717 " WHERE config = %llu"
3718 " AND config_location = " G_STRINGIFY (LOCATION_TABLE)
3719 " AND hidden = 0;",
3720 config);
3721 }
3722
3723 /**
3724 * @brief Return whether a config can be modified.
3725 *
3726 * @param[in] config Config.
3727 *
3728 * @return 1.
3729 */
3730 int
config_writable(config_t config)3731 config_writable (config_t config)
3732 {
3733 return 1;
3734 }
3735
3736 /**
3737 * @brief Return whether a trashcan config is referenced by a task.
3738 *
3739 * @param[in] config Config.
3740 *
3741 * @return 1 if in use, else 0.
3742 */
3743 int
trash_config_in_use(config_t config)3744 trash_config_in_use (config_t config)
3745 {
3746 return !!sql_int ("SELECT count(*) FROM tasks"
3747 " WHERE config = %llu"
3748 " AND config_location = " G_STRINGIFY (LOCATION_TRASH),
3749 config);
3750 }
3751
3752 /**
3753 * @brief Return whether a trashcan config is writable.
3754 *
3755 * @param[in] config Config.
3756 *
3757 * @return 1 if in use, else 0.
3758 */
3759 int
trash_config_writable(config_t config)3760 trash_config_writable (config_t config)
3761 {
3762 return !trash_config_in_use (config);
3763 }
3764
3765 /**
3766 * @brief Return whether a trashcan config is readable.
3767 *
3768 * @param[in] config_id Config UUID.
3769 *
3770 * @return 1 if readable, else 0.
3771 */
3772 int
trash_config_readable_uuid(const gchar * config_id)3773 trash_config_readable_uuid (const gchar *config_id)
3774 {
3775 config_t found;
3776
3777 found = 0;
3778 if (find_trash ("config", config_id, &found))
3779 return 0;
3780 return found > 0;
3781 }
3782
3783 /**
3784 * @brief Initialise a preference iterator.
3785 *
3786 * Assume the caller has permission to access the config.
3787 *
3788 * @param[in] iterator Iterator.
3789 * @param[in] config Config.
3790 */
3791 void
init_config_preference_iterator(iterator_t * iterator,config_t config)3792 init_config_preference_iterator (iterator_t* iterator, config_t config)
3793 {
3794 gchar* sql;
3795
3796 sql = g_strdup_printf ("SELECT name, value, type, default_value, hr_name"
3797 " FROM config_preferences"
3798 " WHERE config = %llu;",
3799 config);
3800 init_iterator (iterator, "%s", sql);
3801 g_free (sql);
3802 }
3803
3804 /**
3805 * @brief Get the name from a preference iterator.
3806 *
3807 * @param[in] iterator Iterator.
3808 *
3809 * Note: For OSP results this corresponds to the "id" field in OSP, not "name".
3810 *
3811 * @return The name of the preference iterator, or NULL if iteration is
3812 * complete. Freed by cleanup_iterator.
3813 */
3814 DEF_ACCESS (config_preference_iterator_name, 0);
3815
3816 /**
3817 * @brief Get the value from a preference iterator.
3818 *
3819 * @param[in] iterator Iterator.
3820 *
3821 * @return The value of the preference iterator, or NULL if iteration is
3822 * complete. Freed by cleanup_iterator.
3823 */
3824 DEF_ACCESS (config_preference_iterator_value, 1);
3825
3826 /**
3827 * @brief Get the type from a preference iterator.
3828 *
3829 * @param[in] iterator Iterator.
3830 *
3831 * @return The value of the preference iterator, or NULL if iteration is
3832 * complete. Freed by cleanup_iterator.
3833 */
3834 DEF_ACCESS (config_preference_iterator_type, 2);
3835
3836 /**
3837 * @brief Get the default from a preference iterator.
3838 *
3839 * @param[in] iterator Iterator.
3840 *
3841 * @return The default of the preference iterator, or NULL if iteration is
3842 * complete. Freed by cleanup_iterator.
3843 */
3844 DEF_ACCESS (config_preference_iterator_default, 3);
3845
3846 /**
3847 * @brief Get the hr_name from a preference iterator.
3848 *
3849 * Note: This corresponds to the "name" in OSP and is not defined for classic
3850 * OpenVAS config preferences.
3851 *
3852 * @param[in] iterator Iterator.
3853 *
3854 * @return The hr_name of the preference iterator, or NULL if iteration is
3855 * complete. Freed by cleanup_iterator.
3856 */
3857 DEF_ACCESS (config_preference_iterator_hr_name, 4);
3858
3859 /**
3860 * @brief Initialise a config preference iterator, with defaults.
3861 *
3862 * Assume the caller has permission to access the config.
3863 *
3864 * This version substitutes the NVT preference when the config preference
3865 * is missing.
3866 *
3867 * @param[in] iterator Iterator.
3868 * @param[in] config Config containing preferences.
3869 * @param[in] section Preference section.
3870 */
3871 void
init_preference_iterator(iterator_t * iterator,config_t config,const char * section)3872 init_preference_iterator (iterator_t* iterator,
3873 config_t config,
3874 const char* section)
3875 {
3876 gchar *quoted_section;
3877
3878 assert (config);
3879 assert (section);
3880 assert ((strcmp (section, "PLUGINS_PREFS") == 0)
3881 || (strcmp (section, "SERVER_PREFS") == 0));
3882
3883 quoted_section = sql_quote (section);
3884
3885 init_iterator (iterator,
3886 "SELECT config_preferences.name, config_preferences.value"
3887 " FROM config_preferences, nvt_preferences"
3888 " WHERE config_preferences.config = %llu"
3889 " AND config_preferences.type = '%s'"
3890 " AND (config_preferences.name = nvt_preferences.name"
3891 " OR config_preferences.name LIKE 'timeout.%%')"
3892 " AND config_preferences.name != 'max_checks'"
3893 " AND config_preferences.name != 'max_hosts'"
3894 " UNION"
3895 " SELECT nvt_preferences.name, nvt_preferences.value"
3896 " FROM nvt_preferences"
3897 " WHERE nvt_preferences.name %s"
3898 " AND (SELECT COUNT(*) FROM config_preferences"
3899 " WHERE config = %llu"
3900 " AND config_preferences.name = nvt_preferences.name) = 0;",
3901 config,
3902 quoted_section,
3903 strcmp (quoted_section, "SERVER_PREFS") == 0
3904 ? "NOT LIKE '%:%:%:%'" : "LIKE '%:%:%:%'",
3905 config);
3906 g_free (quoted_section);
3907 }
3908
3909 /**
3910 * @brief Get the NAME from a preference iterator.
3911 *
3912 * @param[in] iterator Iterator.
3913 *
3914 * @return NAME, or NULL if iteration is complete. Freed by
3915 * cleanup_iterator.
3916 */
3917 DEF_ACCESS (preference_iterator_name, 0);
3918
3919 /**
3920 * @brief Get the value from a preference iterator.
3921 *
3922 * @param[in] iterator Iterator.
3923 *
3924 * @return Value, or NULL if iteration is complete. Freed by
3925 * cleanup_iterator.
3926 */
3927 DEF_ACCESS (preference_iterator_value, 1);
3928
3929 /**
3930 * @brief Return the NVT selector associated with a config.
3931 *
3932 * @param[in] config Config.
3933 *
3934 * @return Name of NVT selector if config exists and NVT selector is set, else
3935 * NULL.
3936 */
3937 char*
config_nvt_selector(config_t config)3938 config_nvt_selector (config_t config)
3939 {
3940 return sql_string ("SELECT nvt_selector FROM configs WHERE id = %llu;",
3941 config);
3942 }
3943
3944 /**
3945 * @brief Update a preference of a config.
3946 *
3947 * @param[in] config Config.
3948 * @param[in] nvt UUID of NVT. NULL for scanner preference.
3949 * @param[in] name Preference name, including NVT name and preference
3950 * type.
3951 * @param[in] value_64 Preference value in base64. NULL for an NVT
3952 * preference removes the preference from the config.
3953 *
3954 * @return 0 success, 1 config in use, 2 empty radio value, 3 failed to find
3955 * config, -1 error.
3956 */
3957 static int
modify_config_preference(config_t config,const char * nvt,const char * name,const char * value_64)3958 modify_config_preference (config_t config, const char* nvt,
3959 const char* name, const char* value_64)
3960 {
3961 gchar *quoted_name, *quoted_value, *value, **splits;
3962
3963 quoted_name = sql_quote (name);
3964
3965 if (strlen (value_64))
3966 {
3967 gsize value_len;
3968 value = (gchar*) g_base64_decode (value_64, &value_len);
3969 }
3970 else
3971 value = g_strdup ("");
3972
3973 /* OID:PrefID:PrefType:PrefName value */
3974 splits = g_strsplit (name, ":", 4);
3975 if (splits && g_strv_length (splits) == 4)
3976 {
3977 if (strcmp (splits[2], "radio") == 0)
3978 {
3979 char *old_value;
3980 gchar **split, **point;
3981 GString *string;
3982
3983 if (strlen (value) == 0)
3984 {
3985 g_free (quoted_name);
3986 g_free (value);
3987 return 2;
3988 }
3989
3990 /* A radio. Put the new value on the front of the list of options. */
3991
3992 old_value = sql_string ("SELECT value FROM config_preferences"
3993 " WHERE config = %llu"
3994 " AND type %s"
3995 " AND name = '%s'",
3996 config,
3997 nvt ? "= 'PLUGINS_PREFS'" : "is NULL",
3998 quoted_name);
3999 if (old_value == NULL)
4000 old_value = sql_string ("SELECT value FROM nvt_preferences"
4001 " WHERE name = '%s'",
4002 quoted_name);
4003 if (old_value)
4004 {
4005 string = g_string_new (value);
4006 split = g_strsplit (old_value, ";", 0);
4007 free (old_value);
4008 point = split;
4009 while (*point)
4010 {
4011 if (strlen (*point) == 0)
4012 {
4013 g_free (quoted_name);
4014 g_strfreev (split);
4015 g_free (value);
4016 g_string_free (string, TRUE);
4017 return -1;
4018 }
4019
4020 if (strcmp (*point, value))
4021 {
4022 g_string_append_c (string, ';');
4023 g_string_append (string, *point);
4024 }
4025 point++;
4026 }
4027 g_strfreev (split);
4028 g_free (value);
4029 value = g_string_free (string, FALSE);
4030 }
4031 }
4032 else if (strcmp (splits[2], "scanner") == 0)
4033 {
4034 /* A scanner preference. Remove type decoration from name. */
4035
4036 g_free (quoted_name);
4037 quoted_name = sql_quote (splits[3]);
4038 }
4039 }
4040 g_strfreev (splits);
4041
4042 quoted_value = sql_quote ((gchar*) value);
4043 g_free (value);
4044
4045 if (config_type (config) > 0)
4046 sql ("UPDATE config_preferences SET value = '%s'"
4047 " WHERE config = %llu AND name = '%s';",
4048 quoted_value, config, quoted_name);
4049 else
4050 {
4051 /* nvt prefs are not present on first modification. */
4052 sql ("DELETE FROM config_preferences"
4053 " WHERE config = %llu AND type %s AND name = '%s'",
4054 config,
4055 nvt ? "= 'PLUGINS_PREFS'" : "= 'SERVER_PREFS'",
4056 quoted_name);
4057 sql ("INSERT INTO config_preferences"
4058 " (config, type, name, value) VALUES (%llu, %s, '%s', '%s');",
4059 config, nvt ? "'PLUGINS_PREFS'" : "'SERVER_PREFS'", quoted_name,
4060 quoted_value);
4061 }
4062
4063 return 0;
4064 }
4065
4066 /**
4067 * @brief Set a preference of a config.
4068 *
4069 * @param[in] config Config to modify.
4070 * @param[in] nvt UUID of NVT. NULL for scanner preference.
4071 * @param[in] name Preference name, including NVT name and preference
4072 * type.
4073 * @param[in] value_64 Preference value in base64. NULL for an NVT
4074 * preference removes the preference from the config.
4075 *
4076 * @return 0 success, 1 config in use, 2 empty radio value, -1 error.
4077 */
4078 int
manage_set_config_preference(config_t config,const char * nvt,const char * name,const char * value_64)4079 manage_set_config_preference (config_t config, const char* nvt,
4080 const char* name, const char* value_64)
4081 {
4082 int ret;
4083
4084 if (value_64 == NULL)
4085 {
4086 gchar *quoted_name, **splits;
4087
4088 if (sql_int ("SELECT count(*) FROM tasks"
4089 " WHERE config = %llu AND hidden = 0;",
4090 config))
4091 {
4092 return 1;
4093 }
4094
4095 quoted_name = sql_quote (name);
4096
4097 /* OID:PrefID:scanner:PrefName */
4098 splits = g_strsplit (name, ":", 4);
4099 if (splits && g_strv_length (splits) == 4
4100 && strcmp (splits[2], "scanner") == 0)
4101 {
4102 /* A scanner preference. Remove type decoration from name. */
4103 g_free (quoted_name);
4104 quoted_name = sql_quote (splits[3]);
4105 }
4106 g_strfreev (splits);
4107
4108 sql ("DELETE FROM config_preferences"
4109 " WHERE config = %llu"
4110 " AND name = '%s';",
4111 config,
4112 quoted_name);
4113
4114 g_free (quoted_name);
4115 return 0;
4116 }
4117
4118 if (sql_int ("SELECT count(*) FROM tasks"
4119 " WHERE config = %llu AND hidden = 0;",
4120 config))
4121 {
4122 return 1;
4123 }
4124
4125 ret = modify_config_preference (config, nvt, name, value_64);
4126 if (ret)
4127 {
4128 return ret;
4129 }
4130
4131 return 0;
4132 }
4133
4134 /**
4135 * @brief Set the name, comment and scanner of a config.
4136 *
4137 * @param[in] config Config to modify.
4138 * @param[in] name New name, not updated if NULL.
4139 * @param[in] comment New comment, not updated if NULL.
4140 * @param[in] scanner_id UUID of new scanner, not updated if NULL.
4141 *
4142 * @return 0 success, 1 config with new name exists already, 2 scanner doesn't
4143 * exist, 3 modification not allowed while config is in use, -1 error.
4144 */
4145 int
manage_set_config(config_t config,const char * name,const char * comment,const char * scanner_id)4146 manage_set_config (config_t config, const char *name, const char *comment,
4147 const char *scanner_id)
4148 {
4149 assert (current_credentials.uuid);
4150
4151 if (name)
4152 {
4153 gchar *quoted_name;
4154 if (resource_with_name_exists (name, "config", config))
4155 {
4156 return 1;
4157 }
4158 quoted_name = sql_quote (name);
4159 sql ("UPDATE configs SET name = '%s', modification_time = m_now ()"
4160 " WHERE id = %llu;", quoted_name, config);
4161 g_free (quoted_name);
4162 }
4163 if (comment)
4164 {
4165 gchar *quoted_comment;
4166 quoted_comment = sql_quote (comment);
4167 sql ("UPDATE configs SET comment = '%s', modification_time = m_now ()"
4168 " WHERE id = %llu;", quoted_comment, config);
4169 g_free (quoted_comment);
4170 }
4171 if (scanner_id)
4172 {
4173 if (config_in_use (config))
4174 {
4175 return 3;
4176 }
4177 scanner_t scanner = 0;
4178
4179 if (find_scanner_with_permission (scanner_id, &scanner, "get_scanners")
4180 || scanner == 0)
4181 {
4182 return 2;
4183 }
4184 sql ("UPDATE configs SET scanner = %llu, modification_time = m_now ()"
4185 " WHERE id = %llu;", scanner, config);
4186 }
4187 return 0;
4188 }
4189
4190 /**
4191 * @brief Check whether a family is "whole-only".
4192 *
4193 * @param[in] family Family name.
4194 *
4195 * @return 1 if whole-only, else 0.
4196 */
4197 int
family_whole_only(const gchar * family)4198 family_whole_only (const gchar *family)
4199 {
4200 static const gchar *wholes[] = FAMILIES_WHOLE_ONLY;
4201
4202 for (const gchar **whole = wholes; *whole; whole++)
4203 if (strcmp (*whole, family) == 0)
4204 return 1;
4205 return 0;
4206 }
4207
4208 /**
4209 * @brief Get whether a config selects every NVT in a given family.
4210 *
4211 * @param[in] config Config.
4212 * @param[in] family Family name.
4213 *
4214 * @return 0 no, 1 yes, -1 error.
4215 */
4216 int
config_family_entire_and_growing(config_t config,const char * family)4217 config_family_entire_and_growing (config_t config, const char* family)
4218 {
4219 char *selector;
4220 int ret;
4221
4222 if (config == 0)
4223 return 0;
4224
4225 selector = config_nvt_selector (config);
4226 if (selector == NULL)
4227 {
4228 /* The config should always have a selector. */
4229 return -1;
4230 }
4231
4232 ret = nvt_selector_entire_and_growing (selector,
4233 family,
4234 config_families_growing (config));
4235 free (selector);
4236
4237 return ret;
4238 }
4239
4240 /**
4241 * @brief Set the NVT's selected for a single family of a config.
4242 *
4243 * @param[in] config Config to modify.
4244 * @param[in] family Family name.
4245 * @param[in] selected_nvts NVT's.
4246 *
4247 * @return 0 success, 1 config in use, 2 whole-only family, -1 error.
4248 */
4249 int
manage_set_config_nvts(config_t config,const char * family,GPtrArray * selected_nvts)4250 manage_set_config_nvts (config_t config, const char* family,
4251 GPtrArray* selected_nvts)
4252 {
4253 char *selector;
4254 gchar *quoted_family, *quoted_selector;
4255 int new_nvt_count = 0, old_nvt_count;
4256
4257 if (family_whole_only (family))
4258 return 2;
4259
4260 if (sql_int ("SELECT count(*) FROM tasks"
4261 " WHERE config = %llu AND hidden = 0;",
4262 config))
4263 {
4264 return 1;
4265 }
4266
4267 quoted_family = sql_quote (family);
4268
4269 selector = config_nvt_selector (config);
4270 if (selector == NULL)
4271 {
4272 /* The config should always have a selector. */
4273 g_free (quoted_family);
4274 return -1;
4275 }
4276
4277 quoted_selector = sql_quote (selector);
4278
4279 /* If the family is growing, then exclude all no's, otherwise the family
4280 * is static, so include all yes's. */
4281
4282 if (nvt_selector_family_growing (selector,
4283 family,
4284 config_families_growing (config)))
4285 {
4286 iterator_t nvts;
4287
4288 old_nvt_count = nvt_selector_nvt_count (selector, family, 1);
4289
4290 free (selector);
4291
4292 /* Clear any NVT selectors for this family from the config. */
4293
4294 if (strcmp (quoted_selector, MANAGE_NVT_SELECTOR_UUID_ALL))
4295 sql ("DELETE FROM nvt_selectors"
4296 " WHERE name = '%s'"
4297 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
4298 " AND family = '%s';",
4299 quoted_selector,
4300 quoted_family);
4301
4302 /* Exclude all no's. */
4303
4304 new_nvt_count = family_nvt_count (family);
4305
4306 init_nvt_iterator (&nvts, (nvt_t) 0, config, family, NULL, 1, NULL);
4307 while (next (&nvts))
4308 {
4309 const char *oid = nvt_iterator_oid (&nvts);
4310 gchar *quoted_oid;
4311
4312 if (member (selected_nvts, oid)) continue;
4313
4314 quoted_oid = sql_quote (oid);
4315 sql ("INSERT INTO nvt_selectors"
4316 " (name, exclude, type, family_or_nvt, family)"
4317 " VALUES ('%s', 1, "
4318 G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
4319 ", '%s', '%s');",
4320 quoted_selector,
4321 quoted_oid,
4322 quoted_family);
4323 g_free (quoted_oid);
4324
4325 new_nvt_count--;
4326 }
4327 cleanup_iterator (&nvts);
4328 }
4329 else
4330 {
4331 old_nvt_count = nvt_selector_nvt_count (selector, family, 0);
4332
4333 free (selector);
4334
4335 /* Clear any NVT selectors for this family from the config. */
4336
4337 if (strcmp (quoted_selector, MANAGE_NVT_SELECTOR_UUID_ALL))
4338 sql ("DELETE FROM nvt_selectors"
4339 " WHERE name = '%s'"
4340 " AND type = " G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
4341 " AND family = '%s';",
4342 quoted_selector,
4343 quoted_family);
4344
4345 /* Include all yes's. */
4346
4347 if (selected_nvts)
4348 {
4349 gchar *nvt;
4350 new_nvt_count = 0;
4351
4352 while ((nvt = (gchar*) g_ptr_array_index (selected_nvts,
4353 new_nvt_count)))
4354 {
4355 gchar *quoted_nvt = sql_quote (nvt);
4356 sql ("INSERT INTO nvt_selectors"
4357 " (name, exclude, type, family_or_nvt, family)"
4358 " VALUES ('%s', 0, "
4359 G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
4360 ", '%s', '%s');",
4361 quoted_selector,
4362 quoted_nvt,
4363 quoted_family);
4364 g_free (quoted_nvt);
4365 new_nvt_count++;
4366 }
4367 }
4368 }
4369
4370 /* Update the cached config info. */
4371
4372 sql ("UPDATE configs SET family_count = family_count + %i,"
4373 " nvt_count = nvt_count - %i + %i,"
4374 " modification_time = m_now ()"
4375 " WHERE id = %llu;",
4376 old_nvt_count == 0
4377 ? (new_nvt_count == 0 ? 0 : 1)
4378 : (new_nvt_count == 0 ? -1 : 0),
4379 old_nvt_count,
4380 MAX (new_nvt_count, 0),
4381 config);
4382
4383 g_free (quoted_family);
4384 g_free (quoted_selector);
4385 return 0;
4386 }
4387
4388 /**
4389 * @brief Switch between constraining and generating representation.
4390 *
4391 * It's up to the caller to start and end a transaction.
4392 *
4393 * @param[in] config Config name.
4394 * @param[in] constraining 1 families currently growing, 0 families currently
4395 * static.
4396 *
4397 * @return 0 success, -1 error.
4398 */
4399 static int
switch_representation(config_t config,int constraining)4400 switch_representation (config_t config, int constraining)
4401 {
4402 char* selector;
4403 gchar *quoted_selector;
4404
4405 selector = config_nvt_selector (config);
4406 if (selector == NULL)
4407 return -1;
4408 quoted_selector = sql_quote (selector);
4409
4410 if (constraining)
4411 {
4412 iterator_t families;
4413
4414 /* Currently constraining the universe. */
4415
4416 /* Remove the all selector. */
4417
4418 nvt_selector_remove_selector (quoted_selector,
4419 NULL,
4420 NVT_SELECTOR_TYPE_ALL);
4421
4422 /* Convert each family. */
4423
4424 init_family_iterator (&families, 0, NULL, 1);
4425 while (next (&families))
4426 {
4427 const char *family = family_iterator_name (&families);
4428 if (family)
4429 {
4430 gchar *quoted_family = sql_quote (family);
4431 if (nvt_selector_family_growing (selector, family, 1))
4432 /* Add a family include. */
4433 nvt_selector_add (quoted_selector,
4434 quoted_family,
4435 NULL,
4436 0);
4437 else
4438 /* Remove the family exclude. */
4439 nvt_selector_remove_selector (quoted_selector,
4440 quoted_family,
4441 NVT_SELECTOR_TYPE_FAMILY);
4442 g_free (quoted_family);
4443 }
4444 }
4445 cleanup_iterator (&families);
4446
4447 /* Update the cached config info. */
4448
4449 sql ("UPDATE configs SET families_growing = 0 WHERE id = %llu;",
4450 config);
4451 }
4452 else
4453 {
4454 iterator_t families;
4455
4456 /* Currently generating from empty. */
4457
4458 /* Add the all selector. */
4459
4460 sql ("INSERT INTO nvt_selectors"
4461 " (name, exclude, type, family_or_nvt)"
4462 " VALUES ('%s', 0, 0, 0);",
4463 quoted_selector);
4464
4465 /* Convert each family. */
4466
4467 init_family_iterator (&families, 0, NULL, 1);
4468 while (next (&families))
4469 {
4470 const char *family = family_iterator_name (&families);
4471 if (family)
4472 {
4473 gchar *quoted_family = sql_quote (family);
4474 if (nvt_selector_family_growing (selector, family, 0))
4475 /* Remove the family include. */
4476 nvt_selector_remove_selector (quoted_selector,
4477 quoted_family,
4478 NVT_SELECTOR_TYPE_FAMILY);
4479 else
4480 /* Add a family exclude. */
4481 nvt_selector_add (quoted_selector,
4482 quoted_family,
4483 NULL,
4484 1);
4485 g_free (quoted_family);
4486 }
4487 }
4488 cleanup_iterator (&families);
4489
4490 /* Update the cached config info. */
4491
4492 sql ("UPDATE configs SET families_growing = 1 WHERE id = %llu;",
4493 config);
4494 }
4495
4496 free (selector);
4497 g_free (quoted_selector);
4498 return 0;
4499 }
4500
4501 /**
4502 * @brief Initialise a config task iterator.
4503 *
4504 * Iterate over all tasks that use the config.
4505 *
4506 * @param[in] iterator Iterator.
4507 * @param[in] config Config.
4508 * @param[in] ascending Whether to sort ascending or descending.
4509 */
4510 void
init_config_task_iterator(iterator_t * iterator,config_t config,int ascending)4511 init_config_task_iterator (iterator_t* iterator, config_t config,
4512 int ascending)
4513 {
4514 gchar *available, *with_clause;
4515 get_data_t get;
4516 array_t *permissions;
4517
4518 assert (config);
4519
4520 get.trash = 0;
4521 permissions = make_array ();
4522 array_add (permissions, g_strdup ("get_tasks"));
4523 available = acl_where_owned ("task", &get, 1, "any", 0, permissions, 0,
4524 &with_clause);
4525 array_free (permissions);
4526
4527 init_iterator (iterator,
4528 "%s"
4529 " SELECT name, uuid, %s FROM tasks"
4530 " WHERE config = %llu"
4531 " AND hidden = 0"
4532 " ORDER BY name %s;",
4533 with_clause ? with_clause : "",
4534 available,
4535 config,
4536 ascending ? "ASC" : "DESC");
4537
4538 g_free (with_clause);
4539 g_free (available);
4540 }
4541
4542 /**
4543 * @brief Get the name from a config_task iterator.
4544 *
4545 * @param[in] iterator Iterator.
4546 *
4547 * @return Name, or NULL if iteration is complete. Freed by
4548 * cleanup_iterator.
4549 */
4550 DEF_ACCESS (config_task_iterator_name, 0);
4551
4552 /**
4553 * @brief Get the UUID from a config_task iterator.
4554 *
4555 * @param[in] iterator Iterator.
4556 *
4557 * @return UUID, or NULL if iteration is complete. Freed by
4558 * cleanup_iterator.
4559 */
4560 DEF_ACCESS (config_task_iterator_uuid, 1);
4561
4562 /**
4563 * @brief Get the read permission status from a GET iterator.
4564 *
4565 * @param[in] iterator Iterator.
4566 *
4567 * @return 1 if may read, else 0.
4568 */
4569 int
config_task_iterator_readable(iterator_t * iterator)4570 config_task_iterator_readable (iterator_t* iterator)
4571 {
4572 if (iterator->done) return 0;
4573 return iterator_int (iterator, 2);
4574 }
4575
4576 /**
4577 * @brief Initialise a config timeout iterator.
4578 *
4579 * Iterate over all timeout preferences of NVTs that have timeouts.
4580 *
4581 * @param[in] iterator Iterator.
4582 * @param[in] config Config.
4583 */
4584 void
init_config_timeout_iterator(iterator_t * iterator,config_t config)4585 init_config_timeout_iterator (iterator_t* iterator, config_t config)
4586 {
4587 init_iterator (iterator,
4588 "SELECT name, substr (name, 9),"
4589 " (SELECT name FROM nvts"
4590 " WHERE oid = substr (config_preferences.name, 9)),"
4591 " value"
4592 " FROM config_preferences"
4593 " WHERE config = %llu"
4594 " AND substr (name, 1, 8) = 'timeout.'"
4595 /* Ensure that the NVT pref comes first, in case an
4596 * error in the GSA added the NVT pref as a Scanner
4597 * pref. */
4598 " ORDER BY type",
4599 config);
4600 }
4601
4602 /**
4603 * @brief Get the NVT OID from a config timeout iterator.
4604 *
4605 * @param[in] iterator Iterator.
4606 *
4607 * @return NVT OID, or NULL if iteration is complete. Freed by
4608 * cleanup_iterator.
4609 */
4610 DEF_ACCESS (config_timeout_iterator_oid, 1);
4611
4612 /**
4613 * @brief Get the NVT OID from a config timeout iterator.
4614 *
4615 * @param[in] iterator Iterator.
4616 *
4617 * @return NVT OID, or NULL if iteration is complete. Freed by
4618 * cleanup_iterator.
4619 */
4620 DEF_ACCESS (config_timeout_iterator_nvt_name, 2);
4621
4622 /**
4623 * @brief Get the value from a config timeout iterator.
4624 *
4625 * @param[in] iterator Iterator.
4626 *
4627 * @return Timeout value, or NULL if iteration is complete. Freed by
4628 * cleanup_iterator.
4629 */
4630 DEF_ACCESS (config_timeout_iterator_value, 3);
4631
4632 /**
4633 * @brief Update or optionally insert a NVT preference.
4634 *
4635 * @param[in] config_id UUID of the config to set the preference in
4636 * @param[in] type Type of the preference, e.g. "PLUGINS_PREFS"
4637 * @param[in] preference_name Full name of the preference
4638 * @param[in] new_value The new value to set
4639 * @param[in] insert Whether to insert the preference if missing
4640 */
4641 void
update_config_preference(const char * config_id,const char * type,const char * preference_name,const char * new_value,gboolean insert)4642 update_config_preference (const char *config_id,
4643 const char *type,
4644 const char *preference_name,
4645 const char *new_value,
4646 gboolean insert)
4647 {
4648 gchar *quoted_config_id = sql_quote (config_id);
4649 gchar *quoted_type = sql_quote (type);
4650 gchar *quoted_name = sql_quote (preference_name);
4651 gchar *quoted_value = sql_quote (new_value);
4652
4653 if (sql_int ("SELECT count (*) FROM config_preferences"
4654 " WHERE config = (SELECT id FROM configs WHERE uuid = '%s')"
4655 " AND type = '%s'"
4656 " AND name = '%s';",
4657 quoted_config_id, quoted_type, quoted_name) == 0)
4658 {
4659 if (insert)
4660 {
4661 sql ("INSERT INTO config_preferences (config, type, name, value)"
4662 " VALUES ((SELECT id FROM configs WHERE uuid = '%s'),"
4663 " '%s', '%s', '%s');",
4664 quoted_config_id, quoted_type, quoted_name, quoted_value);
4665 }
4666 }
4667 else
4668 {
4669 sql ("UPDATE config_preferences SET value = '%s'"
4670 " WHERE config = (SELECT id FROM configs WHERE uuid = '%s')"
4671 " AND type = '%s'"
4672 " AND name = '%s';",
4673 quoted_value, quoted_config_id, quoted_type, quoted_name);
4674 }
4675
4676 g_free (quoted_config_id);
4677 g_free (quoted_type);
4678 g_free (quoted_name);
4679 g_free (quoted_value);
4680 }
4681
4682 /**
4683 * @brief Update the cached count and growing information in a config.
4684 *
4685 * It's up to the caller to organise a transaction.
4686 *
4687 * @param[in] configs Config to update.
4688 */
4689 static void
update_config_cache(iterator_t * configs)4690 update_config_cache (iterator_t *configs)
4691 {
4692 const char *selector;
4693 gchar *quoted_selector, *quoted_name;
4694 int families_growing;
4695
4696 if (config_iterator_type (configs) > 0)
4697 return;
4698
4699 quoted_name = sql_quote (get_iterator_name (configs));
4700 selector = config_iterator_nvt_selector (configs);
4701 families_growing = nvt_selector_families_growing (selector);
4702 quoted_selector = sql_quote (selector);
4703
4704 sql ("UPDATE configs"
4705 " SET family_count = %i, nvt_count = %i,"
4706 " families_growing = %i, nvts_growing = %i"
4707 " WHERE name = '%s';",
4708 nvt_selector_family_count (quoted_selector, families_growing),
4709 nvt_selector_nvt_count (quoted_selector, NULL, families_growing),
4710 families_growing,
4711 nvt_selector_nvts_growing_2 (quoted_selector, families_growing),
4712 quoted_name);
4713
4714 g_free (quoted_name);
4715 g_free (quoted_selector);
4716 }
4717
4718 /**
4719 * @brief Update the cached count and growing information in every config.
4720 *
4721 * Only consider configs for the current user.
4722 *
4723 * It's up to the caller to organise a transaction.
4724 *
4725 * @param[in] config Config to update. 0 for all.
4726 */
4727 static void
update_config_caches(config_t config)4728 update_config_caches (config_t config)
4729 {
4730 iterator_t configs;
4731
4732 init_user_config_iterator (&configs, config, 0, 1, NULL);
4733 while (next (&configs))
4734 update_config_cache (&configs);
4735 cleanup_iterator (&configs);
4736 }
4737
4738 /**
4739 * @brief Update count and growing info in every config across all users.
4740 *
4741 * It's up to the caller to organise a transaction.
4742 */
4743 void
update_all_config_caches()4744 update_all_config_caches ()
4745 {
4746 static column_t select_columns[] = CONFIG_ITERATOR_COLUMNS;
4747 gchar *columns;
4748 iterator_t configs;
4749
4750 columns = columns_build_select (select_columns);
4751 init_iterator (&configs, "SELECT %s FROM configs;", columns);
4752 g_free (columns);
4753 while (next (&configs))
4754 update_config_cache (&configs);
4755 cleanup_iterator (&configs);
4756 }
4757
4758 /**
4759 * @brief Update count and growing info in config, without checking user.
4760 *
4761 * For use during initialisation.
4762 *
4763 * @param[in] uuid Config UUID.
4764 *
4765 * It's up to the caller to organise a transaction.
4766 */
4767 void
update_config_cache_init(const char * uuid)4768 update_config_cache_init (const char *uuid)
4769 {
4770 static column_t select_columns[] = CONFIG_ITERATOR_COLUMNS;
4771 gchar *columns;
4772 iterator_t configs;
4773
4774 columns = columns_build_select (select_columns);
4775 init_iterator (&configs,
4776 "SELECT %s FROM configs WHERE uuid = '%s';",
4777 columns,
4778 uuid);
4779 g_free (columns);
4780 while (next (&configs))
4781 update_config_cache (&configs);
4782 cleanup_iterator (&configs);
4783 }
4784
4785 /**
4786 * @brief Migrate old ownerless configs to the Feed Owner.
4787 */
4788 void
migrate_predefined_configs()4789 migrate_predefined_configs ()
4790 {
4791 sql ("UPDATE configs"
4792 " SET owner = (SELECT id FROM users"
4793 " WHERE uuid = (SELECT value FROM settings"
4794 " WHERE uuid = '%s'))"
4795 " WHERE owner is NULL;",
4796 SETTING_UUID_FEED_IMPORT_OWNER);
4797 }
4798
4799
4800 /* Startup. */
4801
4802 /**
4803 * @brief Check if a config has been updated in the feed.
4804 *
4805 * @param[in] path Full path to config XML in feed.
4806 * @param[in] config Config.
4807 *
4808 * @return 1 if updated in feed, else 0.
4809 */
4810 int
config_updated_in_feed(config_t config,const gchar * path)4811 config_updated_in_feed (config_t config, const gchar *path)
4812 {
4813 GStatBuf state;
4814 int last_config_update;
4815
4816 last_config_update = sql_int ("SELECT modification_time FROM configs"
4817 " WHERE id = %llu;",
4818 config);
4819
4820 if (g_stat (path, &state))
4821 {
4822 g_warning ("%s: Failed to stat feed config file: %s",
4823 __func__,
4824 strerror (errno));
4825 return 0;
4826 }
4827
4828 if (state.st_mtime <= last_config_update)
4829 return 0;
4830
4831 return 1;
4832 }
4833
4834 /**
4835 * @brief Update a config from an XML file.
4836 *
4837 * @param[in] config Existing config.
4838 * @param[in] type New config type.
4839 * @param[in] name New name.
4840 * @param[in] comment New comment.
4841 * @param[in] usage_type New usage type.
4842 * @param[in] all_selector Whether to use "all" selector instead of selectors.
4843 * @param[in] selectors New NVT selectors.
4844 * @param[in] preferences New preferences.
4845 */
4846 void
update_config(config_t config,const gchar * type,const gchar * name,const gchar * comment,const gchar * usage_type,int all_selector,const array_t * selectors,const array_t * preferences)4847 update_config (config_t config, const gchar *type, const gchar *name,
4848 const gchar *comment, const gchar *usage_type,
4849 int all_selector,
4850 const array_t* selectors /* nvt_selector_t. */,
4851 const array_t* preferences /* preference_t. */)
4852 {
4853 gchar *quoted_name, *quoted_comment, *quoted_type, *actual_usage_type;
4854
4855 sql_begin_immediate ();
4856
4857 if (usage_type && strcasecmp (usage_type, "policy") == 0)
4858 actual_usage_type = "policy";
4859 else
4860 actual_usage_type = "scan";
4861
4862 quoted_name = sql_quote (name);
4863 quoted_comment = sql_quote (comment ? comment : "");
4864 quoted_type = sql_quote (type);
4865 sql ("UPDATE configs"
4866 " SET name = '%s', comment = '%s', type = '%s', usage_type = '%s',"
4867 " predefined = 1, modification_time = m_now ()"
4868 " WHERE id = %llu;",
4869 quoted_name,
4870 quoted_comment,
4871 quoted_type,
4872 actual_usage_type,
4873 config);
4874 g_free (quoted_name);
4875 g_free (quoted_comment);
4876 g_free (quoted_type);
4877
4878 /* Replace the NVT selectors. */
4879
4880 if (type == NULL || strcmp (type, "0") == 0)
4881 {
4882 char *selector_uuid;
4883
4884 if (all_selector)
4885 selector_uuid = NULL;
4886 else
4887 {
4888 selector_uuid = gvm_uuid_make ();
4889 if (selector_uuid == NULL)
4890 {
4891 g_warning ("%s: failed to allocate UUID", __func__);
4892 sql_rollback ();
4893 return;
4894 }
4895 }
4896
4897 sql ("DELETE FROM nvt_selectors"
4898 " WHERE name != '" MANAGE_NVT_SELECTOR_UUID_ALL "'"
4899 " AND name = (SELECT nvt_selector FROM configs"
4900 " WHERE id = %llu);",
4901 config);
4902
4903 sql ("UPDATE configs SET nvt_selector = '%s' WHERE id = %llu;",
4904 selector_uuid ? selector_uuid : MANAGE_NVT_SELECTOR_UUID_ALL,
4905 config);
4906
4907 if (selector_uuid && insert_nvt_selectors (selector_uuid, selectors, 0))
4908 {
4909 g_warning ("%s: Error in feed config NVT selector", __func__);
4910 free (selector_uuid);
4911 sql_rollback ();
4912 return;
4913 }
4914
4915 free (selector_uuid);
4916 }
4917
4918 /* Replace the preferences. */
4919
4920 sql ("DELETE FROM config_preferences WHERE config = %llu;", config);
4921 if (config_insert_preferences (config, preferences, type))
4922 {
4923 g_warning ("%s: Error in feed config preference", __func__);
4924 sql_rollback ();
4925 return;
4926 }
4927
4928 sql_commit ();
4929 }
4930
4931 /**
4932 * @brief Check configs, for startup.
4933 */
4934 void
check_db_configs()4935 check_db_configs ()
4936 {
4937 migrate_predefined_configs ();
4938
4939 if (sync_configs_with_feed (FALSE) <= -1)
4940 g_warning ("%s: Failed to sync configs with feed", __func__);
4941
4942 /* Warn about feed resources in the trash. */
4943 if (sql_int ("SELECT EXISTS (SELECT * FROM configs_trash"
4944 " WHERE predefined = 1);"))
4945 {
4946 g_warning ("%s: There are feed configs/policies in the trash."
4947 " These will be excluded from the sync.",
4948 __func__);
4949 }
4950 }
4951
4952 /**
4953 * @brief Check whole-only families.
4954 *
4955 * Called after NVT sync.
4956 */
4957 void
check_whole_only_in_configs()4958 check_whole_only_in_configs ()
4959 {
4960 static const gchar *wholes[] = FAMILIES_WHOLE_ONLY;
4961
4962 for (const gchar **whole = wholes; *whole; whole++)
4963 {
4964 gchar *quoted_family;
4965
4966 quoted_family = sql_quote (*whole);
4967
4968 /* Delete any excluding NVT selectors. */
4969
4970 sql ("DELETE FROM nvt_selectors"
4971 " WHERE type = " G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
4972 " AND exclude = 1"
4973 " AND EXISTS (SELECT * FROM nvts"
4974 " WHERE oid = family_or_nvt"
4975 " AND family = '%s');",
4976 quoted_family);
4977
4978 /* Convert any including NVT selectors to family selectors. */
4979
4980 sql ("WITH sels AS (DELETE FROM nvt_selectors"
4981 " WHERE type = " G_STRINGIFY (NVT_SELECTOR_TYPE_NVT)
4982 " AND EXISTS (SELECT * FROM nvts"
4983 " WHERE oid = family_or_nvt"
4984 " AND family = '%s')"
4985 " RETURNING name),"
4986 " names AS (SELECT distinct * FROM sels)"
4987 " INSERT INTO nvt_selectors"
4988 " (name, exclude, type, family_or_nvt, family)"
4989 " SELECT names.name, 0, " G_STRINGIFY (NVT_SELECTOR_TYPE_FAMILY) ","
4990 " '%s', '%s'"
4991 " FROM names;",
4992 quoted_family,
4993 quoted_family,
4994 quoted_family);
4995
4996 g_free (quoted_family);
4997 }
4998 }
4999