1 /* Copyright (C) 2009-2021 Greenbone Networks GmbH
2  *
3  * SPDX-License-Identifier: AGPL-3.0-or-later
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as
7  * published by the Free Software Foundation, either version 3 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /**
20  * @file  manage.c
21  * @brief The Greenbone Vulnerability Manager management layer.
22  *
23  * This file defines a management layer, for implementing
24  * Managers such as the Greenbone Vulnerability Manager daemon.
25  *
26  * This layer provides facilities for storing and manipulating user
27  * data (credentials, targets, tasks, reports, schedules, roles, etc)
28  * and general security data (NVTs, CVEs, etc).
29  * Task manipulation includes controlling external facilities such as
30  * OSP scanners.
31  *
32  * Simply put, the daemon's GMP implementation uses this layer to do the work.
33  */
34 
35 /**
36  * @brief Enable extra functions.
37  *
38  * time.h in glibc2 needs this for strptime.
39  */
40 #define _XOPEN_SOURCE
41 
42 /**
43  * @brief Enable extra GNU functions.
44  *
45  * pthread_sigmask () needs this with glibc < 2.19
46  */
47 #define _GNU_SOURCE
48 
49 #include "gmp_base.h"
50 #include "manage.h"
51 #include "manage_acl.h"
52 #include "manage_configs.h"
53 #include "manage_port_lists.h"
54 #include "manage_report_formats.h"
55 #include "manage_sql.h"
56 #include "manage_sql_secinfo.h"
57 #include "manage_sql_nvts.h"
58 #include "manage_sql_tickets.h"
59 #include "manage_sql_tls_certificates.h"
60 #include "utils.h"
61 
62 #include <assert.h>
63 #include <ctype.h>
64 #include <errno.h>
65 #include <dirent.h>
66 #include <fcntl.h>
67 #include <glib.h>
68 #include <gnutls/x509.h> /* for gnutls_x509_crt_... */
69 #include <math.h>
70 #include <locale.h>
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74 #include <strings.h>
75 #include <sys/file.h>
76 #include <sys/stat.h>
77 #include <sys/types.h>
78 #include <sys/socket.h>
79 #include <sys/wait.h>
80 #include <time.h>
81 #include <unistd.h>
82 
83 #include <gvm/base/hosts.h>
84 #include <gvm/base/proctitle.h>
85 #include <gvm/osp/osp.h>
86 #include <gvm/util/fileutils.h>
87 #include <gvm/util/serverutils.h>
88 #include <gvm/util/uuidutils.h>
89 #include <gvm/gmp/gmp.h>
90 
91 #undef G_LOG_DOMAIN
92 /**
93  * @brief GLib log domain.
94  */
95 #define G_LOG_DOMAIN "md manage"
96 
97 /**
98  * @brief CPE selection stylesheet location.
99  */
100 #define CPE_GETBYNAME_XSL GVM_SCAP_RES_DIR "/cpe_getbyname.xsl"
101 
102 /**
103  * @brief CVE selection stylesheet location.
104  */
105 #define CVE_GETBYNAME_XSL GVM_SCAP_RES_DIR "/cve_getbyname.xsl"
106 
107 /**
108  * @brief OVALDEF selection stylesheet location.
109  */
110 #define OVALDEF_GETBYNAME_XSL GVM_SCAP_RES_DIR "/ovaldef_getbyname.xsl"
111 
112 /**
113  * @brief CERT_BUND_ADV selection stylesheet location.
114  */
115 #define CERT_BUND_ADV_GETBYNAME_XSL GVM_CERT_RES_DIR "/cert_bund_getbyname.xsl"
116 
117 /**
118  * @brief DFN_CERT_ADV selection stylesheet location.
119  */
120 #define DFN_CERT_ADV_GETBYNAME_XSL GVM_CERT_RES_DIR "/dfn_cert_getbyname.xsl"
121 
122 /**
123  * @brief CPE dictionary location.
124  */
125 #define CPE_DICT_FILENAME GVM_SCAP_DATA_DIR "/official-cpe-dictionary_v2.2.xml"
126 
127 /**
128  * @brief CVE data files location format string.
129  *
130  * %d should be the year expressed as YYYY.
131  */
132 #define CVE_FILENAME_FMT GVM_SCAP_DATA_DIR "/nvdcve-2.0-%d.xml"
133 
134 /**
135  * @brief CERT-Bund data files location format string.
136  *
137  * %d should be the year without the century (expressed as YY),
138  */
139 #define CERT_BUND_ADV_FILENAME_FMT GVM_CERT_DATA_DIR "/CB-K%02d.xml"
140 
141 /**
142  * @brief DFN-CERT data files location format string.
143  *
144  * First %d should be the year expressed as YYYY,
145  * second %d should be should be Month expressed as MM.
146  */
147 #define DFN_CERT_ADV_FILENAME_FMT GVM_CERT_DATA_DIR "/dfn-cert-%04d.xml"
148 
149 /**
150  * @brief SCAP timestamp location.
151  */
152 #define SCAP_TIMESTAMP_FILENAME GVM_SCAP_DATA_DIR "/timestamp"
153 
154 /**
155  * @brief CERT timestamp location.
156  */
157 #define CERT_TIMESTAMP_FILENAME GVM_CERT_DATA_DIR "/timestamp"
158 
159 /**
160  * @brief Default for Scanner max_checks preference.
161  */
162 #define MAX_CHECKS_DEFAULT "4"
163 
164 /**
165  * @brief Default for Scanner max_hosts preference.
166  */
167 #define MAX_HOSTS_DEFAULT "20"
168 
169 /**
170  * @brief Path to the feed lock file
171  */
172 static gchar *feed_lock_path = NULL;
173 
174 /**
175  * @brief Number of seconds to wait for the feed lock to be released.
176  */
177 static int feed_lock_timeout = 0;
178 
179 /**
180  * @brief Path to the relay mapper executable, NULL to disable relays.
181  */
182 static gchar *relay_mapper_path = NULL;
183 
184 /**
185  * @brief Whether to migrate sensors if relays do not match.
186  */
187 static int relay_migrate_sensors = 0;
188 
189 /**
190  * @brief Number of minutes before overdue tasks timeout.
191  */
192 static int schedule_timeout = SCHEDULE_TIMEOUT_DEFAULT;
193 
194 /**
195  * @brief Default number of auto retries if scanner connection is
196  *        lost in a running task.
197  */
198 static int scanner_connection_retry = SCANNER_CONNECTION_RETRY_DEFAULT;
199 
200 
201 /* Certificate and key management. */
202 
203 /**
204  * @brief Truncate a certificate, removing extra data.
205  *
206  * @param[in]  certificate    The certificate.
207  *
208  * @return  The truncated certificate as a newly allocated string or NULL.
209  */
210 gchar *
truncate_certificate(const gchar * certificate)211 truncate_certificate (const gchar* certificate)
212 {
213   GString *cert_buffer;
214   gchar *current_pos, *cert_start, *cert_end;
215   gboolean done = FALSE;
216   cert_buffer = g_string_new ("");
217 
218   current_pos = (gchar *) certificate;
219   while (done == FALSE && *current_pos != '\0')
220     {
221       cert_start = NULL;
222       cert_end = NULL;
223       if (g_str_has_prefix (current_pos,
224                             "-----BEGIN CERTIFICATE-----"))
225         {
226           cert_start = current_pos;
227           cert_end = strstr (cert_start,
228                              "-----END CERTIFICATE-----");
229           if (cert_end)
230             cert_end += strlen ("-----END CERTIFICATE-----");
231           else
232             done = TRUE;
233         }
234       else if (g_str_has_prefix (current_pos,
235                                  "-----BEGIN TRUSTED CERTIFICATE-----"))
236         {
237           cert_start = current_pos;
238           cert_end = strstr (cert_start,
239                              "-----END TRUSTED CERTIFICATE-----");
240           if (cert_end)
241             cert_end += strlen ("-----END TRUSTED CERTIFICATE-----");
242           else
243             done = TRUE;
244         }
245       else if (g_str_has_prefix (current_pos,
246                                  "-----BEGIN PKCS7-----"))
247         {
248           cert_start = current_pos;
249           cert_end = strstr (cert_start,
250                              "-----END PKCS7-----");
251           if (cert_end)
252             cert_end += strlen ("-----END PKCS7-----");
253           else
254             done = TRUE;
255         }
256 
257       if (cert_start && cert_end)
258         {
259           g_string_append_len (cert_buffer, cert_start, cert_end - cert_start);
260           g_string_append_c (cert_buffer, '\n');
261         }
262       current_pos++;
263     }
264 
265   return g_string_free (cert_buffer, cert_buffer->len == 0);
266 }
267 
268 /**
269  * @brief Truncate a private key, removing extra data.
270  *
271  * @param[in]  private_key    The private key.
272  *
273  * @return  The truncated private key as a newly allocated string or NULL.
274  */
275 gchar *
truncate_private_key(const gchar * private_key)276 truncate_private_key (const gchar* private_key)
277 {
278   gchar *key_start, *key_end;
279   key_end = NULL;
280   key_start = strstr (private_key, "-----BEGIN RSA PRIVATE KEY-----");
281   if (key_start)
282     {
283       key_end = strstr (key_start, "-----END RSA PRIVATE KEY-----");
284 
285       if (key_end)
286         key_end += strlen ("-----END RSA PRIVATE KEY-----");
287       else
288         return NULL;
289     }
290 
291   if (key_start == NULL)
292     {
293       key_start = strstr (private_key, "-----BEGIN DSA PRIVATE KEY-----");
294       if (key_start)
295         {
296           key_end = strstr (key_start, "-----END DSA PRIVATE KEY-----");
297 
298           if (key_end)
299             key_end += strlen ("-----END DSA PRIVATE KEY-----");
300           else
301             return NULL;
302         }
303     }
304 
305   if (key_start == NULL)
306     {
307       key_start = strstr (private_key, "-----BEGIN EC PRIVATE KEY-----");
308       if (key_start)
309         {
310           key_end = strstr (key_start, "-----END EC PRIVATE KEY-----");
311 
312           if (key_end)
313             key_end += strlen ("-----END EC PRIVATE KEY-----");
314           else
315             return NULL;
316         }
317     }
318 
319   if (key_end && key_end[0] == '\n')
320     key_end++;
321 
322   if (key_start == NULL || key_end == NULL)
323     return NULL;
324   else
325     return g_strndup (key_start, key_end - key_start);
326 }
327 
328 /**
329  * @brief Gathers info from a certificate.
330  *
331  * @param[in]  certificate        The certificate to get data from.
332  * @param[in]  certificate_len    Length of certificate, -1: null-terminated
333  * @param[out] activation_time    Pointer to write activation time to.
334  * @param[out] expiration_time    Pointer to write expiration time to.
335  * @param[out] md5_fingerprint    Pointer for newly allocated MD5 fingerprint.
336  * @param[out] sha256_fingerprint Pointer for newly allocated SHA-256
337  *                                fingerprint.
338  * @param[out] subject            Pointer for newly allocated subject DN.
339  * @param[out] issuer             Pointer for newly allocated issuer DN.
340  * @param[out] serial             Pointer for newly allocated serial.
341  * @param[out] certificate_format Pointer to certificate format.
342  *
343  * @return 0 success, -1 error.
344  */
345 int
get_certificate_info(const gchar * certificate,gssize certificate_len,time_t * activation_time,time_t * expiration_time,gchar ** md5_fingerprint,gchar ** sha256_fingerprint,gchar ** subject,gchar ** issuer,gchar ** serial,gnutls_x509_crt_fmt_t * certificate_format)346 get_certificate_info (const gchar* certificate, gssize certificate_len,
347                       time_t* activation_time, time_t* expiration_time,
348                       gchar** md5_fingerprint, gchar **sha256_fingerprint,
349                       gchar **subject, gchar** issuer, gchar **serial,
350                       gnutls_x509_crt_fmt_t *certificate_format)
351 {
352   gchar *cert_truncated;
353   gnutls_x509_crt_fmt_t certificate_format_internal;
354 
355   cert_truncated = NULL;
356   if (activation_time)
357     *activation_time = -1;
358   if (expiration_time)
359     *expiration_time = -1;
360   if (md5_fingerprint)
361     *md5_fingerprint = NULL;
362   if (sha256_fingerprint)
363     *sha256_fingerprint = NULL;
364   if (subject)
365     *subject = NULL;
366   if (issuer)
367     *issuer = NULL;
368   if (serial)
369     *serial = NULL;
370   if (certificate_format)
371     *certificate_format = GNUTLS_X509_FMT_DER;
372 
373   if (certificate)
374     {
375       int err;
376       gnutls_datum_t cert_datum;
377       gnutls_x509_crt_t gnutls_cert;
378       static const gchar* begin_str = "-----BEGIN ";
379 
380       if (g_strstr_len (certificate, certificate_len, begin_str))
381         {
382           cert_truncated = truncate_certificate (certificate);
383           if (cert_truncated == NULL)
384             {
385               return -1;
386             }
387           certificate_format_internal = GNUTLS_X509_FMT_PEM;
388         }
389       else
390         {
391           if (certificate_len < 0)
392             {
393               g_warning ("%s: PEM encoded certificate expected if"
394                          " certificate_length is negative",
395                          __func__);
396               return -1;
397             }
398 
399           cert_truncated = g_memdup (certificate, certificate_len);
400           certificate_format_internal = GNUTLS_X509_FMT_DER;
401         }
402 
403       cert_datum.data = (unsigned char*) cert_truncated;
404       if (certificate_len < 0)
405         cert_datum.size = strlen (cert_truncated);
406       else
407         cert_datum.size = certificate_len;
408 
409       gnutls_x509_crt_init (&gnutls_cert);
410       err = gnutls_x509_crt_import (gnutls_cert, &cert_datum,
411                                     certificate_format_internal);
412       if (err)
413         {
414           g_free (cert_truncated);
415           return -1;
416         }
417 
418       if (certificate_format)
419         *certificate_format = certificate_format_internal;
420 
421       if (activation_time)
422         {
423           *activation_time
424             = gnutls_x509_crt_get_activation_time (gnutls_cert);
425         }
426 
427       if (expiration_time)
428         {
429           *expiration_time
430             = gnutls_x509_crt_get_expiration_time (gnutls_cert);
431         }
432 
433       if (md5_fingerprint)
434         {
435           int i;
436           size_t buffer_size = 16;
437           unsigned char buffer[buffer_size];
438           GString *string;
439 
440           string = g_string_new ("");
441 
442           gnutls_x509_crt_get_fingerprint (gnutls_cert, GNUTLS_DIG_MD5,
443                                            buffer, &buffer_size);
444 
445           for (i = 0; i < buffer_size; i++)
446             {
447               if (i != 0)
448                 {
449                   g_string_append_c (string, ':');
450                 }
451               g_string_append_printf (string, "%02x", buffer[i]);
452             }
453 
454           *md5_fingerprint = string->str;
455           g_string_free (string, FALSE);
456         }
457 
458       if (sha256_fingerprint)
459         {
460           int i;
461           size_t buffer_size = 32;
462           unsigned char buffer[buffer_size];
463           GString *string;
464 
465           string = g_string_new ("");
466 
467           gnutls_x509_crt_get_fingerprint (gnutls_cert, GNUTLS_DIG_SHA256,
468                                            buffer, &buffer_size);
469 
470           for (i = 0; i < buffer_size; i++)
471             {
472               g_string_append_printf (string, "%02X", buffer[i]);
473             }
474 
475           *sha256_fingerprint = string->str;
476           g_string_free (string, FALSE);
477         }
478 
479       if (subject)
480         {
481           size_t buffer_size = 0;
482           gchar *buffer;
483           gnutls_x509_crt_get_dn (gnutls_cert, NULL, &buffer_size);
484           buffer = g_malloc (buffer_size);
485           gnutls_x509_crt_get_dn (gnutls_cert, buffer, &buffer_size);
486 
487           *subject = buffer;
488         }
489 
490       if (issuer)
491         {
492           size_t buffer_size = 0;
493           gchar *buffer;
494           gnutls_x509_crt_get_issuer_dn (gnutls_cert, NULL, &buffer_size);
495           buffer = g_malloc (buffer_size);
496           gnutls_x509_crt_get_issuer_dn (gnutls_cert, buffer, &buffer_size);
497 
498           *issuer = buffer;
499         }
500 
501       if (serial)
502         {
503           int i;
504           size_t buffer_size = 0;
505           gchar* buffer;
506           GString *string;
507 
508           string = g_string_new ("");
509 
510           gnutls_x509_crt_get_serial (gnutls_cert, NULL, &buffer_size);
511           buffer = g_malloc (buffer_size);
512           gnutls_x509_crt_get_serial (gnutls_cert, buffer, &buffer_size);
513 
514           for (i = 0; i < buffer_size; i++)
515             {
516               g_string_append_printf (string, "%02X", buffer[i]);
517             }
518 
519           *serial = string->str;
520           g_string_free (string, FALSE);
521         }
522 
523       gnutls_x509_crt_deinit (gnutls_cert);
524       g_free (cert_truncated);
525     }
526   return 0;
527 }
528 
529 /**
530  * @brief Converts a certificate time to an ISO time string.
531  *
532  * @param[in] time  The time as a time_t.
533  *
534  * @return Newly allocated string.
535  */
536 gchar *
certificate_iso_time(time_t time)537 certificate_iso_time (time_t time)
538 {
539   if (time == 0)
540     return g_strdup ("unlimited");
541   else if (time == -1)
542     return g_strdup ("unknown");
543   else
544     return g_strdup (iso_time (&time));
545 }
546 
547 /**
548  * @brief Tests the activation and expiration time of a certificate.
549  *
550  * @param[in] activates  Activation time.
551  * @param[in] expires    Expiration time.
552  *
553  * @return Static status string.
554  */
555 const gchar *
certificate_time_status(time_t activates,time_t expires)556 certificate_time_status (time_t activates, time_t expires)
557 {
558   time_t now;
559   time (&now);
560 
561   if (activates == -1 || expires == -1)
562     return "unknown";
563   else if (activates > now)
564     return "inactive";
565   else if (expires != 0 && expires < now)
566     return "expired";
567   else
568     return "valid";
569 }
570 
571 
572 /* Helpers. */
573 
574 /**
575  * @brief Truncates text to a maximum length, optionally appends a suffix.
576  *
577  * Note: The string is modified in place instead of allocating a new one.
578  * With the xml option the function will avoid cutting the string in the middle
579  *  of XML entities, but element tags will be ignored.
580  *
581  * @param[in,out] string   The string to truncate.
582  * @param[in]     max_len  The maximum length in bytes.
583  * @param[in]     xml      Whether to preserve XML entities.
584  * @param[in]     suffix   The suffix to append when the string is shortened.
585  */
586 static void
truncate_text(gchar * string,size_t max_len,gboolean xml,const char * suffix)587 truncate_text (gchar *string, size_t max_len, gboolean xml, const char *suffix)
588 {
589   if (string == NULL)
590     return;
591 
592   if (strlen (string) <= max_len)
593     return;
594   else
595     {
596       size_t offset;
597       offset = max_len;
598 
599       // Move offset according according to suffix length
600       if (suffix && strlen (suffix) < max_len)
601         offset = offset - strlen (suffix);
602 
603       // Go back to start of UTF-8 character
604       if (offset > 0 && (string[offset] & 0x80) == 0x80)
605         {
606           offset = g_utf8_find_prev_char (string, string + offset) - string;
607         }
608 
609       if (xml)
610         {
611           // If the offset is in the middle of an XML entity,
612           //  move the offset to the start of that entity.
613           ssize_t entity_start_offset = offset;
614 
615           while (entity_start_offset >= 0
616                  && string[entity_start_offset] != '&')
617             {
618               entity_start_offset --;
619             }
620 
621           if (entity_start_offset >= 0)
622             {
623               char *entity_end = strchr(string + entity_start_offset, ';');
624               if (entity_end && (entity_end - string) >= offset)
625                 offset = entity_start_offset;
626             }
627         }
628 
629       // Truncate the string, inserting the suffix if applicable
630       if (suffix && strlen (suffix) < max_len)
631         sprintf (string + offset, "%s", suffix);
632       else
633         string[offset] = '\0';
634     }
635 }
636 
637 /**
638  * @brief XML escapes text truncating to a maximum length with a suffix.
639  *
640  * Note: The function will avoid cutting the string in the middle of XML
641  *  entities.
642  *
643  * @param[in]  string   The string to truncate.
644  * @param[in]  max_len  The maximum length in bytes.
645  * @param[in]  suffix   The suffix to append when the string is shortened.
646  *
647  * @return Newly allocated string with XML escaped, truncated text.
648  */
649 gchar *
xml_escape_text_truncated(const char * string,size_t max_len,const char * suffix)650 xml_escape_text_truncated (const char *string, size_t max_len,
651                            const char *suffix)
652 {
653   gchar *escaped;
654   gssize orig_len;
655 
656   orig_len = strlen (string);
657   if (orig_len <= max_len)
658     escaped = g_markup_escape_text (string, -1);
659   else
660     {
661       gchar *offset_next;
662       ssize_t offset;
663 
664       offset_next = g_utf8_find_next_char (string + max_len,
665                                            string + orig_len);
666       offset = offset_next - string;
667       escaped = g_markup_escape_text (string, offset);
668     }
669 
670   truncate_text (escaped, max_len, TRUE, suffix);
671   return escaped;
672 }
673 
674 /**
675  * @brief Return the plural name of a resource type.
676  *
677  * @param[in]  type  Resource type.
678  *
679  * @return Plural name of type.
680  */
681 const char *
type_name_plural(const char * type)682 type_name_plural (const char* type)
683 {
684   if (type == NULL)
685     return "ERROR";
686 
687   if (strcasecmp (type, "cpe") == 0)
688     return "CPEs";
689   if (strcasecmp (type, "cve") == 0)
690     return "CVEs";
691   if (strcasecmp (type, "cert_bund_adv") == 0)
692     return "CERT-Bund Advisories";
693   if (strcasecmp (type, "dfn_cert_adv") == 0)
694     return "DFN-CERT Advisories";
695   if (strcasecmp (type, "nvt") == 0)
696     return "NVTs";
697   if (strcasecmp (type, "ovaldef") == 0)
698     return "OVAL Definitions";
699 
700   return "ERROR";
701 }
702 
703 /**
704  * @brief Return the name of a resource type.
705  *
706  * @param[in]  type  Resource type.
707  *
708  * @return Name of type.
709  */
710 const char *
type_name(const char * type)711 type_name (const char* type)
712 {
713   if (type == NULL)
714     return "ERROR";
715 
716   if (strcasecmp (type, "cpe") == 0)
717     return "CPE";
718   if (strcasecmp (type, "cve") == 0)
719     return "CVE";
720   if (strcasecmp (type, "cert_bund_adv") == 0)
721     return "CERT-Bund Advisory";
722   if (strcasecmp (type, "dfn_cert_adv") == 0)
723     return "DFN-CERT Advisory";
724   if (strcasecmp (type, "nvt") == 0)
725     return "NVT";
726   if (strcasecmp (type, "ovaldef") == 0)
727     return "OVAL Definition";
728 
729   return "ERROR";
730 }
731 
732 /**
733  * @brief Check if a type is a SCAP type.
734  *
735  * @param[in]  type  Resource type.
736  *
737  * @return Name of type.
738  */
739 int
type_is_scap(const char * type)740 type_is_scap (const char* type)
741 {
742   return (strcasecmp (type, "cpe") == 0)
743          || (strcasecmp (type, "cve") == 0)
744          || (strcasecmp (type, "ovaldef") == 0);
745 }
746 
747 /**
748  * @brief Check whether a resource is available.
749  *
750  * @param[in]   type        Type.
751  * @param[out]  resource    Resource.
752  * @param[out]  permission  Permission required for this operation.
753  *
754  * @return 0 success, -1 error, 99 permission denied.
755  */
756 static int
check_available(const gchar * type,resource_t resource,const gchar * permission)757 check_available (const gchar *type, resource_t resource,
758                  const gchar *permission)
759 {
760   if (resource)
761     {
762       gchar *uuid;
763       resource_t found;
764 
765       uuid = resource_uuid (type, resource);
766       if (find_resource_with_permission (type, uuid, &found, permission, 0))
767         {
768           g_free (uuid);
769           return -1;
770         }
771       g_free (uuid);
772       if (found == 0)
773         return 99;
774 
775       return 0;
776     }
777 
778   return -1;
779 }
780 
781 /**
782  * @brief Check if a scanner type is valid.
783  *
784  * @param[in]  scanner_type  Scanner type.
785  *
786  * @return 1 if valid, else 0.
787  */
788 int
scanner_type_valid(scanner_type_t scanner_type)789 scanner_type_valid (scanner_type_t scanner_type)
790 {
791   if (scanner_type > SCANNER_TYPE_NONE
792       && scanner_type < SCANNER_TYPE_MAX
793       && scanner_type != 4)
794     return 1;
795   return 0;
796 }
797 
798 
799 /* Severity related functions. */
800 
801 /**
802  * @brief Get the message type of a threat.
803  *
804  * @param  threat  Threat.
805  *
806  * @return Static message type name if threat names a threat, else NULL.
807  */
808 const char *
threat_message_type(const char * threat)809 threat_message_type (const char *threat)
810 {
811   if (strcasecmp (threat, "High") == 0)
812     return "Alarm";
813   if (strcasecmp (threat, "Medium") == 0)
814     return "Alarm";
815   if (strcasecmp (threat, "Low") == 0)
816     return "Alarm";
817   if (strcasecmp (threat, "Log") == 0)
818     return "Log Message";
819   if (strcasecmp (threat, "Error") == 0)
820     return "Error Message";
821   if (strcasecmp (threat, "False Positive") == 0)
822     return "False Positive";
823   return NULL;
824 }
825 
826 /**
827  * @brief Check whether a severity falls within a threat level.
828  *
829  * @param[in]  severity  Severity.
830  * @param[in]  level     Threat level.
831  *
832  * @return 1 if in level, else 0.
833  */
834 int
severity_in_level(double severity,const char * level)835 severity_in_level (double severity, const char *level)
836 {
837   if (strcmp (level, "high") == 0)
838     return severity >= 7 && severity <= 10;
839   else if (strcmp (level, "medium") == 0)
840     return severity >= 4 && severity < 7;
841   else if (strcmp (level, "low") == 0)
842     return severity > 0 && severity < 4;
843   else if (strcmp (level, "none") == 0  || strcmp (level, "log") == 0)
844     return severity == 0;
845 
846   return 0;
847 }
848 
849 /**
850  * @brief Get the threat level matching a severity score.
851  *
852  * @param[in] severity  severity score
853  * @param[in] mode      0 for normal levels, 1 to use "Alarm" for severity > 0.0
854  *
855  * @return the level as a static string
856  */
857 const char*
severity_to_level(double severity,int mode)858 severity_to_level (double severity, int mode)
859 {
860   if (severity == SEVERITY_LOG)
861     return "Log";
862   else if (severity == SEVERITY_FP)
863     return "False Positive";
864   else if (severity == SEVERITY_ERROR)
865     return "Error";
866   else if (severity > 0.0 && severity <= 10.0)
867     {
868       if (mode == 1)
869         return "Alarm";
870       else if (severity_in_level (severity, "high"))
871         return "High";
872       else if (severity_in_level (severity, "medium"))
873         return "Medium";
874       else if (severity_in_level (severity, "low"))
875         return "Low";
876       else
877         return "Log";
878     }
879   else
880     {
881       g_warning ("%s: Invalid severity score given: %f",
882                  __func__, severity);
883       return NULL;
884     }
885 }
886 
887 /**
888  * @brief Get the message type matching a severity score.
889  *
890  * @param[in] severity  severity score
891  *
892  * @return the message type as a static string
893  */
894 const char*
severity_to_type(double severity)895 severity_to_type (double severity)
896 {
897   if (severity == SEVERITY_LOG)
898     return "Log Message";
899   else if (severity == SEVERITY_FP)
900     return "False Positive";
901   else if (severity == SEVERITY_ERROR)
902     return "Error Message";
903   else if (severity > 0.0 && severity <= 10.0)
904     return "Alarm";
905   else
906     {
907       g_warning ("%s: Invalid severity score given: %f",
908                  __func__, severity);
909       return NULL;
910     }
911 }
912 
913 
914 /* Credentials. */
915 
916 /**
917  * @brief Current credentials during any GMP command.
918  */
919 credentials_t current_credentials;
920 
921 
922 /* Reports. */
923 
924 /**
925  * @brief Delete all the reports for a task.
926  *
927  * It's up to the caller to ensure that this runs in a contention safe
928  * context (for example within an SQL transaction).
929  *
930  * @param[in]  task  A task descriptor.
931  *
932  * @return 0 on success, -1 on error.
933  */
934 int
delete_reports(task_t task)935 delete_reports (task_t task)
936 {
937   report_t report;
938   iterator_t iterator;
939   init_report_iterator_task (&iterator, task);
940   while (next_report (&iterator, &report))
941     if (delete_report_internal (report))
942       {
943         cleanup_iterator (&iterator);
944         return -1;
945       }
946   cleanup_iterator (&iterator);
947   return 0;
948 }
949 
950 /**
951  * @brief Create a basic filter term to get report results.
952  *
953  * @param[in]  first            First row.
954  * @param[in]  rows             Number of rows.
955  * @param[in]  apply_overrides  Whether to apply overrides.
956  * @param[in]  min_qod          Minimum QOD.
957  *
958  * @return Filter term.
959  */
960 static gchar *
report_results_filter_term(int first,int rows,int apply_overrides,int min_qod)961 report_results_filter_term (int first, int rows,
962                             int apply_overrides, int min_qod)
963 {
964   return g_strdup_printf ("first=%d rows=%d"
965                           " apply_overrides=%d min_qod=%d",
966                           first, rows, apply_overrides, min_qod);
967 }
968 
969 
970 /**
971  * @brief Create a new basic get_data_t struct to get report results.
972  *
973  * @param[in]  first            First row.
974  * @param[in]  rows             Number of rows.
975  * @param[in]  apply_overrides  Whether to apply overrides.
976  * @param[in]  min_qod          Minimum QOD.
977  *
978  * @return GET data struct.
979  */
980 get_data_t*
report_results_get_data(int first,int rows,int apply_overrides,int min_qod)981 report_results_get_data (int first, int rows,
982                          int apply_overrides, int min_qod)
983 {
984   get_data_t* get = g_malloc (sizeof (get_data_t));
985   memset (get, 0, sizeof (get_data_t));
986   get->type = g_strdup ("result");
987   get->filter = report_results_filter_term (first, rows,
988                                             apply_overrides, min_qod);
989 
990   return get;
991 }
992 
993 /**
994  * @brief Array index of severity 0.0 in the severity_data_t.counts array.
995  */
996 #define ZERO_SEVERITY_INDEX 4
997 
998 /**
999  * @brief Convert a severity value into an index in the counts array.
1000  *
1001  * @param[in]   severity        Severity value.
1002  *
1003  * @return      The index, 0 for invalid severity scores.
1004  */
1005 static int
severity_data_index(double severity)1006 severity_data_index (double severity)
1007 {
1008   int ret;
1009   if (severity >= 0.0)
1010     ret = (int)(round (severity * SEVERITY_SUBDIVISIONS)) + ZERO_SEVERITY_INDEX;
1011   else if (severity == SEVERITY_FP || severity == SEVERITY_ERROR)
1012     ret = (int)(round (severity)) + ZERO_SEVERITY_INDEX;
1013   else
1014     ret = 0;
1015 
1016   return ret;
1017 }
1018 
1019 /**
1020  * @brief Convert an index in the counts array to a severity value.
1021  *
1022  * @param[in]   index   Index in the counts array.
1023  *
1024  * @return      The corresponding severity value.
1025  */
1026 double
severity_data_value(int index)1027 severity_data_value (int index)
1028 {
1029   double ret;
1030   if (index <= ZERO_SEVERITY_INDEX && index > 0)
1031     ret = ((double) index) - ZERO_SEVERITY_INDEX;
1032   else if (index <= (ZERO_SEVERITY_INDEX
1033                      + (SEVERITY_SUBDIVISIONS * SEVERITY_MAX)))
1034     ret = (((double) (index - ZERO_SEVERITY_INDEX)) / SEVERITY_SUBDIVISIONS);
1035   else
1036     ret = SEVERITY_MISSING;
1037 
1038   return ret;
1039 }
1040 
1041 /**
1042  * @brief Initialize a severity data structure.
1043  *
1044  * @param[in] data  The data structure to initialize.
1045  */
1046 void
init_severity_data(severity_data_t * data)1047 init_severity_data (severity_data_t* data)
1048 {
1049   int max_i;
1050   max_i = ZERO_SEVERITY_INDEX + (SEVERITY_SUBDIVISIONS * SEVERITY_MAX);
1051 
1052   data->counts = g_malloc0 (sizeof (int) * (max_i + 1));
1053 
1054   data->total = 0;
1055   data->max = SEVERITY_MISSING;
1056 }
1057 
1058 /**
1059  * @brief Clean up a severity data structure.
1060  *
1061  * @param[in] data  The data structure to initialize.
1062  */
1063 void
cleanup_severity_data(severity_data_t * data)1064 cleanup_severity_data (severity_data_t* data)
1065 {
1066   g_free (data->counts);
1067 }
1068 
1069 /**
1070  * @brief Add a severity occurrence to the counts of a severity_data_t.
1071  *
1072  * @param[in]   severity_data   The severity count struct to add to.
1073  * @param[in]   severity        The severity to add.
1074  */
1075 void
severity_data_add(severity_data_t * severity_data,double severity)1076 severity_data_add (severity_data_t* severity_data, double severity)
1077 {
1078   (severity_data->counts)[severity_data_index (severity)]++;
1079 
1080   if (severity_data->total == 0 || severity_data->max <= severity)
1081     severity_data->max = severity;
1082 
1083   (severity_data->total)++;
1084 }
1085 
1086 /**
1087  * @brief Add a multiple severity occurrences to the counts of a severity_data_t.
1088  *
1089  * @param[in]   severity_data   The severity count struct to add to.
1090  * @param[in]   severity        The severity to add.
1091  * @param[in]   count           The number of occurrences to add.
1092  */
1093 void
severity_data_add_count(severity_data_t * severity_data,double severity,int count)1094 severity_data_add_count (severity_data_t* severity_data, double severity,
1095                          int count)
1096 {
1097   (severity_data->counts)[severity_data_index (severity)] += count;
1098 
1099   if (severity_data->total == 0 || severity_data->max <= severity)
1100     severity_data->max = severity;
1101 
1102   (severity_data->total) += count;
1103 }
1104 
1105 /**
1106  * @brief Calculate the total of severity counts in a range.
1107  *
1108  * @param[in]  severity_data   The severity data struct to get counts from.
1109  * @param[in]  min_severity    The minimum severity included in the range.
1110  * @param[in]  max_severity    The maximum severity included in the range.
1111  *
1112  * @return     The total of severity counts in the specified range.
1113  */
1114 static int
severity_data_range_count(const severity_data_t * severity_data,double min_severity,double max_severity)1115 severity_data_range_count (const severity_data_t* severity_data,
1116                            double min_severity, double max_severity)
1117 {
1118   int i, i_max, count;
1119 
1120   i_max = severity_data_index (max_severity);
1121   count = 0;
1122 
1123   for (i = severity_data_index (min_severity);
1124        i <= i_max;
1125        i++)
1126     {
1127       count += (severity_data->counts)[i];
1128     }
1129   return count;
1130 }
1131 
1132 /**
1133  * @brief Count the occurrences of severities in the levels.
1134  *
1135  * @param[in] severity_data    The severity counts data to evaluate.
1136  * @param[out] errors          The number of error messages.
1137  * @param[out] false_positives The number of False Positives.
1138  * @param[out] logs            The number of Log messages.
1139  * @param[out] lows            The number of Low severity results.
1140  * @param[out] mediums         The number of Medium severity results.
1141  * @param[out] highs           The number of High severity results.
1142  */
1143 void
severity_data_level_counts(const severity_data_t * severity_data,int * errors,int * false_positives,int * logs,int * lows,int * mediums,int * highs)1144 severity_data_level_counts (const severity_data_t *severity_data,
1145                             int *errors, int *false_positives,
1146                             int *logs, int *lows, int *mediums, int *highs)
1147 {
1148   if (errors)
1149     *errors
1150       = severity_data_range_count (severity_data,
1151                                    level_min_severity ("Error"),
1152                                    level_max_severity ("Error"));
1153 
1154   if (false_positives)
1155     *false_positives
1156       = severity_data_range_count (severity_data,
1157                                    level_min_severity ("False Positive"),
1158                                    level_max_severity ("False Positive"));
1159 
1160   if (logs)
1161     *logs
1162       = severity_data_range_count (severity_data,
1163                                    level_min_severity ("Log"),
1164                                    level_max_severity ("Log"));
1165 
1166   if (lows)
1167     *lows
1168       = severity_data_range_count (severity_data,
1169                                    level_min_severity ("low"),
1170                                    level_max_severity ("low"));
1171 
1172   if (mediums)
1173     *mediums
1174       = severity_data_range_count (severity_data,
1175                                    level_min_severity ("medium"),
1176                                    level_max_severity ("medium"));
1177 
1178   if (highs)
1179     *highs
1180       = severity_data_range_count (severity_data,
1181                                    level_min_severity ("high"),
1182                                    level_max_severity ("high"));
1183 }
1184 
1185 
1186 /* Task globals. */
1187 
1188 /**
1189  * @brief The task currently running on the scanner.
1190  */
1191 task_t current_scanner_task = (task_t) 0;
1192 
1193 /**
1194  * @brief The report of the current task.
1195  */
1196 report_t global_current_report = (report_t) 0;
1197 
1198 
1199 /* Alerts. */
1200 
1201 /**
1202  * @brief Frees a alert_report_data_t struct, including contained data.
1203  *
1204  * @param[in]  data   The struct to free.
1205  */
1206 void
alert_report_data_free(alert_report_data_t * data)1207 alert_report_data_free (alert_report_data_t *data)
1208 {
1209   if (data == NULL)
1210     return;
1211 
1212   alert_report_data_reset (data);
1213   g_free (data);
1214 }
1215 
1216 /**
1217  * @brief Frees content of an alert_report_data_t, but not the struct itself.
1218  *
1219  * @param[in]  data   The struct to free.
1220  */
1221 void
alert_report_data_reset(alert_report_data_t * data)1222 alert_report_data_reset (alert_report_data_t *data)
1223 {
1224   if (data == NULL)
1225     return;
1226 
1227   g_free (data->content_type);
1228   g_free (data->local_filename);
1229   g_free (data->remote_filename);
1230   g_free (data->report_format_name);
1231 
1232   memset (data, 0, sizeof (alert_report_data_t));
1233 }
1234 
1235 /**
1236  * @brief Get the name of an alert condition.
1237  *
1238  * @param[in]  condition  Condition.
1239  *
1240  * @return The name of the condition (for example, "Always").
1241  */
1242 const char*
alert_condition_name(alert_condition_t condition)1243 alert_condition_name (alert_condition_t condition)
1244 {
1245   switch (condition)
1246     {
1247       case ALERT_CONDITION_ALWAYS:
1248         return "Always";
1249       case ALERT_CONDITION_FILTER_COUNT_AT_LEAST:
1250         return "Filter count at least";
1251       case ALERT_CONDITION_FILTER_COUNT_CHANGED:
1252         return "Filter count changed";
1253       case ALERT_CONDITION_SEVERITY_AT_LEAST:
1254         return "Severity at least";
1255       case ALERT_CONDITION_SEVERITY_CHANGED:
1256         return "Severity changed";
1257       default:
1258         return "Internal Error";
1259     }
1260 }
1261 
1262 /**
1263  * @brief Get the name of an alert event.
1264  *
1265  * @param[in]  event  Event.
1266  *
1267  * @return The name of the event (for example, "Run status changed").
1268  */
1269 const char*
event_name(event_t event)1270 event_name (event_t event)
1271 {
1272   switch (event)
1273     {
1274       case EVENT_TASK_RUN_STATUS_CHANGED: return "Task run status changed";
1275       case EVENT_NEW_SECINFO:             return "New SecInfo arrived";
1276       case EVENT_UPDATED_SECINFO:         return "Updated SecInfo arrived";
1277       case EVENT_TICKET_RECEIVED:         return "Ticket received";
1278       case EVENT_ASSIGNED_TICKET_CHANGED: return "Assigned ticket changed";
1279       case EVENT_OWNED_TICKET_CHANGED:    return "Owned ticket changed";
1280       default:                            return "Internal Error";
1281     }
1282 }
1283 
1284 /**
1285  * @brief Get a description of an alert condition.
1286  *
1287  * @param[in]  condition  Condition.
1288  * @param[in]  alert  Alert.
1289  *
1290  * @return Freshly allocated description of condition.
1291  */
1292 gchar*
alert_condition_description(alert_condition_t condition,alert_t alert)1293 alert_condition_description (alert_condition_t condition,
1294                              alert_t alert)
1295 {
1296   switch (condition)
1297     {
1298       case ALERT_CONDITION_ALWAYS:
1299         return g_strdup ("Always");
1300       case ALERT_CONDITION_FILTER_COUNT_AT_LEAST:
1301         {
1302           char *count;
1303           gchar *ret;
1304 
1305           count = alert_data (alert, "condition", "count");
1306           ret = g_strdup_printf ("Filter count at least %s",
1307                                  count ? count : "0");
1308           free (count);
1309           return ret;
1310         }
1311       case ALERT_CONDITION_FILTER_COUNT_CHANGED:
1312         return g_strdup ("Filter count changed");
1313       case ALERT_CONDITION_SEVERITY_AT_LEAST:
1314         {
1315           char *level = alert_data (alert, "condition", "severity");
1316           gchar *ret = g_strdup_printf ("Task severity is at least '%s'",
1317                                         level);
1318           free (level);
1319           return ret;
1320         }
1321       case ALERT_CONDITION_SEVERITY_CHANGED:
1322         {
1323           char *direction;
1324           direction = alert_data (alert, "condition", "direction");
1325           gchar *ret = g_strdup_printf ("Task severity %s", direction);
1326           free (direction);
1327           return ret;
1328         }
1329       default:
1330         return g_strdup ("Internal Error");
1331     }
1332 }
1333 
1334 /**
1335  * @brief Get a description of an alert event.
1336  *
1337  * @param[in]  event       Event.
1338  * @param[in]  event_data  Event data.
1339  * @param[in]  task_name   Name of task if required in description, else NULL.
1340  *
1341  * @return Freshly allocated description of event.
1342  */
1343 gchar*
event_description(event_t event,const void * event_data,const char * task_name)1344 event_description (event_t event, const void *event_data, const char *task_name)
1345 {
1346   switch (event)
1347     {
1348       case EVENT_TASK_RUN_STATUS_CHANGED:
1349         if (task_name)
1350           return g_strdup_printf
1351                   ("The security scan task '%s' changed status to '%s'",
1352                    task_name,
1353                    run_status_name ((task_status_t) event_data));
1354         return g_strdup_printf ("Task status changed to '%s'",
1355                                 run_status_name ((task_status_t) event_data));
1356         break;
1357       case EVENT_NEW_SECINFO:
1358         return g_strdup_printf ("New SecInfo arrived");
1359         break;
1360       case EVENT_UPDATED_SECINFO:
1361         return g_strdup_printf ("Updated SecInfo arrived");
1362         break;
1363       case EVENT_TICKET_RECEIVED:
1364         return g_strdup_printf ("Ticket received");
1365         break;
1366       case EVENT_ASSIGNED_TICKET_CHANGED:
1367         return g_strdup_printf ("Assigned ticket changed");
1368         break;
1369       case EVENT_OWNED_TICKET_CHANGED:
1370         return g_strdup_printf ("Owned ticket changed");
1371         break;
1372       default:
1373         return g_strdup ("Internal Error");
1374     }
1375 }
1376 
1377 /**
1378  * @brief Get the name of an alert method.
1379  *
1380  * @param[in]  method  Method.
1381  *
1382  * @return The name of the method (for example, "Email" or "SNMP").
1383  */
1384 const char*
alert_method_name(alert_method_t method)1385 alert_method_name (alert_method_t method)
1386 {
1387   switch (method)
1388     {
1389       case ALERT_METHOD_EMAIL:       return "Email";
1390       case ALERT_METHOD_HTTP_GET:    return "HTTP Get";
1391       case ALERT_METHOD_SCP:         return "SCP";
1392       case ALERT_METHOD_SEND:        return "Send";
1393       case ALERT_METHOD_SMB:         return "SMB";
1394       case ALERT_METHOD_SNMP:        return "SNMP";
1395       case ALERT_METHOD_SOURCEFIRE:  return "Sourcefire Connector";
1396       case ALERT_METHOD_START_TASK:  return "Start Task";
1397       case ALERT_METHOD_SYSLOG:      return "Syslog";
1398       case ALERT_METHOD_TIPPINGPOINT:return "TippingPoint SMS";
1399       case ALERT_METHOD_VERINICE:    return "verinice Connector";
1400       case ALERT_METHOD_VFIRE:       return "Alemba vFire";
1401       default:                       return "Internal Error";
1402     }
1403 }
1404 
1405 /**
1406  * @brief Get an alert condition from a name.
1407  *
1408  * @param[in]  name  Condition name.
1409  *
1410  * @return The condition.
1411  */
1412 alert_condition_t
alert_condition_from_name(const char * name)1413 alert_condition_from_name (const char* name)
1414 {
1415   if (strcasecmp (name, "Always") == 0)
1416     return ALERT_CONDITION_ALWAYS;
1417   if (strcasecmp (name, "Filter count at least") == 0)
1418     return ALERT_CONDITION_FILTER_COUNT_AT_LEAST;
1419   if (strcasecmp (name, "Filter count changed") == 0)
1420     return ALERT_CONDITION_FILTER_COUNT_CHANGED;
1421   if (strcasecmp (name, "Severity at least") == 0)
1422     return ALERT_CONDITION_SEVERITY_AT_LEAST;
1423   if (strcasecmp (name, "Severity changed") == 0)
1424     return ALERT_CONDITION_SEVERITY_CHANGED;
1425   return ALERT_CONDITION_ERROR;
1426 }
1427 
1428 /**
1429  * @brief Get an event from a name.
1430  *
1431  * @param[in]  name  Event name.
1432  *
1433  * @return The event.
1434  */
1435 event_t
event_from_name(const char * name)1436 event_from_name (const char* name)
1437 {
1438   if (strcasecmp (name, "Task run status changed") == 0)
1439     return EVENT_TASK_RUN_STATUS_CHANGED;
1440   if (strcasecmp (name, "New SecInfo arrived") == 0)
1441     return EVENT_NEW_SECINFO;
1442   if (strcasecmp (name, "Updated SecInfo arrived") == 0)
1443     return EVENT_UPDATED_SECINFO;
1444   if (strcasecmp (name, "Ticket received") == 0)
1445     return EVENT_TICKET_RECEIVED;
1446   if (strcasecmp (name, "Assigned ticket changed") == 0)
1447     return EVENT_ASSIGNED_TICKET_CHANGED;
1448   if (strcasecmp (name, "Owned ticket changed") == 0)
1449     return EVENT_OWNED_TICKET_CHANGED;
1450   return EVENT_ERROR;
1451 }
1452 
1453 /**
1454  * @brief Get an alert method from a name.
1455  *
1456  * @param[in]  name  Method name.
1457  *
1458  * @return The method.
1459  */
1460 alert_method_t
alert_method_from_name(const char * name)1461 alert_method_from_name (const char* name)
1462 {
1463   if (strcasecmp (name, "Email") == 0)
1464     return ALERT_METHOD_EMAIL;
1465   if (strcasecmp (name, "HTTP Get") == 0)
1466     return ALERT_METHOD_HTTP_GET;
1467   if (strcasecmp (name, "SCP") == 0)
1468     return ALERT_METHOD_SCP;
1469   if (strcasecmp (name, "Send") == 0)
1470     return ALERT_METHOD_SEND;
1471   if (strcasecmp (name, "SMB") == 0)
1472     return ALERT_METHOD_SMB;
1473   if (strcasecmp (name, "SNMP") == 0)
1474     return ALERT_METHOD_SNMP;
1475   if (strcasecmp (name, "Sourcefire Connector") == 0)
1476     return ALERT_METHOD_SOURCEFIRE;
1477   if (strcasecmp (name, "Start Task") == 0)
1478     return ALERT_METHOD_START_TASK;
1479   if (strcasecmp (name, "Syslog") == 0)
1480     return ALERT_METHOD_SYSLOG;
1481   if (strcasecmp (name, "TippingPoint SMS") == 0)
1482     return ALERT_METHOD_TIPPINGPOINT;
1483   if (strcasecmp (name, "verinice Connector") == 0)
1484     return ALERT_METHOD_VERINICE;
1485   if (strcasecmp (name, "Alemba vFire") == 0)
1486     return ALERT_METHOD_VFIRE;
1487   return ALERT_METHOD_ERROR;
1488 }
1489 
1490 
1491 /* General task facilities. */
1492 
1493 /**
1494  * @brief Get the name of a run status.
1495  *
1496  * @param[in]  status  Run status.
1497  *
1498  * @return The name of the status (for example, "Done" or "Running").
1499  */
1500 const char*
run_status_name(task_status_t status)1501 run_status_name (task_status_t status)
1502 {
1503   switch (status)
1504     {
1505       case TASK_STATUS_DELETE_REQUESTED:
1506       case TASK_STATUS_DELETE_WAITING:
1507         return "Delete Requested";
1508       case TASK_STATUS_DELETE_ULTIMATE_REQUESTED:
1509       case TASK_STATUS_DELETE_ULTIMATE_WAITING:
1510         return "Ultimate Delete Requested";
1511       case TASK_STATUS_DONE:             return "Done";
1512       case TASK_STATUS_NEW:              return "New";
1513 
1514       case TASK_STATUS_REQUESTED:        return "Requested";
1515 
1516       case TASK_STATUS_RUNNING:          return "Running";
1517 
1518       case TASK_STATUS_QUEUED:           return "Queued";
1519 
1520       case TASK_STATUS_STOP_REQUESTED:
1521       case TASK_STATUS_STOP_WAITING:
1522         return "Stop Requested";
1523 
1524       case TASK_STATUS_STOPPED:          return "Stopped";
1525       default:                           return "Interrupted";
1526     }
1527 }
1528 
1529 /**
1530  * @brief Get the unique name of a run status.
1531  *
1532  * @param[in]  status  Run status.
1533  *
1534  * @return The name of the status (for example, "Done" or "Running").
1535  */
1536 const char*
run_status_name_internal(task_status_t status)1537 run_status_name_internal (task_status_t status)
1538 {
1539   switch (status)
1540     {
1541       case TASK_STATUS_DELETE_REQUESTED: return "Delete Requested";
1542       case TASK_STATUS_DELETE_ULTIMATE_REQUESTED:
1543         return "Ultimate Delete Requested";
1544       case TASK_STATUS_DELETE_ULTIMATE_WAITING:
1545         return "Ultimate Delete Waiting";
1546       case TASK_STATUS_DELETE_WAITING:   return "Delete Waiting";
1547       case TASK_STATUS_DONE:             return "Done";
1548       case TASK_STATUS_NEW:              return "New";
1549 
1550       case TASK_STATUS_REQUESTED:        return "Requested";
1551 
1552       case TASK_STATUS_RUNNING:          return "Running";
1553 
1554       case TASK_STATUS_QUEUED:           return "Queued";
1555 
1556       case TASK_STATUS_STOP_REQUESTED:
1557         return "Stop Requested";
1558 
1559       case TASK_STATUS_STOP_WAITING:
1560         return "Stop Waiting";
1561 
1562       case TASK_STATUS_STOPPED:          return "Stopped";
1563       default:                           return "Interrupted";
1564     }
1565 }
1566 
1567 /**
1568  * @brief Set a task to interrupted.
1569  *
1570  * Expects global_current_report to match the task.
1571  *
1572  * @param[in]   task     Task
1573  * @param[in]   message  Message for error result.
1574  */
1575 void
set_task_interrupted(task_t task,const gchar * message)1576 set_task_interrupted (task_t task, const gchar *message)
1577 {
1578   set_task_run_status (task, TASK_STATUS_INTERRUPTED);
1579   if (global_current_report)
1580     {
1581       result_t result;
1582       result = make_result (task, "", "", "", "", "Error Message", message,
1583                             NULL);
1584       report_add_result (global_current_report, result);
1585     }
1586 }
1587 
1588 
1589 /* OSP tasks. */
1590 
1591 /**
1592  * @brief Give a task's OSP scan options in a hash table.
1593  *
1594  * @param[in]   task        The task.
1595  * @param[in]   target      The target.
1596  *
1597  * @return Hash table with options names and their values.
1598  */
1599 static GHashTable *
task_scanner_options(task_t task,target_t target)1600 task_scanner_options (task_t task, target_t target)
1601 {
1602   GHashTable *table;
1603   config_t config;
1604   iterator_t prefs;
1605   char *allow_simultaneous_ips;
1606 
1607   config = task_config (task);
1608   init_config_preference_iterator (&prefs, config);
1609   table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1610   while (next (&prefs))
1611     {
1612       char *name, *value = NULL;
1613       const char *type;
1614 
1615       name = g_strdup (config_preference_iterator_name (&prefs));
1616       type = config_preference_iterator_type (&prefs);
1617 
1618       if (g_str_has_prefix (type, "credential_"))
1619         {
1620           credential_t credential = 0;
1621           iterator_t iter;
1622           const char *uuid = config_preference_iterator_value (&prefs);
1623 
1624           if (!strcmp (config_preference_iterator_value (&prefs), "0"))
1625             credential = target_ssh_credential (target);
1626           else if (find_resource ("credential", uuid, &credential))
1627             {
1628               g_warning ("Error getting credential for osp parameter %s", name);
1629               g_free (name);
1630               continue;
1631             }
1632           if (credential == 0)
1633             {
1634               g_warning ("No credential for osp parameter %s", name);
1635               g_free (name);
1636               continue;
1637             }
1638 
1639           init_credential_iterator_one (&iter, credential);
1640           if (!next (&iter))
1641             {
1642               g_warning ("No credential for credential_id %llu", credential);
1643               g_free (name);
1644               continue;
1645             }
1646           if (!strcmp (type, "credential_up")
1647               && !strcmp (credential_iterator_type (&iter), "up"))
1648             value = g_strdup_printf ("%s:%s", credential_iterator_login (&iter),
1649                                      credential_iterator_password (&iter));
1650           else if (!strcmp (type, "credential_up"))
1651             {
1652               g_warning ("OSP Parameter %s requires credentials of type"
1653                          " username+password", name);
1654               g_free (name);
1655               continue;
1656             }
1657           else
1658             abort ();
1659           cleanup_iterator (&iter);
1660           if (!value)
1661             {
1662               g_warning ("No adequate %s for parameter %s", type, name);
1663               g_free (name);
1664               continue;
1665             }
1666         }
1667       else if (!strcmp (name, "definitions_file"))
1668         {
1669           char *fname;
1670 
1671           if (!config_preference_iterator_value (&prefs))
1672             continue;
1673           fname = g_strdup_printf ("%s/%s", GVM_SCAP_DATA_DIR "/",
1674                                    config_preference_iterator_value (&prefs));
1675           value = gvm_file_as_base64 (fname);
1676           if (!value)
1677             continue;
1678         }
1679       else
1680         value = g_strdup (config_preference_iterator_value (&prefs));
1681       g_hash_table_insert (table, name, value);
1682     }
1683   cleanup_iterator (&prefs);
1684 
1685   // Target options sent as scanner preferences
1686   allow_simultaneous_ips = target_allow_simultaneous_ips (target);
1687   if (allow_simultaneous_ips)
1688     {
1689       g_hash_table_replace (table,
1690                             g_strdup ("allow_simultaneous_ips"),
1691                             g_strdup (strcmp (allow_simultaneous_ips, "0")
1692                                         ? "yes"
1693                                         : "no"));
1694     }
1695   free (allow_simultaneous_ips);
1696 
1697   return table;
1698 }
1699 
1700 /**
1701  * @brief Delete an OSP scan.
1702  *
1703  * @param[in]   report_id   Report ID.
1704  * @param[in]   host        Scanner host.
1705  * @param[in]   port        Scanner port.
1706  * @param[in]   ca_pub      CA Certificate.
1707  * @param[in]   key_pub     Certificate.
1708  * @param[in]   key_priv    Private key.
1709  */
1710 static void
delete_osp_scan(const char * report_id,const char * host,int port,const char * ca_pub,const char * key_pub,const char * key_priv)1711 delete_osp_scan (const char *report_id, const char *host, int port,
1712                  const char *ca_pub, const char *key_pub, const char *key_priv)
1713 {
1714   osp_connection_t *connection;
1715 
1716   connection = osp_connect_with_data (host, port, ca_pub, key_pub, key_priv);
1717   if (!connection)
1718     {
1719       return;
1720     }
1721   osp_delete_scan (connection, report_id);
1722   osp_connection_close (connection);
1723 }
1724 
1725 /**
1726  * @brief Get an OSP scan's report.
1727  *
1728  * @param[in]   scan_id     Scan ID.
1729  * @param[in]   host        Scanner host.
1730  * @param[in]   port        Scanner port.
1731  * @param[in]   ca_pub      CA Certificate.
1732  * @param[in]   key_pub     Certificate.
1733  * @param[in]   key_priv    Private key.
1734  * @param[in]   details     1 for detailed report, 0 otherwise.
1735  * @param[in]   pop_results 1 to pop results, 0 to leave results intact.
1736  * @param[out]  report_xml  Scan report.
1737  *
1738  * @return -1 on error, progress value between 0 and 100 on success.
1739  */
1740 static int
get_osp_scan_report(const char * scan_id,const char * host,int port,const char * ca_pub,const char * key_pub,const char * key_priv,int details,int pop_results,char ** report_xml)1741 get_osp_scan_report (const char *scan_id, const char *host, int port,
1742                      const char *ca_pub, const char *key_pub, const char
1743                      *key_priv, int details, int pop_results,
1744                      char **report_xml)
1745 {
1746   osp_connection_t *connection;
1747   int progress;
1748   char *error = NULL;
1749 
1750   connection = osp_connect_with_data (host, port, ca_pub, key_pub, key_priv);
1751   if (!connection)
1752     {
1753       return -1;
1754     }
1755   progress = osp_get_scan_pop (connection, scan_id, report_xml, details,
1756                                pop_results, &error);
1757   if (progress > 100 || progress < 0)
1758     {
1759       g_warning ("OSP get_scan %s: %s", scan_id, error);
1760       g_free (error);
1761       progress = -1;
1762     }
1763 
1764   osp_connection_close (connection);
1765   return progress;
1766 }
1767 
1768 
1769 /**
1770  * @brief Get an OSP scan's status.
1771  *
1772  * @param[in]   scan_id     Scan ID.
1773  * @param[in]   host        Scanner host.
1774  * @param[in]   port        Scanner port.
1775  * @param[in]   ca_pub      CA Certificate.
1776  * @param[in]   key_pub     Certificate.
1777  * @param[in]   key_priv    Private key.
1778  *
1779  * @return 0 in success, -1 otherwise.
1780  */
1781 static osp_scan_status_t
get_osp_scan_status(const char * scan_id,const char * host,int port,const char * ca_pub,const char * key_pub,const char * key_priv)1782 get_osp_scan_status (const char *scan_id, const char *host, int port,
1783                      const char *ca_pub, const char *key_pub, const char
1784                      *key_priv)
1785 {
1786   osp_connection_t *connection;
1787   char *error = NULL;
1788   osp_get_scan_status_opts_t get_scan_opts;
1789   osp_scan_status_t status = OSP_SCAN_STATUS_ERROR;
1790 
1791   connection = osp_connect_with_data (host, port, ca_pub, key_pub, key_priv);
1792   if (!connection)
1793     {
1794       return status;
1795     }
1796 
1797   get_scan_opts.scan_id = scan_id;
1798   status = osp_get_scan_status_ext (connection, get_scan_opts, &error);
1799   if (status == OSP_SCAN_STATUS_ERROR)
1800     {
1801       g_warning ("OSP %s %s: %s", __func__, scan_id, error);
1802       g_free (error);
1803       return status;
1804     }
1805 
1806   osp_connection_close (connection);
1807   return status;
1808 }
1809 
1810 /**
1811  * @brief Handle an ongoing OSP scan, until success or failure.
1812  *
1813  * @param[in]   task      The task.
1814  * @param[in]   report    The report.
1815  * @param[in]   scan_id   The UUID of the scan on the scanner.
1816  *
1817  * @return 0 if success, -1 if error, -2 if scan was stopped,
1818  *         -3 if the scan was interrupted.
1819  */
1820 static int
handle_osp_scan(task_t task,report_t report,const char * scan_id)1821 handle_osp_scan (task_t task, report_t report, const char *scan_id)
1822 {
1823   char *host, *ca_pub, *key_pub, *key_priv;
1824   int rc, port;
1825   scanner_t scanner;
1826   gboolean started, queued_status_updated;
1827   int retry, connection_retry;
1828 
1829   scanner = task_scanner (task);
1830   host = scanner_host (scanner);
1831   port = scanner_port (scanner);
1832   ca_pub = scanner_ca_pub (scanner);
1833   key_pub = scanner_key_pub (scanner);
1834   key_priv = scanner_key_priv (scanner);
1835   started = FALSE;
1836   queued_status_updated = FALSE;
1837   connection_retry = get_scanner_connection_retry ();
1838 
1839   retry = connection_retry;
1840   rc = -1;
1841   while (retry >= 0)
1842     {
1843       int run_status, progress;
1844       osp_scan_status_t osp_scan_status;
1845 
1846       run_status = task_run_status (task);
1847       if (run_status == TASK_STATUS_STOPPED
1848           || run_status == TASK_STATUS_STOP_REQUESTED)
1849         {
1850           rc = -2;
1851           break;
1852         }
1853 
1854       /* Get only the progress, without results and details. */
1855       progress = get_osp_scan_report (scan_id, host, port, ca_pub, key_pub,
1856                                       key_priv, 0, 0, NULL);
1857 
1858       if (progress < 0 || progress > 100)
1859         {
1860           if (retry > 0)
1861             {
1862               retry--;
1863               g_warning ("Connection lost with the scanner at %s. "
1864                          "Trying again in 1 second.", host);
1865               gvm_sleep (1);
1866               continue;
1867             }
1868           result_t result = make_osp_result
1869                              (task, "", "", "",
1870                               threat_message_type ("Error"),
1871                               "Erroneous scan progress value", "", "",
1872                               QOD_DEFAULT, NULL);
1873           report_add_result (report, result);
1874           delete_osp_scan (scan_id, host, port, ca_pub, key_pub,
1875                            key_priv);
1876           rc = -1;
1877           break;
1878         }
1879       else
1880         {
1881           /* Get the full OSP report. */
1882           char *report_xml = NULL;
1883           progress = get_osp_scan_report (scan_id, host, port, ca_pub, key_pub,
1884                                           key_priv, 1, 1, &report_xml);
1885           if (progress < 0 || progress > 100)
1886             {
1887               if (retry > 0)
1888                 {
1889                   retry--;
1890                   g_warning ("Connection lost with the scanner at %s. "
1891                              "Trying again in 1 second.", host);
1892                   gvm_sleep (1);
1893                   continue;
1894                 }
1895 
1896               g_free (report_xml);
1897               result_t result = make_osp_result
1898                                  (task, "", "", "",
1899                                   threat_message_type ("Error"),
1900                                   "Erroneous scan progress value", "", "",
1901                                   QOD_DEFAULT, NULL);
1902               report_add_result (report, result);
1903               rc = -1;
1904               break;
1905             }
1906           else
1907             {
1908               set_report_slave_progress (report, progress);
1909               parse_osp_report (task, report, report_xml);
1910               g_free (report_xml);
1911 
1912               osp_scan_status = get_osp_scan_status (scan_id, host, port,
1913                                                      ca_pub, key_pub, key_priv);
1914 
1915               if (osp_scan_status == OSP_SCAN_STATUS_QUEUED)
1916                 {
1917                   if (queued_status_updated == FALSE)
1918                     {
1919                       set_task_run_status (task, TASK_STATUS_QUEUED);
1920                       set_report_scan_run_status (global_current_report,
1921                                                   TASK_STATUS_QUEUED);
1922                       queued_status_updated = TRUE;
1923                     }
1924                 }
1925               else if (osp_scan_status == OSP_SCAN_STATUS_INTERRUPTED)
1926                 {
1927                   result_t result = make_osp_result
1928                     (task, "", "", "",
1929                      threat_message_type ("Error"),
1930                      "Task interrupted unexpectedly", "", "",
1931                      QOD_DEFAULT, NULL);
1932                   report_add_result (report, result);
1933                   delete_osp_scan (scan_id, host, port, ca_pub, key_pub,
1934                                    key_priv);
1935                   rc = -3;
1936                   break;
1937                 }
1938               else if (progress >= 0 && progress < 100
1939                   && osp_scan_status == OSP_SCAN_STATUS_STOPPED)
1940                 {
1941                   if (retry > 0)
1942                     {
1943                       retry--;
1944                       g_warning ("Connection lost with the scanner at %s. "
1945                                  "Trying again in 1 second.", host);
1946                       gvm_sleep (1);
1947                       continue;
1948                     }
1949 
1950                   result_t result = make_osp_result
1951                     (task, "", "", "",
1952                      threat_message_type ("Error"),
1953                      "Scan stopped unexpectedly by the server", "", "",
1954                      QOD_DEFAULT, NULL);
1955                   report_add_result (report, result);
1956                   delete_osp_scan (scan_id, host, port, ca_pub, key_pub,
1957                                    key_priv);
1958                   rc = -1;
1959                   break;
1960                 }
1961               else if (progress == 100
1962                        && osp_scan_status == OSP_SCAN_STATUS_FINISHED)
1963                 {
1964                   delete_osp_scan (scan_id, host, port, ca_pub, key_pub,
1965                                    key_priv);
1966                   rc = 0;
1967                   break;
1968                 }
1969               else if (osp_scan_status == OSP_SCAN_STATUS_RUNNING
1970                        && started == FALSE)
1971                 {
1972                   set_task_run_status (task, TASK_STATUS_RUNNING);
1973                   set_report_scan_run_status (global_current_report,
1974                                               TASK_STATUS_RUNNING);
1975                   started = TRUE;
1976                 }
1977             }
1978         }
1979 
1980       retry = connection_retry;
1981       gvm_sleep (5);
1982     }
1983 
1984   g_free (host);
1985   g_free (ca_pub);
1986   g_free (key_pub);
1987   g_free (key_priv);
1988   return rc;
1989 }
1990 
1991 /**
1992  * @brief Get an OSP Task's scan options.
1993  *
1994  * @param[in]   task        The task.
1995  * @param[in]   target      The target.
1996  *
1997  * @return OSP Task options, NULL if failure.
1998  */
1999 static GHashTable *
get_osp_task_options(task_t task,target_t target)2000 get_osp_task_options (task_t task, target_t target)
2001 {
2002   char *ssh_port;
2003   const char *user, *pass;
2004   iterator_t iter;
2005   credential_t cred;
2006   GHashTable *options = task_scanner_options (task, target);
2007 
2008   if (!options)
2009     return NULL;
2010 
2011   cred = target_ssh_credential (target);
2012   if (cred)
2013     {
2014       ssh_port = target_ssh_port (target);
2015       g_hash_table_insert (options, g_strdup ("port"), ssh_port);
2016 
2017       init_credential_iterator_one (&iter, cred);
2018       if (!next (&iter))
2019         {
2020           g_warning ("%s: LSC Credential not found.", __func__);
2021           g_hash_table_destroy (options);
2022           cleanup_iterator (&iter);
2023           return NULL;
2024         }
2025       if (credential_iterator_private_key (&iter))
2026         {
2027           g_warning ("%s: LSC Credential not a user/pass pair.", __func__);
2028           g_hash_table_destroy (options);
2029           cleanup_iterator (&iter);
2030           return NULL;
2031         }
2032       user = credential_iterator_login (&iter);
2033       pass = credential_iterator_password (&iter);
2034       g_hash_table_insert (options, g_strdup ("username"), g_strdup (user));
2035       g_hash_table_insert (options, g_strdup ("password"), g_strdup (pass));
2036       cleanup_iterator (&iter);
2037     }
2038   return options;
2039 }
2040 
2041 /**
2042  * @brief Launch an OSP task.
2043  *
2044  * @param[in]   task        The task.
2045  * @param[in]   target      The target.
2046  * @param[out]  scan_id     The new scan uuid.
2047  * @param[out]  error       Error return.
2048  *
2049  * @return 0 success, -1 if scanner is down.
2050  */
2051 static int
launch_osp_task(task_t task,target_t target,const char * scan_id,char ** error)2052 launch_osp_task (task_t task, target_t target, const char *scan_id,
2053                  char **error)
2054 {
2055   osp_connection_t *connection;
2056   char *target_str, *ports_str;
2057   GHashTable *options;
2058   int ret;
2059 
2060   options = get_osp_task_options (task, target);
2061   if (!options)
2062     return -1;
2063   connection = osp_scanner_connect (task_scanner (task));
2064   if (!connection)
2065     {
2066       g_hash_table_destroy (options);
2067       return -1;
2068     }
2069   target_str = target_hosts (target);
2070   ports_str = target_port_range (target);
2071   ret = osp_start_scan (connection, target_str, ports_str, options, scan_id,
2072                         error);
2073 
2074   g_hash_table_destroy (options);
2075   osp_connection_close (connection);
2076   g_free (target_str);
2077   g_free (ports_str);
2078   return ret;
2079 }
2080 
2081 /**
2082  * @brief Get the SSH credential of a target as an osp_credential_t
2083  *
2084  * @param[in]  target  The target to get the credential from.
2085  *
2086  * @return  Pointer to a newly allocated osp_credential_t
2087  */
2088 static osp_credential_t *
target_osp_ssh_credential(target_t target)2089 target_osp_ssh_credential (target_t target)
2090 {
2091   credential_t credential, ssh_elevate_credential;
2092   credential = target_ssh_credential (target);
2093   ssh_elevate_credential = target_ssh_elevate_credential (target);
2094 
2095   if (credential)
2096     {
2097       iterator_t iter, ssh_elevate_iter;
2098       const char *type;
2099       char *ssh_port;
2100       osp_credential_t *osp_credential;
2101 
2102       init_credential_iterator_one (&iter, credential);
2103 
2104       if (!next (&iter))
2105         {
2106           g_warning ("%s: SSH Credential not found.", __func__);
2107           cleanup_iterator (&iter);
2108           return NULL;
2109         }
2110       type = credential_iterator_type (&iter);
2111       if (strcmp (type, "up") && strcmp (type, "usk"))
2112         {
2113           g_warning ("%s: SSH Credential not a user/pass pair"
2114                      " or user/ssh key.", __func__);
2115           cleanup_iterator (&iter);
2116           return NULL;
2117         }
2118 
2119       ssh_port = target_ssh_port (target);
2120       osp_credential = osp_credential_new (type, "ssh", ssh_port);
2121       free (ssh_port);
2122       osp_credential_set_auth_data (osp_credential,
2123                                     "username",
2124                                     credential_iterator_login (&iter));
2125       osp_credential_set_auth_data (osp_credential,
2126                                     "password",
2127                                     credential_iterator_password (&iter));
2128 
2129       if (strcmp (type, "usk") == 0)
2130         {
2131           const char *private_key = credential_iterator_private_key (&iter);
2132           gchar *base64 = g_base64_encode ((guchar *) private_key,
2133                                            strlen (private_key));
2134           osp_credential_set_auth_data (osp_credential,
2135                                         "private", base64);
2136           g_free (base64);
2137         }
2138 
2139       if(ssh_elevate_credential)
2140         {
2141           const char *elevate_type;
2142 
2143           init_credential_iterator_one (&ssh_elevate_iter,
2144                                         ssh_elevate_credential);
2145           if (!next (&ssh_elevate_iter))
2146             {
2147               g_warning ("%s: SSH Elevate Credential not found.", __func__);
2148               cleanup_iterator (&ssh_elevate_iter);
2149               osp_credential_free(osp_credential);
2150               return NULL;
2151             }
2152           elevate_type = credential_iterator_type (&ssh_elevate_iter);
2153           if (strcmp (elevate_type, "up"))
2154             {
2155               g_warning ("%s: SSH Elevate Credential not of type up", __func__);
2156               cleanup_iterator (&ssh_elevate_iter);
2157               osp_credential_free(osp_credential);
2158               return NULL;
2159             }
2160           osp_credential_set_auth_data (osp_credential,
2161                                         "priv_username",
2162                                         credential_iterator_login
2163                                           (&ssh_elevate_iter));
2164           osp_credential_set_auth_data (osp_credential,
2165                                         "priv_password",
2166                                         credential_iterator_password
2167                                           (&ssh_elevate_iter));
2168           cleanup_iterator (&ssh_elevate_iter);
2169         }
2170 
2171       cleanup_iterator (&iter);
2172       return osp_credential;
2173     }
2174   return NULL;
2175 }
2176 
2177 /**
2178  * @brief Get the SMB credential of a target as an osp_credential_t
2179  *
2180  * @param[in]  target  The target to get the credential from.
2181  *
2182  * @return  Pointer to a newly allocated osp_credential_t
2183  */
2184 static osp_credential_t *
target_osp_smb_credential(target_t target)2185 target_osp_smb_credential (target_t target)
2186 {
2187   credential_t credential;
2188   credential = target_smb_credential (target);
2189   if (credential)
2190     {
2191       iterator_t iter;
2192       osp_credential_t *osp_credential;
2193 
2194       init_credential_iterator_one (&iter, credential);
2195       if (!next (&iter))
2196         {
2197           g_warning ("%s: SMB Credential not found.", __func__);
2198           cleanup_iterator (&iter);
2199           return NULL;
2200         }
2201       if (strcmp (credential_iterator_type (&iter), "up"))
2202         {
2203           g_warning ("%s: SMB Credential not a user/pass pair.", __func__);
2204           cleanup_iterator (&iter);
2205           return NULL;
2206         }
2207 
2208       osp_credential = osp_credential_new ("up", "smb", NULL);
2209       osp_credential_set_auth_data (osp_credential,
2210                                     "username",
2211                                     credential_iterator_login (&iter));
2212       osp_credential_set_auth_data (osp_credential,
2213                                     "password",
2214                                     credential_iterator_password (&iter));
2215       cleanup_iterator (&iter);
2216       return osp_credential;
2217     }
2218   return NULL;
2219 }
2220 
2221 /**
2222  * @brief Get the SMB credential of a target as an osp_credential_t
2223  *
2224  * @param[in]  target  The target to get the credential from.
2225  *
2226  * @return  Pointer to a newly allocated osp_credential_t
2227  */
2228 static osp_credential_t *
target_osp_esxi_credential(target_t target)2229 target_osp_esxi_credential (target_t target)
2230 {
2231   credential_t credential;
2232   credential = target_esxi_credential (target);
2233   if (credential)
2234     {
2235       iterator_t iter;
2236       osp_credential_t *osp_credential;
2237 
2238       init_credential_iterator_one (&iter, credential);
2239       if (!next (&iter))
2240         {
2241           g_warning ("%s: ESXi Credential not found.", __func__);
2242           cleanup_iterator (&iter);
2243           return NULL;
2244         }
2245       if (strcmp (credential_iterator_type (&iter), "up"))
2246         {
2247           g_warning ("%s: ESXi Credential not a user/pass pair.",
2248                      __func__);
2249           cleanup_iterator (&iter);
2250           return NULL;
2251         }
2252 
2253       osp_credential = osp_credential_new ("up", "esxi", NULL);
2254       osp_credential_set_auth_data (osp_credential,
2255                                     "username",
2256                                     credential_iterator_login (&iter));
2257       osp_credential_set_auth_data (osp_credential,
2258                                     "password",
2259                                     credential_iterator_password (&iter));
2260       cleanup_iterator (&iter);
2261       return osp_credential;
2262     }
2263   return NULL;
2264 }
2265 
2266 /**
2267  * @brief Get the SMB credential of a target as an osp_credential_t
2268  *
2269  * @param[in]  target  The target to get the credential from.
2270  *
2271  * @return  Pointer to a newly allocated osp_credential_t
2272  */
2273 static osp_credential_t *
target_osp_snmp_credential(target_t target)2274 target_osp_snmp_credential (target_t target)
2275 {
2276   credential_t credential;
2277   credential = target_credential (target, "snmp");
2278   if (credential)
2279     {
2280       iterator_t iter;
2281       osp_credential_t *osp_credential;
2282 
2283       init_credential_iterator_one (&iter, credential);
2284       if (!next (&iter))
2285         {
2286           g_warning ("%s: SNMP Credential not found.", __func__);
2287           cleanup_iterator (&iter);
2288           return NULL;
2289         }
2290       if (strcmp (credential_iterator_type (&iter), "snmp"))
2291         {
2292           g_warning ("%s: SNMP Credential not of type 'snmp'.",
2293                      __func__);
2294           cleanup_iterator (&iter);
2295           return NULL;
2296         }
2297 
2298       osp_credential = osp_credential_new ("snmp", "snmp", NULL);
2299       osp_credential_set_auth_data (osp_credential,
2300                                     "username",
2301                                     credential_iterator_login (&iter)
2302                                       ?: "");
2303       osp_credential_set_auth_data (osp_credential,
2304                                     "password",
2305                                     credential_iterator_password (&iter)
2306                                       ?: "");
2307       osp_credential_set_auth_data (osp_credential,
2308                                     "community",
2309                                     credential_iterator_community (&iter)
2310                                       ?: "");
2311       osp_credential_set_auth_data (osp_credential,
2312                                     "auth_algorithm",
2313                                     credential_iterator_auth_algorithm (&iter)
2314                                       ?: "");
2315       osp_credential_set_auth_data (osp_credential,
2316                                     "privacy_algorithm",
2317                                     credential_iterator_privacy_algorithm
2318                                       (&iter) ?: "");
2319       osp_credential_set_auth_data (osp_credential,
2320                                     "privacy_password",
2321                                     credential_iterator_privacy_password
2322                                       (&iter) ?: "");
2323       cleanup_iterator (&iter);
2324       return osp_credential;
2325     }
2326   return NULL;
2327 }
2328 
2329 /**
2330  * @brief Prepare a report for resuming an OSP scan
2331  *
2332  * @param[in]  task     The task of the scan.
2333  * @param[in]  scan_id  The scan uuid.
2334  * @param[out] error    Error return.
2335  *
2336  * @return 0 scan finished or still running,
2337  *         1 scan must be started,
2338  *         -1 error
2339  */
2340 static int
prepare_osp_scan_for_resume(task_t task,const char * scan_id,char ** error)2341 prepare_osp_scan_for_resume (task_t task, const char *scan_id, char **error)
2342 {
2343   osp_connection_t *connection;
2344   osp_get_scan_status_opts_t status_opts;
2345   osp_scan_status_t status;
2346 
2347   assert (task);
2348   assert (scan_id);
2349   assert (global_current_report);
2350   assert (error);
2351 
2352   status_opts.scan_id = scan_id;
2353 
2354   connection = osp_scanner_connect (task_scanner (task));
2355   if (!connection)
2356     {
2357       *error = g_strdup ("Could not connect to Scanner");
2358       return -1;
2359     }
2360   status = osp_get_scan_status_ext (connection, status_opts, error);
2361 
2362   /* Reset connection. */
2363   osp_connection_close (connection);
2364   connection = osp_scanner_connect (task_scanner (task));
2365   if (!connection)
2366     {
2367       *error = g_strdup ("Could not connect to Scanner");
2368       return -1;
2369     }
2370 
2371   if (status == OSP_SCAN_STATUS_ERROR)
2372     {
2373       if (g_str_has_prefix (*error, "Failed to find scan"))
2374         {
2375           g_debug ("%s: Scan %s not found", __func__, scan_id);
2376           g_free (*error);
2377           *error = NULL;
2378           osp_connection_close (connection);
2379           trim_partial_report (global_current_report);
2380           return 1;
2381         }
2382       else
2383         {
2384           g_warning ("%s: Error getting status of scan %s: %s",
2385                      __func__, scan_id, *error);
2386           osp_connection_close (connection);
2387           return -1;
2388         }
2389     }
2390   else if (status == OSP_SCAN_STATUS_RUNNING
2391            || status == OSP_SCAN_STATUS_QUEUED)
2392     {
2393       g_debug ("%s: Scan %s queued or running", __func__, scan_id);
2394       /* It would be possible to simply continue getting the results
2395        * from the scanner, but gvmd may have crashed while receiving
2396        * or storing the results, so some may be missing. */
2397       if (osp_stop_scan (connection, scan_id, error))
2398         {
2399           osp_connection_close (connection);
2400           return -1;
2401         }
2402       if (osp_delete_scan (connection, scan_id))
2403         {
2404           *error = g_strdup ("Failed to delete old report");
2405           osp_connection_close (connection);
2406           return -1;
2407         }
2408       osp_connection_close (connection);
2409       trim_partial_report (global_current_report);
2410       return 1;
2411     }
2412   else if (status == OSP_SCAN_STATUS_FINISHED)
2413     {
2414       /* OSP can't stop an already finished/interrupted scan,
2415        * but it must be delete to be resumed. */
2416       g_debug ("%s: Scan %s finished", __func__, scan_id);
2417       if (osp_delete_scan (connection, scan_id))
2418         {
2419           *error = g_strdup ("Failed to delete old report");
2420           osp_connection_close (connection);
2421           return -1;
2422         }
2423       osp_connection_close (connection);
2424       trim_partial_report (global_current_report);
2425       return 1;
2426     }
2427   else if (status == OSP_SCAN_STATUS_STOPPED
2428            || status == OSP_SCAN_STATUS_INTERRUPTED)
2429     {
2430       g_debug ("%s: Scan %s stopped or interrupted",
2431                __func__, scan_id);
2432       if (osp_delete_scan (connection, scan_id))
2433         {
2434           *error = g_strdup ("Failed to delete old report");
2435           osp_connection_close (connection);
2436           return -1;
2437         }
2438       osp_connection_close (connection);
2439       trim_partial_report (global_current_report);
2440       return 1;
2441     }
2442 
2443   g_warning ("%s: Unexpected scanner status %d", __func__, status);
2444   *error = g_strdup_printf ("Unexpected scanner status %d", status);
2445   osp_connection_close (connection);
2446   return -1;
2447 }
2448 
2449 /**
2450  * @brief Add OSP preferences for limiting ifaces and hosts for users.
2451  *
2452  * @param[in]  scanner_options  The scanner preferences table to add to.
2453  */
2454 static void
add_user_scan_preferences(GHashTable * scanner_options)2455 add_user_scan_preferences (GHashTable *scanner_options)
2456 {
2457   gchar *hosts, *ifaces, *name;
2458   int hosts_allow, ifaces_allow;
2459 
2460   // Limit access to hosts
2461   hosts = user_hosts (current_credentials.uuid);
2462   hosts_allow = user_hosts_allow (current_credentials.uuid);
2463 
2464   if (hosts_allow == 1)
2465     name = g_strdup ("hosts_allow");
2466   else if (hosts_allow == 0)
2467     name = g_strdup ("hosts_deny");
2468   else
2469     name = NULL;
2470 
2471   if (name
2472       && (hosts_allow || (hosts && strlen (hosts))))
2473     g_hash_table_replace (scanner_options,
2474                           name,
2475                           hosts ? hosts : g_strdup (""));
2476   else
2477     g_free (hosts);
2478 
2479   // Limit access to ifaces
2480   ifaces = user_ifaces (current_credentials.uuid);
2481   ifaces_allow = user_ifaces_allow (current_credentials.uuid);
2482 
2483   if (ifaces_allow == 1)
2484     name = g_strdup ("ifaces_allow");
2485   else if (ifaces_allow == 0)
2486     name = g_strdup ("ifaces_deny");
2487   else
2488     name = NULL;
2489 
2490   if (name
2491       && (ifaces_allow || (ifaces && strlen (ifaces))))
2492     g_hash_table_replace (scanner_options,
2493                           name,
2494                           ifaces ? ifaces : g_strdup (""));
2495   else
2496     g_free (ifaces);
2497 }
2498 
2499 /**
2500  * @brief Launch an OpenVAS via OSP task.
2501  *
2502  * @param[in]   task        The task.
2503  * @param[in]   target      The target.
2504  * @param[in]   scan_id     The scan uuid.
2505  * @param[in]   from        0 start from beginning, 1 continue from stopped,
2506  *                          2 continue if stopped else start from beginning.
2507  * @param[out]  error       Error return.
2508  *
2509  * @return 0 success, -1 if scanner is down.
2510  */
2511 static int
launch_osp_openvas_task(task_t task,target_t target,const char * scan_id,int from,char ** error)2512 launch_osp_openvas_task (task_t task, target_t target, const char *scan_id,
2513                          int from, char **error)
2514 {
2515   osp_connection_t *connection;
2516   char *hosts_str, *ports_str, *exclude_hosts_str, *finished_hosts_str;
2517   gchar *clean_hosts, *clean_exclude_hosts, *clean_finished_hosts_str;
2518   int alive_test, reverse_lookup_only, reverse_lookup_unify;
2519   osp_target_t *osp_target;
2520   GSList *osp_targets, *vts;
2521   GHashTable *vts_hash_table;
2522   osp_credential_t *ssh_credential, *smb_credential, *esxi_credential;
2523   osp_credential_t *snmp_credential;
2524   gchar *max_checks, *max_hosts, *source_iface, *hosts_ordering;
2525   GHashTable *scanner_options;
2526   int ret;
2527   config_t config;
2528   iterator_t scanner_prefs_iter, families, prefs;
2529   osp_start_scan_opts_t start_scan_opts;
2530 
2531   config = task_config (task);
2532 
2533   connection = NULL;
2534 
2535   alive_test = 0;
2536   reverse_lookup_unify = 0;
2537   reverse_lookup_only = 0;
2538 
2539   /* Prepare the report */
2540   if (from)
2541     {
2542       ret = prepare_osp_scan_for_resume (task, scan_id, error);
2543       if (ret == 0)
2544         return 0;
2545       else if (ret == -1)
2546         return -1;
2547       finished_hosts_str = report_finished_hosts_str (global_current_report);
2548       clean_finished_hosts_str = clean_hosts_string (finished_hosts_str);
2549     }
2550   else
2551     {
2552       finished_hosts_str = NULL;
2553       clean_finished_hosts_str = NULL;
2554     }
2555 
2556   /* Set up target(s) */
2557   hosts_str = target_hosts (target);
2558   ports_str = target_port_range (target);
2559   exclude_hosts_str = target_exclude_hosts (target);
2560 
2561   clean_hosts = clean_hosts_string (hosts_str);
2562   clean_exclude_hosts = clean_hosts_string (exclude_hosts_str);
2563 
2564   if (target_alive_tests (target) > 0)
2565    alive_test = target_alive_tests (target);
2566 
2567   if (target_reverse_lookup_only (target) != NULL)
2568     reverse_lookup_only = atoi (target_reverse_lookup_only (target));
2569 
2570   if (target_reverse_lookup_unify (target) != NULL)
2571     reverse_lookup_unify = atoi (target_reverse_lookup_unify (target));
2572 
2573   if (finished_hosts_str)
2574     {
2575       gchar *new_exclude_hosts;
2576 
2577       new_exclude_hosts = g_strdup_printf ("%s,%s",
2578                                            clean_exclude_hosts,
2579                                            clean_finished_hosts_str);
2580       free (clean_exclude_hosts);
2581       clean_exclude_hosts = new_exclude_hosts;
2582     }
2583 
2584   osp_target = osp_target_new (clean_hosts, ports_str, clean_exclude_hosts,
2585                                alive_test, reverse_lookup_unify,
2586                                reverse_lookup_only);
2587   if (finished_hosts_str)
2588     osp_target_set_finished_hosts (osp_target, finished_hosts_str);
2589 
2590   free (hosts_str);
2591   free (ports_str);
2592   free (exclude_hosts_str);
2593   free (finished_hosts_str);
2594   g_free (clean_hosts);
2595   g_free (clean_exclude_hosts);
2596   g_free (clean_finished_hosts_str);
2597   osp_targets = g_slist_append (NULL, osp_target);
2598 
2599   ssh_credential = target_osp_ssh_credential (target);
2600   if (ssh_credential)
2601     osp_target_add_credential (osp_target, ssh_credential);
2602 
2603   smb_credential = target_osp_smb_credential (target);
2604   if (smb_credential)
2605     osp_target_add_credential (osp_target, smb_credential);
2606 
2607   esxi_credential = target_osp_esxi_credential (target);
2608   if (esxi_credential)
2609     osp_target_add_credential (osp_target, esxi_credential);
2610 
2611   snmp_credential = target_osp_snmp_credential (target);
2612   if (snmp_credential)
2613     osp_target_add_credential (osp_target, snmp_credential);
2614 
2615   /* Setup general scanner preferences */
2616   scanner_options
2617     = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
2618   init_preference_iterator (&scanner_prefs_iter, config, "SERVER_PREFS");
2619   while (next (&scanner_prefs_iter))
2620     {
2621       const char *name, *value;
2622       name = preference_iterator_name (&scanner_prefs_iter);
2623       value = preference_iterator_value (&scanner_prefs_iter);
2624       if (name && value)
2625         {
2626           const char *osp_value;
2627 
2628           // Workaround for boolean scanner preferences
2629           if (strcmp (value, "yes") == 0)
2630             osp_value = "1";
2631           else if (strcmp (value, "no") == 0)
2632             osp_value = "0";
2633           else
2634             osp_value = value;
2635           g_hash_table_replace (scanner_options,
2636                                 g_strdup (name),
2637                                 g_strdup (osp_value));
2638         }
2639     }
2640   cleanup_iterator (&scanner_prefs_iter);
2641 
2642   /* Setup user-specific scanner preference */
2643   add_user_scan_preferences (scanner_options);
2644 
2645   /* Setup general task preferences */
2646   max_checks = task_preference_value (task, "max_checks");
2647   g_hash_table_insert (scanner_options, g_strdup ("max_checks"),
2648                        max_checks ? max_checks : g_strdup (MAX_CHECKS_DEFAULT));
2649 
2650   max_hosts = task_preference_value (task, "max_hosts");
2651   g_hash_table_insert (scanner_options, g_strdup ("max_hosts"),
2652                        max_hosts ? max_hosts : g_strdup (MAX_HOSTS_DEFAULT));
2653 
2654   source_iface = task_preference_value (task, "source_iface");
2655   if (source_iface)
2656     g_hash_table_insert (scanner_options, g_strdup ("source_iface"),
2657                         source_iface);
2658 
2659   hosts_ordering = task_hosts_ordering (task);
2660   if (hosts_ordering)
2661     g_hash_table_insert (scanner_options, g_strdup ("hosts_ordering"),
2662                          hosts_ordering);
2663 
2664   /* Setup vulnerability tests (without preferences) */
2665   vts = NULL;
2666   vts_hash_table
2667     = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
2668                              /* Value is freed in vts list. */
2669                              NULL);
2670 
2671   init_family_iterator (&families, 0, NULL, 1);
2672   while (next (&families))
2673     {
2674       const char *family = family_iterator_name (&families);
2675       if (family)
2676         {
2677           iterator_t nvts;
2678           init_nvt_iterator (&nvts, 0, config, family, NULL, 1, NULL);
2679           while (next (&nvts))
2680             {
2681               const char *oid;
2682               osp_vt_single_t *new_vt;
2683 
2684               oid = nvt_iterator_oid (&nvts);
2685               new_vt = osp_vt_single_new (oid);
2686 
2687               vts = g_slist_prepend (vts, new_vt);
2688               g_hash_table_replace (vts_hash_table, g_strdup (oid), new_vt);
2689             }
2690           cleanup_iterator (&nvts);
2691         }
2692     }
2693   cleanup_iterator (&families);
2694 
2695   /* Setup VT preferences */
2696   init_preference_iterator (&prefs, config, "PLUGINS_PREFS");
2697   while (next (&prefs))
2698     {
2699       const char *full_name, *value;
2700       osp_vt_single_t *osp_vt;
2701       gchar **split_name;
2702 
2703       full_name = preference_iterator_name (&prefs);
2704       value = preference_iterator_value (&prefs);
2705       split_name = g_strsplit (full_name, ":", 4);
2706 
2707       osp_vt = NULL;
2708       if (split_name && split_name[0] && split_name[1] && split_name[2])
2709         {
2710           const char *oid = split_name[0];
2711           const char *pref_id = split_name[1];
2712           const char *type = split_name[2];
2713           gchar *osp_value = NULL;
2714 
2715           if (strcmp (type, "checkbox") == 0)
2716             {
2717               if (strcmp (value, "yes") == 0)
2718                 osp_value = g_strdup ("1");
2719               else
2720                 osp_value = g_strdup ("0");
2721             }
2722           else if (strcmp (type, "radio") == 0)
2723             {
2724               gchar** split_value;
2725               split_value = g_strsplit (value, ";", 2);
2726               osp_value = g_strdup (split_value[0]);
2727               g_strfreev (split_value);
2728             }
2729           else if (strcmp (type, "file") == 0)
2730             osp_value = g_base64_encode ((guchar*) value, strlen (value));
2731 
2732           osp_vt = g_hash_table_lookup (vts_hash_table, oid);
2733           if (osp_vt)
2734             osp_vt_single_add_value (osp_vt, pref_id,
2735                                      osp_value ? osp_value : value);
2736           g_free (osp_value);
2737         }
2738 
2739       g_strfreev (split_name);
2740     }
2741   cleanup_iterator (&prefs);
2742   g_hash_table_destroy (vts_hash_table);
2743 
2744   /* Start the scan */
2745   connection = osp_scanner_connect (task_scanner (task));
2746   if (!connection)
2747     {
2748       if (error)
2749         *error = g_strdup ("Could not connect to Scanner");
2750       g_slist_free_full (osp_targets, (GDestroyNotify) osp_target_free);
2751       // Credentials are freed with target
2752       g_slist_free_full (vts, (GDestroyNotify) osp_vt_single_free);
2753       g_hash_table_destroy (scanner_options);
2754       return -1;
2755     }
2756 
2757   start_scan_opts.targets = osp_targets;
2758   start_scan_opts.vt_groups = NULL;
2759   start_scan_opts.vts = vts;
2760   start_scan_opts.scanner_params = scanner_options;
2761   start_scan_opts.scan_id = scan_id;
2762 
2763   ret = osp_start_scan_ext (connection,
2764                             start_scan_opts,
2765                             error);
2766 
2767   osp_connection_close (connection);
2768   g_slist_free_full (osp_targets, (GDestroyNotify) osp_target_free);
2769   // Credentials are freed with target
2770   g_slist_free_full (vts, (GDestroyNotify) osp_vt_single_free);
2771   g_hash_table_destroy (scanner_options);
2772   return ret;
2773 }
2774 
2775 /**
2776  * @brief Get the last stopped report or a new one for an OSP scan.
2777  *
2778  * @param[in]   task      The task.
2779  * @param[in]   from      0 start from beginning, 1 continue from stopped,
2780  *                        2 continue if stopped else start from beginning.
2781  * @param[out]  report_id UUID of the report.
2782  *
2783  * @return 0 success, -1 error
2784  */
2785 static int
run_osp_scan_get_report(task_t task,int from,char ** report_id)2786 run_osp_scan_get_report (task_t task, int from, char **report_id)
2787 {
2788   report_t resume_report;
2789 
2790   resume_report = 0;
2791   *report_id = NULL;
2792 
2793   if (from == 1
2794       && scanner_type (task_scanner (task)) == SCANNER_TYPE_OSP)
2795     {
2796       g_warning ("%s: Scanner type does not support resuming scans",
2797                  __func__);
2798       return -1;
2799     }
2800 
2801   if (from
2802       && scanner_type (task_scanner (task)) != SCANNER_TYPE_OSP
2803       && task_last_resumable_report (task, &resume_report))
2804     {
2805       g_warning ("%s: error getting report to resume", __func__);
2806       return -1;
2807     }
2808 
2809   if (resume_report)
2810     {
2811       // Report to resume found
2812       if (global_current_report)
2813         {
2814            g_warning ("%s: global_current_report already set", __func__);
2815           return -1;
2816         }
2817       global_current_report = resume_report;
2818       *report_id = report_uuid (resume_report);
2819 
2820       /* Ensure the report is marked as requested. */
2821       set_report_scan_run_status (resume_report, TASK_STATUS_REQUESTED);
2822 
2823       /* Clear the end times of the task and partial report. */
2824       set_task_start_time_epoch (task,
2825                                  scan_start_time_epoch (resume_report));
2826       set_task_end_time (task, NULL);
2827       set_scan_end_time (resume_report, NULL);
2828     }
2829   else if (from == 1)
2830     // No report to resume and starting a new one is not allowed
2831     return -1;
2832 
2833   // Try starting a new report
2834   if (resume_report == 0
2835       && create_current_report (task, report_id, TASK_STATUS_REQUESTED))
2836     {
2837       g_debug ("   %s: failed to create report", __func__);
2838       return -1;
2839     }
2840 
2841   return 0;
2842 }
2843 
2844 /**
2845  * @brief Fork a child to handle an OSP scan's fetching and inserting.
2846  *
2847  * @param[in]   task       The task.
2848  * @param[in]   target     The target.
2849  * @param[in]   from       0 start from beginning, 1 continue from stopped,
2850  *                         2 continue if stopped else start from beginning.
2851  * @param[out]  report_id_return   UUID of the report.
2852  *
2853  * @return Parent returns with 0 if success, -1 if failure. Child process
2854  *         doesn't return and simply exits.
2855  */
2856 static int
fork_osp_scan_handler(task_t task,target_t target,int from,char ** report_id_return)2857 fork_osp_scan_handler (task_t task, target_t target, int from,
2858                        char **report_id_return)
2859 {
2860   char *report_id, title[128], *error = NULL;
2861   int rc;
2862 
2863   assert (task);
2864   assert (target);
2865 
2866   if (report_id_return)
2867     *report_id_return = NULL;
2868 
2869   if (run_osp_scan_get_report (task, from, &report_id))
2870     return -1;
2871 
2872   current_scanner_task = task;
2873   set_task_run_status (task, TASK_STATUS_REQUESTED);
2874 
2875   switch (fork ())
2876     {
2877       case 0:
2878         break;
2879       case -1:
2880         /* Parent, failed to fork. */
2881         global_current_report = 0;
2882         g_warning ("%s: Failed to fork: %s",
2883                    __func__,
2884                    strerror (errno));
2885         set_task_interrupted (task,
2886                               "Error forking scan handler."
2887                               "  Interrupting scan.");
2888         set_report_scan_run_status (global_current_report,
2889                                     TASK_STATUS_INTERRUPTED);
2890         global_current_report = (report_t) 0;
2891         current_scanner_task = 0;
2892         g_free (report_id);
2893         return -9;
2894       default:
2895         /* Parent, successfully forked. */
2896         global_current_report = 0;
2897         current_scanner_task = 0;
2898         if (report_id_return)
2899           *report_id_return = report_id;
2900         else
2901           g_free (report_id);
2902         return 0;
2903     }
2904 
2905   /* Child: Re-open DB after fork and periodically check scan progress.
2906    * If progress == 100%: Parse the report results and other info then exit(0).
2907    * Else, exit(1) in error cases like connection to scanner failure.
2908    */
2909   reinit_manage_process ();
2910   manage_session_init (current_credentials.uuid);
2911 
2912   if (scanner_type (task_scanner (task)) == SCANNER_TYPE_OPENVAS
2913       || scanner_type (task_scanner (task) == SCANNER_TYPE_OSP_SENSOR))
2914     {
2915       rc = launch_osp_openvas_task (task, target, report_id, from, &error);
2916     }
2917   else
2918     {
2919       rc = launch_osp_task (task, target, report_id, &error);
2920     }
2921 
2922   if (rc)
2923     {
2924       result_t result;
2925 
2926       g_warning ("OSP start_scan %s: %s", report_id, error);
2927       result = make_osp_result (task, "", "", "",
2928                                 threat_message_type ("Error"),
2929                                 error, "", "", QOD_DEFAULT, NULL);
2930       report_add_result (global_current_report, result);
2931       set_task_run_status (task, TASK_STATUS_DONE);
2932       set_report_scan_run_status (global_current_report, TASK_STATUS_DONE);
2933       set_task_end_time_epoch (task, time (NULL));
2934       set_scan_end_time_epoch (global_current_report, time (NULL));
2935 
2936       g_free (error);
2937       g_free (report_id);
2938       exit (-1);
2939     }
2940 
2941   snprintf (title, sizeof (title), "gvmd: OSP: Handling scan %s", report_id);
2942   proctitle_set (title);
2943 
2944   rc = handle_osp_scan (task, global_current_report, report_id);
2945   g_free (report_id);
2946   if (rc == 0)
2947     {
2948       hosts_set_identifiers (global_current_report);
2949       hosts_set_max_severity (global_current_report, NULL, NULL);
2950       hosts_set_details (global_current_report);
2951       set_task_run_status (task, TASK_STATUS_DONE);
2952       set_report_scan_run_status (global_current_report, TASK_STATUS_DONE);
2953     }
2954   else if (rc == -1 || rc == -2)
2955     {
2956       set_task_run_status (task, TASK_STATUS_STOPPED);
2957       set_report_scan_run_status (global_current_report, TASK_STATUS_STOPPED);
2958     }
2959   else if (rc == -3)
2960     {
2961       set_task_run_status (task, TASK_STATUS_INTERRUPTED);
2962       set_report_scan_run_status (global_current_report, TASK_STATUS_INTERRUPTED);
2963     }
2964 
2965   set_task_end_time_epoch (task, time (NULL));
2966   set_scan_end_time_epoch (global_current_report, time (NULL));
2967   global_current_report = 0;
2968   current_scanner_task = (task_t) 0;
2969   exit (rc);
2970 }
2971 
2972 /**
2973  * @brief Start a task on an OSP or OpenVAS via OSP scanner.
2974  *
2975  * @param[in]   task       The task.
2976  * @param[in]   from       0 start from beginning, 1 continue from stopped,
2977  *                         2 continue if stopped else start from beginning.
2978  * @param[out]  report_id  The report ID.
2979  *
2980  * @return 0 success, 99 permission denied, -1 error.
2981  */
2982 static int
run_osp_task(task_t task,int from,char ** report_id)2983 run_osp_task (task_t task, int from, char **report_id)
2984 {
2985   target_t target;
2986 
2987   target = task_target (task);
2988   if (target)
2989     {
2990       char *uuid;
2991       target_t found;
2992 
2993       uuid = target_uuid (target);
2994       if (find_target_with_permission (uuid, &found, "get_targets"))
2995         {
2996           g_free (uuid);
2997           return -1;
2998         }
2999       g_free (uuid);
3000       if (found == 0)
3001         return 99;
3002     }
3003 
3004   if (fork_osp_scan_handler (task, target, from, report_id))
3005     {
3006       g_warning ("Couldn't fork OSP scan handler");
3007       return -1;
3008     }
3009   return 0;
3010 }
3011 
3012 /**
3013  * @brief Get the number of retries on a scanner connection lost.
3014  *
3015  * @return The number of retries on a scanner connection lost.
3016  */
3017 int
get_scanner_connection_retry()3018 get_scanner_connection_retry ()
3019 {
3020   return scanner_connection_retry;
3021 }
3022 
3023 /**
3024  * @brief Set the number of retries on a scanner connection lost.
3025  *
3026  * @param new_retry The number of retries on a scanner connection lost.
3027  */
3028 void
set_scanner_connection_retry(int new_retry)3029 set_scanner_connection_retry (int new_retry)
3030 {
3031   if (new_retry >= 0)
3032     scanner_connection_retry = new_retry;
3033 }
3034 
3035 
3036 /* CVE tasks. */
3037 
3038 /**
3039  * @brief Perform a CVE "scan" on a host.
3040  *
3041  * @param[in]  task      Task.
3042  * @param[in]  report    The report to add the host, results and details to.
3043  * @param[in]  gvm_host  Host.
3044  *
3045  * @return 0 success, 1 failed to get nthlast report for a host.
3046  */
3047 static int
cve_scan_host(task_t task,report_t report,gvm_host_t * gvm_host)3048 cve_scan_host (task_t task, report_t report, gvm_host_t *gvm_host)
3049 {
3050   report_host_t report_host;
3051   gchar *ip, *host;
3052 
3053   assert (task);
3054   assert (report);
3055 
3056   host = gvm_host_value_str (gvm_host);
3057 
3058   ip = report_host_ip (host);
3059   if (ip == NULL)
3060     ip = g_strdup (host);
3061 
3062   g_debug ("%s: ip: %s", __func__, ip);
3063 
3064   /* Get the last report host that applies to the host IP address. */
3065 
3066   if (host_nthlast_report_host (ip, &report_host, 1))
3067     {
3068       g_warning ("%s: Failed to get nthlast report", __func__);
3069       g_free (ip);
3070       return 1;
3071     }
3072 
3073   g_debug ("%s: report_host: %llu", __func__, report_host);
3074 
3075   if (report_host)
3076     {
3077       iterator_t report_hosts;
3078 
3079       /* Get the report_host for the host. */
3080 
3081       init_report_host_iterator (&report_hosts, 0, NULL, report_host);
3082       if (next (&report_hosts))
3083         {
3084           iterator_t prognosis;
3085           int prognosis_report_host, start_time;
3086           GArray *results;
3087 
3088           /* Add report_host with prognosis results and host details. */
3089 
3090           results = g_array_new (TRUE, TRUE, sizeof (result_t));
3091           start_time = time (NULL);
3092           prognosis_report_host = 0;
3093           init_host_prognosis_iterator (&prognosis, report_host);
3094           while (next (&prognosis))
3095             {
3096               const char *app, *cve;
3097               double severity;
3098               gchar *desc;
3099               iterator_t locations_iter;
3100               GString *locations;
3101               result_t result;
3102 
3103               if (prognosis_report_host == 0)
3104                 prognosis_report_host = manage_report_host_add (report,
3105                                                                 ip,
3106                                                                 start_time,
3107                                                                 0);
3108 
3109               severity = prognosis_iterator_cvss_double (&prognosis);
3110 
3111               app = prognosis_iterator_cpe (&prognosis);
3112               cve = prognosis_iterator_cve (&prognosis);
3113               locations = g_string_new("");
3114 
3115               insert_report_host_detail (global_current_report, ip, "cve", cve,
3116                                          "CVE Scanner", "App", app);
3117 
3118               init_app_locations_iterator (&locations_iter, report_host, app);
3119 
3120               while (next (&locations_iter))
3121                 {
3122                   const char *location;
3123                   location = app_locations_iterator_location (&locations_iter);
3124 
3125                   if (locations->len)
3126                     g_string_append (locations, ", ");
3127                   g_string_append (locations, location);
3128 
3129                   insert_report_host_detail (report, ip, "cve", cve,
3130                                              "CVE Scanner", app, location);
3131 
3132                   insert_report_host_detail (report, ip, "cve", cve,
3133                                              "CVE Scanner", "detected_at",
3134                                              location);
3135 
3136                   insert_report_host_detail (report, ip, "cve", cve,
3137                                              "CVE Scanner", "detected_by",
3138                                              /* Detected by itself. */
3139                                              cve);
3140                 }
3141 
3142               desc = g_strdup_printf ("The host carries the product: %s\n"
3143                                       "It is vulnerable according to: %s.\n"
3144                                       "%s%s%s"
3145                                       "\n"
3146                                       "%s",
3147                                       app,
3148                                       cve,
3149                                       locations->len
3150                                        ? "The product was found at: "
3151                                        : "",
3152                                       locations->len ? locations->str : "",
3153                                       locations->len ? ".\n" : "",
3154                                       prognosis_iterator_description
3155                                        (&prognosis));
3156 
3157               g_debug ("%s: making result with severity %1.1f desc [%s]",
3158                        __func__, severity, desc);
3159 
3160               result = make_cve_result (task, ip, cve, severity, desc);
3161               g_free (desc);
3162 
3163               g_array_append_val (results, result);
3164 
3165               g_string_free (locations, TRUE);
3166             }
3167           cleanup_iterator (&prognosis);
3168 
3169           report_add_results_array (report, results);
3170           g_array_free (results, TRUE);
3171 
3172           if (prognosis_report_host)
3173             {
3174               /* Complete the report_host. */
3175 
3176               report_host_set_end_time (prognosis_report_host, time (NULL));
3177               insert_report_host_detail (report, ip, "cve", "",
3178                                          "CVE Scanner", "CVE Scan", "1");
3179             }
3180         }
3181       cleanup_iterator (&report_hosts);
3182     }
3183 
3184   g_free (ip);
3185   return 0;
3186 }
3187 
3188 /**
3189  * @brief Fork a child to handle a CVE scan's calculating and inserting.
3190  *
3191  * A process is forked to run the task, but the forked process never returns.
3192  *
3193  * @param[in]   task        The task.
3194  * @param[in]   target      The target.
3195  *
3196  * @return 0 success, -1 error, -9 failed to fork.
3197  */
3198 static int
fork_cve_scan_handler(task_t task,target_t target)3199 fork_cve_scan_handler (task_t task, target_t target)
3200 {
3201   int pid;
3202   char *report_id, title[128], *hosts;
3203   gvm_hosts_t *gvm_hosts;
3204   gvm_host_t *gvm_host;
3205 
3206   assert (task);
3207   assert (target);
3208 
3209   if (create_current_report (task, &report_id, TASK_STATUS_REQUESTED))
3210     {
3211       g_debug ("   %s: failed to create report", __func__);
3212       return -1;
3213     }
3214 
3215   set_task_run_status (task, TASK_STATUS_REQUESTED);
3216 
3217   pid = fork ();
3218   switch (pid)
3219     {
3220       case 0:
3221         break;
3222       case -1:
3223         /* Parent, failed to fork. */
3224         g_warning ("%s: Failed to fork: %s",
3225                    __func__,
3226                    strerror (errno));
3227         set_task_interrupted (task,
3228                               "Error forking scan handler."
3229                               "  Interrupting scan.");
3230         set_report_scan_run_status (global_current_report,
3231                                     TASK_STATUS_INTERRUPTED);
3232         global_current_report = (report_t) 0;
3233         return -9;
3234       default:
3235         /* Parent, successfully forked. */
3236         g_debug ("%s: %i forked %i", __func__, getpid (), pid);
3237         return 0;
3238     }
3239 
3240   /* Child.
3241    *
3242    * Re-open DB and do prognostic calculation.  On success exit(0), else
3243    * exit(1). */
3244   reinit_manage_process ();
3245   manage_session_init (current_credentials.uuid);
3246 
3247   /* Setup the task. */
3248 
3249   set_task_run_status (task, TASK_STATUS_RUNNING);
3250 
3251   snprintf (title, sizeof (title), "gvmd: CVE: Handling scan %s", report_id);
3252   g_free (report_id);
3253   proctitle_set (title);
3254 
3255   hosts = target_hosts (target);
3256   if (hosts == NULL)
3257     {
3258       set_task_interrupted (task,
3259                             "Error in target host list."
3260                             "  Interrupting scan.");
3261       set_report_scan_run_status (global_current_report, TASK_STATUS_INTERRUPTED);
3262       exit (1);
3263     }
3264 
3265   reset_task (task);
3266   set_task_start_time_epoch (task, time (NULL));
3267   set_scan_start_time_epoch (global_current_report, time (NULL));
3268 
3269   /* Add the results. */
3270 
3271   gvm_hosts = gvm_hosts_new (hosts);
3272   free (hosts);
3273   while ((gvm_host = gvm_hosts_next (gvm_hosts)))
3274     if (cve_scan_host (task, global_current_report, gvm_host))
3275       {
3276         set_task_interrupted (task,
3277                               "Failed to get nthlast report."
3278                               "  Interrupting scan.");
3279         set_report_scan_run_status (global_current_report, TASK_STATUS_INTERRUPTED);
3280         gvm_hosts_free (gvm_hosts);
3281         exit (1);
3282       }
3283   gvm_hosts_free (gvm_hosts);
3284 
3285   /* Set the end states. */
3286 
3287   set_scan_end_time_epoch (global_current_report, time (NULL));
3288   set_task_end_time_epoch (task, time (NULL));
3289   set_task_run_status (task, TASK_STATUS_DONE);
3290   set_report_scan_run_status (global_current_report, TASK_STATUS_DONE);
3291   global_current_report = 0;
3292   current_scanner_task = (task_t) 0;
3293   exit (0);
3294 }
3295 
3296 /**
3297  * @brief Start a CVE task.
3298  *
3299  * @param[in]   task    The task.
3300  *
3301  * @return 0 success, 99 permission denied, -1 error, -9 failed to fork.
3302  */
3303 static int
run_cve_task(task_t task)3304 run_cve_task (task_t task)
3305 {
3306   target_t target;
3307 
3308   target = task_target (task);
3309   if (target)
3310     {
3311       char *uuid;
3312       target_t found;
3313 
3314       uuid = target_uuid (target);
3315       if (find_target_with_permission (uuid, &found, "get_targets"))
3316         {
3317           g_free (uuid);
3318           return -1;
3319         }
3320       g_free (uuid);
3321       if (found == 0)
3322         return 99;
3323     }
3324 
3325   if (fork_cve_scan_handler (task, target))
3326     {
3327       g_warning ("Couldn't fork CVE scan handler");
3328       return -1;
3329     }
3330   return 0;
3331 }
3332 
3333 
3334 /* Tasks. */
3335 
3336 /**
3337  * @brief Gets the current path of the relay mapper executable.
3338  *
3339  * @return The current relay mapper path.
3340  */
3341 const char *
get_relay_mapper_path()3342 get_relay_mapper_path ()
3343 {
3344   return relay_mapper_path;
3345 }
3346 
3347 /**
3348  * @brief Gets the current path of the relay mapper executable.
3349  *
3350  * @param[in]  new_path  The new relay mapper path.
3351  */
3352 void
set_relay_mapper_path(const char * new_path)3353 set_relay_mapper_path (const char *new_path)
3354 {
3355   g_free (relay_mapper_path);
3356   relay_mapper_path = new_path ? g_strdup (new_path) : NULL;
3357 }
3358 
3359 /**
3360  * @brief Gets whether to migrate sensors if relays do not match.
3361  *
3362  * @return Whether to migrate sensors if relays do not match.
3363  */
3364 int
get_relay_migrate_sensors()3365 get_relay_migrate_sensors ()
3366 {
3367   return relay_migrate_sensors;
3368 }
3369 
3370 /**
3371  * @brief Sets whether to migrate sensors if relays do not match.
3372  *
3373  * @param[in]  new_value  The new value.
3374  */
3375 void
set_relay_migrate_sensors(int new_value)3376 set_relay_migrate_sensors (int new_value)
3377 {
3378   relay_migrate_sensors = new_value;
3379 }
3380 
3381 /**
3382  * @brief Gets the info about a scanner relay as an XML entity_t.
3383  *
3384  * @param[in]  original_host    The original hostname or IP address.
3385  * @param[in]  original_port    The original port number.
3386  * @param[in]  protocol         The protocol to look for, e.g. "GMP" or "OSP".
3387  * @param[out] ret_entity       Return location for the parsed XML.
3388  *
3389  * @return 0: success, -1 error.
3390  */
3391 static int
get_relay_info_entity(const char * original_host,int original_port,const char * protocol,entity_t * ret_entity)3392 get_relay_info_entity (const char *original_host, int original_port,
3393                        const char *protocol, entity_t *ret_entity)
3394 {
3395   gchar **cmd, *stdout_str, *stderr_str;
3396   int ret, exit_code;
3397   GError *err;
3398   entity_t relay_entity;
3399 
3400   if (ret_entity == NULL)
3401     return -1;
3402 
3403   *ret_entity = NULL;
3404   stdout_str = NULL;
3405   stderr_str = NULL;
3406   ret = -1;
3407   exit_code = -1;
3408   err = NULL;
3409 
3410   cmd = (gchar **) g_malloc (8 * sizeof (gchar *));
3411   cmd[0] = g_strdup (relay_mapper_path);
3412   cmd[1] = g_strdup ("--host");
3413   cmd[2] = g_strdup (original_host);
3414   cmd[3] = g_strdup ("--port");
3415   cmd[4] = g_strdup_printf ("%d", original_port);
3416   cmd[5] = g_strdup ("--protocol");
3417   cmd[6] = g_strdup (protocol);
3418   cmd[7] = NULL;
3419 
3420   if (g_spawn_sync (NULL,
3421                     cmd,
3422                     NULL,
3423                     G_SPAWN_SEARCH_PATH,
3424                     NULL,
3425                     NULL,
3426                     &stdout_str,
3427                     &stderr_str,
3428                     &exit_code,
3429                     &err) == FALSE)
3430     {
3431       g_warning ("%s: g_spawn_sync failed: %s",
3432                  __func__, err ? err->message : "");
3433       g_strfreev (cmd);
3434       g_free (stdout_str);
3435       g_free (stderr_str);
3436       return -1;
3437     }
3438   else if (exit_code)
3439     {
3440       g_warning ("%s: mapper exited with code %d",
3441                  __func__, exit_code);
3442       g_message ("%s: mapper stderr:\n%s", __func__, stderr_str);
3443       g_debug ("%s: mapper stdout:\n%s", __func__, stdout_str);
3444       g_strfreev (cmd);
3445       g_free (stdout_str);
3446       g_free (stderr_str);
3447       return -1;
3448     }
3449 
3450   relay_entity = NULL;
3451   if (parse_entity (stdout_str, &relay_entity))
3452     {
3453       g_warning ("%s: failed to parse mapper output",
3454                  __func__);
3455       g_message ("%s: mapper stdout:\n%s", __func__, stdout_str);
3456       g_message ("%s: mapper stderr:\n%s", __func__, stderr_str);
3457     }
3458   else
3459     {
3460       ret = 0;
3461       *ret_entity = relay_entity;
3462     }
3463 
3464   g_strfreev (cmd);
3465   g_free (stdout_str);
3466   g_free (stderr_str);
3467 
3468   return ret;
3469 }
3470 
3471 /**
3472  * @brief Gets whether there is a relay supporting the scanner type.
3473  *
3474  * @param[in]  original_host    The original hostname or IP address.
3475  * @param[in]  original_port    The original port number.
3476  * @param[in]  type             The scanner type to check.
3477  *
3478  * @return Whether there is a relay supporting the scanner type.
3479  */
3480 gboolean
relay_supports_scanner_type(const char * original_host,int original_port,scanner_type_t type)3481 relay_supports_scanner_type (const char *original_host, int original_port,
3482                              scanner_type_t type)
3483 {
3484   entity_t relay_entity = NULL;
3485   const char *protocol;
3486   gboolean ret = FALSE;
3487 
3488   if (type == SCANNER_TYPE_OSP_SENSOR)
3489     protocol = "OSP";
3490   else
3491     return FALSE;
3492 
3493   if (get_relay_info_entity (original_host, original_port,
3494                              protocol, &relay_entity) == 0)
3495     {
3496       entity_t host_entity;
3497       host_entity = entity_child (relay_entity, "host");
3498 
3499       if (host_entity
3500           && strcmp (entity_text (host_entity), ""))
3501         {
3502           ret = TRUE;
3503         }
3504     }
3505   free_entity (relay_entity);
3506   return ret;
3507 }
3508 
3509 /**
3510  * @brief Gets a relay hostname and port for a sensor scanner.
3511  *
3512  * If no mapper is available, a copy of the original host, port and
3513  *  CA certificate are returned.
3514  *
3515  * @param[in]  original_host    The original hostname or IP address.
3516  * @param[in]  original_port    The original port number.
3517  * @param[in]  original_ca_cert The original CA certificate.
3518  * @param[in]  protocol         The protocol to look for, e.g. "GMP" or "OSP".
3519  * @param[out] new_host         The hostname or IP address of the relay.
3520  * @param[out] new_port         The port number of the relay.
3521  * @param[out] new_ca_cert      The CA certificate of the relay.
3522  *
3523  * @return 0 success, 1 relay not found, -1 error.
3524  */
3525 int
slave_get_relay(const char * original_host,int original_port,const char * original_ca_cert,const char * protocol,gchar ** new_host,int * new_port,gchar ** new_ca_cert)3526 slave_get_relay (const char *original_host,
3527                  int original_port,
3528                  const char *original_ca_cert,
3529                  const char *protocol,
3530                  gchar **new_host,
3531                  int *new_port,
3532                  gchar **new_ca_cert)
3533 {
3534   int ret = -1;
3535 
3536   assert (new_host);
3537   assert (new_port);
3538   assert (new_ca_cert);
3539 
3540   if (relay_mapper_path == NULL)
3541     {
3542       *new_host = original_host ? g_strdup (original_host) : NULL;
3543       *new_port = original_port;
3544       *new_ca_cert = original_ca_cert ? g_strdup (original_ca_cert) : NULL;
3545 
3546       return 0;
3547     }
3548   else
3549     {
3550       entity_t relay_entity = NULL;
3551 
3552       if (get_relay_info_entity (original_host, original_port,
3553                                  protocol, &relay_entity) == 0)
3554         {
3555           entity_t host_entity, port_entity, ca_cert_entity;
3556 
3557           host_entity = entity_child (relay_entity, "host");
3558           port_entity = entity_child (relay_entity, "port");
3559           ca_cert_entity = entity_child (relay_entity, "ca_cert");
3560 
3561           if (host_entity && port_entity && ca_cert_entity)
3562             {
3563               if (entity_text (host_entity)
3564                   && entity_text (port_entity)
3565                   && strcmp (entity_text (host_entity), "")
3566                   && strcmp (entity_text (port_entity), ""))
3567                 {
3568                   *new_host = g_strdup (entity_text (host_entity));
3569                   *new_port = atoi (entity_text (port_entity));
3570 
3571                   if (entity_text (ca_cert_entity)
3572                       && strcmp (entity_text (ca_cert_entity), ""))
3573                     {
3574                       *new_ca_cert = g_strdup (entity_text (ca_cert_entity));
3575                     }
3576                   else
3577                     {
3578                       *new_ca_cert = NULL;
3579                     }
3580                   ret = 0;
3581                 }
3582               else
3583                 {
3584                   // Consider relay not found if host or port is empty
3585                   ret = 1;
3586                 }
3587             }
3588           else
3589             {
3590               g_warning ("%s: mapper output did not contain"
3591                          " HOST, PORT and CA_CERT",
3592                          __func__);
3593             }
3594           free_entity (relay_entity);
3595         }
3596     }
3597 
3598   return ret;
3599 }
3600 
3601 /**
3602  * @brief Start or resume a task.
3603  *
3604  * A process will be forked to handle the task, but the forked process will
3605  * never return.
3606  *
3607  * @param[in]   task_id     The task ID.
3608  * @param[out]  report_id   The report ID.
3609  * @param[in]   from        0 start from beginning, 1 continue from stopped, 2
3610  *                          continue if stopped else start from beginning.
3611  *
3612  * @return 1 task is active already,
3613  *         3 failed to find task,
3614  *         4 resuming task not supported,
3615  *         99 permission denied,
3616  *         -1 error,
3617  *         -2 task is missing a target,
3618  *         -3 creating the report failed,
3619  *         -4 target missing hosts,
3620  *         -6 already a task running in this process,
3621  *         -9 fork failed.
3622  */
3623 static int
run_task(const char * task_id,char ** report_id,int from)3624 run_task (const char *task_id, char **report_id, int from)
3625 {
3626   task_t task;
3627   scanner_t scanner;
3628   int ret;
3629   const char *permission;
3630 
3631   if (current_scanner_task)
3632     return -6;
3633 
3634   if (from == 0)
3635     permission = "start_task";
3636   else if (from == 1)
3637     permission = "resume_task";
3638   else
3639     {
3640       assert (0);
3641       permission = "internal_error";
3642     }
3643 
3644   task = 0;
3645   if (find_task_with_permission (task_id, &task, permission))
3646     return -1;
3647   if (task == 0)
3648     return 3;
3649 
3650   scanner = task_scanner (task);
3651   assert (scanner);
3652   ret = check_available ("scanner", scanner, "get_scanners");
3653   if (ret)
3654     return ret;
3655 
3656   if (scanner_type (scanner) == SCANNER_TYPE_CVE)
3657     return run_cve_task (task);
3658 
3659   if (scanner_type (scanner) == SCANNER_TYPE_OPENVAS
3660       || scanner_type (scanner) == SCANNER_TYPE_OSP
3661       || scanner_type (scanner) == SCANNER_TYPE_OSP_SENSOR)
3662     return run_osp_task (task, from, report_id);
3663 
3664   return -1; // Unknown scanner type
3665 }
3666 
3667 /**
3668  * @brief Start a task.
3669  *
3670  * A process will be forked to handle the task, but the forked process will
3671  * never return.
3672  *
3673  * @param[in]   task_id    The task ID.
3674  * @param[out]  report_id  The report ID.
3675  *
3676  * @return 1 task is active already,
3677  *         3 failed to find task,
3678  *         4 resuming task not supported,
3679  *         99 permission denied,
3680  *         -1 error,
3681  *         -2 task is missing a target,
3682  *         -3 creating the report failed,
3683  *         -4 target missing hosts,
3684  *         -6 already a task running in this process,
3685  *         -9 fork failed.
3686  */
3687 int
start_task(const char * task_id,char ** report_id)3688 start_task (const char *task_id, char **report_id)
3689 {
3690   if (acl_user_may ("start_task") == 0)
3691     return 99;
3692 
3693   return run_task (task_id, report_id, 0);
3694 }
3695 
3696 /**
3697  * @brief Stop an OSP task.
3698  *
3699  * @param[in]   task  The task.
3700  *
3701  * @return 0 on success, else -1.
3702  */
3703 static int
stop_osp_task(task_t task)3704 stop_osp_task (task_t task)
3705 {
3706   osp_connection_t *connection;
3707   int ret = -1;
3708   report_t scan_report;
3709   char *scan_id;
3710   task_t previous_task;
3711   report_t previous_report;
3712 
3713   previous_task = current_scanner_task;
3714   previous_report = global_current_report;
3715 
3716   scan_report = task_running_report (task);
3717   scan_id = report_uuid (scan_report);
3718   if (!scan_id)
3719     goto end_stop_osp;
3720   connection = osp_scanner_connect (task_scanner (task));
3721   if (!connection)
3722     goto end_stop_osp;
3723 
3724   current_scanner_task = task;
3725   global_current_report = task_running_report (task);
3726   set_task_run_status (task, TASK_STATUS_STOP_REQUESTED);
3727   ret = osp_stop_scan (connection, scan_id, NULL);
3728   osp_connection_close (connection);
3729   if (ret)
3730     {
3731       g_free (scan_id);
3732       goto end_stop_osp;
3733     }
3734 
3735   connection = osp_scanner_connect (task_scanner (task));
3736   if (!connection)
3737     goto end_stop_osp;
3738   ret = osp_delete_scan (connection, scan_id);
3739   osp_connection_close (connection);
3740   g_free (scan_id);
3741 
3742 end_stop_osp:
3743   set_task_end_time_epoch (task, time (NULL));
3744   set_task_run_status (task, TASK_STATUS_STOPPED);
3745   if (scan_report)
3746     {
3747       set_scan_end_time_epoch (scan_report, time (NULL));
3748       set_report_scan_run_status (scan_report, TASK_STATUS_STOPPED);
3749     }
3750   current_scanner_task = previous_task;
3751   global_current_report = previous_report;
3752   if (ret)
3753     return -1;
3754   return 0;
3755 }
3756 
3757 /**
3758  * @brief Initiate stopping a task.
3759  *
3760  * @param[in]  task  Task.
3761  *
3762  * @return 0 on success, 1 if stop requested.
3763  */
3764 int
stop_task_internal(task_t task)3765 stop_task_internal (task_t task)
3766 {
3767   task_status_t run_status;
3768   task_t previous_task;
3769   report_t previous_report;
3770 
3771   previous_task = current_scanner_task;
3772   previous_report = global_current_report;
3773 
3774   run_status = task_run_status (task);
3775   if (run_status == TASK_STATUS_REQUESTED
3776       || run_status == TASK_STATUS_RUNNING
3777       || run_status == TASK_STATUS_QUEUED)
3778     {
3779       current_scanner_task = task;
3780       global_current_report = task_running_report (task);
3781       set_task_run_status (task, TASK_STATUS_STOP_REQUESTED);
3782       current_scanner_task = previous_task;
3783       global_current_report = previous_report;
3784       return 1;
3785     }
3786 
3787   return 0;
3788 }
3789 
3790 /**
3791  * @brief Initiate stopping a task.
3792  *
3793  * @param[in]  task_id  Task UUID.
3794  *
3795  * @return 0 on success, 1 if stop requested, 3 failed to find task,
3796  *         99 permission denied, -1 error.
3797  */
3798 int
stop_task(const char * task_id)3799 stop_task (const char *task_id)
3800 {
3801   task_t task;
3802 
3803   if (acl_user_may ("stop_task") == 0)
3804     return 99;
3805 
3806   task = 0;
3807   if (find_task_with_permission (task_id, &task, "stop_task"))
3808     return -1;
3809   if (task == 0)
3810     return 3;
3811 
3812   if (scanner_type (task_scanner (task)) == SCANNER_TYPE_OPENVAS
3813       || scanner_type (task_scanner (task)) == SCANNER_TYPE_OSP
3814       || scanner_type (task_scanner (task)) == SCANNER_TYPE_OSP_SENSOR)
3815     return stop_osp_task (task);
3816 
3817   return stop_task_internal (task);
3818 }
3819 
3820 /**
3821  * @brief Resume a task.
3822  *
3823  * A process will be forked to handle the task, but the forked process will
3824  * never return.
3825  *
3826  * @param[in]   task_id    Task UUID.
3827  * @param[out]  report_id  If successful, ID of the resultant report.
3828  *
3829  * @return 1 task is active already,
3830  *         3 failed to find task,
3831  *         4 resuming task not supported,
3832  *         22 caller error (task must be in "stopped" or "interrupted" state),
3833  *         99 permission denied,
3834  *         -1 error,
3835  *         -2 task is missing a target,
3836  *         -3 creating the report failed,
3837  *         -4 target missing hosts,
3838  *         -6 already a task running in this process,
3839  *         -9 fork failed.
3840  */
3841 int
resume_task(const char * task_id,char ** report_id)3842 resume_task (const char *task_id, char **report_id)
3843 {
3844   task_t task;
3845   task_status_t run_status;
3846 
3847   if (acl_user_may ("resume_task") == 0)
3848     return 99;
3849 
3850   task = 0;
3851   if (find_task_with_permission (task_id, &task, "resume_task"))
3852     return -1;
3853   if (task == 0)
3854     return 3;
3855 
3856   run_status = task_run_status (task);
3857   if ((run_status == TASK_STATUS_STOPPED)
3858       || (run_status == TASK_STATUS_INTERRUPTED))
3859     return run_task (task_id, report_id, 1);
3860   return 22;
3861 }
3862 
3863 /**
3864  * @brief Reassign a task to another slave.
3865  *
3866  * @param[in]  task_id    UUID of task.
3867  * @param[in]  slave_id   UUID of slave.
3868  *
3869  * @return 0 success, 2 task not found,
3870  *         3 slave not found, 4 slaves not supported by scanner, 5 task cannot
3871  *         be stopped currently, 6 scanner does not allow stopping, 7 new
3872  *         scanner does not support slaves, 98 stop and resume permission
3873  *         denied, 99 permission denied, -1 error.
3874  */
3875 int
move_task(const char * task_id,const char * slave_id)3876 move_task (const char *task_id, const char *slave_id)
3877 {
3878   task_t task;
3879   int task_scanner_type, slave_scanner_type;
3880   scanner_t slave, scanner;
3881   task_status_t status;
3882   int should_resume_task = 0;
3883 
3884   if (task_id == NULL)
3885     return -1;
3886   if (slave_id == NULL)
3887     return -1;
3888 
3889   if (acl_user_may ("modify_task") == 0)
3890     return 99;
3891 
3892   /* Find the task. */
3893 
3894   if (find_task_with_permission (task_id, &task, "get_tasks"))
3895     return -1;
3896   if (task == 0)
3897     return 2;
3898 
3899   /* Make sure destination scanner supports slavery. */
3900 
3901   if (strcmp (slave_id, "") == 0)
3902     slave_id = SCANNER_UUID_DEFAULT;
3903 
3904   if (find_scanner_with_permission (slave_id, &slave, "get_scanners"))
3905     return -1;
3906   if (slave == 0)
3907     return 3;
3908 
3909   slave_scanner_type = scanner_type (slave);
3910   if (slave_scanner_type != SCANNER_TYPE_OPENVAS)
3911     return 7;
3912 
3913   /* Make sure current scanner supports slavery. */
3914 
3915   scanner = task_scanner (task);
3916   if (scanner == 0)
3917     return -1;
3918 
3919   task_scanner_type = scanner_type (scanner);
3920   if (task_scanner_type != SCANNER_TYPE_OPENVAS)
3921     return 4;
3922 
3923   /* Stop task if required. */
3924 
3925   status = task_run_status (task);
3926 
3927   switch (status)
3928     {
3929       case TASK_STATUS_DELETE_REQUESTED:
3930       case TASK_STATUS_DELETE_ULTIMATE_REQUESTED:
3931       case TASK_STATUS_DELETE_WAITING:
3932       case TASK_STATUS_DELETE_ULTIMATE_WAITING:
3933       case TASK_STATUS_REQUESTED:
3934         // Task cannot be stopped now
3935         return 5;
3936         break;
3937       case TASK_STATUS_RUNNING:
3938       case TASK_STATUS_QUEUED:
3939         if (task_scanner_type == SCANNER_TYPE_CVE)
3940           return 6;
3941         // Check permissions to stop and resume task
3942         if (acl_user_has_access_uuid ("task", task_id, "stop_task", 0)
3943             && acl_user_has_access_uuid ("task", task_id, "resume_task", 0))
3944           {
3945             // Stop the task, wait and resume after changes
3946             stop_task_internal (task);
3947             should_resume_task = 1;
3948 
3949             status = task_run_status (task);
3950             while (status == TASK_STATUS_STOP_REQUESTED
3951                    || status == TASK_STATUS_STOP_WAITING)
3952               {
3953                 sleep (5);
3954                 status = task_run_status (task);
3955               }
3956           }
3957         else
3958           return 98;
3959         break;
3960       case TASK_STATUS_STOP_REQUESTED:
3961       case TASK_STATUS_STOP_WAITING:
3962         while (status == TASK_STATUS_STOP_REQUESTED
3963                || status == TASK_STATUS_STOP_WAITING)
3964           {
3965             sleep (5);
3966             status = task_run_status (task);
3967           }
3968         break;
3969       default:
3970         break;
3971     }
3972 
3973   /* Update scanner. */
3974 
3975   set_task_scanner (task, slave);
3976 
3977   /* Resume task if required. */
3978 
3979   if (should_resume_task)
3980     resume_task (task_id, NULL);
3981 
3982   return 0;
3983 }
3984 
3985 
3986 /* Credentials. */
3987 
3988 /**
3989  * @brief Get the written-out name of an LSC Credential type.
3990  *
3991  * @param[in]  abbreviation  The type abbreviation.
3992  *
3993  * @return The written-out type name.
3994  */
3995 const char*
credential_full_type(const char * abbreviation)3996 credential_full_type (const char* abbreviation)
3997 {
3998   if (abbreviation == NULL)
3999     return NULL;
4000   else if (strcasecmp (abbreviation, "cc") == 0)
4001     return "client certificate";
4002   else if (strcasecmp (abbreviation, "pw") == 0)
4003     return "password only";
4004   else if (strcasecmp (abbreviation, "snmp") == 0)
4005     return "SNMP";
4006   else if (strcasecmp (abbreviation, "up") == 0)
4007     return "username + password";
4008   else if (strcasecmp (abbreviation, "usk") == 0)
4009     return "username + SSH key";
4010   else
4011     return abbreviation;
4012 }
4013 
4014 
4015 /* System reports. */
4016 
4017 /**
4018  * @brief Get a performance report from an OSP scanner.
4019  *
4020  * @param[in]  scanner          The scanner to get the performance report from.
4021  * @param[in]  start            The start time of the performance report.
4022  * @param[in]  end              The end time of the performance report.
4023  * @param[in]  titles           The end titles for the performance report.
4024  * @param[in]  performance_str  The performance string.
4025  * @param[in]  error            The error message text, if any.
4026  *
4027  * @return 0 if successful, 6 could not connect to scanner or failed to get
4028  *         performance report
4029  */
4030 static int
get_osp_performance_string(scanner_t scanner,int start,int end,const char * titles,gchar ** performance_str,gchar ** error)4031 get_osp_performance_string (scanner_t scanner, int start, int end,
4032                             const char *titles, gchar **performance_str,
4033                             gchar **error)
4034 {
4035   char *host, *ca_pub, *key_pub, *key_priv;
4036   int port;
4037   osp_connection_t *connection = NULL;
4038   osp_get_performance_opts_t opts;
4039   int connection_retry, return_value;
4040 
4041   host = scanner_host (scanner);
4042   port = scanner_port (scanner);
4043   ca_pub = scanner_ca_pub (scanner);
4044   key_pub = scanner_key_pub (scanner);
4045   key_priv = scanner_key_priv (scanner);
4046 
4047   connection_retry = get_scanner_connection_retry ();
4048   connection = osp_connect_with_data (host, port, ca_pub, key_pub, key_priv);
4049   while (connection == NULL && connection_retry > 0)
4050     {
4051       sleep(1);
4052       connection = osp_connect_with_data (host, port,
4053                                           ca_pub, key_pub, key_priv);
4054       connection_retry--;
4055     }
4056 
4057   free (host);
4058   free (ca_pub);
4059   free (key_pub);
4060   free (key_priv);
4061 
4062   if (connection == NULL)
4063     {
4064       *error = g_strdup("Could not connect to scanner");
4065       return 6;
4066     }
4067 
4068   opts.start = start;
4069   opts.end = end;
4070   opts.titles = g_strdup (titles);
4071 
4072   return_value = osp_get_performance_ext (connection, opts,
4073                                           performance_str, error);
4074 
4075   if (return_value)
4076     {
4077       osp_connection_close (connection);
4078       g_warning ("Error getting OSP performance report: %s", *error);
4079       g_free (opts.titles);
4080       return 6;
4081     }
4082 
4083   osp_connection_close (connection);
4084   g_free (opts.titles);
4085 
4086   return 0;
4087 }
4088 
4089 /**
4090  * @brief Header for fallback system report.
4091  */
4092 #define FALLBACK_SYSTEM_REPORT_HEADER \
4093 "This is the most basic, fallback report.  The system can be configured to\n" \
4094 "produce more powerful reports.  Please contact your system administrator\n" \
4095 "for more information.\n\n"
4096 
4097 /**
4098  * @brief Get the fallback report as a string.
4099  *
4100  * @param[in]  fallback_report  The string for the fallback report.
4101  */
4102 static void
get_fallback_report_string(GString * fallback_report)4103 get_fallback_report_string(GString *fallback_report)
4104 {
4105   int ret;
4106   double load[3];
4107   GError *get_error;
4108   gchar *output;
4109   gsize output_len;
4110 
4111   g_string_append_printf (fallback_report, FALLBACK_SYSTEM_REPORT_HEADER);
4112 
4113   ret = getloadavg (load, 3);
4114   if (ret == 3)
4115     {
4116       g_string_append_printf (fallback_report,
4117                               "Load average for past minute:     %.1f\n",
4118                               load[0]);
4119       g_string_append_printf (fallback_report,
4120                               "Load average for past 5 minutes:  %.1f\n",
4121                               load[1]);
4122       g_string_append_printf (fallback_report,
4123                               "Load average for past 15 minutes: %.1f\n",
4124                               load[2]);
4125     }
4126   else
4127     g_string_append (fallback_report, "Error getting load averages.\n");
4128 
4129   get_error = NULL;
4130   g_file_get_contents ("/proc/meminfo",
4131                        &output,
4132                        &output_len,
4133                        &get_error);
4134   if (get_error)
4135     g_error_free (get_error);
4136   else
4137     {
4138       gchar *safe;
4139       g_string_append (fallback_report, "\n/proc/meminfo:\n\n");
4140       safe = g_markup_escape_text (output, strlen (output));
4141       g_free (output);
4142       g_string_append (fallback_report, safe);
4143       g_free (safe);
4144     }
4145 }
4146 
4147 /**
4148  * @brief Command called by get_system_report_types.
4149  *        gvmcg stands for gvm-create-graphs.
4150  */
4151 #define COMMAND "gvmcg 0 titles"
4152 
4153 /**
4154  * @brief Get system report types.
4155  *
4156  * @param[in]   required_type  Single type to limit types to.
4157  * @param[out]  types          Types on success.
4158  * @param[out]  start          Actual start of types, which caller must free.
4159  * @param[out]  slave_id       ID of slave.
4160  *
4161  * @return 0 if successful, 1 failed to find report type, 2 failed to find
4162  *         slave, 3 serving the fallback, 4 could not connect to slave,
4163  *         5 authentication failed, 6 failed to get system report,
4164  *         -1 otherwise.
4165  */
4166 static int
get_system_report_types(const char * required_type,gchar *** start,gchar *** types,const char * slave_id)4167 get_system_report_types (const char *required_type, gchar ***start,
4168                          gchar ***types, const char *slave_id)
4169 {
4170   gchar *astdout = NULL;
4171   gchar *astderr = NULL;
4172   gchar *slave_error = NULL;
4173   GError *err = NULL;
4174   gint exit_status;
4175 
4176   if (slave_id && strcmp (slave_id, "0"))
4177     {
4178       int ret;
4179       scanner_t slave;
4180 
4181       slave = 0;
4182 
4183       if (find_scanner_with_permission (slave_id, &slave, "get_scanners"))
4184         return -1;
4185       if (slave == 0)
4186         return 2;
4187 
4188       // Assume OSP scanner
4189       ret = get_osp_performance_string (slave, 0, 0, "titles",
4190                                         &astdout, &slave_error);
4191 
4192       if (ret)
4193         {
4194           g_free (slave_error);
4195           return ret;
4196         }
4197     }
4198   else
4199     {
4200       g_debug ("   command: " COMMAND);
4201 
4202       if ((g_spawn_command_line_sync (COMMAND,
4203                                       &astdout,
4204                                       &astderr,
4205                                       &exit_status,
4206                                       &err)
4207           == FALSE)
4208           || (WIFEXITED (exit_status) == 0)
4209           || WEXITSTATUS (exit_status))
4210         {
4211           g_debug ("%s: gvmcg failed with %d", __func__, exit_status);
4212           g_debug ("%s: stdout: %s", __func__, astdout);
4213           g_debug ("%s: stderr: %s", __func__, astderr);
4214           g_free (astdout);
4215           g_free (astderr);
4216           *start = *types = g_malloc0 (sizeof (gchar*) * 2);
4217           (*start)[0] = g_strdup ("fallback Fallback Report");
4218           (*start)[0][strlen ("fallback")] = '\0';
4219           return 3;
4220         }
4221     }
4222 
4223   if (astdout)
4224     {
4225       char **type;
4226       *start = *types = type = g_strsplit (g_strchomp (astdout), "\n", 0);
4227       while (*type)
4228         {
4229           char *space;
4230           space = strchr (*type, ' ');
4231           if (space == NULL)
4232             {
4233               g_strfreev (*types);
4234               *types = NULL;
4235               g_free (astdout);
4236               g_free (astderr);
4237               g_free (slave_error);
4238               return -1;
4239             }
4240           *space = '\0';
4241           if (required_type && (strcmp (*type, required_type) == 0))
4242             {
4243               char **next;
4244               /* Found the single given type. */
4245               next = type + 1;
4246               while (*next)
4247                 {
4248                   free (*next);
4249                   next++;
4250                 }
4251               next = type + 1;
4252               *next = NULL;
4253               *types = type;
4254               g_free (astdout);
4255               g_free (astderr);
4256               g_free (slave_error);
4257               return 0;
4258             }
4259           type++;
4260         }
4261       if (required_type)
4262         {
4263           /* Failed to find the single given type. */
4264           g_free (astdout);
4265           g_free (astderr);
4266           g_free (slave_error);
4267           g_strfreev (*types);
4268           return 1;
4269         }
4270     }
4271   else
4272     *start = *types = g_malloc0 (sizeof (gchar*));
4273 
4274   g_free (astdout);
4275   g_free (astderr);
4276   g_free (slave_error);
4277   return 0;
4278 }
4279 
4280 #undef COMMAND
4281 
4282 /**
4283  * @brief Initialise a system report type iterator.
4284  *
4285  * @param[in]  iterator    Iterator.
4286  * @param[in]  type        Single report type to iterate over, NULL for all.
4287  * @param[in]  slave_id    ID of slave to get reports from.  0 for local.
4288  *
4289  * @return 0 on success, 1 failed to find report type, 2 failed to find slave,
4290  *         3 used the fallback report,  4 could not connect to slave,
4291  *         5 authentication failed, 6 failed to get system report,
4292  *         99 permission denied, -1 on error.
4293  */
4294 int
init_system_report_type_iterator(report_type_iterator_t * iterator,const char * type,const char * slave_id)4295 init_system_report_type_iterator (report_type_iterator_t* iterator,
4296                                   const char* type,
4297                                   const char* slave_id)
4298 {
4299   int ret;
4300 
4301   if (acl_user_may ("get_system_reports") == 0)
4302     return 99;
4303 
4304   ret = get_system_report_types (type, &iterator->start, &iterator->current,
4305                                  slave_id);
4306   if (ret == 0 || ret == 3)
4307     {
4308       iterator->current--;
4309       return ret;
4310     }
4311   return ret;
4312 }
4313 
4314 /**
4315  * @brief Cleanup a report type iterator.
4316  *
4317  * @param[in]  iterator  Iterator.
4318  */
4319 void
cleanup_report_type_iterator(report_type_iterator_t * iterator)4320 cleanup_report_type_iterator (report_type_iterator_t* iterator)
4321 {
4322   g_strfreev (iterator->start);
4323 }
4324 
4325 /**
4326  * @brief Increment a report type iterator.
4327  *
4328  * The caller must stop using this after it returns FALSE.
4329  *
4330  * @param[in]  iterator  Task iterator.
4331  *
4332  * @return TRUE if there was a next item, else FALSE.
4333  */
4334 gboolean
next_report_type(report_type_iterator_t * iterator)4335 next_report_type (report_type_iterator_t* iterator)
4336 {
4337   iterator->current++;
4338   if (*iterator->current == NULL) return FALSE;
4339   return TRUE;
4340 }
4341 
4342 /**
4343  * @brief Return the name from a report type iterator.
4344  *
4345  * @param[in]  iterator  Iterator.
4346  *
4347  * @return Name.
4348  */
4349 const char*
report_type_iterator_name(report_type_iterator_t * iterator)4350 report_type_iterator_name (report_type_iterator_t* iterator)
4351 {
4352   return (const char*) *iterator->current;
4353 }
4354 
4355 /**
4356  * @brief Return the title from a report type iterator.
4357  *
4358  * @param[in]  iterator  Iterator.
4359  *
4360  * @return Title.
4361  */
4362 const char*
report_type_iterator_title(report_type_iterator_t * iterator)4363 report_type_iterator_title (report_type_iterator_t* iterator)
4364 {
4365   const char *name = *iterator->current;
4366   return name + strlen (name) + 1;
4367 }
4368 
4369 /**
4370  * @brief Default duration for system reports.
4371  */
4372 #define DEFAULT_DURATION 86400L
4373 
4374 /**
4375  * @brief Generate params for gvmcg or OSP get_performance.
4376  *
4377  * @param[in]  duration     The duration as a string
4378  * @param[in]  start_time   The start time as a string
4379  * @param[in]  end_time     The end time as a string
4380  * @param[out] param_1      Output of the first parameter (start or duration)
4381  * @param[out] param_2      Output of the second parameter (end time)
4382  * @param[out] params_count The number of valid parameters
4383  */
4384 void
parse_performance_params(const char * duration,const char * start_time,const char * end_time,time_t * param_1,time_t * param_2,int * params_count)4385 parse_performance_params (const char *duration,
4386                           const char *start_time,
4387                           const char *end_time,
4388                           time_t *param_1,
4389                           time_t *param_2,
4390                           int *params_count)
4391 {
4392   time_t start_time_num, end_time_num, duration_num;
4393   start_time_num = 0;
4394   end_time_num = 0;
4395   duration_num = 0;
4396 
4397   *param_1 = 0;
4398   *param_2 = 0;
4399   *params_count = 0;
4400 
4401   if (duration && strcmp (duration, ""))
4402     {
4403       duration_num = atol (duration);
4404       if (duration_num == 0)
4405         return;
4406     }
4407   if (start_time && strcmp (start_time, ""))
4408     {
4409       start_time_num = parse_iso_time (start_time);
4410       if (start_time_num == 0)
4411         return;
4412     }
4413   if (end_time && strcmp (end_time, ""))
4414     {
4415       end_time_num = parse_iso_time (end_time);
4416       if (end_time_num == 0)
4417         return;
4418     }
4419 
4420   if (start_time && strcmp (start_time, ""))
4421     {
4422       if (end_time && strcmp (end_time, ""))
4423         {
4424           *param_1 = start_time_num;
4425           *param_2 = end_time_num;
4426           *params_count = 2;
4427         }
4428       else if (duration && strcmp (duration, ""))
4429         {
4430           *param_1 = start_time_num;
4431           *param_2 = start_time_num + duration_num;
4432           *params_count = 2;
4433         }
4434       else
4435         {
4436           *param_1 = start_time_num;
4437           *param_2 = start_time_num + DEFAULT_DURATION;
4438           *params_count = 2;
4439         }
4440     }
4441   else if (end_time && strcmp (end_time, ""))
4442     {
4443       if (duration && strcmp (duration, ""))
4444         {
4445           *param_1 = end_time_num - duration_num;
4446           *param_2 = end_time_num;
4447           *params_count = 2;
4448         }
4449       else
4450         {
4451           *param_1 = end_time_num - DEFAULT_DURATION,
4452           *param_1 = end_time_num,
4453           *params_count = 2;
4454         }
4455     }
4456   else
4457     {
4458       if (duration && strcmp (duration, ""))
4459         {
4460           *param_1 = duration_num;
4461           *params_count = 1;
4462         }
4463       else
4464         {
4465           *param_1 = DEFAULT_DURATION;
4466           *params_count = 1;
4467         }
4468     }
4469 }
4470 
4471 /**
4472  * @brief Get a system report.
4473  *
4474  * @param[in]  name       Name of report.
4475  * @param[in]  duration   Time range of report, in seconds.
4476  * @param[in]  start_time Time of first data point in report.
4477  * @param[in]  end_time   Time of last data point in report.
4478  * @param[in]  slave_id   ID of slave to get report from.  0 for local.
4479  * @param[out] report     On success, report in base64 if such a report exists
4480  *                        else NULL.  Arbitrary on error.
4481  *
4482  * @return 0 if successful (including failure to find report), -1 on error,
4483  *         2 could not find slave scanner,
4484  *         3 if used the fallback report or got an error message to print
4485  */
4486 int
manage_system_report(const char * name,const char * duration,const char * start_time,const char * end_time,const char * slave_id,char ** report)4487 manage_system_report (const char *name, const char *duration,
4488                       const char *start_time, const char *end_time,
4489                       const char *slave_id, char **report)
4490 {
4491   gchar *astdout = NULL;
4492   gchar *astderr = NULL;
4493   gchar *slave_error = NULL;
4494   GError *err = NULL;
4495   GString *buffer = NULL;
4496   gint exit_status;
4497   gint return_code = 0;
4498   gchar *command = NULL;
4499   time_t cmd_param_1, cmd_param_2;
4500   int params_count;
4501 
4502   assert (name);
4503 
4504   parse_performance_params (duration, start_time, end_time,
4505                             &cmd_param_1, &cmd_param_2, &params_count);
4506 
4507   *report = NULL;
4508 
4509   if (params_count == 0)
4510     return manage_system_report ("blank", NULL, NULL, NULL, NULL, report);
4511 
4512   if (slave_id && strcmp (slave_id, "0"))
4513     {
4514       scanner_t slave;
4515 
4516       slave = 0;
4517 
4518       if (find_scanner_with_permission (slave_id, &slave, "get_scanners"))
4519         return -1;
4520       if (slave == 0)
4521         return 2;
4522 
4523       if (params_count == 1)
4524         {
4525           // only duration
4526           time_t now;
4527           now = time (NULL);
4528           return_code = get_osp_performance_string (slave,
4529                                                     now - cmd_param_1,
4530                                                     now,
4531                                                     name,
4532                                                     report,
4533                                                     &slave_error);
4534         }
4535       else
4536         {
4537           // start and end time
4538           return_code = get_osp_performance_string (slave,
4539                                                     cmd_param_1,
4540                                                     cmd_param_2,
4541                                                     name,
4542                                                     report,
4543                                                     &slave_error);
4544         }
4545     }
4546   else
4547     {
4548       if (!g_find_program_in_path ("gvmcg"))
4549         {
4550           buffer = g_string_new ("");
4551           get_fallback_report_string(buffer);
4552           *report = g_string_free (buffer, FALSE);
4553           return_code = 7;
4554         }
4555       else
4556         {
4557           /* For simplicity, it's up to the command to do the base64
4558            * encoding.
4559            */
4560           if (params_count == 1)
4561             command = g_strdup_printf ("gvmcg %ld %s",
4562                                        cmd_param_1,
4563                                        name);
4564           else
4565             command = g_strdup_printf ("gvmcg %ld %ld %s",
4566                                        cmd_param_1,
4567                                        cmd_param_2,
4568                                        name);
4569 
4570           g_debug ("   command: %s", command);
4571 
4572           if ((g_spawn_command_line_sync (command,
4573                                           &astdout,
4574                                           &astderr,
4575                                           &exit_status,
4576                                           &err)
4577                == FALSE)
4578               || (WIFEXITED (exit_status) == 0)
4579               || WEXITSTATUS (exit_status))
4580             {
4581               return_code = 3;
4582 
4583               g_warning ("%s: Failed to create performance graph -- %s",
4584                          __func__, astderr);
4585               g_debug ("%s: gvmcg failed with %d", __func__, exit_status);
4586               g_debug ("%s: stdout: %s", __func__, astdout);
4587               g_debug ("%s: stderr: %s", __func__, astderr);
4588             }
4589           g_free (command);
4590         }
4591     }
4592 
4593   if (return_code == 3 || return_code == 6)
4594     {
4595       buffer = g_string_new ("");
4596       g_string_append_printf (buffer,
4597                               "Failed to create performance graph: %s",
4598                               (return_code == 3 ? astderr : slave_error));
4599       *report = g_string_free (buffer, FALSE);
4600     }
4601 
4602   g_free (astderr);
4603   g_free (slave_error);
4604 
4605   if (return_code == 6 || return_code == 7)
4606     return_code = 3;
4607 
4608   if ((astdout == NULL || strlen (astdout) == 0) &&
4609       *report == NULL)
4610     {
4611       g_free (astdout);
4612       if (strcmp (name, "blank") == 0)
4613         return -1;
4614       return manage_system_report ("blank", NULL, NULL, NULL,
4615                                    NULL, report);
4616     }
4617   else if (*report == NULL)
4618     *report = astdout;
4619   else
4620     g_free (astdout);
4621 
4622   return return_code;
4623 }
4624 
4625 
4626 /* Scheduling. */
4627 
4628 /**
4629  * @brief Flag for manage_auth_allow_all.
4630  *
4631  * 1 if set via scheduler, 2 if set via event, else 0.
4632  */
4633 int authenticate_allow_all = 0;
4634 
4635 /**
4636  * @brief UUID of user whose scheduled task is to be started (in connection
4637  *        with authenticate_allow_all).
4638  */
4639 static gchar* schedule_user_uuid = NULL;
4640 
4641 /**
4642  * @brief Ensure that any subsequent authentications succeed.
4643  *
4644  * @param[in]  scheduled  Whether this is happening from the scheduler.
4645  */
4646 void
manage_auth_allow_all(int scheduled)4647 manage_auth_allow_all (int scheduled)
4648 {
4649   authenticate_allow_all = scheduled ? 1 : 2;
4650 }
4651 
4652 /**
4653  * @brief Access UUID of user that scheduled the current task.
4654  *
4655  * @return UUID of user that scheduled the current task.
4656  */
4657 const gchar*
get_scheduled_user_uuid()4658 get_scheduled_user_uuid ()
4659 {
4660   return schedule_user_uuid;
4661 }
4662 
4663 /**
4664  * @brief Set UUID of user that scheduled the current task.
4665  * The previous value is freed and a copy of the UUID is created.
4666  *
4667  * @param user_uuid UUID of user that scheduled the current task.
4668  */
4669 void
set_scheduled_user_uuid(const gchar * user_uuid)4670 set_scheduled_user_uuid (const gchar* user_uuid)
4671 {
4672   gchar *user_uuid_copy = user_uuid ? g_strdup (user_uuid) : NULL;
4673   g_free (schedule_user_uuid);
4674   schedule_user_uuid = user_uuid_copy;
4675 }
4676 
4677 /**
4678  * @brief Task info, for scheduler.
4679  */
4680 typedef struct
4681 {
4682   gchar *owner_uuid;   ///< UUID of owner.
4683   gchar *owner_name;   ///< Name of owner.
4684   gchar *task_uuid;    ///< UUID of task.
4685 } scheduled_task_t;
4686 
4687 /**
4688  * @brief Create a schedule task structure.
4689  *
4690  * @param[in] task_uuid   UUID of task.
4691  * @param[in] owner_uuid  UUID of owner.
4692  * @param[in] owner_name  Name of owner.
4693  *
4694  * @return Scheduled task structure.
4695  */
4696 static scheduled_task_t *
scheduled_task_new(const gchar * task_uuid,const gchar * owner_uuid,const gchar * owner_name)4697 scheduled_task_new (const gchar* task_uuid, const gchar* owner_uuid,
4698                     const gchar* owner_name)
4699 {
4700   scheduled_task_t *scheduled_task;
4701 
4702   scheduled_task = g_malloc (sizeof (*scheduled_task));
4703   scheduled_task->task_uuid = g_strdup (task_uuid);
4704   scheduled_task->owner_uuid = g_strdup (owner_uuid);
4705   scheduled_task->owner_name = g_strdup (owner_name);
4706 
4707   return scheduled_task;
4708 }
4709 
4710 /**
4711  * @brief Set UUID of user that scheduled the current task.
4712  *
4713  * @param[in] scheduled_task  Scheduled task.
4714  */
4715 static void
scheduled_task_free(scheduled_task_t * scheduled_task)4716 scheduled_task_free (scheduled_task_t *scheduled_task)
4717 {
4718   g_free (scheduled_task->task_uuid);
4719   g_free (scheduled_task->owner_uuid);
4720   g_free (scheduled_task->owner_name);
4721   g_free (scheduled_task);
4722 }
4723 
4724 /**
4725  * @brief Start a task, for the scheduler.
4726  *
4727  * @param[in]  scheduled_task   Scheduled task.
4728  * @param[in]  fork_connection  Function that forks a child which is connected
4729  *                              to the Manager.  Must return PID in parent, 0
4730  *                              in child, or -1 on error.
4731  * @param[in]  sigmask_current  Sigmask to restore in child.
4732  *
4733  * @return 0 success, -1 error.  Child does not return.
4734  */
4735 static int
scheduled_task_start(scheduled_task_t * scheduled_task,manage_connection_forker_t fork_connection,sigset_t * sigmask_current)4736 scheduled_task_start (scheduled_task_t *scheduled_task,
4737                       manage_connection_forker_t fork_connection,
4738                       sigset_t *sigmask_current)
4739 {
4740   char title[128];
4741   int pid;
4742   gvm_connection_t connection;
4743   gmp_authenticate_info_opts_t auth_opts;
4744 
4745   /* Fork a child to start the task and wait for the response, so that the
4746    * parent can return to the main loop.  Only the parent returns. */
4747 
4748   pid = fork ();
4749   switch (pid)
4750     {
4751       case 0:
4752         /* Child.  Carry on to start the task, reopen the database (required
4753          * after fork). */
4754 
4755         /* Restore the sigmask that was blanked for pselect. */
4756         pthread_sigmask (SIG_SETMASK, sigmask_current, NULL);
4757 
4758         reinit_manage_process ();
4759         manage_session_init (current_credentials.uuid);
4760         break;
4761 
4762       case -1:
4763         /* Parent on error. */
4764         g_warning ("%s: fork failed", __func__);
4765         return -1;
4766 
4767       default:
4768         /* Parent.  Continue to next task. */
4769         g_debug ("%s: %i forked %i", __func__, getpid (), pid);
4770         return 0;
4771     }
4772 
4773   /* Run the callback to fork a child connected to the Manager. */
4774 
4775   pid = fork_connection (&connection, scheduled_task->owner_uuid);
4776   switch (pid)
4777     {
4778       case 0:
4779         /* Child.  Break, start task, exit. */
4780         break;
4781 
4782       case -1:
4783         /* Parent on error. */
4784         g_warning ("%s: fork_connection failed", __func__);
4785         reschedule_task (scheduled_task->task_uuid);
4786         scheduled_task_free (scheduled_task);
4787         exit (EXIT_FAILURE);
4788         break;
4789 
4790       default:
4791         {
4792           int status;
4793 
4794           /* Parent.  Wait for child, to check return. */
4795 
4796           snprintf (title, sizeof (title),
4797                     "gvmd: scheduler: waiting for %i",
4798                     pid);
4799           proctitle_set (title);
4800 
4801           g_debug ("%s: %i fork_connectioned %i",
4802                    __func__, getpid (), pid);
4803 
4804           if (signal (SIGCHLD, SIG_DFL) == SIG_ERR)
4805             g_warning ("%s: failed to set SIGCHLD", __func__);
4806           while (waitpid (pid, &status, 0) < 0)
4807             {
4808               if (errno == ECHILD)
4809                 {
4810                   g_warning ("%s: Failed to get child exit,"
4811                              " so task '%s' may not have been scheduled",
4812                              __func__,
4813                              scheduled_task->task_uuid);
4814                   scheduled_task_free (scheduled_task);
4815                   exit (EXIT_FAILURE);
4816                 }
4817               if (errno == EINTR)
4818                 continue;
4819               g_warning ("%s: waitpid: %s",
4820                          __func__,
4821                          strerror (errno));
4822               g_warning ("%s: As a result, task '%s' may not have been"
4823                          " scheduled",
4824                          __func__,
4825                          scheduled_task->task_uuid);
4826               scheduled_task_free (scheduled_task);
4827               exit (EXIT_FAILURE);
4828             }
4829           if (WIFEXITED (status))
4830             switch (WEXITSTATUS (status))
4831               {
4832                 case EXIT_SUCCESS:
4833                   {
4834                     schedule_t schedule;
4835                     int periods;
4836                     const gchar *task_uuid;
4837 
4838                     /* Child succeeded, so task successfully started. */
4839 
4840                     task_uuid = scheduled_task->task_uuid;
4841                     schedule = task_schedule_uuid (task_uuid);
4842                     if (schedule
4843                         && schedule_period (schedule) == 0
4844                         && schedule_duration (schedule) == 0
4845                         /* Check next time too, in case the user changed
4846                          * the schedule after this task was added to the
4847                          * "starts" list. */
4848                         && task_schedule_next_time_uuid (task_uuid) == 0)
4849                       /* A once-off schedule without a duration, remove
4850                        * it from the task.  If it has a duration it
4851                        * will be removed by manage_schedule via
4852                        * clear_duration_schedules, after the duration. */
4853                       set_task_schedule_uuid (task_uuid, 0, -1);
4854                     else if ((periods = task_schedule_periods_uuid
4855                                          (task_uuid)))
4856                       {
4857                         /* A task restricted to a certain number of
4858                          * scheduled runs. */
4859                         if (periods > 1)
4860                           {
4861                             set_task_schedule_periods (task_uuid,
4862                                                        periods - 1);
4863                           }
4864                         else if (periods == 1
4865                                  && schedule_duration (schedule) == 0)
4866                           {
4867                             /* Last run of a task restricted to a certain
4868                              * number of scheduled runs. */
4869                             set_task_schedule_uuid (task_uuid, 0, 1);
4870                           }
4871                         else if (periods == 1)
4872                           /* Flag that the task has started, for
4873                            * update_duration_schedule_periods. */
4874                           set_task_schedule_next_time_uuid (task_uuid, 0);
4875                       }
4876                   }
4877                   scheduled_task_free (scheduled_task);
4878                   exit (EXIT_SUCCESS);
4879 
4880                 case EXIT_FAILURE:
4881                 default:
4882                   break;
4883               }
4884 
4885           /* Child failed, reset task schedule time and exit. */
4886 
4887           g_warning ("%s: child failed", __func__);
4888           reschedule_task (scheduled_task->task_uuid);
4889           scheduled_task_free (scheduled_task);
4890           exit (EXIT_FAILURE);
4891         }
4892     }
4893 
4894   /* Start the task. */
4895 
4896   snprintf (title, sizeof (title),
4897             "gvmd: scheduler: starting %s",
4898             scheduled_task->task_uuid);
4899   proctitle_set (title);
4900 
4901   auth_opts = gmp_authenticate_info_opts_defaults;
4902   auth_opts.username = scheduled_task->owner_name;
4903   if (gmp_authenticate_info_ext_c (&connection, auth_opts))
4904     {
4905       g_warning ("%s: gmp_authenticate failed", __func__);
4906       scheduled_task_free (scheduled_task);
4907       gvm_connection_free (&connection);
4908       exit (EXIT_FAILURE);
4909     }
4910 
4911   if (gmp_resume_task_report_c (&connection,
4912                                 scheduled_task->task_uuid,
4913                                 NULL))
4914     {
4915       gmp_start_task_opts_t opts;
4916 
4917       opts = gmp_start_task_opts_defaults;
4918       opts.task_id = scheduled_task->task_uuid;
4919 
4920       switch (gmp_start_task_ext_c (&connection, opts))
4921         {
4922           case 0:
4923             break;
4924 
4925           case 99:
4926             g_warning ("%s: user denied permission to start task", __func__);
4927             scheduled_task_free (scheduled_task);
4928             gvm_connection_free (&connection);
4929             /* Return success, so that parent stops trying to start the task. */
4930             exit (EXIT_SUCCESS);
4931 
4932           default:
4933             g_warning ("%s: gmp_start_task and gmp_resume_task failed", __func__);
4934             scheduled_task_free (scheduled_task);
4935             gvm_connection_free (&connection);
4936             exit (EXIT_FAILURE);
4937         }
4938     }
4939 
4940   scheduled_task_free (scheduled_task);
4941   gvm_connection_free (&connection);
4942   exit (EXIT_SUCCESS);
4943 }
4944 
4945 /**
4946  * @brief Stop a task, for the scheduler.
4947  *
4948  * @param[in]  scheduled_task   Scheduled task.
4949  * @param[in]  fork_connection  Function that forks a child which is connected
4950  *                              to the Manager.  Must return PID in parent, 0
4951  *                              in child, or -1 on error.
4952  * @param[in]  sigmask_current  Sigmask to restore in child.
4953  *
4954  * @return 0 success, -1 error.  Child does not return.
4955  */
4956 static int
scheduled_task_stop(scheduled_task_t * scheduled_task,manage_connection_forker_t fork_connection,sigset_t * sigmask_current)4957 scheduled_task_stop (scheduled_task_t *scheduled_task,
4958                      manage_connection_forker_t fork_connection,
4959                      sigset_t *sigmask_current)
4960 {
4961   char title[128];
4962   gvm_connection_t connection;
4963   gmp_authenticate_info_opts_t auth_opts;
4964 
4965   /* TODO As with starts above, this should retry if the stop failed. */
4966 
4967   /* Run the callback to fork a child connected to the Manager. */
4968 
4969   switch (fork_connection (&connection, scheduled_task->owner_uuid))
4970     {
4971       case 0:
4972         /* Child.  Break, stop task, exit. */
4973         break;
4974 
4975       case -1:
4976         /* Parent on error. */
4977         g_warning ("%s: stop fork failed", __func__);
4978         return -1;
4979 
4980       default:
4981         /* Parent.  Continue to next task. */
4982         return 0;
4983     }
4984 
4985   /* Stop the task. */
4986 
4987   snprintf (title, sizeof (title),
4988             "gvmd: scheduler: stopping %s",
4989             scheduled_task->task_uuid);
4990   proctitle_set (title);
4991 
4992   auth_opts = gmp_authenticate_info_opts_defaults;
4993   auth_opts.username = scheduled_task->owner_name;
4994   if (gmp_authenticate_info_ext_c (&connection, auth_opts))
4995     {
4996       scheduled_task_free (scheduled_task);
4997       gvm_connection_free (&connection);
4998       exit (EXIT_FAILURE);
4999     }
5000 
5001   if (gmp_stop_task_c (&connection, scheduled_task->task_uuid))
5002     {
5003       scheduled_task_free (scheduled_task);
5004       gvm_connection_free (&connection);
5005       exit (EXIT_FAILURE);
5006     }
5007 
5008   scheduled_task_free (scheduled_task);
5009   gvm_connection_free (&connection);
5010   exit (EXIT_SUCCESS);
5011 }
5012 
5013 /**
5014  * @brief Check if a feed sync is needed without acquiring the feed lock.
5015  *
5016  * @return TRUE if a feed sync is needed, FALSE otherwise.
5017  */
5018 gboolean
feed_sync_required()5019 feed_sync_required ()
5020 {
5021   int feed_status_ret;
5022 
5023   feed_status_ret = secinfo_feed_version_status ("cert");
5024   switch (feed_status_ret)
5025     {
5026       case 1:
5027       case 2:
5028       case 3:
5029       case 4:
5030         g_debug ("%s: CERT database needs to be updated (status %d)",
5031                  __func__, feed_status_ret);
5032         return TRUE;
5033       default:
5034         break;
5035     }
5036 
5037   feed_status_ret = secinfo_feed_version_status ("scap");
5038   switch (feed_status_ret)
5039     {
5040       case 1:
5041       case 2:
5042       case 3:
5043       case 4:
5044         g_debug ("%s: SCAP database needs to be updated (status %d)",
5045                  __func__, feed_status_ret);
5046         return TRUE;
5047       default:
5048         break;
5049     }
5050 
5051   if (nvts_feed_version_status () == 1)
5052     {
5053       g_debug ("%s: NVTs need to be updated", __func__);
5054       return TRUE;
5055     }
5056 
5057   return FALSE;
5058 }
5059 
5060 
5061 
5062 /**
5063  * @brief Perform any syncing that is due.
5064  *
5065  * In gvmd, periodically called from the main daemon loop.
5066  *
5067  * @param[in]  sigmask_current  Sigmask to restore in child.
5068  * @param[in]  fork_update_nvt_cache  Function that forks a child that syncs
5069  *                                    the NVTS.  Child does not return.
5070  * @param[in]  try_gvmd_data_sync  Whether to try to sync gvmd data objects.
5071  */
5072 void
manage_sync(sigset_t * sigmask_current,int (* fork_update_nvt_cache)(),gboolean try_gvmd_data_sync)5073 manage_sync (sigset_t *sigmask_current,
5074              int (*fork_update_nvt_cache) (),
5075              gboolean try_gvmd_data_sync)
5076 {
5077   lockfile_t lockfile;
5078 
5079   reinit_manage_process ();
5080   manage_session_init (current_credentials.uuid);
5081 
5082   if (feed_sync_required ())
5083     {
5084       if (feed_lockfile_lock (&lockfile) == 0)
5085         {
5086           manage_sync_nvts (fork_update_nvt_cache);
5087           manage_sync_scap (sigmask_current);
5088           manage_sync_cert (sigmask_current);
5089 
5090           lockfile_unlock (&lockfile);
5091         }
5092     }
5093 
5094   if (try_gvmd_data_sync
5095       && (should_sync_configs ()
5096           || should_sync_port_lists ()
5097           || should_sync_report_formats ()))
5098     {
5099       if (feed_lockfile_lock (&lockfile) == 0)
5100         {
5101           manage_sync_configs ();
5102           manage_sync_port_lists ();
5103           manage_sync_report_formats ();
5104 
5105           lockfile_unlock (&lockfile);
5106         }
5107     }
5108 }
5109 
5110 /**
5111  * @brief Adds a switch statement for handling the return value of a
5112  *        gvmd data rebuild.
5113  * @param type  The type as a description string, e.g. "port lists"
5114  */
5115 #define REBUILD_SWITCH(type) \
5116   switch (ret)                                                              \
5117     {                                                                       \
5118       case 0:                                                               \
5119         g_message ("Rebuilt %s from feed.", type);                          \
5120         break;                                                              \
5121       case 1:                                                               \
5122         if (error_msg)                                                      \
5123           *error_msg = g_strdup_printf ("No %s feed directory.",            \
5124                                         type);                              \
5125         return -1;                                                          \
5126       case 2:                                                               \
5127         if (error_msg)                                                      \
5128           *error_msg = g_strdup_printf ("Feed owner not set or invalid"     \
5129                                         " while rebuilding %s.",            \
5130                                         type);                              \
5131         return -1;                                                          \
5132       case 3:                                                               \
5133         if (error_msg)                                                      \
5134           *error_msg = g_strdup_printf ("NVTs must be available"            \
5135                                         " while rebuilding %s.",            \
5136                                         type);                              \
5137         return -1;                                                          \
5138       default:                                                              \
5139         if (error_msg)                                                      \
5140           *error_msg = g_strdup_printf ("Internal error"                    \
5141                                         " while rebuilding %s.",            \
5142                                         type);                              \
5143         return -1;                                                          \
5144     }
5145 
5146 /**
5147  * @brief Rebuild configs, port lists and report formats from feed.
5148  *
5149  * @param[in]  types      Comma-separated lists of types to rebuild or "all".
5150  * @param[in]  log_config Logging configuration list.
5151  * @param[in]  database   Connection info for manage database.
5152  * @param[out] error_msg  Error message.
5153  *
5154  * @return 0 success, -1 failed.
5155  */
5156 int
manage_rebuild_gvmd_data_from_feed(const char * types,GSList * log_config,const db_conn_info_t * database,gchar ** error_msg)5157 manage_rebuild_gvmd_data_from_feed (const char *types,
5158                                     GSList *log_config,
5159                                     const db_conn_info_t *database,
5160                                     gchar **error_msg)
5161 {
5162   int ret;
5163   lockfile_t lockfile;
5164   gboolean sync_configs, sync_port_lists, sync_report_formats;
5165 
5166   sync_configs = sync_port_lists = sync_report_formats = FALSE;
5167 
5168   if (strcasecmp (types, "all") == 0)
5169     {
5170       sync_configs = TRUE;
5171       sync_port_lists = TRUE;
5172       sync_report_formats = TRUE;
5173     }
5174   else
5175     {
5176       gchar **split, **split_iter;
5177       split = g_strsplit (types, ",", -1);
5178 
5179       if (*split == NULL)
5180         {
5181           g_free (split);
5182           if (error_msg)
5183             *error_msg = g_strdup ("No types given.");
5184           return -1;
5185         }
5186 
5187       split_iter = split;
5188       while (*split_iter)
5189         {
5190           gchar *type = g_strstrip (*split_iter);
5191 
5192           if (strcasecmp (type, "configs") == 0)
5193             sync_configs = TRUE;
5194           else if (strcasecmp (type, "port_lists") == 0)
5195             sync_port_lists = TRUE;
5196           else if (strcasecmp (type, "report_formats") == 0)
5197             sync_report_formats = TRUE;
5198           else
5199             {
5200               if (error_msg)
5201                 *error_msg = g_strdup_printf ("Invalid type \"%s\""
5202                                               " (must be \"configs\","
5203                                               " \"port_lists\","
5204                                               " \"report_formats\""
5205                                               " or \"all\")",
5206                                               type);
5207               g_strfreev (split);
5208               return -1;
5209             }
5210           split_iter ++;
5211         }
5212       g_strfreev (split);
5213     }
5214 
5215   ret = feed_lockfile_lock_timeout (&lockfile);
5216   if (ret == 1)
5217     {
5218       if (error_msg)
5219         *error_msg = g_strdup ("Feed locked.");
5220       return -1;
5221     }
5222   else if (ret)
5223     {
5224       if (error_msg)
5225         *error_msg = g_strdup ("Error acquiring feed lock.");
5226       return -1;
5227     }
5228 
5229   ret = manage_option_setup (log_config, database);
5230   if (ret)
5231     {
5232       if (error_msg)
5233         *error_msg = g_strdup ("Error setting up log config or"
5234                                " database connection.");
5235       return -1;
5236     }
5237 
5238   if (sync_configs)
5239     {
5240       g_message ("Rebuilding configs from feed...");
5241       ret = manage_rebuild_configs ();
5242       REBUILD_SWITCH ("configs")
5243     }
5244 
5245   if (sync_port_lists)
5246     {
5247       g_message ("Rebuilding port lists from feed...");
5248       ret = manage_rebuild_port_lists ();
5249       REBUILD_SWITCH ("port lists")
5250     }
5251 
5252   if (sync_report_formats)
5253     {
5254       g_message ("Rebuilding report formats from feed...");
5255       ret = manage_rebuild_report_formats ();
5256       REBUILD_SWITCH ("report formats")
5257     }
5258 
5259   feed_lockfile_unlock (&lockfile);
5260   return 0;
5261 }
5262 
5263 #undef REBUILD_SWITCH
5264 
5265 /**
5266  * @brief Schedule any actions that are due.
5267  *
5268  * In gvmd, periodically called from the main daemon loop.
5269  *
5270  * @param[in]  fork_connection  Function that forks a child which is connected
5271  *                              to the Manager.  Must return PID in parent, 0
5272  *                              in child, or -1 on error.
5273  * @param[in]  run_tasks        Whether to run scheduled tasks.
5274  * @param[in]  sigmask_current  Sigmask to restore in child.
5275  *
5276  * @return 0 success, 1 failed to get lock, -1 error.
5277  */
5278 int
manage_schedule(manage_connection_forker_t fork_connection,gboolean run_tasks,sigset_t * sigmask_current)5279 manage_schedule (manage_connection_forker_t fork_connection,
5280                  gboolean run_tasks,
5281                  sigset_t *sigmask_current)
5282 {
5283   iterator_t schedules;
5284   GSList *starts, *stops;
5285   int ret;
5286   task_t previous_start_task, previous_stop_task;
5287 
5288   starts = NULL;
5289   stops = NULL;
5290   previous_start_task = 0;
5291   previous_stop_task = 0;
5292 
5293   auto_delete_reports ();
5294 
5295   ret = manage_update_nvti_cache ();
5296   if (ret)
5297     {
5298       if (ret == -1)
5299         {
5300           g_warning ("%s: manage_update_nvti_cache error"
5301                      " (Perhaps the db went down?)",
5302                      __func__);
5303           /* Just ignore, in case the db went down temporarily. */
5304           return 0;
5305         }
5306 
5307       return ret;
5308     }
5309 
5310   if (run_tasks == 0)
5311     return 0;
5312 
5313   /* Assemble "starts" and "stops" list containing task uuid, owner name and
5314    * owner UUID for each (scheduled) task to start or stop. */
5315 
5316   ret = init_task_schedule_iterator (&schedules);
5317   if (ret)
5318     {
5319       if (ret == -1)
5320         {
5321           g_warning ("%s: iterator init error"
5322                      " (Perhaps the db went down?)",
5323                      __func__);
5324           /* Just ignore, in case the db went down temporarily. */
5325           return 0;
5326         }
5327 
5328       return ret;
5329     }
5330   /* This iterator runs in a transaction. */
5331   while (next (&schedules))
5332     if (task_schedule_iterator_start_due (&schedules))
5333       {
5334         const char *icalendar, *zone;
5335         int timed_out;
5336 
5337         /* Check if task schedule is timed out before updating next due time */
5338         timed_out = task_schedule_iterator_timed_out (&schedules);
5339 
5340         /* Update the task schedule info to prevent multiple schedules. */
5341 
5342         icalendar = task_schedule_iterator_icalendar (&schedules);
5343         zone = task_schedule_iterator_timezone (&schedules);
5344 
5345         g_debug ("%s: start due for %llu, setting next_time",
5346                  __func__,
5347                  task_schedule_iterator_task (&schedules));
5348         set_task_schedule_next_time
5349          (task_schedule_iterator_task (&schedules),
5350           icalendar_next_time_from_string (icalendar, zone, 0));
5351 
5352         /* Skip this task if it was already added to the starts list
5353          * to avoid conflicts between multiple users with permissions. */
5354 
5355         if (previous_start_task == task_schedule_iterator_task (&schedules))
5356           continue;
5357 
5358         if (timed_out)
5359           {
5360             g_message (" %s: Task timed out: %s",
5361                        __func__,
5362                        task_schedule_iterator_task_uuid (&schedules));
5363             continue;
5364           }
5365 
5366         previous_start_task = task_schedule_iterator_task (&schedules);
5367 
5368         /* Add task UUID and owner name and UUID to the list. */
5369 
5370         starts = g_slist_prepend
5371                   (starts,
5372                    scheduled_task_new
5373                     (task_schedule_iterator_task_uuid (&schedules),
5374                      task_schedule_iterator_owner_uuid (&schedules),
5375                      task_schedule_iterator_owner_name (&schedules)));
5376       }
5377     else if (task_schedule_iterator_stop_due (&schedules))
5378       {
5379         /* Skip this task if it was already added to the stops list
5380          * to avoid conflicts between multiple users with permissions. */
5381 
5382         if (previous_stop_task == task_schedule_iterator_task (&schedules))
5383           continue;
5384         previous_stop_task = task_schedule_iterator_task (&schedules);
5385 
5386         /* Add task UUID and owner name and UUID to the list. */
5387 
5388         stops = g_slist_prepend
5389                  (stops,
5390                   scheduled_task_new
5391                    (task_schedule_iterator_task_uuid (&schedules),
5392                     task_schedule_iterator_owner_uuid (&schedules),
5393                     task_schedule_iterator_owner_name (&schedules)));
5394       }
5395   cleanup_task_schedule_iterator (&schedules);
5396 
5397   /* Start tasks in forked processes, now that the SQL statement is closed. */
5398 
5399   while (starts)
5400     {
5401       scheduled_task_t *scheduled_task;
5402       GSList *head;
5403 
5404       scheduled_task = starts->data;
5405 
5406       head = starts;
5407       starts = starts->next;
5408       g_slist_free_1 (head);
5409 
5410       if (scheduled_task_start (scheduled_task,
5411                                 fork_connection,
5412                                 sigmask_current))
5413         /* Error.  Reschedule and continue to next task. */
5414         reschedule_task (scheduled_task->task_uuid);
5415       scheduled_task_free (scheduled_task);
5416     }
5417 
5418   /* Stop tasks in forked processes, now that the SQL statement is closed. */
5419 
5420   while (stops)
5421     {
5422       scheduled_task_t *scheduled_task;
5423       GSList *head;
5424 
5425       scheduled_task = stops->data;
5426       head = stops;
5427       stops = stops->next;
5428       g_slist_free_1 (head);
5429 
5430       if (scheduled_task_stop (scheduled_task,
5431                                fork_connection,
5432                                sigmask_current))
5433         {
5434           /* Error.  Exit. */
5435           scheduled_task_free (scheduled_task);
5436           while (stops)
5437             {
5438               scheduled_task_free (stops->data);
5439               stops = g_slist_delete_link (stops, stops);
5440             }
5441           return -1;
5442         }
5443       scheduled_task_free (scheduled_task);
5444     }
5445 
5446   clear_duration_schedules (0);
5447   update_duration_schedule_periods (0);
5448 
5449   return 0;
5450 }
5451 
5452 /**
5453  * @brief Get the current schedule timeout.
5454  *
5455  * @return The schedule timeout in minutes.
5456  */
5457 int
get_schedule_timeout()5458 get_schedule_timeout ()
5459 {
5460   return schedule_timeout;
5461 }
5462 
5463 /**
5464  * @brief Set the schedule timeout.
5465  *
5466  * @param new_timeout The new schedule timeout in minutes.
5467  */
5468 void
set_schedule_timeout(int new_timeout)5469 set_schedule_timeout (int new_timeout)
5470 {
5471   if (new_timeout < 0)
5472     schedule_timeout = -1;
5473   else
5474     schedule_timeout = new_timeout;
5475 }
5476 
5477 
5478 /* SecInfo. */
5479 
5480 /* Defined in gmp.c. */
5481 void buffer_config_preference_xml (GString *, iterator_t *, config_t, int);
5482 
5483 /**
5484  * @brief Return the path to the CPE dictionary.
5485  *
5486  * @return A dynamically allocated string (to be g_free'd) containing the
5487  *         path to the desired file.
5488  */
5489 static char *
get_cpe_filename()5490 get_cpe_filename ()
5491 {
5492   return g_strdup (CPE_DICT_FILENAME);
5493 }
5494 
5495 /**
5496  * @brief Compute the filename where a given CVE can be found.
5497  *
5498  * @param[in] item_id   Full CVE identifier ("CVE-YYYY-ZZZZ").
5499  *
5500  * @return A dynamically allocated string (to be g_free'd) containing the
5501  *         path to the desired file or NULL on error.
5502  */
5503 static char *
get_cve_filename(char * item_id)5504 get_cve_filename (char *item_id)
5505 {
5506   int year;
5507 
5508   if (sscanf (item_id, "%*3s-%d-%*d", &year) == 1)
5509     {
5510       /* CVEs before 2002 are stored in the 2002 file. */
5511       if (year <= 2002)
5512         year = 2002;
5513       return g_strdup_printf (CVE_FILENAME_FMT, year);
5514     }
5515   return NULL;
5516 }
5517 
5518 /**
5519  * @brief Get the filename where a given OVAL definition can be found.
5520  *
5521  * @param[in] item_id   Full OVAL identifier with file suffix.
5522  *
5523  * @return A dynamically allocated string (to be g_free'd) containing the
5524  *         path to the desired file or NULL on error.
5525  */
5526 static char *
get_ovaldef_filename(char * item_id)5527 get_ovaldef_filename (char *item_id)
5528 {
5529   char *result, *short_filename;
5530 
5531   result = NULL;
5532   short_filename = get_ovaldef_short_filename (item_id);
5533 
5534   if (*short_filename)
5535     {
5536       result = g_strdup_printf ("%s/%s", GVM_SCAP_DATA_DIR, short_filename);
5537     }
5538   free (short_filename);
5539 
5540   return result;
5541 }
5542 
5543 /**
5544  * @brief Compute the filename where a given CERT-Bund Advisory can be found.
5545  *
5546  * @param[in] item_id   CERT-Bund identifier without version ("CB-K??/????").
5547  *
5548  * @return A dynamically allocated string (to be g_free'd) containing the
5549  *         path to the desired file or NULL on error.
5550  */
5551 static char *
get_cert_bund_adv_filename(char * item_id)5552 get_cert_bund_adv_filename (char *item_id)
5553 {
5554   int year;
5555 
5556   if (sscanf (item_id, "CB-K%d-%*s", &year) == 1)
5557     {
5558       return g_strdup_printf (CERT_BUND_ADV_FILENAME_FMT, year);
5559     }
5560   return NULL;
5561 }
5562 
5563 /**
5564  * @brief Compute the filename where a given DFN-CERT Advisory can be found.
5565  *
5566  * @param[in] item_id   Full DFN-CERT identifier ("DFN-CERT-YYYY-ZZZZ").
5567  *
5568  * @return A dynamically allocated string (to be g_free'd) containing the
5569  *         path to the desired file or NULL on error.
5570  */
5571 static char *
get_dfn_cert_adv_filename(char * item_id)5572 get_dfn_cert_adv_filename (char *item_id)
5573 {
5574   int year;
5575 
5576   if (sscanf (item_id, "DFN-CERT-%d-%*s", &year) == 1)
5577     {
5578       return g_strdup_printf (DFN_CERT_ADV_FILENAME_FMT, year);
5579     }
5580   return NULL;
5581 }
5582 
5583 /**
5584  * @brief Run xsltproc in an external process.
5585  *
5586  * @param[in] stylesheet    XSL stylesheet to use.
5587  * @param[in] xmlfile       XML file to process.
5588  * @param[in] param_names   NULL terminated array of stringparam names (can
5589  *                          be NULL).
5590  * @param[in] param_values  NULL terminated array of stringparam values (can
5591  *                          be NULL).
5592  *
5593  * @return A dynamically allocated (to be g_free'd) string containing the
5594  *         result of the operation of NULL on failure.
5595  */
5596 static gchar *
xsl_transform(gchar * stylesheet,gchar * xmlfile,gchar ** param_names,gchar ** param_values)5597 xsl_transform (gchar *stylesheet, gchar *xmlfile, gchar **param_names,
5598                gchar **param_values)
5599 {
5600   int i, param_idx;
5601   gchar **cmd, *cmd_full;
5602   gint exit_status;
5603   gboolean success;
5604   gchar *standard_out = NULL, *standard_err = NULL;
5605 
5606   param_idx = 0;
5607   if (param_names && param_values)
5608     while (param_names[param_idx] && param_values[param_idx])
5609       param_idx++;
5610 
5611   cmd = (gchar **)g_malloc ((4 + param_idx * 3) * sizeof (gchar *));
5612 
5613   i = 0;
5614   cmd[i++] = "xsltproc";
5615   if (param_idx)
5616     {
5617       int j;
5618 
5619       for (j = 0; j < param_idx; j++)
5620         {
5621           cmd[i++] = "--stringparam";
5622           cmd[i++] = param_names[j];
5623           cmd[i++] = param_values[j];
5624         }
5625     }
5626   cmd[i++] = stylesheet;
5627   cmd[i++] = xmlfile;
5628   cmd[i] = NULL;
5629 
5630 
5631   /* DEBUG: display the final command line. */
5632   cmd_full = g_strjoinv (" ", cmd);
5633   g_debug ("%s: Spawning in parent dir: %s",
5634            __func__, cmd_full);
5635   g_free (cmd_full);
5636   /* --- */
5637 
5638   if ((g_spawn_sync (NULL,
5639                      cmd,
5640                      NULL,                  /* Environment. */
5641                      G_SPAWN_SEARCH_PATH,
5642                      NULL,                  /* Setup function. */
5643                      NULL,
5644                      &standard_out,
5645                      &standard_err,
5646                      &exit_status,
5647                      NULL)
5648        == FALSE)
5649       || (WIFEXITED (exit_status) == 0)
5650       || WEXITSTATUS (exit_status))
5651     {
5652       g_debug ("%s: failed to transform the xml: %d (WIF %i, WEX %i)",
5653                __func__,
5654                exit_status,
5655                WIFEXITED (exit_status),
5656                WEXITSTATUS (exit_status));
5657       g_debug ("%s: stderr: %s", __func__, standard_err);
5658       g_debug ("%s: stdout: %s", __func__, standard_out);
5659       success = FALSE;
5660     }
5661   else if (strlen (standard_out) == 0)
5662     success = FALSE; /* execution succeeded but nothing was found */
5663   else
5664     success = TRUE; /* execution succeeded and we have a result */
5665 
5666   /* Cleanup. */
5667   g_free (cmd);
5668   g_free (standard_err);
5669 
5670   if (success)
5671     return standard_out;
5672 
5673   g_free (standard_out);
5674   return NULL;
5675 }
5676 
5677 /**
5678  * @brief Define a code snippet for get_nvti_xml.
5679  *
5680  * @param  x  Prefix for names in snippet.
5681  */
5682 #define DEF(x)                                                    \
5683       const char* x = nvt_iterator_ ## x (nvts);                  \
5684       gchar* x ## _text = x                                       \
5685                           ? g_markup_escape_text (x, -1)          \
5686                           : g_strdup ("");
5687 
5688 /**
5689  * @brief Create and return XML description for an NVT.
5690  *
5691  * @param[in]  nvts        The NVT.
5692  * @param[in]  details     If true, detailed XML, else simple XML.
5693  * @param[in]  pref_count  Preference count.  Used if details is true.
5694  * @param[in]  preferences If true, included preferences.
5695  * @param[in]  timeout     Timeout.  Used if details is true.
5696  * @param[in]  config      Config, used if preferences is true.
5697  * @param[in]  close_tag   Whether to close the NVT tag or not.
5698  *
5699  * @return A dynamically allocated string containing the XML description.
5700  */
5701 gchar *
get_nvt_xml(iterator_t * nvts,int details,int pref_count,int preferences,const char * timeout,config_t config,int close_tag)5702 get_nvt_xml (iterator_t *nvts, int details, int pref_count,
5703              int preferences, const char *timeout, config_t config,
5704              int close_tag)
5705 {
5706   const char* oid = nvt_iterator_oid (nvts);
5707   const char* name = nvt_iterator_name (nvts);
5708   gchar *msg, *name_text;
5709 
5710   name_text = name
5711                ? g_markup_escape_text (name, strlen (name))
5712                : g_strdup ("");
5713   if (details)
5714     {
5715       int tag_count;
5716       GString *refs_str, *tags_str, *buffer, *nvt_tags;
5717       iterator_t cert_refs_iterator, tags, severities;
5718       gchar *tag_name_esc, *tag_value_esc, *tag_comment_esc;
5719       char *default_timeout = nvt_default_timeout (oid);
5720 
5721       DEF (family);
5722       DEF (tag);
5723 
5724 #undef DEF
5725 
5726       nvt_tags = g_string_new (tag_text);
5727       g_free (tag_text);
5728 
5729       /* Add the elements that are expected as part of the pipe-separated tag list
5730        * via API although internally already explicitly stored. Once the API is
5731        * extended to have these elements explicitly, they do not need to be
5732        * added to this tag string anymore. */
5733       if (nvt_iterator_summary (nvts) && nvt_iterator_summary (nvts)[0])
5734         {
5735           if (nvt_tags->str)
5736             xml_string_append (nvt_tags, "|summary=%s",
5737                                nvt_iterator_summary (nvts));
5738           else
5739             xml_string_append (nvt_tags, "summary=%s",
5740                                nvt_iterator_summary (nvts));
5741         }
5742       if (nvt_iterator_insight (nvts) && nvt_iterator_insight (nvts)[0])
5743         {
5744           if (nvt_tags->str)
5745             xml_string_append (nvt_tags, "|insight=%s",
5746                                nvt_iterator_insight (nvts));
5747           else
5748             xml_string_append (nvt_tags, "insight=%s",
5749                                nvt_iterator_insight (nvts));
5750         }
5751       if (nvt_iterator_affected (nvts) && nvt_iterator_affected (nvts)[0])
5752         {
5753           if (nvt_tags->str)
5754             xml_string_append (nvt_tags, "|affected=%s",
5755                                nvt_iterator_affected (nvts));
5756           else
5757             xml_string_append (nvt_tags, "affected=%s",
5758                                nvt_iterator_affected (nvts));
5759         }
5760       if (nvt_iterator_impact (nvts) && nvt_iterator_impact (nvts)[0])
5761         {
5762           if (nvt_tags->str)
5763             xml_string_append (nvt_tags, "|impact=%s",
5764                                nvt_iterator_impact (nvts));
5765           else
5766             xml_string_append (nvt_tags, "impact=%s",
5767                                nvt_iterator_impact (nvts));
5768         }
5769       if (nvt_iterator_detection (nvts) && nvt_iterator_detection (nvts)[0])
5770         {
5771           if (nvt_tags->str)
5772             xml_string_append (nvt_tags, "|vuldetect=%s",
5773                                nvt_iterator_detection (nvts));
5774           else
5775             xml_string_append (nvt_tags, "vuldetect=%s",
5776                                nvt_iterator_detection (nvts));
5777         }
5778 
5779       refs_str = g_string_new ("");
5780 
5781       if (manage_cert_loaded())
5782         {
5783           init_nvt_cert_bund_adv_iterator (&cert_refs_iterator, oid);
5784           while (next (&cert_refs_iterator))
5785             {
5786               xml_string_append (refs_str,
5787                                  "<ref type=\"cert-bund\" id=\"%s\"/>",
5788                                  nvt_cert_bund_adv_iterator_name
5789                                   (&cert_refs_iterator));
5790             }
5791           cleanup_iterator (&cert_refs_iterator);
5792 
5793           init_nvt_dfn_cert_adv_iterator (&cert_refs_iterator, oid);
5794           while (next (&cert_refs_iterator))
5795             {
5796               xml_string_append (refs_str,
5797                                  "<ref type=\"dfn-cert\" id=\"%s\"/>",
5798                                  nvt_dfn_cert_adv_iterator_name
5799                                   (&cert_refs_iterator));
5800             }
5801           cleanup_iterator (&cert_refs_iterator);
5802         }
5803       else
5804         {
5805           g_string_append (refs_str,
5806                            "<warning>database not available</warning>");
5807         }
5808 
5809       xml_append_nvt_refs (refs_str, oid, NULL);
5810 
5811       tags_str = g_string_new ("");
5812       tag_count = resource_tag_count ("nvt",
5813                                       get_iterator_resource (nvts),
5814                                       1);
5815 
5816       if (tag_count)
5817         {
5818           g_string_append_printf (tags_str,
5819                                   "<user_tags>"
5820                                   "<count>%i</count>",
5821                                   tag_count);
5822 
5823           init_resource_tag_iterator (&tags, "nvt",
5824                                       get_iterator_resource (nvts),
5825                                       1, NULL, 1);
5826           while (next (&tags))
5827             {
5828               tag_name_esc = g_markup_escape_text (resource_tag_iterator_name
5829                                                     (&tags),
5830                                                   -1);
5831               tag_value_esc = g_markup_escape_text (resource_tag_iterator_value
5832                                                       (&tags),
5833                                                     -1);
5834               tag_comment_esc = g_markup_escape_text (resource_tag_iterator_comment
5835                                                         (&tags),
5836                                                       -1);
5837               g_string_append_printf (tags_str,
5838                                       "<tag id=\"%s\">"
5839                                       "<name>%s</name>"
5840                                       "<value>%s</value>"
5841                                       "<comment>%s</comment>"
5842                                       "</tag>",
5843                                       resource_tag_iterator_uuid (&tags),
5844                                       tag_name_esc,
5845                                       tag_value_esc,
5846                                       tag_comment_esc);
5847               g_free (tag_name_esc);
5848               g_free (tag_value_esc);
5849               g_free (tag_comment_esc);
5850             }
5851           cleanup_iterator (&tags);
5852           g_string_append_printf (tags_str,
5853                                   "</user_tags>");
5854         }
5855 
5856       buffer = g_string_new ("");
5857 
5858       g_string_append_printf (buffer,
5859                               "<nvt oid=\"%s\">"
5860                               "<name>%s</name>"
5861                               "<creation_time>%s</creation_time>"
5862                               "<modification_time>%s</modification_time>"
5863                               "%s" // user_tags
5864                               "<category>%d</category>"
5865                               "<family>%s</family>"
5866                               "<cvss_base>%s</cvss_base>"
5867                               "<severities score=\"%s\">",
5868                               oid,
5869                               name_text,
5870                               get_iterator_creation_time (nvts)
5871                                ? get_iterator_creation_time (nvts)
5872                                : "",
5873                               get_iterator_modification_time (nvts)
5874                                ? get_iterator_modification_time (nvts)
5875                                : "",
5876                               tags_str->str,
5877                               nvt_iterator_category (nvts),
5878                               family_text,
5879                               nvt_iterator_cvss_base (nvts)
5880                                ? nvt_iterator_cvss_base (nvts)
5881                                : "",
5882                               nvt_iterator_cvss_base (nvts)
5883                                ? nvt_iterator_cvss_base (nvts)
5884                                : "");
5885 
5886       init_nvt_severity_iterator (&severities, oid);
5887       while (next (&severities))
5888         {
5889           buffer_xml_append_printf
5890               (buffer,
5891                "<severity type=\"%s\">"
5892                "<origin>%s</origin>"
5893                "<date>%s</date>"
5894                "<score>%0.1f</score>"
5895                "<value>%s</value>"
5896                "</severity>",
5897                nvt_severity_iterator_type (&severities),
5898                nvt_severity_iterator_origin (&severities),
5899                nvt_severity_iterator_date (&severities),
5900                nvt_severity_iterator_score (&severities),
5901                nvt_severity_iterator_value (&severities));
5902         }
5903       cleanup_iterator (&severities);
5904 
5905       g_string_append_printf (buffer,
5906                               "</severities>"
5907                               "<qod>"
5908                               "<value>%s</value>"
5909                               "<type>%s</type>"
5910                               "</qod>"
5911                               "<refs>%s</refs>"
5912                               "<tags>%s</tags>"
5913                               "<preference_count>%i</preference_count>"
5914                               "<timeout>%s</timeout>"
5915                               "<default_timeout>%s</default_timeout>",
5916                               nvt_iterator_qod (nvts),
5917                               nvt_iterator_qod_type (nvts),
5918                               refs_str->str,
5919                               nvt_tags->str,
5920                               pref_count,
5921                               timeout ? timeout : "",
5922                               default_timeout ? default_timeout : "");
5923       g_free (family_text);
5924       g_string_free(nvt_tags, 1);
5925       g_string_free(refs_str, 1);
5926       g_string_free(tags_str, 1);
5927 
5928       if (nvt_iterator_solution (nvts) ||
5929           nvt_iterator_solution_type (nvts) ||
5930           nvt_iterator_solution_method (nvts))
5931         {
5932           buffer_xml_append_printf (buffer, "<solution");
5933 
5934           if (nvt_iterator_solution_type (nvts))
5935             buffer_xml_append_printf (buffer, " type='%s'",
5936               nvt_iterator_solution_type (nvts));
5937 
5938           if (nvt_iterator_solution_method (nvts))
5939             buffer_xml_append_printf (buffer, " method='%s'",
5940               nvt_iterator_solution_method (nvts));
5941 
5942           if (nvt_iterator_solution (nvts))
5943             buffer_xml_append_printf (buffer, ">%s</solution>",
5944               nvt_iterator_solution (nvts));
5945           else
5946             buffer_xml_append_printf (buffer, "/>");
5947         }
5948 
5949 
5950       if (preferences)
5951         {
5952           iterator_t prefs;
5953           const char *nvt_oid = nvt_iterator_oid (nvts);
5954 
5955           /* Send the preferences for the NVT. */
5956 
5957           xml_string_append (buffer,
5958                              "<preferences>"
5959                              "<timeout>%s</timeout>"
5960                              "<default_timeout>%s</default_timeout>",
5961                              timeout ? timeout : "",
5962                              default_timeout ? default_timeout : "");
5963 
5964           init_nvt_preference_iterator (&prefs, nvt_oid);
5965           while (next (&prefs))
5966             buffer_config_preference_xml (buffer, &prefs, config, 1);
5967           cleanup_iterator (&prefs);
5968 
5969           xml_string_append (buffer, "</preferences>");
5970         }
5971 
5972       xml_string_append (buffer, close_tag ? "</nvt>" : "");
5973       msg = g_string_free (buffer, FALSE);
5974       free (default_timeout);
5975     }
5976   else
5977     {
5978       int tag_count;
5979       tag_count = resource_tag_count ("nvt",
5980                                       get_iterator_resource (nvts),
5981                                       1);
5982 
5983       if (tag_count)
5984         {
5985           msg = g_strdup_printf
5986                  ("<nvt oid=\"%s\"><name>%s</name>"
5987                   "<user_tags><count>%i</count></user_tags>%s",
5988                   oid, name_text,
5989                   tag_count,
5990                   close_tag ? "</nvt>" : "");
5991         }
5992       else
5993         {
5994           msg = g_strdup_printf
5995                  ("<nvt oid=\"%s\"><name>%s</name>%s",
5996                   oid, name_text,
5997                   close_tag ? "</nvt>" : "");
5998         }
5999     }
6000   g_free (name_text);
6001   return msg;
6002 }
6003 
6004 /**
6005  * @brief GET SCAP update time, as a string.
6006  *
6007  * @return Last update time as a static string, or "" on error.
6008  */
6009 const char *
manage_scap_update_time()6010 manage_scap_update_time ()
6011 {
6012   gchar *content;
6013   GError *error;
6014   gsize content_size;
6015   struct tm update_time;
6016 
6017   /* Read in the contents. */
6018 
6019   error = NULL;
6020   if (g_file_get_contents (SCAP_TIMESTAMP_FILENAME,
6021                            &content,
6022                            &content_size,
6023                            &error)
6024       == FALSE)
6025     {
6026       if (error)
6027         {
6028           g_debug ("%s: failed to read %s: %s",
6029                    __func__, SCAP_TIMESTAMP_FILENAME, error->message);
6030           g_error_free (error);
6031         }
6032       return "";
6033     }
6034 
6035   memset (&update_time, 0, sizeof (struct tm));
6036   if (strptime (content, "%Y%m%d%H%M", &update_time))
6037     {
6038       static char time_string[100];
6039       #if !defined(__GLIBC__)
6040         strftime (time_string, 99, "%Y-%m-%dT%T.000", &update_time);
6041       #else
6042         strftime (time_string, 99, "%FT%T.000%z", &update_time);
6043       #endif
6044       return time_string;
6045     }
6046   return "";
6047 }
6048 
6049 /**
6050  * @brief Read raw information.
6051  *
6052  * @param[in]   type    Type of the requested information.
6053  * @param[in]   uid     Unique identifier of the requested information
6054  * @param[in]   name    Name or identifier of the requested information.
6055  * @param[out]  result  Pointer to the read information location. Will point
6056  *                      to NULL on error.
6057  *
6058  * @return 1 success, -1 error.
6059  */
6060 int
manage_read_info(gchar * type,gchar * uid,gchar * name,gchar ** result)6061 manage_read_info (gchar *type, gchar *uid, gchar *name, gchar **result)
6062 {
6063   gchar *fname;
6064   gchar *pnames[2] = { "refname", NULL };
6065   gchar *pvalues[2] = { name, NULL };
6066 
6067   assert (result != NULL);
6068   *result = NULL;
6069 
6070   if (g_ascii_strcasecmp ("CPE", type) == 0)
6071     {
6072       fname = get_cpe_filename ();
6073       if (fname)
6074         {
6075           gchar *cpe;
6076           cpe = xsl_transform (CPE_GETBYNAME_XSL, fname, pnames, pvalues);
6077           g_free (fname);
6078           if (cpe)
6079             *result = cpe;
6080         }
6081     }
6082   else if (g_ascii_strcasecmp ("CVE", type) == 0)
6083     {
6084       fname = get_cve_filename (uid);
6085       if (fname)
6086         {
6087           gchar *cve;
6088           cve = xsl_transform (CVE_GETBYNAME_XSL, fname, pnames, pvalues);
6089           g_free (fname);
6090           if (cve)
6091             *result = cve;
6092         }
6093     }
6094   else if (g_ascii_strcasecmp ("NVT", type) == 0)
6095     {
6096       iterator_t nvts;
6097       nvt_t nvt;
6098 
6099       if (!find_nvt (uid ? uid : name, &nvt) && nvt)
6100         {
6101           init_nvt_iterator (&nvts, nvt, 0, NULL, NULL, 0, NULL);
6102 
6103           if (next (&nvts))
6104             *result = get_nvt_xml (&nvts,
6105                                    1,    /* Include details. */
6106                                    0,    /* Preference count. */
6107                                    1,    /* Include preferences. */
6108                                    NULL, /* Timeout. */
6109                                    0,    /* Config. */
6110                                    1);   /* Close tag. */
6111 
6112           cleanup_iterator (&nvts);
6113         }
6114     }
6115   else if (g_ascii_strcasecmp ("OVALDEF", type) == 0)
6116     {
6117       fname = get_ovaldef_filename (uid);
6118       if (fname)
6119         {
6120           gchar *ovaldef;
6121           ovaldef = xsl_transform (OVALDEF_GETBYNAME_XSL, fname,
6122                                    pnames, pvalues);
6123           g_free (fname);
6124           if (ovaldef)
6125             *result = ovaldef;
6126         }
6127     }
6128   else if (g_ascii_strcasecmp ("CERT_BUND_ADV", type) == 0)
6129     {
6130       fname = get_cert_bund_adv_filename (uid);
6131       if (fname)
6132         {
6133           gchar *adv;
6134           adv = xsl_transform (CERT_BUND_ADV_GETBYNAME_XSL, fname,
6135                                pnames, pvalues);
6136           g_free (fname);
6137           if (adv)
6138             *result = adv;
6139         }
6140     }
6141   else if (g_ascii_strcasecmp ("DFN_CERT_ADV", type) == 0)
6142     {
6143       fname = get_dfn_cert_adv_filename (uid);
6144       if (fname)
6145         {
6146           gchar *adv;
6147           adv = xsl_transform (DFN_CERT_ADV_GETBYNAME_XSL, fname,
6148                                pnames, pvalues);
6149           g_free (fname);
6150           if (adv)
6151             *result = adv;
6152         }
6153     }
6154 
6155   if (*result == NULL)
6156     return -1;
6157 
6158   return 1;
6159 }
6160 
6161 
6162 /* Users. */
6163 
6164 /**
6165  *
6166  * @brief Validates a username.
6167  *
6168  * @param[in]  name  The name.
6169  *
6170  * @return 0 if the username is valid, 1 if not.
6171  */
6172 int
validate_username(const gchar * name)6173 validate_username (const gchar * name)
6174 {
6175   if (g_regex_match_simple ("^[[:alnum:]-_.]+$", name, 0, 0))
6176     return 0;
6177   else
6178     return 1;
6179 }
6180 
6181 
6182 /* Resource aggregates. */
6183 
6184 /**
6185  * @brief Free a sort_data_t struct and its related resources.
6186  *
6187  * @param[in] sort_data  The sort_data struct to free.
6188  */
6189 void
sort_data_free(sort_data_t * sort_data)6190 sort_data_free (sort_data_t *sort_data)
6191 {
6192   g_free (sort_data->field);
6193   g_free (sort_data->stat);
6194   g_free (sort_data);
6195 }
6196 
6197 
6198 /* Feeds. */
6199 
6200 /**
6201  * @brief Tests if the gvmd data feed directory and its subdirectories exist.
6202  *
6203  * @return TRUE if the directory exists.
6204  */
6205 gboolean
manage_gvmd_data_feed_dirs_exist()6206 manage_gvmd_data_feed_dirs_exist ()
6207 {
6208   return gvm_file_is_readable (GVMD_FEED_DIR)
6209          && configs_feed_dir_exists ()
6210          && port_lists_feed_dir_exists ()
6211          && report_formats_feed_dir_exists ();
6212 }
6213 
6214 /**
6215  * @brief Get the feed lock file path.
6216  *
6217  * @return The current path to the lock file.
6218  */
6219 const gchar *
get_feed_lock_path()6220 get_feed_lock_path ()
6221 {
6222   return feed_lock_path;
6223 }
6224 
6225 /**
6226  * @brief Set the feed lock file path.
6227  *
6228  * @param new_path The new path to the lock file.
6229  */
6230 void
set_feed_lock_path(const char * new_path)6231 set_feed_lock_path (const char *new_path)
6232 {
6233   g_free (feed_lock_path);
6234   if (new_path && strcmp (new_path, ""))
6235     feed_lock_path = g_strdup (new_path);
6236   else
6237     feed_lock_path = g_strdup (GVM_FEED_LOCK_PATH);
6238 }
6239 
6240 /**
6241  * @brief Get the feed lock timeout.
6242  *
6243  * @return The current timeout in seconds.
6244  */
6245 int
get_feed_lock_timeout()6246 get_feed_lock_timeout ()
6247 {
6248   return feed_lock_timeout;
6249 }
6250 
6251 /**
6252  * @brief Set the feed lock timeout.
6253  *
6254  * @param new_timeout The new timeout in seconds.
6255  */
6256 void
set_feed_lock_timeout(int new_timeout)6257 set_feed_lock_timeout (int new_timeout)
6258 {
6259   if (new_timeout < 0)
6260     feed_lock_timeout = 0;
6261   else
6262     feed_lock_timeout = new_timeout;
6263 }
6264 
6265 /**
6266  * @brief Write start time to sync lock file.
6267  *
6268  * @param[in]  lockfile_fd  File descriptor of the lock file.
6269  */
6270 void
write_sync_start(int lockfile_fd)6271 write_sync_start (int lockfile_fd)
6272 {
6273   time_t now;
6274   char now_string[26];
6275   char *now_string_ptr = now_string;
6276 
6277   now = time (NULL);
6278   ctime_r (&now, now_string);
6279   while (*now_string_ptr)
6280     {
6281       ssize_t count;
6282       count = write (lockfile_fd,
6283                      now_string,
6284                      strlen (now_string));
6285       if (count < 0)
6286         {
6287           if (errno == EAGAIN || errno == EINTR)
6288             /* Interrupted, try write again. */
6289             continue;
6290           g_warning ("%s: failed to write to lockfile: %s",
6291                      __func__,
6292                      strerror (errno));
6293           break;
6294         }
6295       now_string_ptr += count;
6296     }
6297 }
6298 
6299 /**
6300  * @brief Acquires the feed lock and writes the current time to the lockfile.
6301  *
6302  * @param[out] lockfile   Lockfile data struct.
6303  *
6304  * @return 0 success, 1 already locked, -1 error
6305  */
6306 int
feed_lockfile_lock(lockfile_t * lockfile)6307 feed_lockfile_lock (lockfile_t *lockfile)
6308 {
6309   int ret;
6310 
6311   /* Try to lock the file */
6312   ret = lockfile_lock_path_nb (lockfile, get_feed_lock_path ());
6313   if (ret)
6314     {
6315       return ret;
6316     }
6317 
6318   /* Write the file contents (timestamp) */
6319   write_sync_start (lockfile->fd);
6320 
6321   return 0;
6322 }
6323 
6324 /**
6325  * @brief Acquires the feed lock and writes the current time to the lockfile.
6326  *
6327  * @param[out] lockfile   Lockfile data struct.
6328  *
6329  * @return 0 success, 1 already locked, -1 error
6330  */
6331 int
feed_lockfile_lock_timeout(lockfile_t * lockfile)6332 feed_lockfile_lock_timeout (lockfile_t *lockfile)
6333 {
6334   int lock_status;
6335   gboolean log_timeout;
6336   time_t timeout_end;
6337 
6338   /* Try to lock the file */
6339 
6340   log_timeout = TRUE;
6341   timeout_end = time (NULL) + feed_lock_timeout;
6342   do
6343     {
6344       lock_status = feed_lockfile_lock (lockfile);
6345       if (lock_status == 1 /* already locked, but no error */
6346           && timeout_end > time (NULL))
6347         {
6348           if (log_timeout)
6349             {
6350               log_timeout = FALSE;
6351               g_message ("%s: Feed is currently locked by another process,"
6352                          " will retry until %s.",
6353                          __func__, iso_time (&timeout_end));
6354             }
6355           gvm_sleep (1);
6356         }
6357       else if (lock_status) /* error */
6358         {
6359           return lock_status;
6360         }
6361     } while (lock_status); /* lock is acquired when lock_status is 0 */
6362 
6363   return 0;
6364 }
6365 
6366 /**
6367  * @brief Releases the feed lock and clears the contents.
6368  *
6369  * @param[in] lockfile   Lockfile data struct.
6370  *
6371  * @return 0 success, -1 error
6372  */
6373 int
feed_lockfile_unlock(lockfile_t * lockfile)6374 feed_lockfile_unlock (lockfile_t *lockfile)
6375 {
6376   int ret;
6377 
6378   /* Clear timestamp from lock file. */
6379   if (ftruncate (lockfile->fd, 0))
6380     g_warning ("%s: failed to ftruncate lockfile: %s",
6381                __func__,
6382                strerror (errno));
6383 
6384   /* Unlock the lockfile */
6385   ret = lockfile_unlock (lockfile);
6386   if (ret)
6387     {
6388       g_critical ("%s: Error releasing checking lock", __func__);
6389       return -1;
6390     }
6391 
6392   return 0;
6393 }
6394 
6395 /**
6396  * @brief Request a feed synchronization script selftest.
6397  *
6398  * Ask a feed synchronization script to perform a selftest and report
6399  * the results.
6400  *
6401  * @param[in]   sync_script  The file name of the synchronization script.
6402  * @param[out]  result       Return location for selftest errors, or NULL.
6403  *
6404  * @return TRUE if the selftest was successful, or FALSE if an error occurred.
6405  */
6406 gboolean
gvm_sync_script_perform_selftest(const gchar * sync_script,gchar ** result)6407 gvm_sync_script_perform_selftest (const gchar * sync_script,
6408                                   gchar ** result)
6409 {
6410   g_assert (sync_script);
6411   g_assert_cmpstr (*result, ==, NULL);
6412 
6413   gchar *script_working_dir = g_path_get_dirname (sync_script);
6414 
6415   gchar **argv = (gchar **) g_malloc (3 * sizeof (gchar *));
6416   argv[0] = g_strdup (sync_script);
6417   argv[1] = g_strdup ("--selftest");
6418   argv[2] = NULL;
6419 
6420   gchar *script_out;
6421   gchar *script_err;
6422   gint script_exit;
6423   GError *error = NULL;
6424 
6425   if (!g_spawn_sync
6426       (script_working_dir, argv, NULL, 0, NULL, NULL, &script_out, &script_err,
6427        &script_exit, &error))
6428     {
6429       if (*result != NULL)
6430         {
6431           *result =
6432             g_strdup_printf ("Failed to execute synchronization " "script: %s",
6433                              error->message);
6434         }
6435 
6436       g_free (script_working_dir);
6437       g_strfreev (argv);
6438       g_free (script_out);
6439       g_free (script_err);
6440       g_error_free (error);
6441 
6442       return FALSE;
6443     }
6444 
6445   if (script_exit != 0)
6446     {
6447       if (script_err != NULL)
6448         {
6449           *result = g_strdup_printf ("%s", script_err);
6450         }
6451 
6452       g_free (script_working_dir);
6453       g_strfreev (argv);
6454       g_free (script_out);
6455       g_free (script_err);
6456 
6457       return FALSE;
6458     }
6459 
6460   g_free (script_working_dir);
6461   g_strfreev (argv);
6462   g_free (script_out);
6463   g_free (script_err);
6464 
6465   return TRUE;
6466 }
6467 
6468 /**
6469  * @brief Retrieves the ID string of a feed sync script, with basic validation.
6470  *
6471  * @param[in]   sync_script     The file name of the synchronization script.
6472  * @param[out]  identification  Return location of the identification string.
6473  * @param[in]   feed_type       Could be NVT_FEED, SCAP_FEED or CERT_FEED.
6474  *
6475  * @return TRUE if the identification string was retrieved, or FALSE if an
6476  *         error occurred.
6477  */
6478 gboolean
gvm_get_sync_script_identification(const gchar * sync_script,gchar ** identification,int feed_type)6479 gvm_get_sync_script_identification (const gchar * sync_script,
6480                                     gchar ** identification,
6481                                     int feed_type)
6482 {
6483   g_assert (sync_script);
6484   if (identification)
6485     g_assert_cmpstr (*identification, ==, NULL);
6486 
6487   gchar *script_working_dir = g_path_get_dirname (sync_script);
6488 
6489   gchar **argv = (gchar **) g_malloc (3 * sizeof (gchar *));
6490   argv[0] = g_strdup (sync_script);
6491   argv[1] = g_strdup ("--identify");
6492   argv[2] = NULL;
6493 
6494   gchar *script_out;
6495   gchar *script_err;
6496   gint script_exit;
6497   GError *error = NULL;
6498 
6499   gchar **script_identification;
6500 
6501   if (!g_spawn_sync
6502         (script_working_dir, argv, NULL, 0, NULL, NULL, &script_out, &script_err,
6503          &script_exit, &error))
6504     {
6505       g_warning ("Failed to execute %s: %s", sync_script, error->message);
6506 
6507       g_free (script_working_dir);
6508       g_strfreev (argv);
6509       g_free (script_out);
6510       g_free (script_err);
6511       g_error_free (error);
6512 
6513       return FALSE;
6514     }
6515 
6516   if (script_exit != 0)
6517     {
6518       g_warning ("%s returned a non-zero exit code.", sync_script);
6519 
6520       g_free (script_working_dir);
6521       g_strfreev (argv);
6522       g_free (script_out);
6523       g_free (script_err);
6524 
6525       return FALSE;
6526     }
6527 
6528   script_identification = g_strsplit (script_out, "|", 6);
6529 
6530   if ((script_identification[0] == NULL)
6531       || (feed_type == NVT_FEED
6532           && g_ascii_strncasecmp (script_identification[0], "NVTSYNC", 7))
6533       || (feed_type == SCAP_FEED
6534           && g_ascii_strncasecmp (script_identification[0], "SCAPSYNC", 7))
6535       || (feed_type == CERT_FEED
6536           && g_ascii_strncasecmp (script_identification[0], "CERTSYNC", 7))
6537       || g_ascii_strncasecmp (script_identification[0], script_identification[5], 7))
6538     {
6539       g_warning ("%s is not a feed synchronization script", sync_script);
6540 
6541       g_free (script_working_dir);
6542       g_strfreev (argv);
6543       g_free (script_out);
6544       g_free (script_err);
6545 
6546       g_strfreev (script_identification);
6547 
6548       return FALSE;
6549     }
6550 
6551   if (identification)
6552     *identification = g_strdup (script_out);
6553 
6554   g_free (script_working_dir);
6555   g_strfreev (argv);
6556   g_free (script_out);
6557   g_free (script_err);
6558 
6559   g_strfreev (script_identification);
6560 
6561   return TRUE;
6562 }
6563 
6564 /**
6565  * @brief Retrieves description of a feed sync script, with basic validation.
6566  *
6567  * @param[in]   sync_script  The file name of the synchronization script.
6568  * @param[out]  description  Return location of the description string.
6569  *
6570  * @return TRUE if the description was retrieved, or FALSE if an error
6571  *         occurred.
6572  */
6573 gboolean
gvm_get_sync_script_description(const gchar * sync_script,gchar ** description)6574 gvm_get_sync_script_description (const gchar * sync_script,
6575                                  gchar ** description)
6576 {
6577   g_assert (sync_script);
6578   g_assert_cmpstr (*description, ==, NULL);
6579 
6580   gchar *script_working_dir = g_path_get_dirname (sync_script);
6581 
6582   gchar **argv = (gchar **) g_malloc (3 * sizeof (gchar *));
6583   argv[0] = g_strdup (sync_script);
6584   argv[1] = g_strdup ("--describe");
6585   argv[2] = NULL;
6586 
6587   gchar *script_out;
6588   gchar *script_err;
6589   gint script_exit;
6590   GError *error = NULL;
6591 
6592   if (!g_spawn_sync
6593       (script_working_dir, argv, NULL, 0, NULL, NULL, &script_out, &script_err,
6594        &script_exit, &error))
6595     {
6596       g_warning ("Failed to execute %s: %s", sync_script, error->message);
6597 
6598       g_free (script_working_dir);
6599       g_strfreev (argv);
6600       g_free (script_out);
6601       g_free (script_err);
6602       g_error_free (error);
6603 
6604       return FALSE;
6605     }
6606 
6607   if (script_exit != 0)
6608     {
6609       g_warning ("%s returned a non-zero exit code.", sync_script);
6610 
6611       g_free (script_working_dir);
6612       g_strfreev (argv);
6613       g_free (script_out);
6614       g_free (script_err);
6615 
6616       return FALSE;
6617     }
6618 
6619   *description = g_strdup (script_out);
6620 
6621   g_free (script_working_dir);
6622   g_strfreev (argv);
6623   g_free (script_out);
6624   g_free (script_err);
6625 
6626   return TRUE;
6627 }
6628 
6629 /**
6630  * @brief Retrieves the version of a feed handled by the sync, with basic
6631  * validation.
6632  *
6633  * @param[in]   sync_script  The file name of the synchronization script.
6634  * @param[out]  feed_version  Return location of the feed version string.
6635  *
6636  * @return TRUE if the feed version was retrieved, or FALSE if an error
6637  *         occurred.
6638  */
6639 gboolean
gvm_get_sync_script_feed_version(const gchar * sync_script,gchar ** feed_version)6640 gvm_get_sync_script_feed_version (const gchar * sync_script,
6641                                   gchar ** feed_version)
6642 {
6643   g_assert (sync_script);
6644   g_assert_cmpstr (*feed_version, ==, NULL);
6645 
6646   gchar *script_working_dir = g_path_get_dirname (sync_script);
6647 
6648   gchar **argv = (gchar **) g_malloc (3 * sizeof (gchar *));
6649   argv[0] = g_strdup (sync_script);
6650   argv[1] = g_strdup ("--feedversion");
6651   argv[2] = NULL;
6652 
6653   gchar *script_out;
6654   gchar *script_err;
6655   gint script_exit;
6656   GError *error = NULL;
6657 
6658   if (!g_spawn_sync
6659         (script_working_dir, argv, NULL, 0, NULL, NULL, &script_out, &script_err,
6660          &script_exit, &error))
6661     {
6662       g_warning ("Failed to execute %s: %s", sync_script, error->message);
6663 
6664       g_free (script_working_dir);
6665       g_strfreev (argv);
6666       g_free (script_out);
6667       g_free (script_err);
6668       g_error_free (error);
6669 
6670       return FALSE;
6671     }
6672 
6673   if (script_exit != 0)
6674     {
6675       g_warning ("%s returned a non-zero exit code.", sync_script);
6676 
6677       g_free (script_working_dir);
6678       g_strfreev (argv);
6679       g_free (script_out);
6680       g_free (script_err);
6681 
6682       return FALSE;
6683     }
6684 
6685   *feed_version = g_strdup (script_out);
6686 
6687   g_free (script_working_dir);
6688   g_strfreev (argv);
6689   g_free (script_out);
6690   g_free (script_err);
6691 
6692   return TRUE;
6693 }
6694 
6695 /**
6696  * @brief Migrates SCAP or CERT database, waiting until migration terminates.
6697  *
6698  * Calls a sync script to migrate the SCAP or CERT database.
6699  *
6700  * @param[in]  feed_type     Could be SCAP_FEED or CERT_FEED.
6701  *
6702  * @return 0 sync complete, 1 sync already in progress, -1 error
6703  */
6704 int
gvm_migrate_secinfo(int feed_type)6705 gvm_migrate_secinfo (int feed_type)
6706 {
6707   lockfile_t lockfile;
6708   int ret;
6709 
6710   if (feed_type != SCAP_FEED && feed_type != CERT_FEED)
6711     {
6712       g_warning ("%s: unsupported feed_type", __func__);
6713       return -1;
6714     }
6715 
6716   ret = feed_lockfile_lock_timeout (&lockfile);
6717   if (ret == 1)
6718     return 1;
6719   else if (ret)
6720     return -1;
6721 
6722   if (feed_type == SCAP_FEED)
6723     ret = check_scap_db_version ();
6724   else
6725     ret = check_cert_db_version ();
6726 
6727   feed_lockfile_unlock (&lockfile);
6728 
6729   return ret;
6730 }
6731 
6732 /**
6733  * @brief Update NVT cache using OSP.
6734  *
6735  * @param[in]  update_socket  Socket to use to contact ospd-openvas scanner.
6736  *
6737  * @return 0 success, -1 error, 1 VT integrity check failed.
6738  */
6739 int
manage_update_nvts_osp(const gchar * update_socket)6740 manage_update_nvts_osp (const gchar *update_socket)
6741 {
6742   return manage_update_nvt_cache_osp (update_socket);
6743 }
6744 
6745 
6746 /* Wizards. */
6747 
6748 /**
6749  * @brief Run a wizard.
6750  *
6751  * @param[in]  wizard_name       Wizard name.
6752  * @param[in]  run_command       Function to run GMP command.
6753  * @param[in]  run_command_data  Argument for run_command.
6754  * @param[in]  params            Wizard params.  Array of name_value_t.
6755  * @param[in]  read_only         Whether to only allow wizards marked as
6756  *                               read only.
6757  * @param[in]  mode              Name of the mode to run the wizard in.
6758  * @param[out] command_error     Either NULL or an address for an error message
6759  *                               when return is 0, 4 or 6.
6760  * @param[out] command_error_code  Either NULL or an address for a status code
6761  *                                 from the failed command when return is 0
6762  *                                 or 4.
6763  * @param[out] ret_response      Address for response string of last command.
6764  *
6765  * @return 0 success,
6766  *         1 name error,
6767  *         4 command in wizard failed,
6768  *         5 wizard not read only,
6769  *         6 Parameter validation failed,
6770  *         -1 internal error,
6771  *         99 permission denied.
6772  */
6773 int
manage_run_wizard(const gchar * wizard_name,int (* run_command)(void *,gchar *,gchar **),void * run_command_data,array_t * params,int read_only,const char * mode,gchar ** command_error,gchar ** command_error_code,gchar ** ret_response)6774 manage_run_wizard (const gchar *wizard_name,
6775                    int (*run_command) (void*, gchar*, gchar**),
6776                    void *run_command_data,
6777                    array_t *params,
6778                    int read_only,
6779                    const char *mode,
6780                    gchar **command_error,
6781                    gchar **command_error_code,
6782                    gchar **ret_response)
6783 {
6784   GString *params_xml;
6785   gchar *file, *file_name, *response, *extra, *extra_wrapped, *wizard;
6786   gsize wizard_len;
6787   GError *get_error;
6788   entity_t entity, mode_entity, params_entity, read_only_entity;
6789   entity_t param_def, step;
6790   entities_t modes, steps, param_defs;
6791   int ret;
6792   const gchar *point;
6793 
6794   if (acl_user_may ("run_wizard") == 0)
6795     return 99;
6796 
6797   if (command_error)
6798     *command_error = NULL;
6799 
6800   if (command_error_code)
6801     *command_error_code = NULL;
6802 
6803   if (ret_response)
6804     *ret_response = NULL;
6805 
6806   point = wizard_name;
6807   while (*point && (isalnum (*point) || *point == '_')) point++;
6808   if (*point)
6809     return 1;
6810 
6811   /* Read wizard from file. */
6812 
6813   file_name = g_strdup_printf ("%s.xml", wizard_name);
6814   file = g_build_filename (GVMD_DATA_DIR,
6815                            "wizards",
6816                            file_name,
6817                            NULL);
6818   g_free (file_name);
6819 
6820   get_error = NULL;
6821   g_file_get_contents (file,
6822                        &wizard,
6823                        &wizard_len,
6824                        &get_error);
6825   g_free (file);
6826   if (get_error)
6827     {
6828       g_warning ("%s: Failed to read wizard: %s",
6829                  __func__,
6830                  get_error->message);
6831       g_error_free (get_error);
6832       return -1;
6833     }
6834 
6835   /* Parse wizard. */
6836 
6837   entity = NULL;
6838   if (parse_entity (wizard, &entity))
6839     {
6840       g_warning ("%s: Failed to parse wizard", __func__);
6841       g_free (wizard);
6842       return -1;
6843     }
6844   g_free (wizard);
6845 
6846   /* Select mode */
6847   if (mode && strcmp (mode, ""))
6848     {
6849       modes = entity->entities;
6850       int mode_found = 0;
6851       while (mode_found == 0 && (mode_entity = first_entity (modes)))
6852         {
6853           if (strcasecmp (entity_name (mode_entity), "mode") == 0)
6854             {
6855               entity_t name_entity;
6856               name_entity = entity_child (mode_entity, "name");
6857 
6858               if (strcmp (entity_text (name_entity), mode) == 0)
6859                 mode_found = 1;
6860             }
6861           modes = next_entities (modes);
6862         }
6863 
6864       if (mode_found == 0)
6865         {
6866           free_entity (entity);
6867           if (ret_response)
6868             *ret_response = g_strdup ("");
6869 
6870           return 0;
6871         }
6872     }
6873   else
6874     {
6875       mode_entity = entity;
6876     }
6877 
6878   /* If needed, check if wizard is marked as read only.
6879    * This does not check the actual commands.
6880    */
6881   if (read_only)
6882     {
6883       read_only_entity = entity_child (mode_entity, "read_only");
6884       if (read_only_entity == NULL)
6885         {
6886           free_entity (entity);
6887           return 5;
6888         }
6889     }
6890 
6891   /* Check params */
6892   params_xml = g_string_new ("");
6893   params_entity = entity_child (mode_entity, "params");
6894   if (params_entity)
6895     param_defs = params_entity->entities;
6896 
6897   while (params_entity && (param_def = first_entity (param_defs)))
6898     {
6899       if (strcasecmp (entity_name (param_def), "param") == 0)
6900         {
6901           entity_t name_entity, regex_entity, optional_entity;
6902           const char *name, *regex;
6903           int optional;
6904           int param_found = 0;
6905 
6906           name_entity = entity_child (param_def, "name");
6907           if ((name_entity == NULL)
6908               || (strcmp (entity_text (name_entity), "") == 0))
6909             {
6910               g_warning ("%s: Wizard PARAM missing NAME",
6911                          __func__);
6912               free_entity (entity);
6913               return -1;
6914             }
6915           else
6916             name = entity_text (name_entity);
6917 
6918           regex_entity = entity_child (param_def, "regex");
6919           if ((regex_entity == NULL)
6920               || (strcmp (entity_text (regex_entity), "") == 0))
6921             {
6922               g_warning ("%s: Wizard PARAM missing REGEX",
6923                          __func__);
6924               free_entity (entity);
6925               return -1;
6926             }
6927           else
6928             regex = entity_text (regex_entity);
6929 
6930           optional_entity = entity_child (param_def, "optional");
6931           optional = (optional_entity
6932                       && strcmp (entity_text (optional_entity), "")
6933                       && strcmp (entity_text (optional_entity), "0"));
6934 
6935           if (params)
6936             {
6937               guint index = params->len;
6938               while (index--)
6939                 {
6940                   name_value_t *pair;
6941 
6942                   pair = (name_value_t*) g_ptr_array_index (params, index);
6943 
6944                   if (pair == NULL)
6945                     continue;
6946 
6947                   if ((pair->name)
6948                       && (pair->value)
6949                       && (strcmp (pair->name, name) == 0))
6950                     {
6951                       index = 0; // end loop;
6952                       param_found = 1;
6953 
6954                       if (g_regex_match_simple (regex, pair->value, 0, 0) == 0)
6955                         {
6956                           if (command_error)
6957                             {
6958                               *command_error
6959                                 = g_strdup_printf ("Value '%s' is not valid for"
6960                                                   " parameter '%s'.",
6961                                                   pair->value, name);
6962                             }
6963                           free_entity (entity);
6964                           g_string_free (params_xml, TRUE);
6965                           return 6;
6966                         }
6967                     }
6968                 }
6969             }
6970 
6971           if (optional == 0 && param_found == 0)
6972             {
6973               if (command_error)
6974                 {
6975                   *command_error = g_strdup_printf ("Mandatory wizard param '%s'"
6976                                                     " missing",
6977                                                     name);
6978                 }
6979               free_entity (entity);
6980               return 6;
6981             }
6982 
6983 
6984         }
6985       param_defs = next_entities (param_defs);
6986     }
6987 
6988   /* Buffer params */
6989   if (params)
6990     {
6991       guint index = params->len;
6992       while (index--)
6993         {
6994           name_value_t *pair;
6995 
6996           pair = (name_value_t*) g_ptr_array_index (params, index);
6997           xml_string_append (params_xml,
6998                              "<param>"
6999                              "<name>%s</name>"
7000                              "<value>%s</value>"
7001                              "</param>",
7002                              pair->name ? pair->name : "",
7003                              pair->value ? pair->value : "");
7004         }
7005     }
7006 
7007   /* Run each step of the wizard. */
7008 
7009   response = NULL;
7010   extra = NULL;
7011   steps = mode_entity->entities;
7012   while ((step = first_entity (steps)))
7013     {
7014       if (strcasecmp (entity_name (step), "step") == 0)
7015         {
7016           entity_t command, extra_xsl;
7017           gchar *gmp;
7018           int xsl_fd, xml_fd;
7019           char xsl_file_name[] = "/tmp/gvmd-xsl-XXXXXX";
7020           FILE *xsl_file, *xml_file;
7021           char xml_file_name[] = "/tmp/gvmd-xml-XXXXXX";
7022           char extra_xsl_file_name[] = "/tmp/gvmd-extra-xsl-XXXXXX";
7023           char extra_xml_file_name[] = "/tmp/gvmd-extra-xml-XXXXXX";
7024 
7025           /* Get the command element. */
7026 
7027           command = entity_child (step, "command");
7028           if (command == NULL)
7029             {
7030               g_warning ("%s: Wizard STEP missing COMMAND",
7031                          __func__);
7032               free_entity (entity);
7033               g_free (response);
7034               g_free (extra);
7035               g_string_free (params_xml, TRUE);
7036               return -1;
7037             }
7038 
7039           /* Save the command XSL from the element to a file. */
7040 
7041           xsl_fd = mkstemp (xsl_file_name);
7042           if (xsl_fd == -1)
7043             {
7044               g_warning ("%s: Wizard XSL file create failed",
7045                          __func__);
7046               free_entity (entity);
7047               g_free (response);
7048               g_free (extra);
7049               g_string_free (params_xml, TRUE);
7050               return -1;
7051             }
7052 
7053           xsl_file = fdopen (xsl_fd, "w");
7054           if (xsl_file == NULL)
7055             {
7056               g_warning ("%s: Wizard XSL file open failed",
7057                          __func__);
7058               close (xsl_fd);
7059               free_entity (entity);
7060               g_free (response);
7061               g_free (extra);
7062               g_string_free (params_xml, TRUE);
7063               return -1;
7064             }
7065 
7066           if (first_entity (command->entities))
7067             print_entity (xsl_file, first_entity (command->entities));
7068 
7069           /* Write the params as XML to a file. */
7070 
7071           xml_fd = mkstemp (xml_file_name);
7072           if (xml_fd == -1)
7073             {
7074               g_warning ("%s: Wizard XML file create failed",
7075                          __func__);
7076               fclose (xsl_file);
7077               unlink (xsl_file_name);
7078               free_entity (entity);
7079               g_free (response);
7080               g_free (extra);
7081               g_string_free (params_xml, TRUE);
7082               return -1;
7083             }
7084 
7085           xml_file = fdopen (xml_fd, "w");
7086           if (xml_file == NULL)
7087             {
7088               g_warning ("%s: Wizard XML file open failed",
7089                          __func__);
7090               fclose (xsl_file);
7091               unlink (xsl_file_name);
7092               close (xml_fd);
7093               free_entity (entity);
7094               g_free (response);
7095               g_free (extra);
7096               g_string_free (params_xml, TRUE);
7097               return -1;
7098             }
7099 
7100           if (fprintf (xml_file,
7101                        "<wizard>"
7102                        "<params>%s</params>"
7103                        "<previous>"
7104                        "<response>%s</response>"
7105                        "<extra_data>%s</extra_data>"
7106                        "</previous>"
7107                        "</wizard>\n",
7108                        params_xml->str ? params_xml->str : "",
7109                        response ? response : "",
7110                        extra ? extra : "")
7111               < 0)
7112             {
7113               fclose (xsl_file);
7114               unlink (xsl_file_name);
7115               fclose (xml_file);
7116               unlink (xml_file_name);
7117               free_entity (entity);
7118               g_warning ("%s: Wizard failed to write XML",
7119                          __func__);
7120               g_free (response);
7121               g_free (extra);
7122               g_string_free (params_xml, TRUE);
7123               return -1;
7124             }
7125 
7126           fflush (xml_file);
7127 
7128           /* Combine XSL and XML to get the GMP command. */
7129 
7130           gmp = xsl_transform (xsl_file_name, xml_file_name, NULL,
7131                                NULL);
7132           fclose (xsl_file);
7133           unlink (xsl_file_name);
7134           fclose (xml_file);
7135           unlink (xml_file_name);
7136           if (gmp == NULL)
7137             {
7138               g_warning ("%s: Wizard XSL transform failed",
7139                          __func__);
7140               free_entity (entity);
7141               g_free (response);
7142               g_free (extra);
7143               g_string_free (params_xml, TRUE);
7144               return -1;
7145             }
7146 
7147           /* Run the GMP command. */
7148 
7149           g_free (response);
7150           response = NULL;
7151           ret = run_command (run_command_data, gmp, &response);
7152           if (ret == 0)
7153             {
7154               /* Command succeeded. */
7155             }
7156           else
7157             {
7158               free_entity (entity);
7159               g_free (response);
7160               g_free (extra);
7161               g_string_free (params_xml, TRUE);
7162               return -1;
7163             }
7164 
7165           /* Exit if the command failed. */
7166 
7167           if (response)
7168             {
7169               const char *status;
7170               entity_t response_entity;
7171 
7172               response_entity = NULL;
7173               if (parse_entity (response, &response_entity))
7174                 {
7175                   g_warning ("%s: Wizard failed to parse response",
7176                              __func__);
7177                   free_entity (entity);
7178                   g_free (response);
7179                   g_free (extra);
7180                   g_string_free (params_xml, TRUE);
7181                   return -1;
7182                 }
7183 
7184               status = entity_attribute (response_entity, "status");
7185               if ((status == NULL)
7186                   || (strlen (status) == 0)
7187                   || (status[0] != '2'))
7188                 {
7189                   g_debug ("response was %s", response);
7190                   if (command_error)
7191                     {
7192                       const char *text;
7193                       text = entity_attribute (response_entity, "status_text");
7194                       if (text)
7195                         *command_error = g_strdup (text);
7196                     }
7197                   if (command_error_code)
7198                     {
7199                       *command_error_code = g_strdup (status);
7200                     }
7201                   free_entity (response_entity);
7202                   free_entity (entity);
7203                   g_free (response);
7204                   g_free (extra);
7205                   g_string_free (params_xml, TRUE);
7206                   return 4;
7207                 }
7208 
7209               free_entity (response_entity);
7210             }
7211 
7212           /* Get the extra_data element. */
7213 
7214           extra_xsl = entity_child (step, "extra_data");
7215           if (extra_xsl)
7216             {
7217               /* Save the extra_data XSL from the element to a file. */
7218 
7219               xsl_fd = mkstemp (extra_xsl_file_name);
7220               if (xsl_fd == -1)
7221                 {
7222                   g_warning ("%s: Wizard extra_data XSL file create failed",
7223                             __func__);
7224                   free_entity (entity);
7225                   g_free (response);
7226                   g_free (extra);
7227                   g_string_free (params_xml, TRUE);
7228                   return -1;
7229                 }
7230 
7231               xsl_file = fdopen (xsl_fd, "w");
7232               if (xsl_file == NULL)
7233                 {
7234                   g_warning ("%s: Wizard extra_data XSL file open failed",
7235                             __func__);
7236                   close (xsl_fd);
7237                   free_entity (entity);
7238                   g_free (response);
7239                   g_free (extra);
7240                   g_string_free (params_xml, TRUE);
7241                   return -1;
7242                 }
7243 
7244               if (first_entity (extra_xsl->entities))
7245                 print_entity (xsl_file, first_entity (extra_xsl->entities));
7246 
7247               /* Write the params as XML to a file. */
7248 
7249               xml_fd = mkstemp (extra_xml_file_name);
7250               if (xml_fd == -1)
7251                 {
7252                   g_warning ("%s: Wizard XML file create failed",
7253                             __func__);
7254                   fclose (xsl_file);
7255                   unlink (xsl_file_name);
7256                   free_entity (entity);
7257                   g_free (response);
7258                   g_free (extra);
7259                   g_string_free (params_xml, TRUE);
7260                   return -1;
7261                 }
7262 
7263               xml_file = fdopen (xml_fd, "w");
7264               if (xml_file == NULL)
7265                 {
7266                   g_warning ("%s: Wizard XML file open failed",
7267                             __func__);
7268                   fclose (xsl_file);
7269                   unlink (xsl_file_name);
7270                   close (xml_fd);
7271                   free_entity (entity);
7272                   g_free (response);
7273                   g_free (extra);
7274                   g_string_free (params_xml, TRUE);
7275                   return -1;
7276                 }
7277 
7278               if (fprintf (xml_file,
7279                            "<wizard>"
7280                            "<params>%s</params>"
7281                            "<current>"
7282                            "<response>%s</response>"
7283                            "</current>"
7284                            "<previous>"
7285                            "<extra_data>%s</extra_data>"
7286                            "</previous>"
7287                            "</wizard>\n",
7288                            params_xml->str ? params_xml->str : "",
7289                            response ? response : "",
7290                            extra ? extra : "")
7291                   < 0)
7292                 {
7293                   fclose (xsl_file);
7294                   unlink (extra_xsl_file_name);
7295                   fclose (xml_file);
7296                   unlink (extra_xml_file_name);
7297                   free_entity (entity);
7298                   g_warning ("%s: Wizard failed to write XML",
7299                             __func__);
7300                   g_free (response);
7301                   g_free (extra);
7302                   g_string_free (params_xml, TRUE);
7303                   return -1;
7304                 }
7305 
7306               fflush (xml_file);
7307 
7308               g_free (extra);
7309               extra = xsl_transform (extra_xsl_file_name, extra_xml_file_name,
7310                                      NULL, NULL);
7311               fclose (xsl_file);
7312               unlink (extra_xsl_file_name);
7313               fclose (xml_file);
7314               unlink (extra_xml_file_name);
7315             }
7316         }
7317       steps = next_entities (steps);
7318     }
7319 
7320   if (extra)
7321     extra_wrapped = g_strdup_printf ("<extra_data>%s</extra_data>",
7322                                      extra);
7323   else
7324     extra_wrapped = NULL;
7325   g_free (extra);
7326 
7327   if (ret_response)
7328     *ret_response = response;
7329 
7330   if (extra_wrapped)
7331     {
7332       entity_t extra_entity, status_entity, status_text_entity;
7333       ret = parse_entity (extra_wrapped, &extra_entity);
7334       if (ret == 0)
7335         {
7336           status_entity = entity_child (extra_entity, "status");
7337           status_text_entity = entity_child (extra_entity, "status_text");
7338 
7339           if (status_text_entity && command_error)
7340             {
7341               *command_error = g_strdup (entity_text (status_text_entity));
7342             }
7343 
7344           if (status_entity && command_error_code)
7345             {
7346               *command_error_code = g_strdup (entity_text (status_entity));
7347             }
7348           free_entity (extra_entity);
7349         }
7350       else
7351         {
7352           g_warning ("%s: failed to parse extra data", __func__);
7353           free_entity (entity);
7354           g_string_free (params_xml, TRUE);
7355           return -1;
7356         }
7357     }
7358 
7359   free_entity (entity);
7360   g_string_free (params_xml, TRUE);
7361 
7362   /* All the steps succeeded. */
7363 
7364   return 0;
7365 }
7366 
7367 
7368 /* Resources. */
7369 
7370 /**
7371  * @brief Delete a resource.
7372  *
7373  * @param[in]  type         Type of resource.
7374  * @param[in]  resource_id  UUID of resource.
7375  * @param[in]  ultimate     Whether to remove entirely, or to trashcan.
7376  *
7377  * @return 0 success, 1 resource in use, 2 failed to find resource,
7378  *         99 permission denied, -1 error.
7379  */
7380 int
delete_resource(const char * type,const char * resource_id,int ultimate)7381 delete_resource (const char *type, const char *resource_id, int ultimate)
7382 {
7383   if (strcasecmp (type, "ticket") == 0)
7384     return delete_ticket (resource_id, ultimate);
7385   if (strcasecmp (type, "tls_certificate") == 0)
7386     return delete_tls_certificate (resource_id, ultimate);
7387   assert (0);
7388   return -1;
7389 }
7390