1 /* Copyright (C) 2020-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_report_formats.c
21 * @brief GVM management layer: Report format SQL
22 *
23 * The report format SQL for the GVM management layer.
24 */
25
26 #include "manage_sql_report_formats.h"
27 #include "manage_acl.h"
28 #include "manage_report_formats.h"
29 #include "sql.h"
30 #include "utils.h"
31
32 #include <errno.h>
33 #include <glib.h>
34 #include <glib/gstdio.h>
35 #include <grp.h>
36 #include <libgen.h>
37 #include <limits.h>
38 #include <locale.h>
39 #include <pwd.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <sys/types.h>
43 #include <sys/wait.h>
44 #include <unistd.h>
45
46 #include <gvm/base/proctitle.h>
47 #include <gvm/util/uuidutils.h>
48 #include <gvm/util/fileutils.h>
49
50 #undef G_LOG_DOMAIN
51 /**
52 * @brief GLib log domain.
53 */
54 #define G_LOG_DOMAIN "md manage"
55
56
57 /* Non-SQL internals defined in manage_report_formats.c. */
58
59 int
60 sync_report_formats_with_feed (gboolean);
61
62
63 /* Static headers. */
64
65 static int
66 validate_param_value (report_format_t, report_format_param_t param, const char *,
67 const char *);
68
69 static void
70 set_report_format_name (report_format_t, const char *);
71
72 static void
73 set_report_format_summary (report_format_t, const char *);
74
75 static void
76 set_report_format_active (report_format_t, int);
77
78 static int
79 set_report_format_param (report_format_t, const char *, const char *);
80
81
82 /* Helpers. */
83
84 /**
85 * @brief Return the name of the sysconf GnuPG home directory
86 *
87 * Returns the name of the GnuPG home directory to use when checking
88 * signatures. It is the directory openvas/gnupg under the sysconfdir
89 * that was set by configure (usually $prefix/etc).
90 *
91 * @return Static name of the Sysconf GnuPG home directory.
92 */
93 static const char *
get_sysconf_gpghome()94 get_sysconf_gpghome ()
95 {
96 static char *name;
97
98 if (!name)
99 name = g_build_filename (GVM_SYSCONF_DIR, "gnupg", NULL);
100
101 return name;
102 }
103
104 /**
105 * @brief Return the name of the trusted keys file name.
106 *
107 * We currently use the name pubring.gpg to be compatible with
108 * previous installations. That file should best be installed
109 * read-only so that it is not accidentally accessed while we are
110 * running a verification. All files in that keyring are assumed to
111 * be fully trustworthy.
112 *
113 * @return Static file name.
114 */
115 static const char *
get_trustedkeys_name()116 get_trustedkeys_name ()
117 {
118 static char *name;
119
120 if (!name)
121 name = g_build_filename (get_sysconf_gpghome (), "pubring.gpg", NULL);
122
123 return name;
124 }
125
126
127 /* Predefined resources.
128 *
129 * These are only used by report formats, because report formats from the feed
130 * are automatically trusted, so we need to track them. */
131
132 /**
133 * @brief Return whether a resource is predefined.
134 *
135 * @param[in] type Type of resource.
136 * @param[in] resource Resource.
137 *
138 * @return 1 if predefined, else 0.
139 */
140 int
resource_predefined(const gchar * type,resource_t resource)141 resource_predefined (const gchar *type, resource_t resource)
142 {
143 assert (valid_type (type));
144 return sql_int ("SELECT EXISTS (SELECT * FROM resources_predefined"
145 " WHERE resource_type = '%s'"
146 " AND resource = %llu);",
147 type,
148 resource);
149 }
150
151
152 /* Signature utils. */
153
154 /**
155 * @brief Execute gpg to verify an installer signature.
156 *
157 * @param[in] installer Installer.
158 * @param[in] installer_size Size of installer.
159 * @param[in] signature Installer signature.
160 * @param[in] signature_size Size of installer signature.
161 * @param[out] trust Trust value.
162 *
163 * @return 0 success, -1 error.
164 */
165 static int
verify_signature(const gchar * installer,gsize installer_size,const gchar * signature,gsize signature_size,int * trust)166 verify_signature (const gchar *installer, gsize installer_size,
167 const gchar *signature, gsize signature_size,
168 int *trust)
169 {
170 gchar **cmd;
171 gint exit_status;
172 int ret = 0, installer_fd, signature_fd;
173 gchar *standard_out = NULL;
174 gchar *standard_err = NULL;
175 char installer_file[] = "/tmp/gvmd-installer-XXXXXX";
176 char signature_file[] = "/tmp/gvmd-signature-XXXXXX";
177 GError *error = NULL;
178
179 installer_fd = mkstemp (installer_file);
180 if (installer_fd == -1)
181 return -1;
182
183 g_file_set_contents (installer_file, installer, installer_size, &error);
184 if (error)
185 {
186 g_warning ("%s", error->message);
187 g_error_free (error);
188 close (installer_fd);
189 return -1;
190 }
191
192 signature_fd = mkstemp (signature_file);
193 if (signature_fd == -1)
194 {
195 close (installer_fd);
196 return -1;
197 }
198
199 g_file_set_contents (signature_file, signature, signature_size, &error);
200 if (error)
201 {
202 g_warning ("%s", error->message);
203 g_error_free (error);
204 close (installer_fd);
205 close (signature_fd);
206 return -1;
207 }
208
209 cmd = (gchar **) g_malloc (10 * sizeof (gchar *));
210
211 cmd[0] = g_strdup ("gpgv");
212 cmd[1] = g_strdup ("--homedir");
213 cmd[2] = g_strdup (get_sysconf_gpghome ());
214 cmd[3] = g_strdup ("--quiet");
215 cmd[4] = g_strdup ("--keyring");
216 cmd[5] = g_strdup (get_trustedkeys_name ());
217 cmd[6] = g_strdup ("--");
218 cmd[7] = g_strdup (signature_file);
219 cmd[8] = g_strdup (installer_file);
220 cmd[9] = NULL;
221 g_debug ("%s: Spawning in /tmp/: %s %s %s %s %s %s %s %s %s",
222 __func__,
223 cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5],
224 cmd[6], cmd[7], cmd[8]);
225 if ((g_spawn_sync ("/tmp/",
226 cmd,
227 NULL, /* Environment. */
228 G_SPAWN_SEARCH_PATH,
229 NULL, /* Setup func. */
230 NULL,
231 &standard_out,
232 &standard_err,
233 &exit_status,
234 NULL) == FALSE)
235 || (WIFEXITED (exit_status) == 0)
236 || WEXITSTATUS (exit_status))
237 {
238 if (WEXITSTATUS (exit_status) == 1)
239 *trust = TRUST_NO;
240 else
241 {
242 /* This can be caused by the contents of the signature file, so
243 * always return success. */
244 *trust = TRUST_UNKNOWN;
245 }
246 }
247 else
248 *trust = TRUST_YES;
249
250 g_free (cmd[0]);
251 g_free (cmd[1]);
252 g_free (cmd[2]);
253 g_free (cmd[3]);
254 g_free (cmd[4]);
255 g_free (cmd[5]);
256 g_free (cmd[6]);
257 g_free (cmd[7]);
258 g_free (cmd[8]);
259 g_free (cmd);
260 g_free (standard_out);
261 g_free (standard_err);
262 close (installer_fd);
263 close (signature_fd);
264 g_remove (installer_file);
265 g_remove (signature_file);
266
267 return ret;
268 }
269
270 /**
271 * @brief Find a signature in a feed.
272 *
273 * @param[in] location Feed directory to search for signature.
274 * @param[in] installer_filename Installer filename.
275 * @param[out] signature Freshly allocated installer signature.
276 * @param[out] signature_size Size of installer signature.
277 * @param[out] uuid Address for basename of linked signature
278 * when the signature was found in the private
279 * directory, if desired, else NULL. Private
280 * directory is only checked if this is given.
281 *
282 * @return 0 success, -1 error.
283 */
284 static int
find_signature(const gchar * location,const gchar * installer_filename,gchar ** signature,gsize * signature_size,gchar ** uuid)285 find_signature (const gchar *location, const gchar *installer_filename,
286 gchar **signature, gsize *signature_size, gchar **uuid)
287 {
288 gchar *installer_basename;
289
290 installer_basename = g_path_get_basename (installer_filename);
291
292 if (uuid)
293 *uuid = NULL;
294
295 if (strlen (installer_basename))
296 {
297 gchar *signature_filename, *signature_basename;
298 GError *error = NULL;
299
300 signature_basename = g_strdup_printf ("%s.asc", installer_basename);
301 g_free (installer_basename);
302 signature_filename = g_build_filename (GVM_NVT_DIR,
303 location,
304 signature_basename,
305 NULL);
306 g_debug ("signature_filename: %s", signature_filename);
307
308 g_file_get_contents (signature_filename, signature, signature_size,
309 &error);
310 if (error)
311 {
312 if (uuid && (error->code == G_FILE_ERROR_NOENT))
313 {
314 char *real;
315 gchar *real_basename;
316 gchar **split;
317
318 g_error_free (error);
319 error = NULL;
320 signature_filename = g_build_filename (GVMD_STATE_DIR,
321 "signatures",
322 location,
323 signature_basename,
324 NULL);
325 g_debug ("signature_filename (private): %s", signature_filename);
326 g_free (signature_basename);
327 g_file_get_contents (signature_filename, signature, signature_size,
328 &error);
329 if (error)
330 {
331 g_free (signature_filename);
332 g_error_free (error);
333 return -1;
334 }
335
336 real = realpath (signature_filename, NULL);
337 g_free (signature_filename);
338 g_debug ("real pathname: %s", real);
339 if (real == NULL)
340 return -1;
341 real_basename = g_path_get_basename (real);
342 split = g_strsplit (real_basename, ".", 2);
343 if (*split)
344 *uuid = g_strdup (*split);
345 else
346 *uuid = g_strdup (real_basename);
347 g_debug ("*uuid: %s", *uuid);
348 g_free (real_basename);
349 g_strfreev (split);
350 free (real);
351 return 0;
352 }
353 else
354 {
355 g_debug ("%s: failed to read %s: %s", __func__,
356 signature_filename, error->message);
357 g_free (signature_filename);
358 }
359
360 g_free (signature_basename);
361 g_error_free (error);
362 return -1;
363 }
364 g_free (signature_basename);
365 return 0;
366 }
367
368 g_free (installer_basename);
369 return -1;
370 }
371
372
373 /* Report formats. */
374
375 /**
376 * @brief Possible port types.
377 */
378 typedef enum
379 {
380 REPORT_FORMAT_FLAG_ACTIVE = 1
381 } report_format_flag_t;
382
383 /**
384 * @brief Get trash directory of a report format.
385 *
386 * @param[in] report_format_id UUID of report format. NULL for the
387 * base dir that holds the report format trash.
388 *
389 * @return Freshly allocated trash dir.
390 */
391 static gchar *
report_format_trash_dir(const gchar * report_format_id)392 report_format_trash_dir (const gchar *report_format_id)
393 {
394 if (report_format_id)
395 return g_build_filename (GVMD_STATE_DIR,
396 "report_formats_trash",
397 report_format_id,
398 NULL);
399
400 return g_build_filename (GVMD_STATE_DIR,
401 "report_formats_trash",
402 NULL);
403 }
404
405 /**
406 * @brief Find a report format given a name.
407 *
408 * @param[in] name Name of report_format.
409 * @param[out] report_format Report format return, 0 if successfully failed to
410 * find report_format.
411 *
412 * @return FALSE on success (including if failed to find report format), TRUE
413 * on error.
414 */
415 gboolean
lookup_report_format(const char * name,report_format_t * report_format)416 lookup_report_format (const char* name, report_format_t* report_format)
417 {
418 iterator_t report_formats;
419 gchar *quoted_name;
420
421 assert (report_format);
422
423 *report_format = 0;
424 quoted_name = sql_quote (name);
425 init_iterator (&report_formats,
426 "SELECT id, uuid FROM report_formats"
427 " WHERE name = '%s'"
428 " AND CAST (flags & %llu AS boolean)"
429 " ORDER BY (CASE WHEN " ACL_USER_OWNS () " THEN 0"
430 " WHEN owner is NULL THEN 1"
431 " ELSE 2"
432 " END);",
433 quoted_name,
434 (long long int) REPORT_FORMAT_FLAG_ACTIVE,
435 current_credentials.uuid);
436 g_free (quoted_name);
437 while (next (&report_formats))
438 {
439 const char *uuid;
440
441 uuid = iterator_string (&report_formats, 1);
442 if (uuid
443 && acl_user_has_access_uuid ("report_format",
444 uuid,
445 "get_report_formats",
446 0))
447 {
448 *report_format = iterator_int64 (&report_formats, 0);
449 break;
450 }
451 }
452 cleanup_iterator (&report_formats);
453
454 return FALSE;
455 }
456
457 /**
458 * @brief Find a report format given a UUID.
459 *
460 * This does not do any permission checks.
461 *
462 * @param[in] uuid UUID of resource.
463 * @param[out] report_format Report Format return, 0 if no such report format.
464 *
465 * @return FALSE on success (including if no such report format), TRUE on error.
466 */
467 gboolean
find_report_format_no_acl(const char * uuid,report_format_t * report_format)468 find_report_format_no_acl (const char *uuid, report_format_t *report_format)
469 {
470 gchar *quoted_uuid;
471
472 quoted_uuid = sql_quote (uuid);
473 switch (sql_int64 (report_format,
474 "SELECT id FROM report_formats WHERE uuid = '%s';",
475 quoted_uuid))
476 {
477 case 0:
478 break;
479 case 1: /* Too few rows in result of query. */
480 *report_format = 0;
481 break;
482 default: /* Programming error. */
483 assert (0);
484 case -1:
485 g_free (quoted_uuid);
486 return TRUE;
487 break;
488 }
489
490 g_free (quoted_uuid);
491 return FALSE;
492 }
493
494 /**
495 * @brief Find a trash report format given a UUID.
496 *
497 * This does not do any permission checks.
498 *
499 * This considers the actual UUID of the report format, not the original_uuid.
500 *
501 * @param[in] uuid UUID of resource.
502 * @param[out] report_format Report Format return, 0 if no such report format.
503 *
504 * @return FALSE on success (including if no such report format), TRUE on error.
505 */
506 gboolean
find_trash_report_format_no_acl(const char * uuid,report_format_t * report_format)507 find_trash_report_format_no_acl (const char *uuid, report_format_t *report_format)
508 {
509 gchar *quoted_uuid;
510
511 quoted_uuid = sql_quote (uuid);
512 switch (sql_int64 (report_format,
513 "SELECT id FROM report_formats_trash WHERE uuid = '%s';",
514 quoted_uuid))
515 {
516 case 0:
517 break;
518 case 1: /* Too few rows in result of query. */
519 *report_format = 0;
520 break;
521 default: /* Programming error. */
522 assert (0);
523 case -1:
524 g_free (quoted_uuid);
525 return TRUE;
526 break;
527 }
528
529 g_free (quoted_uuid);
530 return FALSE;
531 }
532
533 /**
534 * @brief Compare files for create_report_format.
535 *
536 * @param[in] one First.
537 * @param[in] two Second.
538 *
539 * @return Less than, equal to, or greater than zero if one is found to be
540 * less than, to match, or be greater than two.
541 */
542 static gint
compare_files(gconstpointer one,gconstpointer two)543 compare_files (gconstpointer one, gconstpointer two)
544 {
545 gchar *file_one, *file_two;
546 file_one = *((gchar**) one);
547 file_two = *((gchar**) two);
548 if (file_one == NULL)
549 {
550 if (file_two == NULL)
551 return 0;
552 return 1;
553 }
554 else if (file_two == NULL)
555 return -1;
556 return strcoll (file_one, file_two);
557 }
558
559 /**
560 * @brief Save files of a report format.
561 *
562 * @param[in] report_id UUID of format.
563 * @param[in] files Array of memory. Each item is a file name
564 * string, a terminating NULL, the file contents
565 * in base64 and a terminating NULL.
566 * @param[out] report_format_dir Address for dir, or NULL.
567 *
568 * @return 0 success, 2 empty file name, -1 error.
569 */
570 static int
save_report_format_files(const gchar * report_id,array_t * files,gchar ** report_format_dir)571 save_report_format_files (const gchar *report_id, array_t *files,
572 gchar **report_format_dir)
573 {
574 gchar *dir, *report_dir, *file_name;
575 int index;
576
577 dir = g_build_filename (GVMD_STATE_DIR,
578 "report_formats",
579 current_credentials.uuid,
580 report_id,
581 NULL);
582
583 if (gvm_file_exists (dir) && gvm_file_remove_recurse (dir))
584 {
585 g_warning ("%s: failed to remove dir %s", __func__, dir);
586 g_free (dir);
587 return -1;
588 }
589
590 if (g_mkdir_with_parents (dir, 0755 /* "rwxr-xr-x" */))
591 {
592 g_warning ("%s: failed to create dir %s: %s",
593 __func__, dir, strerror (errno));
594 g_free (dir);
595 return -1;
596 }
597
598 /* glib seems to apply the mode to the first dir only. */
599
600 report_dir = g_build_filename (GVMD_STATE_DIR,
601 "report_formats",
602 current_credentials.uuid,
603 NULL);
604
605 if (chmod (report_dir, 0755 /* rwxr-xr-x */))
606 {
607 g_warning ("%s: chmod failed: %s",
608 __func__,
609 strerror (errno));
610 g_free (dir);
611 g_free (report_dir);
612 return -1;
613 }
614
615 g_free (report_dir);
616
617 /* glib seems to apply the mode to the first dir only. */
618 if (chmod (dir, 0755 /* rwxr-xr-x */))
619 {
620 g_warning ("%s: chmod failed: %s",
621 __func__,
622 strerror (errno));
623 g_free (dir);
624 return -1;
625 }
626
627 index = 0;
628 while ((file_name = (gchar*) g_ptr_array_index (files, index++)))
629 {
630 gchar *contents, *file, *full_file_name;
631 gsize contents_size;
632 GError *error;
633 int ret;
634
635 if (strlen (file_name) == 0)
636 {
637 gvm_file_remove_recurse (dir);
638 g_free (dir);
639 return 2;
640 }
641
642 file = file_name + strlen (file_name) + 1;
643 if (strlen (file))
644 contents = (gchar*) g_base64_decode (file, &contents_size);
645 else
646 {
647 contents = g_strdup ("");
648 contents_size = 0;
649 }
650
651 full_file_name = g_build_filename (dir, file_name, NULL);
652
653 error = NULL;
654 g_file_set_contents (full_file_name, contents, contents_size, &error);
655 g_free (contents);
656 if (error)
657 {
658 g_warning ("%s: %s", __func__, error->message);
659 g_error_free (error);
660 gvm_file_remove_recurse (dir);
661 g_free (full_file_name);
662 g_free (dir);
663 return -1;
664 }
665
666 if (strcmp (file_name, "generate") == 0)
667 ret = chmod (full_file_name, 0755 /* rwxr-xr-x */);
668 else
669 ret = chmod (full_file_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
670 if (ret)
671 {
672 g_warning ("%s: chmod failed: %s",
673 __func__,
674 strerror (errno));
675 gvm_file_remove_recurse (dir);
676 g_free (full_file_name);
677 g_free (dir);
678 return -1;
679 }
680
681 g_free (full_file_name);
682 }
683
684 if (report_format_dir)
685 *report_format_dir = dir;
686
687 return 0;
688 }
689
690 /**
691 * @brief Add params to a report format.
692 *
693 * @param[in] report_format Report format.
694 * @param[in] params Array of params.
695 * @param[in] params_options Array. Each item is an array corresponding to
696 * params. Each item of an inner array is a string,
697 * the text of an option in a selection.
698 *
699 * @return 0 success, 3 param value validation failed, 4 param value
700 * validation failed, 5 param default missing, 6 param min or max
701 * out of range, 7 param type missing, 8 duplicate param name,
702 * 9 bogus param type name, 99 permission denied, -1 error.
703 */
704 static int
add_report_format_params(report_format_t report_format,array_t * params,array_t * params_options)705 add_report_format_params (report_format_t report_format, array_t *params,
706 array_t *params_options)
707 {
708 int index;
709 create_report_format_param_t *param;
710
711 index = 0;
712 while ((param = (create_report_format_param_t*) g_ptr_array_index (params,
713 index++)))
714 {
715 gchar *quoted_param_name, *quoted_param_value, *quoted_param_fallback;
716 rowid_t param_rowid;
717 long long int min, max;
718
719 if (param->type == NULL)
720 return 7;
721
722 if (report_format_param_type_from_name (param->type)
723 == REPORT_FORMAT_PARAM_TYPE_ERROR)
724 return 9;
725
726 /* Param min and max are optional. LLONG_MIN and LLONG_MAX mark in the db
727 * that they were missing, so if the user gives LLONG_MIN or LLONG_MAX it
728 * is an error. This ensures that GPG verification works, because the
729 * verification knows when to leave out min and max. */
730
731 if (param->type_min)
732 {
733 min = strtoll (param->type_min, NULL, 0);
734 if (min == LLONG_MIN)
735 return 6;
736 }
737 else
738 min = LLONG_MIN;
739
740 if (param->type_max)
741 {
742 max = strtoll (param->type_max, NULL, 0);
743 if (max == LLONG_MAX)
744 return 6;
745 }
746 else
747 max = LLONG_MAX;
748
749 if (param->fallback == NULL)
750 return 5;
751
752 quoted_param_name = sql_quote (param->name);
753
754 if (sql_int ("SELECT count(*) FROM report_format_params"
755 " WHERE name = '%s' AND report_format = %llu;",
756 quoted_param_name,
757 report_format))
758 {
759 g_free (quoted_param_name);
760 return 8;
761 }
762
763 quoted_param_value = sql_quote (param->value);
764 quoted_param_fallback = sql_quote (param->fallback);
765
766 sql ("INSERT INTO report_format_params"
767 " (report_format, name, type, value, type_min, type_max, type_regex,"
768 " fallback)"
769 " VALUES (%llu, '%s', %u, '%s', %lli, %lli, '', '%s');",
770 report_format,
771 quoted_param_name,
772 report_format_param_type_from_name (param->type),
773 quoted_param_value,
774 min,
775 max,
776 quoted_param_fallback);
777
778 g_free (quoted_param_name);
779 g_free (quoted_param_value);
780 g_free (quoted_param_fallback);
781
782 param_rowid = sql_last_insert_id ();
783
784 {
785 array_t *options;
786 int option_index;
787 gchar *option_value;
788
789 options = (array_t*) g_ptr_array_index (params_options, index - 1);
790 if (options == NULL)
791 {
792 g_warning ("%s: options was NULL", __func__);
793 return -1;
794 }
795 option_index = 0;
796 while ((option_value = (gchar*) g_ptr_array_index (options,
797 option_index++)))
798 {
799 gchar *quoted_option_value = sql_quote (option_value);
800 sql ("INSERT INTO report_format_param_options"
801 " (report_format_param, value)"
802 " VALUES (%llu, '%s');",
803 param_rowid,
804 quoted_option_value);
805 g_free (quoted_option_value);
806 }
807 }
808
809 if (validate_param_value (report_format, param_rowid, param->name,
810 param->value))
811 return 3;
812
813 if (validate_param_value (report_format, param_rowid, param->name,
814 param->fallback))
815 return 4;
816 }
817
818 return 0;
819 }
820
821
822 /**
823 * @brief Create a report format.
824 *
825 * @param[in] check_access Whether to check for permission.
826 * @param[in] may_exist Whether it is OK if there is already a report
827 * format with this UUID.
828 * @param[in] active Whether report format is active.
829 * @param[in] trusted Whether to assumed report format is trusted.
830 * @param[in] uuid UUID of format.
831 * @param[in] name Name of format.
832 * @param[in] content_type Content type of format.
833 * @param[in] extension File extension of format.
834 * @param[in] summary Summary of format.
835 * @param[in] description Description of format.
836 * @param[in] files Array of memory. Each item is a file name
837 * string, a terminating NULL, the file contents
838 * in base64 and a terminating NULL.
839 * @param[in] params Array of params.
840 * @param[in] params_options Array. Each item is an array corresponding to
841 * params. Each item of an inner array is a string,
842 * the text of an option in a selection.
843 * @param[in] predefined Whether report format is from the feed.
844 * @param[in] signature Signature.
845 * @param[out] report_format Created report format.
846 *
847 * @return 0 success, 1 report format exists, 2 empty file name, 3 param value
848 * validation failed, 4 param value validation failed, 5 param default
849 * missing, 6 param min or max out of range, 7 param type missing,
850 * 8 duplicate param name, 9 bogus param type name, 99 permission
851 * denied, -1 error.
852 */
853 static int
create_report_format_internal(int check_access,int may_exist,int active,int trusted,const char * uuid,const char * name,const char * content_type,const char * extension,const char * summary,const char * description,array_t * files,array_t * params,array_t * params_options,const char * signature,int predefined,report_format_t * report_format)854 create_report_format_internal (int check_access, int may_exist, int active,
855 int trusted, const char *uuid, const char *name,
856 const char *content_type, const char *extension,
857 const char *summary, const char *description,
858 array_t *files, array_t *params,
859 array_t *params_options, const char *signature,
860 int predefined,
861 report_format_t *report_format)
862 {
863 gchar *quoted_name, *quoted_summary, *quoted_description, *quoted_extension;
864 gchar *quoted_content_type, *quoted_signature, *file_name, *dir;
865 gchar *candidate_name, *new_uuid, *uuid_actual;
866 report_format_t report_format_rowid;
867 int index, num, ret;
868 gchar *format_signature = NULL;
869 gsize format_signature_size;
870 int format_trust = TRUST_UNKNOWN;
871 create_report_format_param_t *param;
872
873 assert (current_credentials.uuid);
874 assert (uuid);
875 assert (name);
876 assert (files);
877 assert (params);
878
879 if (trusted)
880 format_trust = TRUST_YES;
881
882 /* Verify the signature. */
883
884 if (trusted == 0
885 && ((find_signature ("report_formats", uuid, &format_signature,
886 &format_signature_size, &uuid_actual)
887 == 0)
888 || signature))
889 {
890 char *locale;
891 GString *format;
892
893 format = g_string_new ("");
894
895 g_string_append_printf (format,
896 "%s%s%s%i",
897 uuid_actual ? uuid_actual : uuid,
898 extension,
899 content_type,
900 0); /* Old global flag. */
901
902 index = 0;
903 locale = setlocale (LC_ALL, "C");
904 g_ptr_array_sort (files, compare_files);
905 setlocale (LC_ALL, locale);
906 while ((file_name = (gchar*) g_ptr_array_index (files, index++)))
907 g_string_append_printf (format,
908 "%s%s",
909 file_name,
910 file_name + strlen (file_name) + 1);
911
912 index = 0;
913 while ((param
914 = (create_report_format_param_t*) g_ptr_array_index (params,
915 index++)))
916 {
917 g_string_append_printf (format,
918 "%s%s",
919 param->name,
920 param->type);
921
922 if (param->type_min)
923 {
924 long long int min;
925 min = strtoll (param->type_min, NULL, 0);
926 if (min == LLONG_MIN)
927 return 6;
928 g_string_append_printf (format, "%lli", min);
929 }
930
931 if (param->type_max)
932 {
933 long long int max;
934 max = strtoll (param->type_max, NULL, 0);
935 if (max == LLONG_MAX)
936 return 6;
937 g_string_append_printf (format, "%lli", max);
938 }
939
940 g_string_append_printf (format,
941 "%s",
942 param->fallback);
943
944 {
945 array_t *options;
946 int option_index;
947 gchar *option_value;
948
949 options = (array_t*) g_ptr_array_index (params_options, index - 1);
950 if (options == NULL)
951 return -1;
952 option_index = 0;
953 while ((option_value = (gchar*) g_ptr_array_index (options,
954 option_index++)))
955 g_string_append_printf (format, "%s", option_value);
956 }
957 }
958
959 g_string_append_printf (format, "\n");
960
961 if (format_signature)
962 signature = (const char*) format_signature;
963
964 if (verify_signature (format->str, format->len, signature,
965 strlen (signature), &format_trust))
966 {
967 g_free (format_signature);
968 g_string_free (format, TRUE);
969 return -1;
970 }
971 g_string_free (format, TRUE);
972 }
973
974 sql_begin_immediate ();
975
976 if (check_access && (acl_user_may ("create_report_format") == 0))
977 {
978 sql_rollback ();
979 return 99;
980 }
981
982 if (sql_int ("SELECT COUNT(*) FROM report_formats WHERE uuid = '%s';",
983 uuid)
984 || sql_int ("SELECT COUNT(*) FROM report_formats_trash"
985 " WHERE original_uuid = '%s';",
986 uuid))
987 {
988 gchar *base, *new, *old, *path;
989 char *real_old;
990
991 if (may_exist == 0)
992 {
993 sql_rollback ();
994 return 10;
995 }
996
997 /* Make a new UUID, because a report format exists with the given UUID. */
998
999 new_uuid = gvm_uuid_make ();
1000 if (new_uuid == NULL)
1001 {
1002 sql_rollback ();
1003 return -1;
1004 }
1005
1006 /* Setup a private/report_formats/ link to the signature of the existing
1007 * report format in the feed. This allows the signature to be shared. */
1008
1009 base = g_strdup_printf ("%s.asc", uuid);
1010 old = g_build_filename (GVM_NVT_DIR, "report_formats", base, NULL);
1011 real_old = realpath (old, NULL);
1012 if (real_old)
1013 {
1014 /* Signature exists in regular directory. */
1015
1016 g_free (old);
1017 old = g_strdup (real_old);
1018 free (real_old);
1019 }
1020 else
1021 {
1022 struct stat state;
1023
1024 /* Signature may be in private directory. */
1025
1026 g_free (old);
1027 old = g_build_filename (GVMD_STATE_DIR,
1028 "signatures",
1029 "report_formats",
1030 base,
1031 NULL);
1032 if (lstat (old, &state))
1033 {
1034 /* No. Signature may not exist in the feed yet. */
1035 g_free (old);
1036 old = g_build_filename (GVM_NVT_DIR, "report_formats", base,
1037 NULL);
1038 g_debug ("using standard old: %s", old);
1039 }
1040 else
1041 {
1042 int count;
1043
1044 /* Yes. Use the path it links to. */
1045
1046 real_old = g_malloc (state.st_size + 1);
1047 count = readlink (old, real_old, state.st_size + 1);
1048 if (count < 0 || count > state.st_size)
1049 {
1050 g_free (real_old);
1051 g_free (old);
1052 g_warning ("%s: readlink failed", __func__);
1053 sql_rollback ();
1054 return -1;
1055 }
1056
1057 real_old[state.st_size] = '\0';
1058 g_free (old);
1059 old = real_old;
1060 g_debug ("using linked old: %s", old);
1061 }
1062 }
1063 g_free (base);
1064
1065 path = g_build_filename (GVMD_STATE_DIR,
1066 "signatures", "report_formats", NULL);
1067
1068 if (g_mkdir_with_parents (path, 0755 /* "rwxr-xr-x" */))
1069 {
1070 g_warning ("%s: failed to create dir %s: %s",
1071 __func__, path, strerror (errno));
1072 g_free (old);
1073 g_free (path);
1074 sql_rollback ();
1075 return -1;
1076 }
1077
1078 base = g_strdup_printf ("%s.asc", new_uuid);
1079 new = g_build_filename (path, base, NULL);
1080 g_free (path);
1081 g_free (base);
1082 if (symlink (old, new))
1083 {
1084 g_free (old);
1085 g_free (new);
1086 g_warning ("%s: symlink failed: %s", __func__, strerror (errno));
1087 sql_rollback ();
1088 return -1;
1089 }
1090 }
1091 else
1092 new_uuid = NULL;
1093
1094 candidate_name = g_strdup (name);
1095 quoted_name = sql_quote (candidate_name);
1096
1097 num = 1;
1098 while (1)
1099 {
1100 if (!resource_with_name_exists (quoted_name, "report_format", 0))
1101 break;
1102 g_free (candidate_name);
1103 g_free (quoted_name);
1104 candidate_name = g_strdup_printf ("%s %u", name, ++num);
1105 quoted_name = sql_quote (candidate_name);
1106 }
1107 g_free (candidate_name);
1108
1109 /* Write files to disk. */
1110
1111 ret = save_report_format_files (new_uuid ? new_uuid : uuid, files, &dir);
1112 if (ret)
1113 {
1114 g_free (quoted_name);
1115 g_free (new_uuid);
1116 sql_rollback ();
1117 return ret;
1118 }
1119
1120 /* Add format to database. */
1121
1122 quoted_summary = summary ? sql_quote (summary) : NULL;
1123 quoted_description = description ? sql_quote (description) : NULL;
1124 quoted_extension = extension ? sql_quote (extension) : NULL;
1125 quoted_content_type = content_type ? sql_quote (content_type) : NULL;
1126 quoted_signature = signature ? sql_quote (signature) : NULL;
1127 g_free (format_signature);
1128
1129 sql ("INSERT INTO report_formats"
1130 " (uuid, name, owner, summary, description, extension, content_type,"
1131 " signature, trust, trust_time, flags, predefined, creation_time,"
1132 " modification_time)"
1133 " VALUES ('%s', '%s',"
1134 " (SELECT id FROM users WHERE users.uuid = '%s'),"
1135 " '%s', '%s', '%s', '%s', '%s', %i, %i, %i, %i, m_now (), m_now ());",
1136 new_uuid ? new_uuid : uuid,
1137 quoted_name,
1138 current_credentials.uuid,
1139 quoted_summary ? quoted_summary : "",
1140 quoted_description ? quoted_description : "",
1141 quoted_extension ? quoted_extension : "",
1142 quoted_content_type ? quoted_content_type : "",
1143 quoted_signature ? quoted_signature : "",
1144 format_trust,
1145 time (NULL),
1146 active ? REPORT_FORMAT_FLAG_ACTIVE : 0,
1147 predefined ? 1 : 0);
1148
1149 g_free (new_uuid);
1150 g_free (quoted_summary);
1151 g_free (quoted_description);
1152 g_free (quoted_extension);
1153 g_free (quoted_content_type);
1154 g_free (quoted_signature);
1155 g_free (quoted_name);
1156
1157 /* Add params to database. */
1158
1159 report_format_rowid = sql_last_insert_id ();
1160 ret = add_report_format_params (report_format_rowid, params, params_options);
1161 if (ret)
1162 {
1163 gvm_file_remove_recurse (dir);
1164 g_free (dir);
1165 sql_rollback ();
1166 return ret;
1167 }
1168
1169 if (report_format)
1170 *report_format = report_format_rowid;
1171
1172 g_free (dir);
1173
1174 sql_commit ();
1175
1176 return 0;
1177 }
1178
1179 /**
1180 * @brief Create a report format.
1181 *
1182 * @param[in] uuid UUID of format.
1183 * @param[in] name Name of format.
1184 * @param[in] content_type Content type of format.
1185 * @param[in] extension File extension of format.
1186 * @param[in] summary Summary of format.
1187 * @param[in] description Description of format.
1188 * @param[in] files Array of memory. Each item is a file name
1189 * string, a terminating NULL, the file contents
1190 * in base64 and a terminating NULL.
1191 * @param[in] params Array of params.
1192 * @param[in] params_options Array. Each item is an array corresponding to
1193 * params. Each item of an inner array is a string,
1194 * the text of an option in a selection.
1195 * @param[in] signature Signature.
1196 * @param[out] report_format Created report format.
1197 *
1198 * @return 0 success, 2 empty file name, 3 param value
1199 * validation failed, 4 param value validation failed, 5 param default
1200 * missing, 6 param min or max out of range, 7 param type missing,
1201 * 8 duplicate param name, 9 bogus param type name, 99 permission
1202 * denied, -1 error.
1203 */
1204 int
create_report_format(const char * uuid,const char * name,const char * content_type,const char * extension,const char * summary,const char * description,array_t * files,array_t * params,array_t * params_options,const char * signature,report_format_t * report_format)1205 create_report_format (const char *uuid, const char *name,
1206 const char *content_type, const char *extension,
1207 const char *summary, const char *description,
1208 array_t *files, array_t *params, array_t *params_options,
1209 const char *signature, report_format_t *report_format)
1210 {
1211 return create_report_format_internal (1, /* Check permission. */
1212 1, /* Allow existing report format. */
1213 0, /* Active. */
1214 0, /* Assume trusted. */
1215 uuid, name, content_type, extension,
1216 summary, description, files, params,
1217 params_options, signature,
1218 0, /* Predefined. */
1219 report_format);
1220 }
1221
1222 /**
1223 * @brief Create a report format.
1224 *
1225 * @param[in] uuid UUID of format.
1226 * @param[in] name Name of format.
1227 * @param[in] content_type Content type of format.
1228 * @param[in] extension File extension of format.
1229 * @param[in] summary Summary of format.
1230 * @param[in] description Description of format.
1231 * @param[in] files Array of memory. Each item is a file name
1232 * string, a terminating NULL, the file contents
1233 * in base64 and a terminating NULL.
1234 * @param[in] params Array of params.
1235 * @param[in] params_options Array. Each item is an array corresponding to
1236 * params. Each item of an inner array is a string,
1237 * the text of an option in a selection.
1238 * @param[in] signature Signature.
1239 * @param[in] predefined Whether report format is from the feed.
1240 * @param[out] report_format Created report format.
1241 *
1242 * @return 0 success, 1 report format exists, 2 empty file name, 3 param value
1243 * validation failed, 4 param value validation failed, 5 param default
1244 * missing, 6 param min or max out of range, 7 param type missing,
1245 * 8 duplicate param name, 9 bogus param type name, 99 permission
1246 * denied, -1 error.
1247 */
1248 int
create_report_format_no_acl(const char * uuid,const char * name,const char * content_type,const char * extension,const char * summary,const char * description,array_t * files,array_t * params,array_t * params_options,const char * signature,int predefined,report_format_t * report_format)1249 create_report_format_no_acl (const char *uuid, const char *name,
1250 const char *content_type, const char *extension,
1251 const char *summary, const char *description,
1252 array_t *files, array_t *params,
1253 array_t *params_options, const char *signature,
1254 int predefined, report_format_t *report_format)
1255 {
1256 return create_report_format_internal (0, /* Check permission. */
1257 0, /* Allow existing report format. */
1258 1, /* Active. */
1259 1, /* Assume trusted. */
1260 uuid, name, content_type, extension,
1261 summary, description, files, params,
1262 params_options, signature,
1263 predefined, report_format);
1264 }
1265
1266 /**
1267 * @brief Create a report format dir.
1268 *
1269 * @param[in] source_dir Full path of source directory, including UUID.
1270 * @param[in] copy_parent Path of destination directory, excluding UUID.
1271 * @param[in] copy_uuid UUID (dirname) of destination directory.
1272 *
1273 * @return 0 success, -1 error.
1274 */
1275 static int
copy_report_format_dir(const gchar * source_dir,const gchar * copy_parent,const gchar * copy_uuid)1276 copy_report_format_dir (const gchar *source_dir, const gchar *copy_parent,
1277 const gchar *copy_uuid)
1278 {
1279 gchar *copy_dir;
1280
1281 g_debug ("%s: copy %s to %s/%s", __func__, source_dir, copy_parent,
1282 copy_uuid);
1283
1284 /* Check that the source directory exists. */
1285
1286 if (!gvm_file_is_readable (source_dir))
1287 {
1288 g_warning ("%s: report format directory %s not found",
1289 __func__, source_dir);
1290 return -1;
1291 }
1292
1293 /* Prepare directory to copy into. */
1294
1295 copy_dir = g_build_filename (copy_parent, copy_uuid, NULL);
1296
1297 if (gvm_file_exists (copy_dir)
1298 && gvm_file_remove_recurse (copy_dir))
1299 {
1300 g_warning ("%s: failed to remove dir %s", __func__, copy_dir);
1301 g_free (copy_dir);
1302 return -1;
1303 }
1304
1305 if (g_mkdir_with_parents (copy_dir, 0755 /* "rwxr-xr-x" */))
1306 {
1307 g_warning ("%s: failed to create dir %s", __func__, copy_dir);
1308 g_free (copy_dir);
1309 return -1;
1310 }
1311
1312 /* Correct permissions as glib doesn't seem to do so. */
1313
1314 if (chmod (copy_parent, 0755 /* rwxr-xr-x */))
1315 {
1316 g_warning ("%s: chmod %s failed: %s",
1317 __func__,
1318 copy_parent,
1319 strerror (errno));
1320 g_free (copy_dir);
1321 return -1;
1322 }
1323
1324 if (chmod (copy_dir, 0755 /* rwxr-xr-x */))
1325 {
1326 g_warning ("%s: chmod %s failed: %s",
1327 __func__,
1328 copy_dir,
1329 strerror (errno));
1330 g_free (copy_dir);
1331 return -1;
1332 }
1333
1334 /* Copy files into new directory. */
1335 {
1336 GDir *directory;
1337 GError *error;
1338
1339 error = NULL;
1340 directory = g_dir_open (source_dir, 0, &error);
1341 if (directory == NULL)
1342 {
1343 if (error)
1344 {
1345 g_warning ("g_dir_open(%s) failed - %s",
1346 source_dir, error->message);
1347 g_error_free (error);
1348 }
1349 g_free (copy_dir);
1350 return -1;
1351 }
1352 else
1353 {
1354 gchar *source_file, *copy_file;
1355 const gchar *filename;
1356
1357 filename = g_dir_read_name (directory);
1358 while (filename)
1359 {
1360 source_file = g_build_filename (source_dir, filename, NULL);
1361 copy_file = g_build_filename (copy_dir, filename, NULL);
1362
1363 if (gvm_file_copy (source_file, copy_file) == FALSE)
1364 {
1365 g_warning ("%s: copy of %s to %s failed",
1366 __func__, source_file, copy_file);
1367 g_free (source_file);
1368 g_free (copy_file);
1369 g_free (copy_dir);
1370 return -1;
1371 }
1372 g_free (source_file);
1373 g_free (copy_file);
1374 filename = g_dir_read_name (directory);
1375 }
1376 }
1377 }
1378
1379 g_free (copy_dir);
1380 return 0;
1381 }
1382
1383 /**
1384 * @brief Create Report Format from an existing Report Format.
1385 *
1386 * @param[in] name Name of new Report Format. NULL to copy
1387 * from existing.
1388 * @param[in] source_uuid UUID of existing Report Format.
1389 * @param[out] new_report_format New Report Format.
1390 *
1391 * @return 0 success, 1 Report Format exists already, 2 failed to find existing
1392 * Report Format, 99 permission denied, -1 error.
1393 */
1394 int
copy_report_format(const char * name,const char * source_uuid,report_format_t * new_report_format)1395 copy_report_format (const char* name, const char* source_uuid,
1396 report_format_t* new_report_format)
1397 {
1398 report_format_t new, old;
1399 gchar *copy_uuid, *source_dir, *copy_dir, *owner_uuid;
1400 int ret;
1401
1402 assert (current_credentials.uuid);
1403
1404 sql_begin_immediate ();
1405
1406 ret = copy_resource_lock ("report_format", name, NULL, source_uuid,
1407 "extension, content_type, summary, description,"
1408 " signature, trust, trust_time, flags",
1409 1, &new, &old);
1410 if (ret)
1411 {
1412 sql_rollback ();
1413 return ret;
1414 }
1415
1416 sql ("UPDATE report_formats SET predefined = 0 WHERE id = %llu;", new);
1417
1418 if (report_format_predefined (old))
1419 sql ("UPDATE report_formats SET trust = %i, trust_time = %i"
1420 " WHERE id = %llu;",
1421 TRUST_YES,
1422 time (NULL),
1423 new);
1424
1425 /* Copy report format parameters. */
1426
1427 sql ("INSERT INTO report_format_params "
1428 " (report_format, name, type, value, type_min, type_max,"
1429 " type_regex, fallback)"
1430 " SELECT %llu, name, type, value, type_min, type_max,"
1431 " type_regex, fallback"
1432 " FROM report_format_params WHERE report_format = %llu;",
1433 new,
1434 old);
1435
1436 /* Copy files on disk. */
1437
1438 owner_uuid = report_format_owner_uuid (old);
1439 assert (owner_uuid);
1440 source_dir = g_build_filename (GVMD_STATE_DIR,
1441 "report_formats",
1442 owner_uuid,
1443 source_uuid,
1444 NULL);
1445 g_free (owner_uuid);
1446
1447 copy_uuid = report_format_uuid (new);
1448 if (copy_uuid == NULL)
1449 {
1450 sql_rollback ();
1451 return -1;
1452 }
1453
1454 copy_dir = g_build_filename (GVMD_STATE_DIR,
1455 "report_formats",
1456 current_credentials.uuid,
1457 NULL);
1458
1459 if (copy_report_format_dir (source_dir, copy_dir, copy_uuid))
1460 {
1461 sql_rollback ();
1462 g_free (source_dir);
1463 g_free (copy_dir);
1464 return -1;
1465 }
1466
1467 sql_commit ();
1468 g_free (source_dir);
1469 g_free (copy_dir);
1470 if (new_report_format) *new_report_format = new;
1471 return 0;
1472 }
1473
1474 /**
1475 * @brief Return whether a report format is predefined.
1476 *
1477 * @param[in] report_format_id UUID of report format.
1478 *
1479 * @return 1 if predefined, else 0.
1480 */
1481 static int
report_format_predefined_uuid(const gchar * report_format_id)1482 report_format_predefined_uuid (const gchar *report_format_id)
1483 {
1484 report_format_t report_format;
1485
1486 if (find_report_format_no_acl (report_format_id, &report_format)
1487 || report_format == 0)
1488 return 0;
1489
1490 return report_format_predefined (report_format);
1491 }
1492
1493 /**
1494 * @brief Modify a report format.
1495 *
1496 * @param[in] report_format_id UUID of report format.
1497 * @param[in] name Name of report format.
1498 * @param[in] summary Summary of report format.
1499 * @param[in] active Active flag.
1500 * @param[in] param_name Parameter to modify.
1501 * @param[in] param_value Value of parameter.
1502 *
1503 * @return 0 success, 1 failed to find report format, 2 report_format_id
1504 * required, 3 failed to find report format parameter, 4 parameter value
1505 * validation failed, 99 permission denied, -1 internal error.
1506 */
1507 int
modify_report_format(const char * report_format_id,const char * name,const char * summary,const char * active,const char * param_name,const char * param_value)1508 modify_report_format (const char *report_format_id, const char *name,
1509 const char *summary, const char *active,
1510 const char *param_name, const char *param_value)
1511 {
1512 report_format_t report_format;
1513 int ret = 0;
1514
1515 if (report_format_id == NULL)
1516 return 2;
1517
1518 sql_begin_immediate ();
1519
1520 assert (current_credentials.uuid);
1521
1522 if (acl_user_may ("modify_report_format") == 0)
1523 {
1524 sql_rollback ();
1525 return 99;
1526 }
1527
1528 if (report_format_predefined_uuid (report_format_id))
1529 {
1530 sql_rollback ();
1531 return 99;
1532 }
1533
1534 report_format = 0;
1535 if (find_report_format_with_permission (report_format_id, &report_format,
1536 "modify_report_format"))
1537 {
1538 sql_rollback ();
1539 return -1;
1540 }
1541
1542 if (report_format == 0)
1543 {
1544 sql_rollback ();
1545 return 1;
1546 }
1547
1548 /* Update values */
1549 if (name)
1550 set_report_format_name (report_format, name);
1551
1552 if (summary)
1553 set_report_format_summary (report_format, summary);
1554
1555 if (active)
1556 set_report_format_active (report_format, strcmp (active, "0"));
1557
1558 sql_commit ();
1559
1560 /* Update format params if set */
1561 if (param_name)
1562 {
1563 ret = set_report_format_param (report_format, param_name, param_value);
1564 if (ret == 1)
1565 ret = 3;
1566 if (ret == 2)
1567 ret = 4;
1568 }
1569
1570 return ret;
1571 }
1572
1573 /**
1574 * @brief Move a report format directory.
1575 *
1576 * @param[in] dir Old dir.
1577 * @param[in] new_dir New dir.
1578 *
1579 * @return 0 success, -1 error.
1580 */
1581 static int
move_report_format_dir(const char * dir,const char * new_dir)1582 move_report_format_dir (const char *dir, const char *new_dir)
1583 {
1584 if (gvm_file_is_readable (dir)
1585 && gvm_file_check_is_dir (dir))
1586 {
1587 gchar *new_dir_parent;
1588
1589 g_warning ("%s: rename %s to %s", __func__, dir, new_dir);
1590
1591 /* Ensure parent of new_dir exists. */
1592 new_dir_parent = g_path_get_dirname (new_dir);
1593 if (g_mkdir_with_parents (new_dir_parent, 0755 /* "rwxr-xr-x" */))
1594 {
1595 g_warning ("%s: failed to create parent %s", __func__,
1596 new_dir_parent);
1597 g_free (new_dir_parent);
1598 return -1;
1599 }
1600 g_free (new_dir_parent);
1601
1602 if (rename (dir, new_dir))
1603 {
1604 GError *error;
1605 GDir *directory;
1606 const gchar *entry;
1607
1608 if (errno == EXDEV)
1609 {
1610 /* Across devices, move by hand. */
1611
1612 if (g_mkdir_with_parents (new_dir, 0755 /* "rwxr-xr-x" */))
1613 {
1614 g_warning ("%s: failed to create dir %s", __func__,
1615 new_dir);
1616 return -1;
1617 }
1618
1619 error = NULL;
1620 directory = g_dir_open (dir, 0, &error);
1621
1622 if (directory == NULL)
1623 {
1624 g_warning ("%s: failed to g_dir_open %s: %s",
1625 __func__, dir, error->message);
1626 g_error_free (error);
1627 return -1;
1628 }
1629
1630 entry = NULL;
1631 while ((entry = g_dir_read_name (directory)))
1632 {
1633 gchar *entry_path, *new_path;
1634 entry_path = g_build_filename (dir, entry, NULL);
1635 new_path = g_build_filename (new_dir, entry, NULL);
1636 if (gvm_file_move (entry_path, new_path) == FALSE)
1637 {
1638 g_warning ("%s: failed to move %s to %s",
1639 __func__, entry_path, new_path);
1640 g_free (entry_path);
1641 g_free (new_path);
1642 g_dir_close (directory);
1643 return -1;
1644 }
1645 g_free (entry_path);
1646 g_free (new_path);
1647 }
1648
1649 g_dir_close (directory);
1650
1651 gvm_file_remove_recurse (dir);
1652 }
1653 else
1654 {
1655 g_warning ("%s: rename %s to %s: %s",
1656 __func__, dir, new_dir, strerror (errno));
1657 return -1;
1658 }
1659 }
1660 }
1661 else
1662 {
1663 g_warning ("%s: report dir missing: %s",
1664 __func__, dir);
1665 return -1;
1666 }
1667 return 0;
1668 }
1669
1670 /**
1671 * @brief Delete a report format from the db.
1672 *
1673 * @param[in] report_format Report format.
1674 */
1675 static void
delete_report_format_rows(report_format_t report_format)1676 delete_report_format_rows (report_format_t report_format)
1677 {
1678 sql ("DELETE FROM report_format_param_options WHERE report_format_param"
1679 " IN (SELECT id from report_format_params WHERE report_format = %llu);",
1680 report_format);
1681 sql ("DELETE FROM report_format_params WHERE report_format = %llu;",
1682 report_format);
1683 sql ("DELETE FROM report_formats WHERE id = %llu;", report_format);
1684 }
1685
1686 /**
1687 * @brief Delete a report format.
1688 *
1689 * @param[in] report_format_id UUID of Report format.
1690 * @param[in] ultimate Whether to remove entirely, or to trashcan.
1691 *
1692 * @return 0 success, 1 report format in use, 2 failed to find report format,
1693 * 99 permission denied, -1 error.
1694 */
1695 int
delete_report_format(const char * report_format_id,int ultimate)1696 delete_report_format (const char *report_format_id, int ultimate)
1697 {
1698 gchar *dir;
1699 char *owner_uuid;
1700 report_format_t report_format, trash_report_format;
1701
1702 /* This is complicated in two ways
1703 *
1704 * - the UUID of a report format is the same every time it is
1705 * imported, so to prevent multiple deletes from producing
1706 * duplicate UUIDs in the trashcan, each report format in the
1707 * trashcan gets a new UUID (except feed report formats),
1708 *
1709 * - the report format has information on disk on top of the
1710 * info in the db, so the disk information has to be held
1711 * in a special trashcan directory. */
1712
1713 sql_begin_immediate ();
1714
1715 if (acl_user_may ("delete_report_format") == 0)
1716 {
1717 sql_rollback ();
1718 return 99;
1719 }
1720
1721 /* Look in the "real" table. */
1722
1723 if (find_report_format_with_permission (report_format_id, &report_format,
1724 "delete_report_format"))
1725 {
1726 sql_rollback ();
1727 return -1;
1728 }
1729
1730 if (report_format == 0)
1731 {
1732 gchar *report_format_string, *base;
1733
1734 /* Look in the trashcan. */
1735
1736 if (find_trash ("report_format", report_format_id, &report_format))
1737 {
1738 sql_rollback ();
1739 return -1;
1740 }
1741 if (report_format == 0)
1742 {
1743 sql_rollback ();
1744 return 2;
1745 }
1746 if (ultimate == 0)
1747 {
1748 /* It's already in the trashcan. */
1749 sql_commit ();
1750 return 0;
1751 }
1752
1753 /* Check if it's in use by a trash alert. */
1754
1755 if (trash_report_format_in_use (report_format))
1756 {
1757 sql_rollback ();
1758 return 1;
1759 }
1760
1761 /* Remove entirely. */
1762
1763 permissions_set_orphans ("report_format", report_format, LOCATION_TRASH);
1764 tags_remove_resource ("report_format", report_format, LOCATION_TRASH);
1765
1766 base = sql_string ("SELECT original_uuid || '.asc'"
1767 " FROM report_formats_trash"
1768 " WHERE id = %llu;",
1769 report_format);
1770 sql ("DELETE FROM report_format_param_options_trash"
1771 " WHERE report_format_param"
1772 " IN (SELECT id from report_format_params_trash"
1773 " WHERE report_format = %llu);",
1774 report_format);
1775 sql ("DELETE FROM report_format_params_trash WHERE report_format = %llu;",
1776 report_format);
1777 sql ("DELETE FROM report_formats_trash WHERE id = %llu;",
1778 report_format);
1779
1780 /* Remove the dirs last, in case any SQL rolls back. */
1781
1782 /* Trash files. */
1783 report_format_string = g_strdup_printf ("%llu", report_format);
1784 dir = report_format_trash_dir (report_format_string);
1785 g_free (report_format_string);
1786 if (gvm_file_exists (dir) && gvm_file_remove_recurse (dir))
1787 {
1788 g_free (dir);
1789 g_free (base);
1790 sql_rollback ();
1791 return -1;
1792 }
1793 g_free (dir);
1794
1795 /* Links to the feed signatures. */
1796 dir = g_build_filename (GVMD_STATE_DIR, "signatures",
1797 "report_formats", base, NULL);
1798 g_free (base);
1799 unlink (dir);
1800 g_free (dir);
1801 sql_commit ();
1802
1803 return 0;
1804 }
1805
1806 owner_uuid = report_format_owner_uuid (report_format);
1807 dir = g_build_filename (GVMD_STATE_DIR,
1808 "report_formats",
1809 owner_uuid,
1810 report_format_id,
1811 NULL);
1812 free (owner_uuid);
1813
1814 if (ultimate)
1815 {
1816 permissions_set_orphans ("report_format", report_format, LOCATION_TABLE);
1817 tags_remove_resource ("report_format", report_format, LOCATION_TABLE);
1818
1819 /* Check if it's in use by a trash or regular alert. */
1820
1821 if (sql_int ("SELECT count(*) FROM alert_method_data_trash"
1822 " WHERE data = (SELECT uuid FROM report_formats"
1823 " WHERE id = %llu)"
1824 " AND (name = 'notice_attach_format'"
1825 " OR name = 'notice_report_format');",
1826 report_format))
1827 {
1828 g_free (dir);
1829 sql_rollback ();
1830 return 1;
1831 }
1832
1833 if (report_format_in_use (report_format))
1834 {
1835 g_free (dir);
1836 sql_rollback ();
1837 return 1;
1838 }
1839
1840 /* Remove directory. */
1841
1842 if (gvm_file_exists (dir) && gvm_file_remove_recurse (dir))
1843 {
1844 g_free (dir);
1845 sql_rollback ();
1846 return -1;
1847 }
1848
1849 /* Remove from "real" tables. */
1850
1851 delete_report_format_rows (report_format);
1852 }
1853 else
1854 {
1855 iterator_t params;
1856 gchar *trash_dir, *new_dir, *report_format_string;
1857
1858 /* Check if it's in use by a regular alert. */
1859
1860 if (report_format_in_use (report_format))
1861 {
1862 g_free (dir);
1863 sql_rollback ();
1864 return 1;
1865 }
1866
1867 /* Move to trash. */
1868
1869 trash_dir = report_format_trash_dir (NULL);
1870 if (g_mkdir_with_parents (trash_dir, 0755 /* "rwxr-xr-x" */))
1871 {
1872 g_warning ("%s: failed to create dir %s", __func__, trash_dir);
1873 g_free (trash_dir);
1874 sql_rollback ();
1875 return -1;
1876 }
1877 g_free (trash_dir);
1878
1879 sql ("INSERT INTO report_formats_trash"
1880 " (uuid, owner, name, extension, content_type, summary,"
1881 " description, signature, trust, trust_time, flags, original_uuid,"
1882 " predefined, creation_time, modification_time)"
1883 " SELECT"
1884 " %s, owner, name, extension, content_type, summary,"
1885 " description, signature, trust, trust_time, flags, uuid,"
1886 " predefined, creation_time, modification_time"
1887 " FROM report_formats"
1888 " WHERE id = %llu;",
1889 report_format_predefined (report_format) ? "uuid" : "make_uuid ()",
1890 report_format);
1891
1892 trash_report_format = sql_last_insert_id ();
1893
1894 init_report_format_param_iterator (¶ms, report_format, 0, 1, NULL);
1895 while (next (¶ms))
1896 {
1897 report_format_param_t param, trash_param;
1898
1899 param = report_format_param_iterator_param (¶ms);
1900
1901 sql ("INSERT INTO report_format_params_trash"
1902 " (report_format, name, type, value, type_min, type_max,"
1903 " type_regex, fallback)"
1904 " SELECT"
1905 " %llu, name, type, value, type_min, type_max,"
1906 " type_regex, fallback"
1907 " FROM report_format_params"
1908 " WHERE id = %llu;",
1909 trash_report_format,
1910 param);
1911
1912 trash_param = sql_last_insert_id ();
1913
1914 sql ("INSERT INTO report_format_param_options_trash"
1915 " (report_format_param, value)"
1916 " SELECT %llu, value"
1917 " FROM report_format_param_options"
1918 " WHERE report_format_param = %llu;",
1919 trash_param,
1920 param);
1921 }
1922 cleanup_iterator (¶ms);
1923
1924 permissions_set_locations ("report_format", report_format,
1925 trash_report_format, LOCATION_TRASH);
1926 tags_set_locations ("report_format", report_format,
1927 trash_report_format, LOCATION_TRASH);
1928
1929 /* Remove from "real" tables. */
1930
1931 delete_report_format_rows (report_format);
1932
1933 /* Move the dir last, in case any SQL rolls back. */
1934
1935 report_format_string = g_strdup_printf ("%llu", trash_report_format);
1936 new_dir = report_format_trash_dir (report_format_string);
1937 g_free (report_format_string);
1938 if (move_report_format_dir (dir, new_dir))
1939 {
1940 g_free (dir);
1941 g_free (new_dir);
1942 sql_rollback ();
1943 return -1;
1944 }
1945 g_free (new_dir);
1946 }
1947
1948 g_free (dir);
1949
1950 sql_commit ();
1951
1952 return 0;
1953 }
1954
1955 /**
1956 * @brief Try restore a report format.
1957 *
1958 * If success, ends transaction for caller before exiting.
1959 *
1960 * @param[in] report_format_id UUID of resource.
1961 *
1962 * @return 0 success, 1 fail because resource is in use, 2 failed to find
1963 * resource, 4 fail because resource with UUID exists, -1 error.
1964 */
1965 int
restore_report_format(const char * report_format_id)1966 restore_report_format (const char *report_format_id)
1967 {
1968 report_format_t resource, report_format;
1969 iterator_t params;
1970 gchar *dir, *trash_dir, *resource_string;
1971 char *trash_uuid, *owner_uuid;
1972
1973 if (find_trash ("report_format", report_format_id, &resource))
1974 {
1975 sql_rollback ();
1976 return -1;
1977 }
1978
1979 if (resource == 0)
1980 return 2;
1981
1982 if (sql_int ("SELECT count(*) FROM report_formats"
1983 " WHERE name ="
1984 " (SELECT name FROM report_formats_trash WHERE id = %llu)"
1985 " AND " ACL_USER_OWNS () ";",
1986 resource,
1987 current_credentials.uuid))
1988 {
1989 sql_rollback ();
1990 return 3;
1991 }
1992
1993 if (sql_int ("SELECT count(*) FROM report_formats"
1994 " WHERE uuid = (SELECT original_uuid"
1995 " FROM report_formats_trash"
1996 " WHERE id = %llu);",
1997 resource))
1998 {
1999 sql_rollback ();
2000 return 4;
2001 }
2002
2003 /* Move to "real" tables. */
2004
2005 sql ("INSERT INTO report_formats"
2006 " (uuid, owner, name, extension, content_type, summary,"
2007 " description, signature, trust, trust_time, flags,"
2008 " predefined, creation_time, modification_time)"
2009 " SELECT"
2010 " original_uuid, owner, name, extension, content_type, summary,"
2011 " description, signature, trust, trust_time, flags,"
2012 " predefined, creation_time, modification_time"
2013 " FROM report_formats_trash"
2014 " WHERE id = %llu;",
2015 resource);
2016
2017 report_format = sql_last_insert_id ();
2018
2019 init_report_format_param_iterator (¶ms, resource, 1, 1, NULL);
2020 while (next (¶ms))
2021 {
2022 report_format_param_t param, trash_param;
2023
2024 trash_param = report_format_param_iterator_param (¶ms);
2025
2026 sql ("INSERT INTO report_format_params"
2027 " (report_format, name, type, value, type_min, type_max,"
2028 " type_regex, fallback)"
2029 " SELECT"
2030 " %llu, name, type, value, type_min, type_max,"
2031 " type_regex, fallback"
2032 " FROM report_format_params_trash"
2033 " WHERE id = %llu;",
2034 report_format,
2035 trash_param);
2036
2037 param = sql_last_insert_id ();
2038
2039 sql ("INSERT INTO report_format_param_options"
2040 " (report_format_param, value)"
2041 " SELECT %llu, value"
2042 " FROM report_format_param_options_trash"
2043 " WHERE report_format_param = %llu;",
2044 param,
2045 trash_param);
2046 }
2047 cleanup_iterator (¶ms);
2048
2049 trash_uuid = sql_string ("SELECT original_uuid FROM report_formats_trash"
2050 " WHERE id = %llu;",
2051 resource);
2052 if (trash_uuid == NULL)
2053 abort ();
2054
2055 permissions_set_locations ("report_format", resource, report_format,
2056 LOCATION_TABLE);
2057 tags_set_locations ("report_format", resource, report_format,
2058 LOCATION_TABLE);
2059
2060 /* Remove from trash tables. */
2061
2062 sql ("DELETE FROM report_format_param_options_trash"
2063 " WHERE report_format_param"
2064 " IN (SELECT id from report_format_params_trash"
2065 " WHERE report_format = %llu);",
2066 resource);
2067 sql ("DELETE FROM report_format_params_trash WHERE report_format = %llu;",
2068 resource);
2069 sql ("DELETE FROM report_formats_trash WHERE id = %llu;",
2070 resource);
2071
2072 /* Move the dir last, in case any SQL rolls back. */
2073
2074 owner_uuid = report_format_owner_uuid (report_format);
2075 dir = g_build_filename (GVMD_STATE_DIR,
2076 "report_formats",
2077 owner_uuid,
2078 trash_uuid,
2079 NULL);
2080 free (trash_uuid);
2081 free (owner_uuid);
2082
2083 resource_string = g_strdup_printf ("%llu", resource);
2084 trash_dir = report_format_trash_dir (resource_string);
2085 g_free (resource_string);
2086 if (move_report_format_dir (trash_dir, dir))
2087 {
2088 g_free (dir);
2089 g_free (trash_dir);
2090 sql_rollback ();
2091 return -1;
2092 }
2093 g_free (dir);
2094 g_free (trash_dir);
2095
2096 sql_commit ();
2097 return 0;
2098 }
2099
2100 /**
2101 * @brief Return the UUID of a report format.
2102 *
2103 * @param[in] report_format Report format.
2104 *
2105 * @return Newly allocated UUID.
2106 */
2107 char *
report_format_uuid(report_format_t report_format)2108 report_format_uuid (report_format_t report_format)
2109 {
2110 return sql_string ("SELECT uuid FROM report_formats WHERE id = %llu;",
2111 report_format);
2112 }
2113
2114 /**
2115 * @brief Return the UUID of the owner of a report format.
2116 *
2117 * @param[in] report_format Report format.
2118 *
2119 * @return Newly allocated owner UUID if there is an owner, else NULL.
2120 */
2121 char *
report_format_owner_uuid(report_format_t report_format)2122 report_format_owner_uuid (report_format_t report_format)
2123 {
2124 if (sql_int ("SELECT " ACL_IS_GLOBAL () " FROM report_formats"
2125 " WHERE id = %llu;",
2126 report_format))
2127 return NULL;
2128 return sql_string ("SELECT uuid FROM users"
2129 " WHERE id = (SELECT owner FROM report_formats"
2130 " WHERE id = %llu);",
2131 report_format);
2132 }
2133
2134 /**
2135 * @brief Set the active flag of a report format.
2136 *
2137 * @param[in] report_format The report format.
2138 * @param[in] active Active flag.
2139 */
2140 static void
set_report_format_active(report_format_t report_format,int active)2141 set_report_format_active (report_format_t report_format, int active)
2142 {
2143 if (active)
2144 sql ("UPDATE report_formats SET flags = (flags | %llu), "
2145 " modification_time = m_now ()"
2146 " WHERE id = %llu;",
2147 (long long int) REPORT_FORMAT_FLAG_ACTIVE,
2148 report_format);
2149 else
2150 sql ("UPDATE report_formats SET flags = (flags & ~ %llu), "
2151 " modification_time = m_now ()"
2152 " WHERE id = %llu;",
2153 (long long int) REPORT_FORMAT_FLAG_ACTIVE,
2154 report_format);
2155 }
2156
2157 /**
2158 * @brief Return the name of a report format.
2159 *
2160 * @param[in] report_format Report format.
2161 *
2162 * @return Newly allocated name.
2163 */
2164 char *
report_format_name(report_format_t report_format)2165 report_format_name (report_format_t report_format)
2166 {
2167 return sql_string ("SELECT name FROM report_formats WHERE id = %llu;",
2168 report_format);
2169 }
2170
2171 /**
2172 * @brief Return the content type of a report format.
2173 *
2174 * @param[in] report_format Report format.
2175 *
2176 * @return Newly allocated content type.
2177 */
2178 char *
report_format_content_type(report_format_t report_format)2179 report_format_content_type (report_format_t report_format)
2180 {
2181 return sql_string ("SELECT content_type FROM report_formats"
2182 " WHERE id = %llu;",
2183 report_format);
2184 }
2185
2186 /**
2187 * @brief Return whether a report format is referenced by an alert.
2188 *
2189 * @param[in] report_format Report Format.
2190 *
2191 * @return 1 if in use, else 0.
2192 */
2193 int
report_format_in_use(report_format_t report_format)2194 report_format_in_use (report_format_t report_format)
2195 {
2196 return !!sql_int ("SELECT count(*) FROM alert_method_data"
2197 " WHERE data = (SELECT uuid FROM report_formats"
2198 " WHERE id = %llu)"
2199 " AND (name = 'notice_attach_format'"
2200 " OR name = 'notice_report_format'"
2201 " OR name = 'scp_report_format'"
2202 " OR name = 'send_report_format'"
2203 " OR name = 'smb_report_format'"
2204 " OR name = 'verinice_server_report_format');",
2205 report_format);
2206 }
2207
2208 /**
2209 * @brief Return whether a report format in trash is referenced by an alert.
2210 *
2211 * @param[in] report_format Report Format.
2212 *
2213 * @return 1 if in use, else 0.
2214 */
2215 int
trash_report_format_in_use(report_format_t report_format)2216 trash_report_format_in_use (report_format_t report_format)
2217 {
2218 return !!sql_int ("SELECT count(*) FROM alert_method_data_trash"
2219 " WHERE data = (SELECT original_uuid"
2220 " FROM report_formats_trash"
2221 " WHERE id = %llu)"
2222 " AND (name = 'notice_attach_format'"
2223 " OR name = 'notice_report_format'"
2224 " OR name = 'scp_report_format'"
2225 " OR name = 'send_report_format'"
2226 " OR name = 'smb_report_format'"
2227 " OR name = 'verinice_server_report_format');",
2228 report_format);
2229 }
2230
2231 /**
2232 * @brief Return whether a report format is predefined.
2233 *
2234 * @param[in] report_format Report format.
2235 *
2236 * @return 1 if predefined, else 0.
2237 */
2238 int
report_format_predefined(report_format_t report_format)2239 report_format_predefined (report_format_t report_format)
2240 {
2241 return sql_int ("SELECT predefined FROM report_formats"
2242 " WHERE id = %llu;",
2243 report_format);
2244 }
2245
2246 /**
2247 * @brief Return whether a trash report format is predefined.
2248 *
2249 * @param[in] report_format Report format.
2250 *
2251 * @return 1 if predefined, else 0.
2252 */
2253 int
trash_report_format_predefined(report_format_t report_format)2254 trash_report_format_predefined (report_format_t report_format)
2255 {
2256 return sql_int ("SELECT predefined FROM report_formats_trash"
2257 " WHERE id = %llu;",
2258 report_format);
2259 }
2260
2261 /**
2262 * @brief Return the extension of a report format.
2263 *
2264 * @param[in] report_format Report format.
2265 *
2266 * @return Newly allocated extension.
2267 */
2268 char *
report_format_extension(report_format_t report_format)2269 report_format_extension (report_format_t report_format)
2270 {
2271 return sql_string ("SELECT extension FROM report_formats WHERE id = %llu;",
2272 report_format);
2273 }
2274
2275 /**
2276 * @brief Set the name of the report format.
2277 *
2278 * @param[in] report_format The report format.
2279 * @param[in] name Name.
2280 */
2281 static void
set_report_format_name(report_format_t report_format,const char * name)2282 set_report_format_name (report_format_t report_format, const char *name)
2283 {
2284 gchar *quoted_name = sql_quote (name);
2285 sql ("UPDATE report_formats SET name = '%s', modification_time = m_now ()"
2286 " WHERE id = %llu;",
2287 quoted_name,
2288 report_format);
2289 g_free (quoted_name);
2290 }
2291
2292 /**
2293 * @brief Return whether a report format is active.
2294 *
2295 * @param[in] report_format Report format.
2296 *
2297 * @return -1 on error, 1 if active, else 0.
2298 */
2299 int
report_format_active(report_format_t report_format)2300 report_format_active (report_format_t report_format)
2301 {
2302 long long int flag;
2303 switch (sql_int64 (&flag,
2304 "SELECT flags & %llu FROM report_formats"
2305 " WHERE id = %llu;",
2306 (long long int) REPORT_FORMAT_FLAG_ACTIVE,
2307 report_format))
2308 {
2309 case 0:
2310 break;
2311 case 1: /* Too few rows in result of query. */
2312 return 0;
2313 break;
2314 default: /* Programming error. */
2315 assert (0);
2316 case -1:
2317 return -1;
2318 break;
2319 }
2320 return flag ? 1 : 0;
2321 }
2322
2323 /**
2324 * @brief Set the summary of the report format.
2325 *
2326 * @param[in] report_format The report format.
2327 * @param[in] summary Summary.
2328 */
2329 static void
set_report_format_summary(report_format_t report_format,const char * summary)2330 set_report_format_summary (report_format_t report_format, const char *summary)
2331 {
2332 gchar *quoted_summary = sql_quote (summary);
2333 sql ("UPDATE report_formats SET summary = '%s', modification_time = m_now ()"
2334 " WHERE id = %llu;",
2335 quoted_summary,
2336 report_format);
2337 g_free (quoted_summary);
2338 }
2339
2340 /**
2341 * @brief Return the type max of a report format param.
2342 *
2343 * @param[in] report_format Report format.
2344 * @param[in] name Name of param.
2345 *
2346 * @return Param type.
2347 */
2348 static report_format_param_type_t
report_format_param_type(report_format_t report_format,const char * name)2349 report_format_param_type (report_format_t report_format, const char *name)
2350 {
2351 report_format_param_type_t type;
2352 gchar *quoted_name = sql_quote (name);
2353 type = (report_format_param_type_t)
2354 sql_int ("SELECT type FROM report_format_params"
2355 " WHERE report_format = %llu AND name = '%s';",
2356 report_format,
2357 quoted_name);
2358 g_free (quoted_name);
2359 return type;
2360 }
2361
2362 /**
2363 * @brief Return the type max of a report format param.
2364 *
2365 * @param[in] report_format Report format.
2366 * @param[in] name Name of param.
2367 *
2368 * @return Max.
2369 */
2370 static long long int
report_format_param_type_max(report_format_t report_format,const char * name)2371 report_format_param_type_max (report_format_t report_format, const char *name)
2372 {
2373 long long int max = 0;
2374 gchar *quoted_name = sql_quote (name);
2375 /* Assume it's there. */
2376 sql_int64 (&max,
2377 "SELECT type_max FROM report_format_params"
2378 " WHERE report_format = %llu AND name = '%s';",
2379 report_format,
2380 quoted_name);
2381 g_free (quoted_name);
2382 return max;
2383 }
2384
2385 /**
2386 * @brief Return the type min of a report format param.
2387 *
2388 * @param[in] report_format Report format.
2389 * @param[in] name Name of param.
2390 *
2391 * @return Min.
2392 */
2393 static long long int
report_format_param_type_min(report_format_t report_format,const char * name)2394 report_format_param_type_min (report_format_t report_format, const char *name)
2395 {
2396 long long int min = 0;
2397 gchar *quoted_name = sql_quote (name);
2398 /* Assume it's there. */
2399 sql_int64 (&min,
2400 "SELECT type_min FROM report_format_params"
2401 " WHERE report_format = %llu AND name = '%s';",
2402 report_format,
2403 quoted_name);
2404 g_free (quoted_name);
2405 return min;
2406 }
2407
2408 /**
2409 * @brief Validate a value for a report format param.
2410 *
2411 * @param[in] report_format Report format.
2412 * @param[in] param Param.
2413 * @param[in] name Name of param.
2414 * @param[in] value Potential value of param.
2415 *
2416 * @return 0 success, 1 fail.
2417 */
2418 static int
validate_param_value(report_format_t report_format,report_format_param_t param,const char * name,const char * value)2419 validate_param_value (report_format_t report_format,
2420 report_format_param_t param, const char *name,
2421 const char *value)
2422 {
2423 switch (report_format_param_type (report_format, name))
2424 {
2425 case REPORT_FORMAT_PARAM_TYPE_INTEGER:
2426 {
2427 long long int min, max, actual;
2428 min = report_format_param_type_min (report_format, name);
2429 /* Simply truncate out of range values. */
2430 actual = strtoll (value, NULL, 0);
2431 if (actual < min)
2432 return 1;
2433 max = report_format_param_type_max (report_format, name);
2434 if (actual > max)
2435 return 1;
2436 }
2437 break;
2438 case REPORT_FORMAT_PARAM_TYPE_SELECTION:
2439 {
2440 iterator_t options;
2441 int found = 0;
2442
2443 init_param_option_iterator (&options, param, 1, NULL);
2444 while (next (&options))
2445 if (param_option_iterator_value (&options)
2446 && (strcmp (param_option_iterator_value (&options), value)
2447 == 0))
2448 {
2449 found = 1;
2450 break;
2451 }
2452 cleanup_iterator (&options);
2453 if (found)
2454 break;
2455 return 1;
2456 }
2457 case REPORT_FORMAT_PARAM_TYPE_STRING:
2458 case REPORT_FORMAT_PARAM_TYPE_TEXT:
2459 {
2460 long long int min, max, actual;
2461 min = report_format_param_type_min (report_format, name);
2462 actual = strlen (value);
2463 if (actual < min)
2464 return 1;
2465 max = report_format_param_type_max (report_format, name);
2466 if (actual > max)
2467 return 1;
2468 }
2469 break;
2470 case REPORT_FORMAT_PARAM_TYPE_REPORT_FORMAT_LIST:
2471 {
2472 if (g_regex_match_simple
2473 ("^(?:[[:alnum:]-_]+)?(?:,(?:[[:alnum:]-_])+)*$", value, 0, 0)
2474 == FALSE)
2475 return 1;
2476 else
2477 return 0;
2478 }
2479 break;
2480 default:
2481 break;
2482 }
2483 return 0;
2484 }
2485
2486 /**
2487 * @brief Set the value of the report format param.
2488 *
2489 * @param[in] report_format The report format.
2490 * @param[in] name Param name.
2491 * @param[in] value_64 Param value in base64.
2492 *
2493 * @return 0 success, 1 failed to find param, 2 validation of value failed,
2494 * -1 error.
2495 */
2496 static int
set_report_format_param(report_format_t report_format,const char * name,const char * value_64)2497 set_report_format_param (report_format_t report_format, const char *name,
2498 const char *value_64)
2499 {
2500 gchar *quoted_name, *quoted_value, *value;
2501 gsize value_size;
2502 report_format_param_t param;
2503
2504 quoted_name = sql_quote (name);
2505
2506 sql_begin_immediate ();
2507
2508 /* Ensure the param exists. */
2509
2510 switch (sql_int64 (¶m,
2511 "SELECT id FROM report_format_params"
2512 " WHERE name = '%s';",
2513 quoted_name))
2514 {
2515 case 0:
2516 break;
2517 case 1: /* Too few rows in result of query. */
2518 g_free (quoted_name);
2519 sql_rollback ();
2520 return 1;
2521 break;
2522 default: /* Programming error. */
2523 assert (0);
2524 case -1:
2525 g_free (quoted_name);
2526 sql_rollback ();
2527 return -1;
2528 break;
2529 }
2530
2531 /* Translate the value. */
2532
2533 if (value_64 && strlen (value_64))
2534 value = (gchar*) g_base64_decode (value_64, &value_size);
2535 else
2536 {
2537 value = g_strdup ("");
2538 value_size = 0;
2539 }
2540
2541 /* Validate the value. */
2542
2543 if (validate_param_value (report_format, param, name, value))
2544 {
2545 sql_rollback ();
2546 g_free (quoted_name);
2547 return 2;
2548 }
2549
2550 quoted_value = sql_quote (value);
2551 g_free (value);
2552
2553 /* Update the database. */
2554
2555 sql ("UPDATE report_format_params SET value = '%s'"
2556 " WHERE report_format = %llu AND name = '%s';",
2557 quoted_value,
2558 report_format,
2559 quoted_name);
2560
2561 g_free (quoted_name);
2562 g_free (quoted_value);
2563
2564 sql_commit ();
2565
2566 return 0;
2567 }
2568
2569 /**
2570 * @brief Return the trust of a report format.
2571 *
2572 * @param[in] report_format Report format.
2573 *
2574 * @return Trust: 1 yes, 2 no, 3 unknown.
2575 */
2576 int
report_format_trust(report_format_t report_format)2577 report_format_trust (report_format_t report_format)
2578 {
2579 return sql_int ("SELECT trust FROM report_formats WHERE id = %llu;",
2580 report_format);
2581 }
2582
2583 /**
2584 * @brief Filter columns for Report Format iterator.
2585 */
2586 #define REPORT_FORMAT_ITERATOR_FILTER_COLUMNS \
2587 { ANON_GET_ITERATOR_FILTER_COLUMNS, "name", "extension", "content_type", \
2588 "summary", "description", "trust", "trust_time", "active", "predefined", \
2589 NULL }
2590
2591 /**
2592 * @brief Report Format iterator columns.
2593 */
2594 #define REPORT_FORMAT_ITERATOR_COLUMNS \
2595 { \
2596 { "id", NULL, KEYWORD_TYPE_INTEGER }, \
2597 { "uuid", NULL, KEYWORD_TYPE_STRING }, \
2598 { "name", NULL, KEYWORD_TYPE_STRING }, \
2599 { "''", NULL, KEYWORD_TYPE_STRING }, \
2600 { "iso_time (creation_time)", NULL, KEYWORD_TYPE_STRING }, \
2601 { "iso_time (modification_time)", NULL, KEYWORD_TYPE_STRING }, \
2602 { "creation_time", "created", KEYWORD_TYPE_INTEGER }, \
2603 { "modification_time", "modified", KEYWORD_TYPE_INTEGER }, \
2604 { \
2605 "(SELECT name FROM users WHERE users.id = report_formats.owner)", \
2606 "_owner", \
2607 KEYWORD_TYPE_STRING \
2608 }, \
2609 { "owner", NULL, KEYWORD_TYPE_INTEGER }, \
2610 { "extension", NULL, KEYWORD_TYPE_STRING }, \
2611 { "content_type", NULL, KEYWORD_TYPE_STRING }, \
2612 { "summary", NULL, KEYWORD_TYPE_STRING }, \
2613 { "description", NULL, KEYWORD_TYPE_STRING }, \
2614 { "signature", NULL, KEYWORD_TYPE_STRING }, \
2615 { "trust", NULL, KEYWORD_TYPE_INTEGER }, \
2616 { "trust_time", NULL, KEYWORD_TYPE_INTEGER }, \
2617 { "flags & 1", "active", KEYWORD_TYPE_INTEGER }, \
2618 { "predefined", NULL, KEYWORD_TYPE_INTEGER }, \
2619 { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \
2620 }
2621
2622 /**
2623 * @brief Report Format iterator columns for trash case.
2624 */
2625 #define REPORT_FORMAT_ITERATOR_TRASH_COLUMNS \
2626 { \
2627 { "id", NULL, KEYWORD_TYPE_INTEGER }, \
2628 { "uuid", NULL, KEYWORD_TYPE_STRING }, \
2629 { "name", NULL, KEYWORD_TYPE_STRING }, \
2630 { "''", NULL, KEYWORD_TYPE_STRING }, \
2631 { "iso_time (creation_time)", NULL, KEYWORD_TYPE_STRING }, \
2632 { "iso_time (modification_time)", NULL, KEYWORD_TYPE_STRING }, \
2633 { "creation_time", "created", KEYWORD_TYPE_INTEGER }, \
2634 { "modification_time", "modified", KEYWORD_TYPE_INTEGER }, \
2635 { \
2636 "(SELECT name FROM users" \
2637 " WHERE users.id = report_formats_trash.owner)", \
2638 "_owner", \
2639 KEYWORD_TYPE_STRING \
2640 }, \
2641 { "owner", NULL, KEYWORD_TYPE_INTEGER }, \
2642 { "extension", NULL, KEYWORD_TYPE_STRING }, \
2643 { "content_type", NULL, KEYWORD_TYPE_STRING }, \
2644 { "summary", NULL, KEYWORD_TYPE_STRING }, \
2645 { "description", NULL, KEYWORD_TYPE_STRING }, \
2646 { "signature", NULL, KEYWORD_TYPE_STRING }, \
2647 { "trust", NULL, KEYWORD_TYPE_INTEGER }, \
2648 { "trust_time", NULL, KEYWORD_TYPE_INTEGER }, \
2649 { "flags & 1", "active", KEYWORD_TYPE_INTEGER }, \
2650 { "predefined", NULL, KEYWORD_TYPE_INTEGER }, \
2651 { NULL, NULL, KEYWORD_TYPE_UNKNOWN } \
2652 }
2653
2654 /**
2655 * @brief Get filter columns.
2656 *
2657 * @return Constant array of filter columns.
2658 */
2659 const char**
report_format_filter_columns()2660 report_format_filter_columns ()
2661 {
2662 static const char *columns[] = REPORT_FORMAT_ITERATOR_FILTER_COLUMNS;
2663 return columns;
2664 }
2665
2666 /**
2667 * @brief Get select columns.
2668 *
2669 * @return Constant array of select columns.
2670 */
2671 column_t*
report_format_select_columns()2672 report_format_select_columns ()
2673 {
2674 static column_t columns[] = REPORT_FORMAT_ITERATOR_COLUMNS;
2675 return columns;
2676 }
2677
2678 /**
2679 * @brief Count the number of Report Formats.
2680 *
2681 * @param[in] get GET params.
2682 *
2683 * @return Total number of Report Formats filtered set.
2684 */
2685 int
report_format_count(const get_data_t * get)2686 report_format_count (const get_data_t *get)
2687 {
2688 static const char *filter_columns[] = REPORT_FORMAT_ITERATOR_FILTER_COLUMNS;
2689 static column_t columns[] = REPORT_FORMAT_ITERATOR_COLUMNS;
2690 static column_t trash_columns[] = REPORT_FORMAT_ITERATOR_TRASH_COLUMNS;
2691 return count ("report_format", get, columns, trash_columns, filter_columns,
2692 0, 0, 0, TRUE);
2693 }
2694
2695 /**
2696 * @brief Initialise a Report Format iterator, including observed Report
2697 * Formats.
2698 *
2699 * @param[in] iterator Iterator.
2700 * @param[in] get GET data.
2701 *
2702 * @return 0 success, 1 failed to find Report Format, 2 failed to find filter,
2703 * -1 error.
2704 */
2705 int
init_report_format_iterator(iterator_t * iterator,const get_data_t * get)2706 init_report_format_iterator (iterator_t* iterator, const get_data_t *get)
2707 {
2708 static const char *filter_columns[] = REPORT_FORMAT_ITERATOR_FILTER_COLUMNS;
2709 static column_t columns[] = REPORT_FORMAT_ITERATOR_COLUMNS;
2710 static column_t trash_columns[] = REPORT_FORMAT_ITERATOR_TRASH_COLUMNS;
2711
2712 return init_get_iterator (iterator,
2713 "report_format",
2714 get,
2715 columns,
2716 trash_columns,
2717 filter_columns,
2718 0,
2719 NULL,
2720 NULL,
2721 TRUE);
2722 }
2723
2724 /**
2725 * @brief Get the extension from a report format iterator.
2726 *
2727 * @param[in] iterator Iterator.
2728 *
2729 * @return Extension, or NULL if iteration is complete. Freed by
2730 * cleanup_iterator.
2731 */
2732 DEF_ACCESS (report_format_iterator_extension, GET_ITERATOR_COLUMN_COUNT);
2733
2734 /**
2735 * @brief Get the content type from a report format iterator.
2736 *
2737 * @param[in] iterator Iterator.
2738 *
2739 * @return Content type, or NULL if iteration is complete. Freed by
2740 * cleanup_iterator.
2741 */
2742 DEF_ACCESS (report_format_iterator_content_type, GET_ITERATOR_COLUMN_COUNT + 1);
2743
2744 /**
2745 * @brief Get the summary from a report format iterator.
2746 *
2747 * @param[in] iterator Iterator.
2748 *
2749 * @return Summary, or NULL if iteration is complete. Freed by
2750 * cleanup_iterator.
2751 */
2752 DEF_ACCESS (report_format_iterator_summary, GET_ITERATOR_COLUMN_COUNT + 2);
2753
2754 /**
2755 * @brief Get the description from a report format iterator.
2756 *
2757 * @param[in] iterator Iterator.
2758 *
2759 * @return Description, or NULL if iteration is complete. Freed by
2760 * cleanup_iterator.
2761 */
2762 DEF_ACCESS (report_format_iterator_description, GET_ITERATOR_COLUMN_COUNT + 3);
2763
2764 /**
2765 * @brief Get the signature from a report format iterator.
2766 *
2767 * @param[in] iterator Iterator.
2768 *
2769 * @return Signature, or NULL if iteration is complete. Freed by
2770 * cleanup_iterator.
2771 */
2772 DEF_ACCESS (report_format_iterator_signature, GET_ITERATOR_COLUMN_COUNT + 4);
2773
2774 /**
2775 * @brief Get the trust value from a report format iterator.
2776 *
2777 * @param[in] iterator Iterator.
2778 *
2779 * @return Trust value.
2780 */
2781 const char*
report_format_iterator_trust(iterator_t * iterator)2782 report_format_iterator_trust (iterator_t* iterator)
2783 {
2784 if (iterator->done) return NULL;
2785 switch (iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 5))
2786 {
2787 case 1: return "yes";
2788 case 2: return "no";
2789 case 3: return "unknown";
2790 default: return NULL;
2791 }
2792 }
2793
2794 /**
2795 * @brief Get the trust time from a report format iterator.
2796 *
2797 * @param[in] iterator Iterator.
2798 *
2799 * @return Time report format was verified.
2800 */
2801 time_t
report_format_iterator_trust_time(iterator_t * iterator)2802 report_format_iterator_trust_time (iterator_t* iterator)
2803 {
2804 int ret;
2805 if (iterator->done) return -1;
2806 ret = (time_t) iterator_int (iterator, GET_ITERATOR_COLUMN_COUNT + 6);
2807 return ret;
2808 }
2809
2810 /**
2811 * @brief Get the active flag from a report format iterator.
2812 *
2813 * @param[in] iterator Iterator.
2814 *
2815 * @return Active flag, or -1 if iteration is complete.
2816 */
2817 int
report_format_iterator_active(iterator_t * iterator)2818 report_format_iterator_active (iterator_t* iterator)
2819 {
2820 if (iterator->done) return -1;
2821 return (iterator_int64 (iterator, GET_ITERATOR_COLUMN_COUNT + 7)
2822 & REPORT_FORMAT_FLAG_ACTIVE) ? 1 : 0;
2823 }
2824
2825 /**
2826 * @brief Initialise a Report Format alert iterator.
2827 *
2828 * Iterates over all alerts that use the Report Format.
2829 *
2830 * @param[in] iterator Iterator.
2831 * @param[in] report_format Report Format.
2832 */
2833 void
init_report_format_alert_iterator(iterator_t * iterator,report_format_t report_format)2834 init_report_format_alert_iterator (iterator_t* iterator,
2835 report_format_t report_format)
2836 {
2837 gchar *available, *with_clause;
2838 get_data_t get;
2839 array_t *permissions;
2840
2841 assert (report_format);
2842
2843 get.trash = 0;
2844 permissions = make_array ();
2845 array_add (permissions, g_strdup ("get_alerts"));
2846 available = acl_where_owned ("alert", &get, 1, "any", 0, permissions, 0,
2847 &with_clause);
2848 array_free (permissions);
2849
2850 init_iterator (iterator,
2851 "%s"
2852 " SELECT DISTINCT alerts.name, alerts.uuid, %s"
2853 " FROM alerts, alert_method_data"
2854 " WHERE alert_method_data.data = '%s'"
2855 " AND alert_method_data.alert = alerts.id"
2856 " ORDER BY alerts.name ASC;",
2857 with_clause ? with_clause : "",
2858 available,
2859 report_format_uuid (report_format));
2860
2861 g_free (with_clause);
2862 g_free (available);
2863 }
2864
2865 /**
2866 * @brief Get the name from a report_format_alert iterator.
2867 *
2868 * @param[in] iterator Iterator.
2869 *
2870 * @return The name of the Report Format, or NULL if iteration is complete.
2871 * Freed by cleanup_iterator.
2872 */
2873 DEF_ACCESS (report_format_alert_iterator_name, 0);
2874
2875 /**
2876 * @brief Get the UUID from a report_format_alert iterator.
2877 *
2878 * @param[in] iterator Iterator.
2879 *
2880 * @return The UUID of the Report Format, or NULL if iteration is complete.
2881 * Freed by cleanup_iterator.
2882 */
2883 DEF_ACCESS (report_format_alert_iterator_uuid, 1);
2884
2885 /**
2886 * @brief Get the read permission status from a GET iterator.
2887 *
2888 * @param[in] iterator Iterator.
2889 *
2890 * @return 1 if may read, else 0.
2891 */
2892 int
report_format_alert_iterator_readable(iterator_t * iterator)2893 report_format_alert_iterator_readable (iterator_t* iterator)
2894 {
2895 if (iterator->done) return 0;
2896 return iterator_int (iterator, 2);
2897 }
2898
2899 /**
2900 * @brief Initialise a report format iterator.
2901 *
2902 * @param[in] iterator Iterator.
2903 * @param[in] report_format Single report_format to iterate over, or 0 for all.
2904 * @param[in] trash Whether to iterate over trashcan report formats.
2905 * @param[in] ascending Whether to sort ascending or descending.
2906 * @param[in] sort_field Field to sort on, or NULL for "id".
2907 */
2908 void
init_report_format_param_iterator(iterator_t * iterator,report_format_t report_format,int trash,int ascending,const char * sort_field)2909 init_report_format_param_iterator (iterator_t* iterator,
2910 report_format_t report_format,
2911 int trash,
2912 int ascending,
2913 const char* sort_field)
2914 {
2915 if (report_format)
2916 init_iterator (iterator,
2917 "SELECT id, name, value, type, type_min, type_max,"
2918 " type_regex, fallback"
2919 " FROM report_format_params%s"
2920 " WHERE report_format = %llu"
2921 " ORDER BY %s %s;",
2922 trash ? "_trash" : "",
2923 report_format,
2924 sort_field ? sort_field : "id",
2925 ascending ? "ASC" : "DESC");
2926 else
2927 init_iterator (iterator,
2928 "SELECT id, name, value, type, type_min, type_max,"
2929 " type_regex, fallback"
2930 " FROM report_format_params%s"
2931 " ORDER BY %s %s;",
2932 trash ? "_trash" : "",
2933 sort_field ? sort_field : "id",
2934 ascending ? "ASC" : "DESC");
2935 }
2936
2937 /**
2938 * @brief Get the report format param from a report format param iterator.
2939 *
2940 * @param[in] iterator Iterator.
2941 *
2942 * @return Report format param.
2943 */
2944 report_format_param_t
report_format_param_iterator_param(iterator_t * iterator)2945 report_format_param_iterator_param (iterator_t* iterator)
2946 {
2947 if (iterator->done) return 0;
2948 return (report_format_param_t) iterator_int64 (iterator, 0);
2949 }
2950
2951 /**
2952 * @brief Get the name from a report format param iterator.
2953 *
2954 * @param[in] iterator Iterator.
2955 *
2956 * @return Name, or NULL if iteration is complete. Freed by
2957 * cleanup_iterator.
2958 */
2959 DEF_ACCESS (report_format_param_iterator_name, 1);
2960
2961 /**
2962 * @brief Get the value from a report format param iterator.
2963 *
2964 * @param[in] iterator Iterator.
2965 *
2966 * @return Value, or NULL if iteration is complete. Freed by
2967 * cleanup_iterator.
2968 */
2969 DEF_ACCESS (report_format_param_iterator_value, 2);
2970
2971 /**
2972 * @brief Get the name of the type of a report format param iterator.
2973 *
2974 * @param[in] iterator Iterator.
2975 *
2976 * @return Static string naming type, or NULL if iteration is complete.
2977 */
2978 const char *
report_format_param_iterator_type_name(iterator_t * iterator)2979 report_format_param_iterator_type_name (iterator_t* iterator)
2980 {
2981 if (iterator->done) return NULL;
2982 return report_format_param_type_name (iterator_int (iterator, 3));
2983 }
2984
2985 /**
2986 * @brief Get the type from a report format param iterator.
2987 *
2988 * @param[in] iterator Iterator.
2989 *
2990 * @return Type.
2991 */
2992 report_format_param_type_t
report_format_param_iterator_type(iterator_t * iterator)2993 report_format_param_iterator_type (iterator_t* iterator)
2994 {
2995 if (iterator->done) return -1;
2996 return iterator_int (iterator, 3);
2997 }
2998
2999 /**
3000 * @brief Get the type min from a report format param iterator.
3001 *
3002 * @param[in] iterator Iterator.
3003 *
3004 * @return Type min.
3005 */
3006 long long int
report_format_param_iterator_type_min(iterator_t * iterator)3007 report_format_param_iterator_type_min (iterator_t* iterator)
3008 {
3009 if (iterator->done) return -1;
3010 return iterator_int64 (iterator, 4);
3011 }
3012
3013 /**
3014 * @brief Get the type max from a report format param iterator.
3015 *
3016 * @param[in] iterator Iterator.
3017 *
3018 * @return Type max.
3019 */
3020 long long int
report_format_param_iterator_type_max(iterator_t * iterator)3021 report_format_param_iterator_type_max (iterator_t* iterator)
3022 {
3023 if (iterator->done) return -1;
3024 return iterator_int64 (iterator, 5);
3025 }
3026
3027 /**
3028 * @brief Get the type regex from a report format param iterator.
3029 *
3030 * @param[in] iterator Iterator.
3031 *
3032 * @return Type regex, or NULL if iteration is complete. Freed by
3033 * cleanup_iterator.
3034 */
3035 static
3036 DEF_ACCESS (report_format_param_iterator_type_regex, 6);
3037
3038 /**
3039 * @brief Get the default from a report format param iterator.
3040 *
3041 * @param[in] iterator Iterator.
3042 *
3043 * @return Default, or NULL if iteration is complete. Freed by
3044 * cleanup_iterator.
3045 */
3046 DEF_ACCESS (report_format_param_iterator_fallback, 7);
3047
3048 /**
3049 * @brief Initialise a report format param option iterator.
3050 *
3051 * @param[in] iterator Iterator.
3052 * @param[in] report_format_param Param whose options to iterate over.
3053 * @param[in] ascending Whether to sort ascending or descending.
3054 * @param[in] sort_field Field to sort on, or NULL for "id".
3055 */
3056 void
init_param_option_iterator(iterator_t * iterator,report_format_param_t report_format_param,int ascending,const char * sort_field)3057 init_param_option_iterator (iterator_t* iterator,
3058 report_format_param_t report_format_param,
3059 int ascending, const char *sort_field)
3060 {
3061 init_iterator (iterator,
3062 "SELECT id, value"
3063 " FROM report_format_param_options"
3064 " WHERE report_format_param = %llu"
3065 " ORDER BY %s %s;",
3066 report_format_param,
3067 sort_field ? sort_field : "id",
3068 ascending ? "ASC" : "DESC");
3069 }
3070
3071 /**
3072 * @brief Get the value from a report format param option iterator.
3073 *
3074 * @param[in] iterator Iterator.
3075 *
3076 * @return Value, or NULL if iteration is complete. Freed by
3077 * cleanup_iterator.
3078 */
3079 DEF_ACCESS (param_option_iterator_value, 1);
3080
3081 /**
3082 * @brief Verify a report format.
3083 *
3084 * @param[in] report_format Report format.
3085 *
3086 * @return 0 success, -1 error.
3087 */
3088 static int
verify_report_format_internal(report_format_t report_format)3089 verify_report_format_internal (report_format_t report_format)
3090 {
3091 int format_trust = TRUST_UNKNOWN;
3092 iterator_t formats;
3093 get_data_t get;
3094 gchar *uuid;
3095
3096 memset(&get, '\0', sizeof (get));
3097 get.id = report_format_uuid (report_format);
3098 init_report_format_iterator (&formats, &get);
3099 if (next (&formats))
3100 {
3101 const char *signature;
3102 gchar *format_signature = NULL;
3103 gsize format_signature_size;
3104
3105 signature = report_format_iterator_signature (&formats);
3106
3107 find_signature ("report_formats", get_iterator_uuid (&formats),
3108 &format_signature, &format_signature_size, &uuid);
3109
3110 if ((signature && strlen (signature))
3111 || format_signature)
3112 {
3113 GString *format;
3114 file_iterator_t files;
3115 iterator_t params;
3116
3117 format = g_string_new ("");
3118
3119 g_string_append_printf
3120 (format, "%s%s%s%i", uuid ? uuid : get_iterator_uuid (&formats),
3121 report_format_iterator_extension (&formats),
3122 report_format_iterator_content_type (&formats),
3123 report_format_predefined (report_format) & 1);
3124 g_free (uuid);
3125
3126 init_report_format_file_iterator (&files, report_format);
3127 while (next_file (&files))
3128 {
3129 gchar *content = file_iterator_content_64 (&files);
3130 g_string_append_printf (format,
3131 "%s%s",
3132 file_iterator_name (&files),
3133 content);
3134 g_free (content);
3135 }
3136 cleanup_file_iterator (&files);
3137
3138 init_report_format_param_iterator (¶ms,
3139 report_format,
3140 0,
3141 1,
3142 NULL);
3143 while (next (¶ms))
3144 {
3145 g_string_append_printf
3146 (format,
3147 "%s%s",
3148 report_format_param_iterator_name (¶ms),
3149 report_format_param_iterator_type_name (¶ms));
3150
3151 if (report_format_param_iterator_type_min (¶ms) > LLONG_MIN)
3152 g_string_append_printf
3153 (format,
3154 "%lli",
3155 report_format_param_iterator_type_min (¶ms));
3156
3157 if (report_format_param_iterator_type_max (¶ms) < LLONG_MAX)
3158 g_string_append_printf
3159 (format,
3160 "%lli",
3161 report_format_param_iterator_type_max (¶ms));
3162
3163 g_string_append_printf
3164 (format,
3165 "%s%s",
3166 report_format_param_iterator_type_regex (¶ms),
3167 report_format_param_iterator_fallback (¶ms));
3168
3169 {
3170 iterator_t options;
3171 init_param_option_iterator
3172 (&options,
3173 report_format_param_iterator_param (¶ms),
3174 1,
3175 NULL);
3176 while (next (&options))
3177 if (param_option_iterator_value (&options))
3178 g_string_append_printf
3179 (format,
3180 "%s",
3181 param_option_iterator_value (&options));
3182 }
3183 }
3184 cleanup_iterator (¶ms);
3185
3186 g_string_append_printf (format, "\n");
3187
3188 if (format_signature)
3189 {
3190 /* Try the feed signature. */
3191 if (verify_signature (format->str, format->len, format_signature,
3192 strlen (format_signature), &format_trust))
3193 {
3194 cleanup_iterator (&formats);
3195 g_free (format_signature);
3196 g_string_free (format, TRUE);
3197 return -1;
3198 }
3199 }
3200 else if (signature && strlen (signature))
3201 {
3202 /* Try the signature from the database. */
3203 if (verify_signature (format->str, format->len, signature,
3204 strlen (signature), &format_trust))
3205 {
3206 cleanup_iterator (&formats);
3207 g_free (format_signature);
3208 g_string_free (format, TRUE);
3209 return -1;
3210 }
3211 }
3212
3213 g_free (format_signature);
3214 g_string_free (format, TRUE);
3215 }
3216 }
3217 else
3218 {
3219 return -1;
3220 }
3221 cleanup_iterator (&formats);
3222
3223 sql ("UPDATE report_formats SET trust = %i, trust_time = %i,"
3224 " modification_time = m_now ()"
3225 " WHERE id = %llu;",
3226 format_trust,
3227 time (NULL),
3228 report_format);
3229
3230 return 0;
3231 }
3232
3233 /**
3234 * @brief Verify a report format.
3235 *
3236 * @param[in] report_format_id Report format UUID.
3237 *
3238 * @return 0 success, 1 failed to find report format, 99 permission denied,
3239 * -1 error.
3240 */
3241 int
verify_report_format(const char * report_format_id)3242 verify_report_format (const char *report_format_id)
3243 {
3244 int ret;
3245 report_format_t report_format;
3246
3247 sql_begin_immediate ();
3248
3249 if (acl_user_may ("verify_report_format") == 0)
3250 {
3251 sql_rollback ();
3252 return 99;
3253 }
3254
3255 report_format = 0;
3256 if (find_report_format_with_permission (report_format_id, &report_format,
3257 "verify_report_format"))
3258 {
3259 sql_rollback ();
3260 return -1;
3261 }
3262 if (report_format == 0)
3263 {
3264 sql_rollback ();
3265 return 1;
3266 }
3267
3268 ret = verify_report_format_internal (report_format);
3269 if (ret)
3270 {
3271 sql_rollback ();
3272 return ret;
3273 }
3274 sql_commit ();
3275 return 0;
3276 }
3277
3278 /**
3279 * @brief Runs the script of a report format.
3280 *
3281 * @param[in] report_format_id UUID of the report format.
3282 * @param[in] xml_file Path to main part of the report XML.
3283 * @param[in] xml_dir Path of the dir with XML and subreports.
3284 * @param[in] report_format_extra Extra data for report format.
3285 * @param[in] output_file Path to write report to.
3286 *
3287 * @return 0 success, -1 error.
3288 */
3289 static int
run_report_format_script(gchar * report_format_id,gchar * xml_file,gchar * xml_dir,gchar * report_format_extra,gchar * output_file)3290 run_report_format_script (gchar *report_format_id,
3291 gchar *xml_file,
3292 gchar *xml_dir,
3293 gchar *report_format_extra,
3294 gchar *output_file)
3295 {
3296 iterator_t formats;
3297 report_format_t report_format;
3298 gchar *script, *script_dir, *owner;
3299 get_data_t report_format_get;
3300
3301 gchar *command;
3302 char *previous_dir;
3303 int ret;
3304
3305 /* Setup file names and complete report. */
3306
3307 memset (&report_format_get, '\0', sizeof (report_format_get));
3308 report_format_get.id = report_format_id;
3309
3310 init_report_format_iterator (&formats, &report_format_get);
3311 if (next (&formats) == FALSE)
3312 {
3313 cleanup_iterator (&formats);
3314 return -1;
3315 }
3316
3317 report_format = get_iterator_resource (&formats);
3318
3319 owner = sql_string ("SELECT uuid FROM users"
3320 " WHERE id = (SELECT owner FROM"
3321 " report_formats WHERE id = %llu);",
3322 report_format);
3323 script_dir = g_build_filename (GVMD_STATE_DIR,
3324 "report_formats",
3325 owner,
3326 report_format_id,
3327 NULL);
3328 g_free (owner);
3329
3330 cleanup_iterator (&formats);
3331
3332 script = g_build_filename (script_dir, "generate", NULL);
3333
3334 if (!gvm_file_is_readable (script))
3335 {
3336 g_warning ("%s: No generate script found at %s",
3337 __func__, script);
3338 g_free (script);
3339 g_free (script_dir);
3340 return -1;
3341 }
3342 else if (!gvm_file_is_executable (script))
3343 {
3344 g_warning ("%s: script %s is not executable",
3345 __func__, script);
3346 g_free (script);
3347 g_free (script_dir);
3348 return -1;
3349 }
3350
3351 /* Change into the script directory. */
3352
3353 previous_dir = getcwd (NULL, 0);
3354 if (previous_dir == NULL)
3355 {
3356 g_warning ("%s: Failed to getcwd: %s",
3357 __func__,
3358 strerror (errno));
3359 g_free (previous_dir);
3360 g_free (script);
3361 g_free (script_dir);
3362 return -1;
3363 }
3364
3365 if (chdir (script_dir))
3366 {
3367 g_warning ("%s: Failed to chdir: %s",
3368 __func__,
3369 strerror (errno));
3370 g_free (previous_dir);
3371 g_free (script);
3372 g_free (script_dir);
3373 return -1;
3374 }
3375 g_free (script_dir);
3376
3377 /* Call the script. */
3378
3379 command = g_strdup_printf ("%s %s '%s' > %s"
3380 " 2> /dev/null",
3381 script,
3382 xml_file,
3383 report_format_extra,
3384 output_file);
3385 g_free (script);
3386
3387 g_debug (" command: %s", command);
3388
3389 if (geteuid () == 0)
3390 {
3391 pid_t pid;
3392 struct passwd *nobody;
3393
3394 /* Run the command with lower privileges in a fork. */
3395
3396 nobody = getpwnam ("nobody");
3397 if ((nobody == NULL)
3398 || chown (xml_dir, nobody->pw_uid, nobody->pw_gid)
3399 || chown (xml_file, nobody->pw_uid, nobody->pw_gid)
3400 || chown (output_file, nobody->pw_uid, nobody->pw_gid))
3401 {
3402 g_warning ("%s: Failed to set dir permissions: %s",
3403 __func__,
3404 strerror (errno));
3405 g_free (previous_dir);
3406 return -1;
3407 }
3408
3409 pid = fork ();
3410 switch (pid)
3411 {
3412 case 0:
3413 {
3414 /* Child. Drop privileges, run command, exit. */
3415
3416 proctitle_set ("gvmd: Generating report");
3417
3418 cleanup_manage_process (FALSE);
3419
3420 if (setgroups (0,NULL))
3421 {
3422 g_warning ("%s (child): setgroups: %s",
3423 __func__, strerror (errno));
3424 exit (EXIT_FAILURE);
3425 }
3426 if (setgid (nobody->pw_gid))
3427 {
3428 g_warning ("%s (child): setgid: %s",
3429 __func__,
3430 strerror (errno));
3431 exit (EXIT_FAILURE);
3432 }
3433 if (setuid (nobody->pw_uid))
3434 {
3435 g_warning ("%s (child): setuid: %s",
3436 __func__,
3437 strerror (errno));
3438 exit (EXIT_FAILURE);
3439 }
3440
3441 ret = system (command);
3442 /* Report scripts should return 0 since version 21.04 */
3443 if (ret == -1 || WIFEXITED(ret) == 0 || WEXITSTATUS(ret))
3444 {
3445 g_warning ("%s (child):"
3446 " system failed with ret %i, %i, %s",
3447 __func__,
3448 ret,
3449 WEXITSTATUS (ret),
3450 command);
3451 exit (EXIT_FAILURE);
3452 }
3453
3454 exit (EXIT_SUCCESS);
3455 }
3456
3457 case -1:
3458 /* Parent when error. */
3459
3460 g_warning ("%s: Failed to fork: %s",
3461 __func__,
3462 strerror (errno));
3463 if (chdir (previous_dir))
3464 g_warning ("%s: and chdir failed",
3465 __func__);
3466 g_free (previous_dir);
3467 g_free (command);
3468 return -1;
3469 break;
3470
3471 default:
3472 {
3473 int status;
3474
3475 /* Parent on success. Wait for child, and check result. */
3476
3477
3478 while (waitpid (pid, &status, 0) < 0)
3479 {
3480 if (errno == ECHILD)
3481 {
3482 g_warning ("%s: Failed to get child exit status",
3483 __func__);
3484 if (chdir (previous_dir))
3485 g_warning ("%s: and chdir failed",
3486 __func__);
3487 g_free (previous_dir);
3488 return -1;
3489 }
3490 if (errno == EINTR)
3491 continue;
3492 g_warning ("%s: wait: %s",
3493 __func__,
3494 strerror (errno));
3495 if (chdir (previous_dir))
3496 g_warning ("%s: and chdir failed",
3497 __func__);
3498 g_free (previous_dir);
3499 return -1;
3500 }
3501 if (WIFEXITED (status))
3502 switch (WEXITSTATUS (status))
3503 {
3504 case EXIT_SUCCESS:
3505 break;
3506 case EXIT_FAILURE:
3507 default:
3508 g_warning ("%s: child failed, %s",
3509 __func__,
3510 command);
3511 if (chdir (previous_dir))
3512 g_warning ("%s: and chdir failed",
3513 __func__);
3514 g_free (previous_dir);
3515 g_free (command);
3516 return -1;
3517 }
3518 else
3519 {
3520 g_warning ("%s: child failed, %s",
3521 __func__,
3522 command);
3523 if (chdir (previous_dir))
3524 g_warning ("%s: and chdir failed",
3525 __func__);
3526 g_free (command);
3527 g_free (previous_dir);
3528 return -1;
3529 }
3530 g_free (command);
3531
3532 /* Child succeeded, continue to process result. */
3533
3534 break;
3535 }
3536 }
3537 }
3538 else
3539 {
3540 /* Just run the command as the current user. */
3541
3542 ret = system (command);
3543 /* Report scripts should return 0 since version 21.04 */
3544 if (ret == -1 || WIFEXITED(ret) == 0 || WEXITSTATUS(ret))
3545 {
3546 g_warning ("%s: system failed with ret %i, %i, %s",
3547 __func__,
3548 ret,
3549 WEXITSTATUS (ret),
3550 command);
3551 if (chdir (previous_dir))
3552 g_warning ("%s: and chdir failed",
3553 __func__);
3554 g_free (previous_dir);
3555 g_free (command);
3556 return -1;
3557 }
3558
3559 g_free (command);
3560 }
3561
3562 /* Change back to the previous directory. */
3563
3564 if (chdir (previous_dir))
3565 {
3566 g_warning ("%s: Failed to chdir back: %s",
3567 __func__,
3568 strerror (errno));
3569 g_free (previous_dir);
3570 return -1;
3571 }
3572 g_free (previous_dir);
3573
3574 return 0;
3575 }
3576
3577 /**
3578 * @brief Completes a report by adding report format info.
3579 *
3580 * @param[in] xml_start Path of file containing start of report.
3581 * @param[in] xml_full Path to file to print full report to.
3582 * @param[in] report_format Format of report that will be created from XML.
3583 *
3584 * @return 0 success, -1 error.
3585 */
3586 int
print_report_xml_end(gchar * xml_start,gchar * xml_full,report_format_t report_format)3587 print_report_xml_end (gchar *xml_start, gchar *xml_full,
3588 report_format_t report_format)
3589 {
3590 FILE *out;
3591
3592 if (gvm_file_copy (xml_start, xml_full) == FALSE)
3593 {
3594 g_warning ("%s: failed to copy xml_start file", __func__);
3595 return -1;
3596 }
3597
3598 out = fopen (xml_full, "a");
3599 if (out == NULL)
3600 {
3601 g_warning ("%s: fopen failed: %s",
3602 __func__,
3603 strerror (errno));
3604 return -1;
3605 }
3606
3607 /* A bit messy having report XML here, but simplest for now. */
3608
3609 if (report_format > 0)
3610 {
3611 iterator_t params;
3612 PRINT (out, "<report_format>");
3613 init_report_format_param_iterator (¶ms, report_format, 0, 1, NULL);
3614 while (next (¶ms))
3615 PRINT (out,
3616 "<param><name>%s</name><value>%s</value></param>",
3617 report_format_param_iterator_name (¶ms),
3618 report_format_param_iterator_value (¶ms));
3619 cleanup_iterator (¶ms);
3620
3621 PRINT (out, "</report_format>");
3622 }
3623
3624 PRINT (out, "</report>");
3625
3626 if (fclose (out))
3627 {
3628 g_warning ("%s: fclose failed: %s",
3629 __func__,
3630 strerror (errno));
3631 return -1;
3632 }
3633
3634 return 0;
3635 }
3636
3637 /**
3638 * @brief Applies a report format to an XML report.
3639 *
3640 * @param[in] report_format_id Report format to apply.
3641 * @param[in] xml_start Path to the main part of the report XML.
3642 * @param[in] xml_file Path to the report XML file.
3643 * @param[in] xml_dir Path to the temporary dir.
3644 * @param[in] used_rfps List of already applied report formats.
3645 *
3646 * @return Path to the generated file or NULL.
3647 */
3648 gchar*
apply_report_format(gchar * report_format_id,gchar * xml_start,gchar * xml_file,gchar * xml_dir,GList ** used_rfps)3649 apply_report_format (gchar *report_format_id,
3650 gchar *xml_start,
3651 gchar *xml_file,
3652 gchar *xml_dir,
3653 GList **used_rfps)
3654 {
3655 report_format_t report_format;
3656 GHashTable *subreports;
3657 GList *temp_dirs, *temp_files;
3658 gchar *rf_dependencies_string, *output_file, *out_file_part, *out_file_ext;
3659 gchar *files_xml;
3660 int output_fd;
3661
3662 assert (report_format_id);
3663 assert (xml_start);
3664 assert (xml_file);
3665 assert (xml_dir);
3666 assert (used_rfps);
3667
3668 /* Check if there would be an infinite recursion loop. */
3669 if (*used_rfps
3670 && g_list_find_custom (*used_rfps, report_format_id,
3671 (GCompareFunc) strcmp))
3672 {
3673 g_message ("%s: Recursion loop for report_format '%s'",
3674 __func__, report_format_id);
3675 return NULL;
3676 }
3677
3678 /* Check if report format is available. */
3679 if (find_report_format_with_permission (report_format_id, &report_format,
3680 "get_report_formats")
3681 || report_format == 0)
3682 {
3683 g_message ("%s: Report format '%s' not found",
3684 __func__, report_format_id);
3685 return NULL;
3686 }
3687
3688 /* Check if report format is active */
3689 if (report_format_active (report_format) == 0)
3690 {
3691 g_message ("%s: Report format '%s' is not active",
3692 __func__, report_format_id);
3693 return NULL;
3694 }
3695
3696 /* Get subreports. */
3697 temp_dirs = NULL;
3698 temp_files = NULL;
3699 subreports = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
3700
3701 rf_dependencies_string
3702 = sql_string ("SELECT value"
3703 " FROM report_format_params"
3704 " WHERE report_format = %llu"
3705 " AND type = %i",
3706 report_format,
3707 REPORT_FORMAT_PARAM_TYPE_REPORT_FORMAT_LIST);
3708
3709 if (rf_dependencies_string)
3710 {
3711 gchar **rf_dependencies, **current_rf_dependency;
3712 GString *files_xml_buf;
3713 GHashTableIter files_iter;
3714 gchar *key, *value;
3715
3716 *used_rfps = g_list_append (*used_rfps, report_format_id);
3717
3718 /* Recursively create subreports for dependencies. */
3719 rf_dependencies = g_strsplit (rf_dependencies_string, ",", -1);
3720 current_rf_dependency = rf_dependencies;
3721
3722 while (*current_rf_dependency)
3723 {
3724 gchar *subreport_dir, *subreport_xml, *subreport_file;
3725 subreport_file = NULL;
3726
3727 subreport_dir = g_strdup ("/tmp/gvmd_XXXXXX");
3728
3729 if (mkdtemp (subreport_dir) == NULL)
3730 {
3731 g_warning ("%s: mkdtemp failed", __func__);
3732 g_free (subreport_dir);
3733 break;
3734 }
3735 subreport_xml = g_build_filename (subreport_dir, "report.xml", NULL);
3736 temp_dirs = g_list_append (temp_dirs, subreport_dir);
3737 temp_files = g_list_append (temp_files, subreport_xml);
3738
3739 if (g_hash_table_contains (subreports, *current_rf_dependency)
3740 == FALSE)
3741 {
3742 subreport_file = apply_report_format (*current_rf_dependency,
3743 xml_start,
3744 subreport_xml,
3745 subreport_dir,
3746 used_rfps);
3747 if (subreport_file)
3748 {
3749 g_hash_table_insert (subreports,
3750 g_strdup (*current_rf_dependency),
3751 subreport_file);
3752 }
3753 }
3754
3755 current_rf_dependency ++;
3756 }
3757
3758 g_strfreev (rf_dependencies);
3759
3760 *used_rfps = g_list_remove (*used_rfps, report_format_id);
3761
3762 /* Build dependencies XML. */
3763 files_xml_buf = g_string_new ("<files>");
3764 xml_string_append (files_xml_buf,
3765 "<basedir>%s</basedir>",
3766 xml_dir);
3767
3768 g_hash_table_iter_init (&files_iter, subreports);
3769 while (g_hash_table_iter_next (&files_iter,
3770 (void**)&key, (void**)&value))
3771 {
3772 get_data_t report_format_get;
3773 iterator_t file_format_iter;
3774
3775 memset (&report_format_get, '\0', sizeof (report_format_get));
3776 report_format_get.id = key;
3777
3778 init_report_format_iterator (&file_format_iter, &report_format_get);
3779 if (next (&file_format_iter))
3780 {
3781 xml_string_append (files_xml_buf,
3782 "<file id=\"%s\""
3783 " content_type=\"%s\""
3784 " report_format_name=\"%s\">"
3785 "%s"
3786 "</file>",
3787 key,
3788 report_format_iterator_content_type
3789 (&file_format_iter),
3790 get_iterator_name (&file_format_iter),
3791 value);
3792 }
3793 else
3794 {
3795 xml_string_append (files_xml_buf,
3796 "<file id=\"%s\">%s</file>",
3797 key, value);
3798 }
3799 cleanup_iterator (&file_format_iter);
3800 }
3801
3802 g_string_append (files_xml_buf, "</files>");
3803 files_xml = g_string_free (files_xml_buf, FALSE);
3804 }
3805 else
3806 {
3807 GString *files_xml_buf;
3808 /* Build dependencies XML. */
3809 files_xml_buf = g_string_new ("<files>");
3810 xml_string_append (files_xml_buf,
3811 "<basedir>%s</basedir>",
3812 xml_dir);
3813 g_string_append (files_xml_buf, "</files>");
3814 files_xml = g_string_free (files_xml_buf, FALSE);
3815 }
3816
3817 /* Generate output file. */
3818 out_file_ext = report_format_extension (report_format);
3819 out_file_part = g_strdup_printf ("%s-XXXXXX.%s",
3820 report_format_id, out_file_ext);
3821 output_file = g_build_filename (xml_dir, out_file_part, NULL);
3822 output_fd = mkstemps (output_file, strlen (out_file_ext) + 1);
3823 if (output_fd == -1)
3824 {
3825 g_warning ("%s: mkstemps failed: %s", __func__, strerror (errno));
3826 g_free (output_file);
3827 output_file = NULL;
3828 goto cleanup;
3829 }
3830 g_free (out_file_ext);
3831 g_free (out_file_part);
3832
3833 /* Add second half of input XML */
3834
3835 if (print_report_xml_end (xml_start, xml_file, report_format))
3836 {
3837 g_free (output_file);
3838 output_file = NULL;
3839 goto cleanup;
3840 }
3841
3842 run_report_format_script (report_format_id,
3843 xml_file, xml_dir, files_xml, output_file);
3844
3845 /* Clean up and return filename. */
3846 cleanup:
3847 while (temp_dirs)
3848 {
3849 gvm_file_remove_recurse (temp_dirs->data);
3850 gpointer data = temp_dirs->data;
3851 temp_dirs = g_list_remove (temp_dirs, data);
3852 g_free (data);
3853 }
3854 while (temp_files)
3855 {
3856 gpointer data = temp_files->data;
3857 temp_files = g_list_remove (temp_files, data);
3858 g_free (data);
3859 }
3860 g_free (files_xml);
3861 g_hash_table_destroy (subreports);
3862 if (close (output_fd))
3863 {
3864 g_warning ("%s: close of output_fd failed: %s",
3865 __func__, strerror (errno));
3866 g_free (output_file);
3867 return NULL;
3868 }
3869
3870 return output_file;
3871 }
3872
3873 /**
3874 * @brief Empty trashcan.
3875 *
3876 * @return 0 success, -1 error.
3877 */
3878 int
empty_trashcan_report_formats()3879 empty_trashcan_report_formats ()
3880 {
3881 GArray *report_formats;
3882 int index, length;
3883 iterator_t rows;
3884
3885 sql ("DELETE FROM report_format_param_options_trash"
3886 " WHERE report_format_param"
3887 " IN (SELECT id from report_format_params_trash"
3888 " WHERE report_format"
3889 " IN (SELECT id FROM report_formats_trash"
3890 " WHERE owner = (SELECT id FROM users"
3891 " WHERE uuid = '%s')));",
3892 current_credentials.uuid);
3893 sql ("DELETE FROM report_format_params_trash"
3894 " WHERE report_format IN (SELECT id from report_formats_trash"
3895 " WHERE owner = (SELECT id FROM users"
3896 " WHERE uuid = '%s'));",
3897 current_credentials.uuid);
3898
3899 init_iterator (&rows,
3900 "SELECT id FROM report_formats_trash"
3901 " WHERE owner = (SELECT id FROM users WHERE uuid = '%s');",
3902 current_credentials.uuid);
3903 report_formats = g_array_new (FALSE, FALSE, sizeof (report_format_t));
3904 length = 0;
3905 while (next (&rows))
3906 {
3907 report_format_t id;
3908 id = iterator_int64 (&rows, 0);
3909 g_array_append_val (report_formats, id);
3910 length++;
3911 }
3912 cleanup_iterator (&rows);
3913
3914 sql ("DELETE FROM report_formats_trash"
3915 " WHERE owner = (SELECT id FROM users WHERE uuid = '%s');",
3916 current_credentials.uuid);
3917
3918 /* Remove the report formats dirs last, in case any SQL rolls back. */
3919
3920 for (index = 0; index < length; index++)
3921 {
3922 gchar *dir, *name;
3923
3924 name = g_strdup_printf ("%llu",
3925 g_array_index (report_formats,
3926 report_format_t,
3927 index));
3928 dir = report_format_trash_dir (name);
3929 g_free (name);
3930
3931 if (gvm_file_exists (dir) && gvm_file_remove_recurse (dir))
3932 {
3933 g_warning ("%s: failed to remove trash dir %s", __func__, dir);
3934 g_free (dir);
3935 return -1;
3936 }
3937
3938 g_free (dir);
3939 }
3940
3941 g_array_free (report_formats, TRUE);
3942 return 0;
3943 }
3944
3945 /**
3946 * @brief Change ownership of report formats, for user deletion.
3947 *
3948 * @param[in] report_format_id UUID of report format.
3949 * @param[in] user_id UUID of current owner.
3950 * @param[in] inheritor New owner.
3951 */
3952 void
inherit_report_format_dir(const gchar * report_format_id,const gchar * user_id,user_t inheritor)3953 inherit_report_format_dir (const gchar *report_format_id, const gchar *user_id,
3954 user_t inheritor)
3955 {
3956 gchar *inheritor_id, *old_dir, *new_dir;
3957
3958 g_debug ("%s: %s from %s to %llu", __func__, report_format_id, user_id,
3959 inheritor);
3960
3961 inheritor_id = user_uuid (inheritor);
3962 if (inheritor_id == NULL)
3963 {
3964 g_warning ("%s: inheritor_id NULL, skipping report format dir", __func__);
3965 return;
3966 }
3967
3968 old_dir = g_build_filename (GVMD_STATE_DIR,
3969 "report_formats",
3970 user_id,
3971 report_format_id,
3972 NULL);
3973
3974 new_dir = g_build_filename (GVMD_STATE_DIR,
3975 "report_formats",
3976 inheritor_id,
3977 report_format_id,
3978 NULL);
3979
3980 g_free (inheritor_id);
3981
3982 if (move_report_format_dir (old_dir, new_dir))
3983 g_warning ("%s: failed to move %s dir, but will try the rest",
3984 __func__,
3985 report_format_id);
3986
3987 g_free (old_dir);
3988 g_free (new_dir);
3989 }
3990
3991 /**
3992 * @brief Change ownership of report formats, for user deletion.
3993 *
3994 * @param[in] user Current owner.
3995 * @param[in] inheritor New owner.
3996 * @param[in] rows Iterator for inherited report formats, with next
3997 * already called.
3998 *
3999 * @return TRUE if there is a row available, else FALSE.
4000 */
4001 gboolean
inherit_report_formats(user_t user,user_t inheritor,iterator_t * rows)4002 inherit_report_formats (user_t user, user_t inheritor, iterator_t *rows)
4003 {
4004 sql ("UPDATE report_formats_trash SET owner = %llu WHERE owner = %llu;",
4005 inheritor, user);
4006
4007 init_iterator (rows,
4008 "UPDATE report_formats SET owner = %llu"
4009 " WHERE owner = %llu"
4010 " RETURNING uuid;",
4011 inheritor, user);
4012
4013 /* This executes the SQL. */
4014 return next (rows);
4015 }
4016
4017 /**
4018 * @brief Delete all report formats owned by a user.
4019 *
4020 * @param[in] user The user.
4021 * @param[in] rows Trash report format ids.
4022 *
4023 * @return TRUE if there are rows in rows, else FALSE.
4024 */
4025 gboolean
delete_report_formats_user(user_t user,iterator_t * rows)4026 delete_report_formats_user (user_t user, iterator_t *rows)
4027 {
4028 /* Remove report formats from db. */
4029
4030 sql ("DELETE FROM report_format_param_options"
4031 " WHERE report_format_param"
4032 " IN (SELECT id FROM report_format_params"
4033 " WHERE report_format IN (SELECT id"
4034 " FROM report_formats"
4035 " WHERE owner = %llu));",
4036 user);
4037 sql ("DELETE FROM report_format_param_options_trash"
4038 " WHERE report_format_param"
4039 " IN (SELECT id FROM report_format_params_trash"
4040 " WHERE report_format IN (SELECT id"
4041 " FROM report_formats_trash"
4042 " WHERE owner = %llu));",
4043 user);
4044 sql ("DELETE FROM report_format_params"
4045 " WHERE report_format IN (SELECT id FROM report_formats"
4046 " WHERE owner = %llu);",
4047 user);
4048 sql ("DELETE FROM report_format_params_trash"
4049 " WHERE report_format IN (SELECT id"
4050 " FROM report_formats_trash"
4051 " WHERE owner = %llu);",
4052 user);
4053 sql ("DELETE FROM report_formats WHERE owner = %llu;", user);
4054 init_iterator (rows,
4055 "DELETE FROM report_formats_trash WHERE owner = %llu"
4056 " RETURNING id;",
4057 user);
4058
4059 /* This executes the SQL. */
4060 return next (rows);
4061 }
4062
4063 /**
4064 * @brief Delete all report formats owned by a user.
4065 *
4066 * @param[in] user_id UUID of user.
4067 * @param[in] rows Trash report format ids if any, else NULL. Cleaned up
4068 * before returning.
4069 */
4070 void
delete_report_format_dirs_user(const gchar * user_id,iterator_t * rows)4071 delete_report_format_dirs_user (const gchar *user_id, iterator_t *rows)
4072 {
4073 gchar *dir;
4074
4075 /* Remove trash report formats from trash directory. */
4076
4077 if (rows)
4078 {
4079 do
4080 {
4081 gchar *id;
4082
4083 id = g_strdup_printf ("%llu", iterator_int64 (rows, 0));
4084 dir = report_format_trash_dir (id);
4085 g_free (id);
4086 if (gvm_file_remove_recurse (dir))
4087 g_warning ("%s: failed to remove dir %s, continuing anyway",
4088 __func__, dir);
4089 g_free (dir);
4090 } while (next (rows));
4091 cleanup_iterator (rows);
4092 }
4093
4094 /* Remove user's regular report formats directory. */
4095
4096 dir = g_build_filename (GVMD_STATE_DIR,
4097 "report_formats",
4098 user_id,
4099 NULL);
4100
4101 if (gvm_file_exists (dir) && gvm_file_remove_recurse (dir))
4102 g_warning ("%s: failed to remove dir %s, continuing anyway",
4103 __func__, dir);
4104 g_free (dir);
4105 }
4106
4107
4108 /* Feed report formats. */
4109
4110 /**
4111 * @brief Update a report format from an XML file.
4112 *
4113 * @param[in] report_format Existing report format.
4114 * @param[in] report_id UUID of report format.
4115 * @param[in] name New name.
4116 * @param[in] content_type New content type.
4117 * @param[in] extension New extension.
4118 * @param[in] summary New summary.
4119 * @param[in] description New description.
4120 * @param[in] signature New signature.
4121 * @param[in] files New files.
4122 * @param[in] params New params.
4123 * @param[in] params_options Options for new params.
4124 */
4125 void
update_report_format(report_format_t report_format,const gchar * report_id,const gchar * name,const gchar * content_type,const gchar * extension,const gchar * summary,const gchar * description,const gchar * signature,array_t * files,array_t * params,array_t * params_options)4126 update_report_format (report_format_t report_format, const gchar *report_id, const gchar *name,
4127 const gchar *content_type, const gchar *extension,
4128 const gchar *summary, const gchar *description,
4129 const gchar *signature, array_t *files, array_t *params,
4130 array_t *params_options)
4131 {
4132 int ret;
4133 gchar *quoted_name, *quoted_content_type, *quoted_extension, *quoted_summary;
4134 gchar *quoted_description, *quoted_signature;
4135
4136 sql_begin_immediate ();
4137
4138 quoted_name = sql_quote (name ? name : "");
4139 quoted_content_type = sql_quote (content_type ? content_type : "");
4140 quoted_extension = sql_quote (extension ? extension : "");
4141 quoted_summary = sql_quote (summary ? summary : "");
4142 quoted_description = sql_quote (description ? description : "");
4143 quoted_signature = sql_quote (signature ? signature : "");
4144 sql ("UPDATE report_formats"
4145 " SET name = '%s', content_type = '%s', extension = '%s',"
4146 " summary = '%s', description = '%s', signature = '%s',"
4147 " predefined = 1, modification_time = m_now ()"
4148 " WHERE id = %llu;",
4149 quoted_name,
4150 quoted_content_type,
4151 quoted_extension,
4152 quoted_summary,
4153 quoted_description,
4154 quoted_signature,
4155 report_format);
4156 g_free (quoted_name);
4157 g_free (quoted_content_type);
4158 g_free (quoted_extension);
4159 g_free (quoted_summary);
4160 g_free (quoted_description);
4161 g_free (quoted_signature);
4162
4163 /* Replace the params. */
4164
4165 sql ("DELETE FROM report_format_param_options"
4166 " WHERE report_format_param IN (SELECT id FROM report_format_params"
4167 " WHERE report_format = %llu);",
4168 report_format);
4169 sql ("DELETE FROM report_format_params WHERE report_format = %llu;",
4170 report_format);
4171
4172 ret = add_report_format_params (report_format, params, params_options);
4173 if (ret)
4174 {
4175 if (ret == 3)
4176 g_warning ("%s: Parameter value validation failed", __func__);
4177 else if (ret == 4)
4178 g_warning ("%s: Parameter default validation failed", __func__);
4179 else if (ret == 5)
4180 g_warning ("%s: PARAM requires a DEFAULT element", __func__);
4181 else if (ret == 6)
4182 g_warning ("%s: PARAM MIN or MAX out of range", __func__);
4183 else if (ret == 7)
4184 g_warning ("%s: PARAM requires a TYPE element", __func__);
4185 else if (ret == 8)
4186 g_warning ("%s: Duplicate PARAM name", __func__);
4187 else if (ret == 9)
4188 g_warning ("%s: Bogus PARAM type", __func__);
4189 else if (ret)
4190 g_warning ("%s: Internal error", __func__);
4191
4192 sql_rollback ();
4193 return;
4194 }
4195
4196 /* Replace the files. */
4197
4198 save_report_format_files (report_id, files, NULL);
4199
4200 sql_commit ();
4201 }
4202
4203 /**
4204 * @brief Check if a report format has been updated in the feed.
4205 *
4206 * @param[in] path Full path to report format XML in feed.
4207 * @param[in] report_format Report Format.
4208 *
4209 * @return 1 if updated in feed, else 0.
4210 */
4211 int
report_format_updated_in_feed(report_format_t report_format,const gchar * path)4212 report_format_updated_in_feed (report_format_t report_format, const gchar *path)
4213 {
4214 GStatBuf state;
4215 int last_update;
4216
4217 last_update = sql_int ("SELECT modification_time FROM report_formats"
4218 " WHERE id = %llu;",
4219 report_format);
4220
4221 if (g_stat (path, &state))
4222 {
4223 g_warning ("%s: Failed to stat feed report_format file: %s",
4224 __func__,
4225 strerror (errno));
4226 return 0;
4227 }
4228
4229 if (state.st_mtime <= last_update)
4230 return 0;
4231
4232 return 1;
4233 }
4234
4235 /**
4236 * @brief Migrate old ownerless report formats to the Feed Owner.
4237 *
4238 * @return 0 success, -1 error.
4239 */
4240 int
migrate_predefined_report_formats()4241 migrate_predefined_report_formats ()
4242 {
4243 iterator_t rows;
4244 gchar *owner_uuid, *quoted_owner_uuid;
4245
4246 setting_value (SETTING_UUID_FEED_IMPORT_OWNER, &owner_uuid);
4247
4248 if (owner_uuid == NULL)
4249 return 0;
4250
4251 if (strlen (owner_uuid) == 0)
4252 {
4253 g_free (owner_uuid);
4254 return 0;
4255 }
4256
4257 quoted_owner_uuid = sql_quote (owner_uuid);
4258 init_iterator (&rows,
4259 "UPDATE report_formats"
4260 " SET owner = (SELECT id FROM users"
4261 " WHERE uuid = '%s')"
4262 " WHERE owner is NULL"
4263 " RETURNING uuid;",
4264 quoted_owner_uuid);
4265 g_free (quoted_owner_uuid);
4266
4267 /* Move report format files to the Feed Owner's report format dir. */
4268
4269 while (next (&rows))
4270 {
4271 gchar *old, *new;
4272
4273 if (iterator_string (&rows, 0) == NULL)
4274 continue;
4275
4276 old = g_build_filename (GVMD_DATA_DIR,
4277 "report_formats",
4278 iterator_string (&rows, 0),
4279 NULL);
4280
4281 new = g_build_filename (GVMD_STATE_DIR,
4282 "report_formats",
4283 owner_uuid,
4284 NULL);
4285
4286 if (copy_report_format_dir (old, new, iterator_string (&rows, 0)))
4287 {
4288 g_warning ("%s: failed at report format %s", __func__,
4289 iterator_string (&rows, 0));
4290 g_free (old);
4291 g_free (new);
4292 cleanup_iterator (&rows);
4293 g_free (owner_uuid);
4294 return -1;
4295 }
4296
4297 g_free (old);
4298 g_free (new);
4299 }
4300 cleanup_iterator (&rows);
4301 g_free (owner_uuid);
4302 return 0;
4303 }
4304
4305
4306 /* Startup. */
4307
4308 /**
4309 * @brief Ensure every report format has a unique UUID.
4310 *
4311 * @return 0 success, -1 error.
4312 */
4313 static int
make_report_format_uuids_unique()4314 make_report_format_uuids_unique ()
4315 {
4316 iterator_t rows;
4317
4318 sql ("CREATE TEMPORARY TABLE duplicates"
4319 " AS SELECT id, uuid, make_uuid () AS new_uuid, owner,"
4320 " (SELECT uuid FROM users"
4321 " WHERE users.id = outer_report_formats.owner)"
4322 " AS owner_uuid,"
4323 " (SELECT owner from report_formats"
4324 " WHERE uuid = outer_report_formats.uuid"
4325 " ORDER BY id ASC LIMIT 1)"
4326 " AS original_owner,"
4327 " (SELECT uuid FROM users"
4328 " WHERE users.id = (SELECT owner from report_formats"
4329 " WHERE uuid = outer_report_formats.uuid"
4330 " ORDER BY id ASC LIMIT 1))"
4331 " AS original_owner_uuid"
4332 " FROM report_formats AS outer_report_formats"
4333 " WHERE id > (SELECT id from report_formats"
4334 " WHERE uuid = outer_report_formats.uuid"
4335 " ORDER BY id ASC LIMIT 1);");
4336
4337 sql ("UPDATE alert_method_data"
4338 " SET data = (SELECT new_uuid FROM duplicates"
4339 " WHERE duplicates.id = alert_method_data.alert)"
4340 " WHERE alert IN (SELECT id FROM duplicates);");
4341
4342 /* Update UUIDs on disk. */
4343 init_iterator (&rows,
4344 "SELECT id, uuid, new_uuid, owner, owner_uuid, original_owner,"
4345 " original_owner_uuid"
4346 " FROM duplicates;");
4347 while (next (&rows))
4348 {
4349 gchar *dir, *new_dir;
4350 const char *old_uuid, *new_uuid;
4351 int copy;
4352
4353 old_uuid = iterator_string (&rows, 1);
4354 new_uuid = iterator_string (&rows, 2);
4355
4356 if (iterator_int64 (&rows, 3) == 0)
4357 {
4358 /* Old-style "global" report format. I don't think this is possible
4359 * with any released version, so ignore. */
4360 continue;
4361 }
4362 else if (iterator_int64 (&rows, 5) == 0)
4363 {
4364 const char *owner_uuid;
4365 /* Dedicated subdir in user dir, but must be renamed. */
4366 copy = 0;
4367 owner_uuid = iterator_string (&rows, 4);
4368 dir = g_build_filename (GVMD_STATE_DIR,
4369 "report_formats",
4370 owner_uuid,
4371 old_uuid,
4372 NULL);
4373 new_dir = g_build_filename (GVMD_STATE_DIR,
4374 "report_formats",
4375 owner_uuid,
4376 new_uuid,
4377 NULL);
4378 }
4379 else
4380 {
4381 const char *owner_uuid, *original_owner_uuid;
4382
4383 /* Two user-owned report formats, may be the same user. */
4384
4385 owner_uuid = iterator_string (&rows, 4);
4386 original_owner_uuid = iterator_string (&rows, 6);
4387
4388 /* Copy the subdir if both report formats owned by one user. */
4389 copy = owner_uuid
4390 && original_owner_uuid
4391 && (strcmp (owner_uuid, original_owner_uuid) == 0);
4392
4393 dir = g_build_filename (GVMD_STATE_DIR,
4394 "report_formats",
4395 owner_uuid,
4396 old_uuid,
4397 NULL);
4398 new_dir = g_build_filename (GVMD_STATE_DIR,
4399 "report_formats",
4400 owner_uuid,
4401 new_uuid,
4402 NULL);
4403 }
4404
4405 if (copy)
4406 {
4407 gchar *command;
4408 int ret;
4409
4410 command = g_strdup_printf ("cp -a %s %s > /dev/null 2>&1",
4411 dir,
4412 new_dir);
4413 g_debug (" command: %s", command);
4414 ret = system (command);
4415 g_free (command);
4416
4417 if (ret == -1 || WEXITSTATUS (ret))
4418 {
4419 /* Presume dir missing, just log a warning. */
4420 g_warning ("%s: cp %s to %s failed",
4421 __func__, dir, new_dir);
4422 }
4423 else
4424 g_debug ("%s: copied %s to %s", __func__, dir, new_dir);
4425 }
4426 else
4427 {
4428 if (rename (dir, new_dir))
4429 {
4430 g_warning ("%s: rename %s to %s: %s",
4431 __func__, dir, new_dir, strerror (errno));
4432 if (errno != ENOENT)
4433 {
4434 g_free (dir);
4435 g_free (new_dir);
4436 sql_rollback ();
4437 return -1;
4438 }
4439 }
4440 else
4441 g_debug ("%s: moved %s to %s", __func__, dir, new_dir);
4442 }
4443 g_free (dir);
4444 g_free (new_dir);
4445 }
4446 cleanup_iterator (&rows);
4447
4448 sql ("UPDATE report_formats"
4449 " SET uuid = (SELECT new_uuid FROM duplicates"
4450 " WHERE duplicates.id = report_formats.id)"
4451 " WHERE id IN (SELECT id FROM duplicates);");
4452
4453 if (sql_changes () > 0)
4454 g_debug ("%s: gave %d report format(s) new UUID(s) to keep UUIDs unique.",
4455 __func__, sql_changes ());
4456
4457 sql ("DROP TABLE duplicates;");
4458
4459 return 0;
4460 }
4461
4462 /**
4463 * @brief Check that trash report formats are correct.
4464 *
4465 * @return 0 success, -1 error.
4466 */
4467 static int
check_db_trash_report_formats()4468 check_db_trash_report_formats ()
4469 {
4470 gchar *dir;
4471 struct stat state;
4472
4473 dir = g_build_filename (GVMD_STATE_DIR,
4474 "report_formats_trash",
4475 NULL);
4476
4477 if (g_lstat (dir, &state))
4478 {
4479 iterator_t report_formats;
4480 int count;
4481
4482 if (errno != ENOENT)
4483 {
4484 g_warning ("%s: g_lstat (%s) failed: %s",
4485 __func__, dir, g_strerror (errno));
4486 g_free (dir);
4487 return -1;
4488 }
4489
4490 /* Remove all trash report formats. */
4491
4492 count = 0;
4493 init_iterator (&report_formats, "SELECT id FROM report_formats_trash;");
4494 while (next (&report_formats))
4495 {
4496 report_format_t report_format;
4497
4498 report_format = iterator_int64 (&report_formats, 0);
4499
4500 sql ("DELETE FROM alert_method_data_trash"
4501 " WHERE data = (SELECT original_uuid"
4502 " FROM report_formats_trash"
4503 " WHERE id = %llu)"
4504 " AND (name = 'notice_attach_format'"
4505 " OR name = 'notice_report_format');",
4506 report_format);
4507
4508 permissions_set_orphans ("report_format", report_format,
4509 LOCATION_TRASH);
4510 tags_remove_resource ("report_format", report_format, LOCATION_TRASH);
4511
4512 sql ("DELETE FROM report_format_param_options_trash"
4513 " WHERE report_format_param"
4514 " IN (SELECT id from report_format_params_trash"
4515 " WHERE report_format = %llu);",
4516 report_format);
4517 sql ("DELETE FROM report_format_params_trash"
4518 " WHERE report_format = %llu;",
4519 report_format);
4520 sql ("DELETE FROM report_formats_trash WHERE id = %llu;",
4521 report_format);
4522
4523 count++;
4524 }
4525 cleanup_iterator (&report_formats);
4526
4527 if (count)
4528 g_message ("Trash report format directory was missing."
4529 " Removed all %i trash report formats.",
4530 count);
4531 }
4532
4533 g_free (dir);
4534 return 0;
4535 }
4536
4537 /**
4538 * @brief Ensure the predefined report formats exist.
4539 *
4540 * @return 0 success, -1 error.
4541 */
4542 int
check_db_report_formats()4543 check_db_report_formats ()
4544 {
4545 if (migrate_predefined_report_formats ())
4546 return -1;
4547
4548 if (sync_report_formats_with_feed (FALSE) <= -1)
4549 g_warning ("%s: Failed to sync report formats with feed", __func__);
4550
4551 if (check_db_trash_report_formats ())
4552 return -1;
4553
4554 if (make_report_format_uuids_unique ())
4555 return -1;
4556
4557 /* Warn about feed resources in the trash. */
4558 if (sql_int ("SELECT EXISTS (SELECT * FROM report_formats_trash"
4559 " WHERE predefined = 1);"))
4560 {
4561 g_warning ("%s: There are feed report formats in the trash."
4562 " These will be excluded from the sync.",
4563 __func__);
4564 }
4565
4566 return 0;
4567 }
4568
4569 /**
4570 * @brief Ensure that the report formats trash directory matches the database.
4571 *
4572 * @return -1 if error, 0 if success.
4573 */
4574 int
check_db_report_formats_trash()4575 check_db_report_formats_trash ()
4576 {
4577 gchar *dir;
4578 GError *error;
4579 GDir *directory;
4580 const gchar *entry;
4581
4582 dir = report_format_trash_dir (NULL);
4583 error = NULL;
4584 directory = g_dir_open (dir, 0, &error);
4585
4586 if (directory == NULL)
4587 {
4588 assert (error);
4589 if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
4590 {
4591 g_warning ("g_dir_open (%s) failed - %s", dir, error->message);
4592 g_error_free (error);
4593 g_free (dir);
4594 return -1;
4595 }
4596 }
4597 else
4598 {
4599 entry = NULL;
4600 while ((entry = g_dir_read_name (directory)) != NULL)
4601 {
4602 gchar *end;
4603 if (strtol (entry, &end, 10) < 0)
4604 /* Only interested in positive numbers. */
4605 continue;
4606 if (*end != '\0')
4607 /* Only interested in numbers. */
4608 continue;
4609
4610 /* Check whether the db has a report format with this ID. */
4611 if (sql_int ("SELECT count(*) FROM report_formats_trash"
4612 " WHERE id = %s;",
4613 entry)
4614 == 0)
4615 {
4616 int ret;
4617 gchar *entry_path;
4618
4619 /* Remove the directory. */
4620
4621 entry_path = g_build_filename (dir, entry, NULL);
4622 ret = gvm_file_remove_recurse (entry_path);
4623 g_free (entry_path);
4624 if (ret)
4625 {
4626 g_warning ("%s: failed to remove %s from %s",
4627 __func__, entry, dir);
4628 g_dir_close (directory);
4629 g_free (dir);
4630 return -1;
4631 }
4632 }
4633 }
4634 g_dir_close (directory);
4635 }
4636 g_free (dir);
4637 return 0;
4638 }
4639