1 /* Portions Copyright (C) 2009-2021 Greenbone Networks GmbH
2  * Portions Copyright (C) 2006 Software in the Public Interest, Inc.
3  * Based on work Copyright (C) 1998 - 2006 Tenable Network Security, Inc.
4  *
5  * SPDX-License-Identifier: GPL-2.0-only
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 /**
22  * @file utils.c
23  * @brief A bunch of miscellaneous functions, mostly file conversions.
24  */
25 
26 #include "../misc/scanneraux.h" /* for struct scan_globals */
27 
28 #include <errno.h>          /* for errno() */
29 #include <gvm/base/prefs.h> /* for prefs_get() */
30 #include <stdlib.h>         /* for atoi() */
31 #include <string.h>         /* for strcmp() */
32 #include <sys/ioctl.h>      /* for ioctl() */
33 #include <sys/wait.h>       /* for waitpid() */
34 
35 extern int global_max_hosts;
36 extern int global_max_checks;
37 
38 #undef G_LOG_DOMAIN
39 /**
40  * @brief GLib log domain.
41  */
42 #define G_LOG_DOMAIN "sd   main"
43 
44 /**
45  * @brief Adds a 'translation' entry for a file sent by the client.
46  *
47  * Files sent by the client are stored in memory on the server side.
48  * In order to access these files, their original name ('local' to the client)
49  * can be 'translated' into the file contents of the in-memory copy of the
50  * file on the server side.
51  *
52  * @param globals    Global struct.
53  * @param file_hash  hash to reference the file.
54  * @param contents   Contents of the file.
55  */
56 static void
files_add_translation(struct scan_globals * globals,const char * file_hash,char * contents)57 files_add_translation (struct scan_globals *globals, const char *file_hash,
58                        char *contents)
59 {
60   GHashTable *trans = globals->files_translation;
61   // Register the mapping table if none there yet
62   if (trans == NULL)
63     {
64       trans = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
65       globals->files_translation = trans;
66     }
67 
68   g_hash_table_insert (trans, g_strdup (file_hash), contents);
69 }
70 
71 /**
72  * @brief Adds a 'content size' entry for a file sent by the client.
73  *
74  * Files sent by the client are stored in memory on the server side.
75  * Because they may be binary we need to store the size of the uploaded file as
76  * well. This function sets up a mapping from the original name sent by the
77  * client to the file size.
78  *
79  * @param globals    Global struct.
80  * @param file_hash  hash to reference the file.
81  * @param filesize   Size of the file in bytes.
82  */
83 static void
files_add_size_translation(struct scan_globals * globals,const char * file_hash,const long filesize)84 files_add_size_translation (struct scan_globals *globals, const char *file_hash,
85                             const long filesize)
86 {
87   GHashTable *trans = globals->files_size_translation;
88   gchar *filesize_str = g_strdup_printf ("%ld", filesize);
89 
90   // Register the mapping table if none there yet
91   if (trans == NULL)
92     {
93       trans = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
94       globals->files_size_translation = trans;
95     }
96 
97   g_hash_table_insert (trans, g_strdup (file_hash), g_strdup (filesize_str));
98 }
99 
100 /**
101  * @brief Stores a file type preference in a hash table.
102  *
103  * @param globals    Global struct.
104  * @param file       File content.
105  * @param file_hash  hash to reference the file.
106  *
107  * @return 0 if successful, -1 in case of errors.
108  */
109 int
store_file(struct scan_globals * globals,const char * file,const char * file_hash)110 store_file (struct scan_globals *globals, const char *file,
111             const char *file_hash)
112 {
113   char *origname;
114   gchar *contents = NULL;
115 
116   size_t bytes = 0;
117 
118   if (!file_hash || *file_hash == '\0')
119     return -1;
120 
121   origname = g_strdup (file_hash);
122 
123   contents = (gchar *) g_base64_decode (file, &bytes);
124 
125   if (contents == NULL)
126     {
127       g_debug ("store_file: Failed to allocate memory for uploaded file.");
128       g_free (origname);
129       return -1;
130     }
131 
132   files_add_translation (globals, origname, contents);
133   files_add_size_translation (globals, origname, bytes);
134 
135   g_free (origname);
136   return 0;
137 }
138 
139 /**
140  * Get the max number of hosts to test at the same time.
141  */
142 int
get_max_hosts_number(void)143 get_max_hosts_number (void)
144 {
145   int max_hosts;
146   if (prefs_get ("max_hosts"))
147     {
148       max_hosts = atoi (prefs_get ("max_hosts"));
149       if (max_hosts <= 0)
150         {
151           g_debug ("Error ! max_hosts = %d -- check %s", max_hosts,
152                    (char *) prefs_get ("config_file"));
153           max_hosts = global_max_hosts;
154         }
155       else if (max_hosts > global_max_hosts)
156         {
157           g_debug ("Client tried to raise the maximum hosts number - %d."
158                    " Using %d. Change 'max_hosts' in openvas.conf if you"
159                    " believe this is incorrect",
160                    max_hosts, global_max_hosts);
161           max_hosts = global_max_hosts;
162         }
163     }
164   else
165     max_hosts = global_max_hosts;
166   return (max_hosts);
167 }
168 
169 /**
170  * Get the max number of plugins to launch against the remote
171  * host at the same time
172  */
173 int
get_max_checks_number(void)174 get_max_checks_number (void)
175 {
176   int max_checks;
177   if (prefs_get ("max_checks"))
178     {
179       max_checks = atoi (prefs_get ("max_checks"));
180       if (max_checks <= 0)
181         {
182           g_debug ("Error ! max_hosts = %d -- check %s", max_checks,
183                    (char *) prefs_get ("config_file"));
184           max_checks = global_max_checks;
185         }
186       else if (max_checks > global_max_checks)
187         {
188           g_debug ("Client tried to raise the maximum checks number - %d."
189                    " Using %d. Change 'max_checks' in openvas.conf if you"
190                    " believe this is incorrect",
191                    max_checks, global_max_checks);
192           max_checks = global_max_checks;
193         }
194     }
195   else
196     max_checks = global_max_checks;
197   return (max_checks);
198 }
199 
200 /**
201  * Determines if a process is alive - as reliably as we can
202  */
203 int
process_alive(pid_t pid)204 process_alive (pid_t pid)
205 {
206   int i, ret;
207   if (pid == 0)
208     return 0;
209 
210   for (i = 0, ret = 1; (i < 10) && (ret > 0); i++)
211     ret = waitpid (pid, NULL, WNOHANG);
212 
213   return kill (pid, 0) == 0;
214 }
215 
216 int
data_left(int soc)217 data_left (int soc)
218 {
219   int data = 0;
220   ioctl (soc, FIONREAD, &data);
221   return data;
222 }
223 
224 void
wait_for_children1(void)225 wait_for_children1 (void)
226 {
227   int e, n = 0;
228   do
229     {
230       errno = 0;
231       e = waitpid (-1, NULL, WNOHANG);
232       n++;
233     }
234   while ((e > 0 || errno == EINTR) && n < 20);
235 }
236 
237 /*
238  * @brief Checks if a provided preference is scanner-only and can't be
239  * read/written by the client.
240  *
241  * @return 1 if pref is scanner-only, 0 otherwise.
242  */
243 int
is_scanner_only_pref(const char * pref)244 is_scanner_only_pref (const char *pref)
245 {
246   if (pref == NULL)
247     return 0;
248   if (!strcmp (pref, "config_file") || !strcmp (pref, "plugins_folder")
249       || !strcmp (
250         pref,
251         "kb_location") // old name of db_address, ignore from old conf's
252       || !strcmp (pref, "db_address") || !strcmp (pref, "negot_timeout")
253       || !strcmp (pref, "force_pubkey_auth")
254       || !strcmp (pref, "log_whole_attack")
255       || !strcmp (pref, "log_plugins_name_at_load")
256       || !strcmp (pref, "nasl_no_signature_check")
257       || !strcmp (pref, "vendor_version") || !strcmp (pref, "drop_privileges")
258       || !strcmp (pref, "nasl_drop_privileges_user")
259       || !strcmp (pref, "debug_tls") || !strcmp (pref, "min_free_mem")
260       || !strcmp (pref, "max_sysload")
261       /* Preferences starting with sys_ are scanner-side only. */
262       || !strncmp (pref, "sys_", 4))
263     return 1;
264   return 0;
265 }
266