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