1 /* Portions Copyright (C) 2009-2021 Greenbone Networks GmbH
2  * Based on work Copyright (C) 2002 - 2005 Tenable Network Security
3  *
4  * SPDX-License-Identifier: GPL-2.0-only
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * version 2 as published by the Free Software Foundation.
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 General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 /**
21  * @file nasl.c
22  * @brief Source of the standalone NASL interpreter of OpenVAS.
23  */
24 
25 #include "nasl.h"
26 
27 #include "../misc/network.h"
28 #include "../misc/nvt_categories.h"
29 #include "../misc/vendorversion.h"
30 #include "exec.h"
31 #include "nasl_lex_ctxt.h"
32 
33 #include <errno.h>  /* for errno */
34 #include <gcrypt.h> /* for gcry_control */
35 #include <glib.h>
36 #include <gnutls/gnutls.h>       /* for gnutls_check_version */
37 #include <gpgme.h>               /* for gpgme_check_version */
38 #include <gvm/base/hosts.h>      /* for gvm_hosts_* and gvm_host_* */
39 #include <gvm/base/networking.h> /* for gvm_source_iface_init */
40 #include <gvm/base/nvti.h>
41 #include <gvm/base/prefs.h> /* for prefs_get */
42 #include <gvm/util/kb.h>    /* for kb_new */
43 #include <libssh/libssh.h>  /* for ssh_version */
44 #include <signal.h>         /* for SIGINT */
45 #include <stdlib.h>         /* for exit */
46 #include <string.h>         /* for strlen */
47 #include <sys/wait.h>
48 #include <unistd.h> /* for geteuid */
49 
50 #ifndef MAP_FAILED
51 #define MAP_FAILED ((void *) -1)
52 #endif
53 
54 #undef G_LOG_DOMAIN
55 /**
56  * @brief GLib logging domain.
57  */
58 #define G_LOG_DOMAIN "lib  nasl"
59 
60 extern char *
61 nasl_version (void);
62 
63 void
sighandler()64 sighandler ()
65 {
66   exit (0);
67 }
68 
69 static void
my_gnutls_log_func(int level,const char * text)70 my_gnutls_log_func (int level, const char *text)
71 {
72   fprintf (stderr, "[%d] (%d) %s", getpid (), level, text);
73   if (*text && text[strlen (text) - 1] != '\n')
74     putc ('\n', stderr);
75 }
76 
77 struct script_infos *
init(struct in6_addr * ip,GSList * vhosts,kb_t kb)78 init (struct in6_addr *ip, GSList *vhosts, kb_t kb)
79 {
80   struct script_infos *infos = g_malloc0 (sizeof (struct script_infos));
81 
82   infos->standalone = 1;
83   infos->key = kb;
84   infos->results = kb;
85   infos->ip = ip;
86   infos->vhosts = vhosts;
87   if (prefs_get_bool ("test_empty_vhost"))
88     {
89       gvm_vhost_t *vhost =
90         gvm_vhost_new (addr6_as_str (ip), g_strdup ("IP-address"));
91       infos->vhosts = g_slist_prepend (infos->vhosts, vhost);
92     }
93   infos->globals = g_malloc0 (sizeof (struct scan_globals));
94 
95   return infos;
96 }
97 
98 extern FILE *nasl_trace_fp;
99 
100 static nvti_t *
parse_script_infos(struct script_infos * infos)101 parse_script_infos (struct script_infos *infos)
102 {
103   nvti_t *nvti;
104   int mode = NASL_EXEC_DESCR | NASL_ALWAYS_SIGNED;
105 
106   nvti = nvti_new ();
107   infos->nvti = nvti;
108   if (exec_nasl_script (infos, mode) < 0)
109     {
110       printf ("%s could not be loaded\n", infos->name);
111       return NULL;
112     }
113   infos->nvti = NULL;
114   infos->oid = g_strdup (nvti_oid (nvti));
115 
116   return nvti;
117 }
118 
119 /**
120  * @brief Checks that an NVT category is safe.
121  *
122  * @param category  Category to check.
123  *
124  * @return 0 if category is unsafe, 1 otherwise.
125  */
126 static int
nvti_category_is_safe(int category)127 nvti_category_is_safe (int category)
128 {
129   if (category == ACT_DESTRUCTIVE_ATTACK || category == ACT_KILL_HOST
130       || category == ACT_FLOOD || category == ACT_DENIAL)
131     return 0;
132   return 1;
133 }
134 
135 /**
136  * @brief Initialize Gcrypt.
137  */
138 static void
gcrypt_init()139 gcrypt_init ()
140 {
141   if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P))
142     return;
143   gcry_check_version (NULL);
144   gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
145   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
146   gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
147   gcry_control (GCRYCTL_INITIALIZATION_FINISHED);
148 }
149 
150 /**
151  * @brief Main of the standalone nasl interpreter.
152  * @return The number of times a NVT was launched
153  *         (should be (number of targets) * (number of NVTS provided)).
154  */
155 int
main(int argc,char ** argv)156 main (int argc, char **argv)
157 {
158   struct script_infos *script_infos;
159   gvm_hosts_t *hosts;
160   gvm_host_t *host;
161   static gchar *target = NULL;
162   gchar *default_target = "127.0.0.1";
163   int mode = 0, err = 0, pos;
164   extern int global_nasl_debug;
165   GSList *unresolved;
166 
167   static gboolean display_version = FALSE;
168   static gboolean nasl_debug = FALSE;
169   static gboolean description_only = FALSE;
170   static gboolean both_modes = FALSE;
171   static gboolean parse_only = FALSE;
172   static gboolean do_lint = FALSE;
173   static gchar *trace_file = NULL;
174   static gchar *config_file = NULL;
175   static gchar *source_iface = NULL;
176   static gchar *port_range = NULL;
177   static gboolean with_safe_checks = FALSE;
178   static gboolean signing_mode = FALSE;
179   static gchar *include_dir = NULL;
180   static gchar **nasl_filenames = NULL;
181   static gchar **kb_values = NULL;
182   static int debug_tls = 0;
183   GError *error = NULL;
184   GOptionContext *option_context;
185   static GOptionEntry entries[] = {
186     {"version", 'V', 0, G_OPTION_ARG_NONE, &display_version,
187      "Display version information", NULL},
188     {"debug", 'd', 0, G_OPTION_ARG_NONE, &nasl_debug,
189      "Output debug information to stderr.", NULL},
190     {"description", 'D', 0, G_OPTION_ARG_NONE, &description_only,
191      "Only run the 'description' part of the script", NULL},
192     {"both", 'B', 0, G_OPTION_ARG_NONE, &both_modes,
193      "Run in description mode before running the script.", NULL},
194     {"parse", 'p', 0, G_OPTION_ARG_NONE, &parse_only,
195      "Only parse the script, don't execute it", NULL},
196     {"lint", 'L', 0, G_OPTION_ARG_NONE, &do_lint,
197      "'lint' the script (extended checks)", NULL},
198     {"target", 't', 0, G_OPTION_ARG_STRING, &target,
199      "Execute the scripts against <target>", "<target>"},
200     {"trace", 'T', 0, G_OPTION_ARG_FILENAME, &trace_file,
201      "Log actions to <file> (or '-' for stderr)", "<file>"},
202     {"config-file", 'c', 0, G_OPTION_ARG_FILENAME, &config_file,
203      "Configuration file", "<filename>"},
204     {"source-iface", 'e', 0, G_OPTION_ARG_STRING, &source_iface,
205      "Source network interface for established connections.", "<iface_name>"},
206     {"safe", 's', 0, G_OPTION_ARG_NONE, &with_safe_checks,
207      "Specifies that the script should be run with 'safe checks' enabled",
208      NULL},
209     {"disable-signing", 'X', 0, G_OPTION_ARG_NONE, &signing_mode,
210      "Run the script with disabled signature verification", NULL},
211     {"include-dir", 'i', 0, G_OPTION_ARG_STRING, &include_dir,
212      "Search for includes in <dir>", "<dir>"},
213     {"debug-tls", 0, 0, G_OPTION_ARG_INT, &debug_tls,
214      "Enable TLS debugging at <level>", "<level>"},
215     {"kb", 'k', 0, G_OPTION_ARG_STRING_ARRAY, &kb_values,
216      "Set KB key to value. Can be used multiple times", "<key=value>"},
217     {"port-range", 'r', 0, G_OPTION_ARG_STRING, &port_range,
218      "Set the <port-range> used by nasl scripts. ", "<port-range>"},
219     {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &nasl_filenames,
220      "Absolute path to one or more nasl scripts", "NASL_FILE..."},
221     {NULL, 0, 0, 0, NULL, NULL, NULL}};
222 
223   option_context =
224     g_option_context_new ("- standalone NASL interpreter for OpenVAS");
225   g_option_context_add_main_entries (option_context, entries, NULL);
226   if (!g_option_context_parse (option_context, &argc, &argv, &error))
227     {
228       g_print ("%s\n\n", error->message);
229       exit (0);
230     }
231   g_option_context_free (option_context);
232   /*--------------------------------------------
233          Command-line options
234    ---------------------------------------------*/
235 
236   if (display_version)
237     {
238       printf ("openvas-nasl %s\n", nasl_version ());
239       if (debug_tls)
240         {
241           printf ("gnutls %s\n", gnutls_check_version (NULL));
242           printf ("libssh %s\n", ssh_version (0));
243           printf ("gpgme %s\n", gpgme_check_version (NULL));
244         }
245       else
246         putchar ('\n');
247       printf ("Copyright (C) 2002 - 2004 Tenable Network Security\n");
248       printf ("Copyright (C) 2021 Greenbone Networks GmbH\n\n");
249       exit (0);
250     }
251   if (nasl_debug)
252     global_nasl_debug = 1;
253   mode |= NASL_COMMAND_LINE;
254   if (signing_mode)
255     mode |= NASL_ALWAYS_SIGNED;
256   if (description_only)
257     mode |= NASL_EXEC_DESCR;
258   if (do_lint)
259     mode |= NASL_LINT;
260   if (parse_only)
261     mode |= NASL_EXEC_PARSE_ONLY;
262   if (trace_file)
263     {
264       if (!strcmp (trace_file, "-"))
265         nasl_trace_fp = stderr;
266       else
267         {
268           FILE *fp = fopen (trace_file, "w");
269           if (fp == NULL)
270             {
271               perror (optarg);
272               exit (2);
273             }
274           setvbuf (fp, NULL, _IOLBF, BUFSIZ);
275           nasl_trace_fp = fp;
276         }
277     }
278 
279   gcrypt_init ();
280   openvas_SSL_init ();
281   if (!nasl_filenames)
282     {
283       fprintf (stderr, "Error. No input file(s) specified !\n");
284       exit (1);
285     }
286 
287   if (!(mode & (NASL_EXEC_PARSE_ONLY | NASL_LINT)) && geteuid ())
288     {
289       fprintf (stderr, "** WARNING : packet forgery will not work\n");
290       fprintf (stderr, "** as NASL is not running as root\n");
291     }
292   signal (SIGINT, sighandler);
293   signal (SIGTERM, sighandler);
294   signal (SIGPIPE, SIG_IGN);
295 
296   if (source_iface && gvm_source_iface_init (source_iface))
297     {
298       fprintf (stderr, "Erroneous network source interface: %s\n",
299                source_iface);
300       exit (1);
301     }
302   if (debug_tls)
303     {
304       gnutls_global_set_log_function (my_gnutls_log_func);
305       gnutls_global_set_log_level (debug_tls);
306     }
307 
308   if (!target)
309     target = g_strdup (default_target);
310 
311   hosts = gvm_hosts_new (target);
312   if (!hosts)
313     {
314       fprintf (stderr, "Erroneous target %s\n", target);
315       exit (1);
316     }
317   unresolved = gvm_hosts_resolve (hosts);
318   while (unresolved)
319     {
320       g_warning ("Couldn't resolve hostname '%s'", (char *) unresolved->data);
321       unresolved = unresolved->next;
322     }
323   g_slist_free_full (unresolved, g_free);
324   g_free (target);
325 
326   // for absolute and relative paths
327   add_nasl_inc_dir ("");
328   if (include_dir != NULL)
329     {
330       add_nasl_inc_dir (include_dir);
331     }
332 
333   prefs_config (config_file ?: OPENVAS_CONF);
334 
335   if (prefs_get ("vendor_version") != NULL)
336     vendor_version_set (prefs_get ("vendor_version"));
337 
338   if (port_range != NULL)
339     {
340       prefs_set ("port_range", port_range);
341       g_free (port_range);
342     }
343 
344   if (with_safe_checks)
345     prefs_set ("safe_checks", "yes");
346 
347   pos = 0; // Append the item on the right side of the list
348   while ((host = gvm_hosts_next (hosts)))
349     {
350       struct in6_addr ip6;
351       kb_t kb;
352       int rc, i = 0;
353 
354       if (prefs_get_bool ("expand_vhosts"))
355         gvm_host_add_reverse_lookup (host);
356       gvm_vhosts_exclude (host, prefs_get ("exclude_hosts"));
357       gvm_host_get_addr6 (host, &ip6);
358       rc = kb_new (&kb, prefs_get ("db_address") ?: KB_PATH_DEFAULT);
359       if (rc)
360         exit (1);
361 
362       script_infos = init (&ip6, host->vhosts, kb);
363       while (nasl_filenames[i])
364         {
365           pid_t pid;
366 
367           script_infos->name = nasl_filenames[i];
368           if (both_modes || with_safe_checks)
369             {
370               nvti_t *nvti = parse_script_infos (script_infos);
371               if (!nvti)
372                 {
373                   err++;
374                   i++;
375                   continue;
376                 }
377               else if (with_safe_checks
378                        && !nvti_category_is_safe (nvti_category (nvti)))
379                 {
380                   printf ("%s isn't safe\n", nasl_filenames[i]);
381                   nvti_free (nvti);
382                   err++;
383                   i++;
384                   continue;
385                 }
386               nvti_free (nvti);
387             }
388           if (kb_values)
389             {
390               gchar **kb_values_aux = kb_values;
391               while (*kb_values_aux)
392                 {
393                   gchar **splits = g_strsplit (*kb_values_aux, "=", -1);
394                   if (splits[2] || !splits[1])
395                     {
396                       fprintf (stderr, "Erroneous --kb entry %s\n",
397                                *kb_values_aux);
398                       exit (1);
399                     }
400                   kb_item_add_str_unique (kb, splits[0], splits[1], 0, pos);
401                   kb_values_aux++;
402                   g_strfreev (splits);
403                 }
404             }
405 
406           if ((pid = fork ()) == 0)
407             {
408               if (exec_nasl_script (script_infos, mode) < 0)
409                 exit (1);
410               else
411                 exit (0);
412             }
413           else if (pid < 0)
414             {
415               fprintf (stderr, "fork(): %s\n", strerror (errno));
416               exit (1);
417             }
418           else
419             {
420               int status;
421               waitpid (pid, &status, 0);
422               if (status)
423                 err++;
424             }
425           i++;
426         }
427       g_free (script_infos->globals);
428       g_free (script_infos);
429       kb_delete (kb);
430     }
431 
432   if (nasl_trace_fp != NULL)
433     fflush (nasl_trace_fp);
434 
435   gvm_hosts_free (hosts);
436   return err;
437 }
438