1 /* Copyright (C) 2009-2020 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  gmpd.c
21  * @brief The Greenbone Vulnerability Manager GMP daemon.
22  *
23  * This file defines the Greenbone Vulnerability Manager daemon.  The Manager
24  * serves the Greenbone Management Protocol (GMP) to clients such as the
25  * Greenbone Security Assistant (GSA). The Manager and GMP give clients full
26  * access to an OpenVAS Scanner.
27  *
28  * The library provides two functions: \ref init_gmpd and \ref serve_gmp.
29  * \ref init_gmpd initialises the daemon.
30  * \ref serve_gmp serves GMP to a single client socket until end of file is
31  * reached on the socket.
32  */
33 
34 #include "gmpd.h"
35 #include "gmp.h"
36 
37 #include <assert.h>
38 #include <dirent.h>
39 #include <errno.h>
40 #include <string.h>
41 #include <sys/select.h>
42 #include <sys/socket.h>
43 #include <sys/time.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <unistd.h>
47 
48 #include <gvm/util/serverutils.h>
49 
50 #if FROM_BUFFER_SIZE > SSIZE_MAX
51 #error FROM_BUFFER_SIZE too big for "read"
52 #endif
53 
54 #undef G_LOG_DOMAIN
55 /**
56  * @brief GLib log domain.
57  */
58 #define G_LOG_DOMAIN "md   main"
59 
60 /**
61  * @brief Buffer of input from the client.
62  */
63 char from_client[FROM_BUFFER_SIZE];
64 
65 /**
66  * @brief Size of \ref from_client data buffer, in bytes.
67  */
68 buffer_size_t from_buffer_size = FROM_BUFFER_SIZE;
69 
70 /**
71  * @brief The start of the data in the \ref from_client buffer.
72  */
73 buffer_size_t from_client_start = 0;
74 
75 /**
76  * @brief The end of the data in the \ref from_client buffer.
77  */
78 buffer_size_t from_client_end = 0;
79 
80 /**
81  * @brief Initialise the GMP library for the GMP daemon.
82  *
83  * @param[in]  log_config      Log configuration
84  * @param[in]  database        Location of manage database.
85  * @param[in]  max_ips_per_target  Max number of IPs per target.
86  * @param[in]  max_email_attachment_size  Max size of email attachments.
87  * @param[in]  max_email_include_size     Max size of email inclusions.
88  * @param[in]  max_email_message_size     Max size of email user message text.
89  * @param[in]  fork_connection  Function to fork a connection to the GMP
90  *                              daemon layer, or NULL.
91  * @param[in]  skip_db_check    Skip DB check.
92  *
93  * @return 0 success, -1 error, -2 database is wrong version,
94  *         -4 max_ips_per_target out of range.
95  */
96 int
init_gmpd(GSList * log_config,const db_conn_info_t * database,int max_ips_per_target,int max_email_attachment_size,int max_email_include_size,int max_email_message_size,manage_connection_forker_t fork_connection,int skip_db_check)97 init_gmpd (GSList *log_config, const db_conn_info_t *database,
98            int max_ips_per_target, int max_email_attachment_size,
99            int max_email_include_size, int max_email_message_size,
100            manage_connection_forker_t fork_connection, int skip_db_check)
101 {
102   return init_gmp (log_config, database, max_ips_per_target,
103                    max_email_attachment_size, max_email_include_size,
104                    max_email_message_size,
105                    fork_connection, skip_db_check);
106 }
107 
108 /**
109  * @brief Initialise a process forked within the GMP daemon.
110  *
111  * @param[in]  database  Location of manage database.
112  * @param[in]  disable   Commands to disable.
113  */
114 void
init_gmpd_process(const db_conn_info_t * database,gchar ** disable)115 init_gmpd_process (const db_conn_info_t *database, gchar **disable)
116 {
117   from_client_start = 0;
118   from_client_end = 0;
119   init_gmp_process (database, NULL, NULL, disable);
120 }
121 
122 /**
123  * @brief Read as much from the client as the \ref from_client buffer will hold.
124  *
125  * @param[in]  client_socket  The socket.
126  *
127  * @return 0 on reading everything available, -1 on error, -2 if
128  *         from_client buffer is full or -3 on reaching end of file.
129  */
130 static int
read_from_client_unix(int client_socket)131 read_from_client_unix (int client_socket)
132 {
133   while (from_client_end < from_buffer_size)
134     {
135       int count;
136       count = read (client_socket,
137                     from_client + from_client_end,
138                     from_buffer_size - from_client_end);
139       if (count < 0)
140         {
141           if (errno == EAGAIN)
142             /* Got everything available, return to `select'. */
143             return 0;
144           if (errno == EINTR)
145             /* Interrupted, try read again. */
146             continue;
147           g_warning ("%s: failed to read from client: %s",
148                      __func__, strerror (errno));
149           return -1;
150         }
151       if (count == 0)
152         {
153           /* End of file. */
154 
155           if (from_client_end)
156             /* There's still client input to process, so pretend we read
157              * something, to prevent serve_gmp from exiting.
158              *
159              * This should instead be dealt with in serve_gmp, but that function
160              * has got quite complex. */
161             return 0;
162 
163           return -3;
164         }
165       from_client_end += count;
166     }
167 
168   /* Buffer full. */
169   return -2;
170 }
171 
172 /**
173  * @brief Read as much from the client as the \ref from_client buffer will hold.
174  *
175  * @param[in]  client_session  The TLS session with the client.
176  *
177  * @return 0 on reading everything available, -1 on error, -2 if
178  * from_client buffer is full or -3 on reaching end of file.
179  */
180 static int
read_from_client_tls(gnutls_session_t * client_session)181 read_from_client_tls (gnutls_session_t* client_session)
182 {
183   while (from_client_end < from_buffer_size)
184     {
185       ssize_t count;
186       count = gnutls_record_recv (*client_session,
187                                   from_client + from_client_end,
188                                   from_buffer_size - from_client_end);
189       if (count < 0)
190         {
191           if (count == GNUTLS_E_AGAIN)
192             /* Got everything available, return to `select'. */
193             return 0;
194           if (count == GNUTLS_E_INTERRUPTED)
195             /* Interrupted, try read again. */
196             continue;
197           if (count == GNUTLS_E_REHANDSHAKE)
198             {
199               /** @todo Rehandshake. */
200               g_debug ("   should rehandshake");
201               continue;
202             }
203           if (gnutls_error_is_fatal ((int) count) == 0
204               && (count == GNUTLS_E_WARNING_ALERT_RECEIVED
205                   || count == GNUTLS_E_FATAL_ALERT_RECEIVED))
206             {
207               int alert = gnutls_alert_get (*client_session);
208               const char* alert_name = gnutls_alert_get_name (alert);
209               g_warning ("%s: TLS Alert %d: %s",
210                          __func__, alert, alert_name);
211             }
212           g_warning ("%s: failed to read from client: %s",
213                      __func__, gnutls_strerror ((int) count));
214           return -1;
215         }
216       if (count == 0)
217         {
218           /* End of file. */
219 
220           if (from_client_end)
221             /* There's still client input to process, so pretend we read
222              * something, to prevent serve_gmp from exiting.
223              *
224              * This should instead be dealt with in serve_gmp, but that function
225              * has got quite complex. */
226             return 0;
227 
228           return -3;
229         }
230       from_client_end += count;
231     }
232 
233   /* Buffer full. */
234   return -2;
235 }
236 
237 /**
238  * @brief Read as much from the client as the \ref from_client buffer will hold.
239  *
240  * @param[in]  client_connection  The connection with the client.
241  *
242  * @return 0 on reading everything available, -1 on error, -2 if
243  * from_client buffer is full or -3 on reaching end of file.
244  */
245 static int
read_from_client(gvm_connection_t * client_connection)246 read_from_client (gvm_connection_t *client_connection)
247 {
248   if (client_connection->tls)
249     return read_from_client_tls (&client_connection->session);
250   return read_from_client_unix (client_connection->socket);
251 }
252 
253 /** @todo Move to openvas-libraries? */
254 /**
255  * @brief Write as much as possible from \ref to_client to the client.
256  *
257  * @param[in]  client_session  The client session.
258  *
259  * @return 0 wrote everything, -1 error, -2 wrote as much as client accepted.
260  */
261 static int
write_to_client_tls(gnutls_session_t * client_session)262 write_to_client_tls (gnutls_session_t* client_session)
263 {
264   while (to_client_start < to_client_end)
265     {
266       ssize_t count;
267       count = gnutls_record_send (*client_session,
268                                   to_client + to_client_start,
269                                   to_client_end - to_client_start);
270       if (count < 0)
271         {
272           if (count == GNUTLS_E_AGAIN)
273             /* Wrote as much as client would accept. */
274             return -2;
275           if (count == GNUTLS_E_INTERRUPTED)
276             /* Interrupted, try write again. */
277             continue;
278           if (count == GNUTLS_E_REHANDSHAKE)
279             /** @todo Rehandshake. */
280             continue;
281           g_warning ("%s: failed to write to client: %s",
282                      __func__,
283                      gnutls_strerror ((int) count));
284           return -1;
285         }
286       to_client_start += count;
287       g_debug ("=> client  %u bytes", (unsigned int) count);
288     }
289   g_debug ("=> client  done");
290   to_client_start = to_client_end = 0;
291 
292   /* Wrote everything. */
293   return 0;
294 }
295 
296 /**
297  * @brief Write as much as possible from \ref to_client to the client.
298  *
299  * @param[in]  client_socket  The client socket.
300  *
301  * @return 0 wrote everything, -1 error, -2 wrote as much as client accepted.
302  */
303 static int
write_to_client_unix(int client_socket)304 write_to_client_unix (int client_socket)
305 {
306   while (to_client_start < to_client_end)
307     {
308       ssize_t count;
309       count = write (client_socket,
310                      to_client + to_client_start,
311                      to_client_end - to_client_start);
312       if (count < 0)
313         {
314           if (errno == EAGAIN)
315             /* Wrote as much as client would accept. */
316             return -2;
317           if (errno == EINTR)
318             /* Interrupted, try write again. */
319             continue;
320           g_warning ("%s: failed to write to client: %s",
321                      __func__,
322                      strerror (errno));
323           return -1;
324         }
325       to_client_start += count;
326       g_debug ("=> client  %u bytes", (unsigned int) count);
327     }
328   g_debug ("=> client  done");
329   to_client_start = to_client_end = 0;
330 
331   /* Wrote everything. */
332   return 0;
333 }
334 
335 /**
336  * @brief Write as much as possible from \ref to_client to the client.
337  *
338  * @param[in]  client_connection  The client connection.
339  *
340  * @return 0 wrote everything, -1 error, -2 wrote as much as client accepted.
341  */
342 static int
write_to_client(gvm_connection_t * client_connection)343 write_to_client (gvm_connection_t *client_connection)
344 {
345   if (client_connection->tls)
346     return write_to_client_tls (&client_connection->session);
347   return write_to_client_unix (client_connection->socket);
348 }
349 
350 /**
351  * @brief Send a response message to the client.
352  *
353  * Queue a message in \ref to_client.
354  *
355  * @param[in]  msg                   The message, a string.
356  * @param[in]  write_to_client_data  Argument to \p write_to_client.
357  *
358  * @return TRUE if write to client failed, else FALSE.
359  */
360 static gboolean
gmpd_send_to_client(const char * msg,void * write_to_client_data)361 gmpd_send_to_client (const char* msg, void* write_to_client_data)
362 {
363   assert (to_client_end <= TO_CLIENT_BUFFER_SIZE);
364   assert (msg);
365 
366   while (((buffer_size_t) TO_CLIENT_BUFFER_SIZE) - to_client_end
367          < strlen (msg))
368     {
369       buffer_size_t length;
370 
371       /* Too little space in to_client buffer for message. */
372 
373       switch (write_to_client (write_to_client_data))
374         {
375           case  0:      /* Wrote everything in to_client. */
376             break;
377           case -1:      /* Error. */
378             g_debug ("   %s full (%i < %zu); client write failed",
379                     __func__,
380                     ((buffer_size_t) TO_CLIENT_BUFFER_SIZE) - to_client_end,
381                     strlen (msg));
382             return TRUE;
383           case -2:      /* Wrote as much as client was willing to accept. */
384             break;
385           default:      /* Programming error. */
386             assert (0);
387         }
388 
389       length = ((buffer_size_t) TO_CLIENT_BUFFER_SIZE) - to_client_end;
390 
391       if (length > strlen (msg))
392         break;
393 
394       /* length can be 0 if write_to_client returns -2. */
395 
396       if (length > 0)
397         {
398           memmove (to_client + to_client_end, msg, length);
399           g_debug ("-> client: %.*s", (int) length, msg);
400           to_client_end += length;
401           msg += length;
402         }
403     }
404 
405   if (strlen (msg))
406     {
407       assert (strlen (msg)
408               <= (((buffer_size_t) TO_CLIENT_BUFFER_SIZE) - to_client_end));
409       memmove (to_client + to_client_end, msg, strlen (msg));
410       g_debug ("-> client: %s", msg);
411       to_client_end += strlen (msg);
412     }
413 
414   return FALSE;
415 }
416 
417 /**
418  * @brief Get nfds value.
419  *
420  * @param[in]  socket  Highest socket number.
421  *
422  * @return nfds value for select.
423  */
424 static int
get_nfds(int socket)425 get_nfds (int socket)
426 {
427   return 1 + socket;
428 }
429 
430 /**
431  * @brief Serve the Greenbone Management Protocol (GMP).
432  *
433  * Loop reading input from the sockets, processing
434  * the input, and writing any results to the appropriate socket.
435  * Exit the loop on reaching end of file on the client socket.
436  *
437  * Read input from the client.
438  * Process the input with \ref process_gmp_client_input.  Write the results
439  * to the client.
440  *
441  * \if STATIC
442  *
443  * Read input with \ref read_from_client.
444  * Write the results with \ref write_to_client.
445  *
446  * \endif
447  *
448  * @param[in]  client_connection    Connection.
449  * @param[in]  database             Location of manage database.
450  * @param[in]  disable              Commands to disable.
451  *
452  * @return 0 success, -1 error.
453  */
454 int
serve_gmp(gvm_connection_t * client_connection,const db_conn_info_t * database,gchar ** disable)455 serve_gmp (gvm_connection_t *client_connection, const db_conn_info_t *database,
456            gchar **disable)
457 {
458   int nfds, rc = 0;
459 
460   g_debug ("   Serving GMP");
461 
462   /* Initialise the XML parser and the manage library. */
463   init_gmp_process (database,
464                     (int (*) (const char*, void*)) gmpd_send_to_client,
465                     (void*) client_connection,
466                     disable);
467 
468   /** @todo Confirm and clarify complications, especially last one. */
469   /* Loop handling input from the sockets.
470    *
471    * That is, select on all the socket fds and then, as necessary
472    *   - read from the client into buffer from_client
473    *   - write to the client from buffer to_client.
474    *
475    * On reading from an fd, immediately try react to the input.  On reading
476    * from the client call process_gmp_client_input, which parses GMP
477    * commands and may write to to_client.
478    *
479    * There are a few complications here
480    *   - the program must read from or write to an fd returned by select
481    *     before selecting on the fd again,
482    *   - the program need only select on the fds for writing if there is
483    *     something to write,
484    *   - similarly, the program need only select on the fds for reading
485    *     if there is buffer space available,
486    *   - the buffer from_client can become full during reading
487    *   - a read from the client can be stalled by the to_client buffer
488    *     filling up (in which case process_gmp_client_input will try to
489    *     write the to_client buffer itself),
490    */
491 
492   nfds = get_nfds (client_connection->socket);
493   while (1)
494     {
495       int ret;
496       fd_set readfds, writefds;
497 
498       /* Setup for select. */
499 
500       /** @todo nfds must only include a socket if it's in >= one set. */
501 
502       FD_ZERO (&readfds);
503       FD_ZERO (&writefds);
504 
505       /** @todo Shutdown on failure (for example, if a read fails). */
506 
507       /* See whether to read from the client.  */
508       if (from_client_end < from_buffer_size)
509         FD_SET (client_connection->socket, &readfds);
510       /* See whether to write to the client.  */
511       if (to_client_start < to_client_end)
512         FD_SET (client_connection->socket, &writefds);
513 
514       /* Select, then handle result.  Due to GNUTLS internal buffering
515        * we test for pending records first and emulate a select call
516        * in that case.  Note, that GNUTLS guarantees that writes are
517        * not buffered.  Note also that GNUTLS versions < 3 did not
518        * exhibit a problem in Scanner due to a different buffering
519        * strategy.  */
520       ret = 0;
521       if (client_connection->socket > 0
522           && client_connection->tls
523           && FD_ISSET (client_connection->socket, &readfds)
524           && gnutls_record_check_pending (client_connection->session))
525         {
526           FD_ZERO (&readfds);
527           FD_ZERO (&writefds);
528           ret++;
529           FD_SET (client_connection->socket, &readfds);
530         }
531 
532       if (!ret)
533         ret = select (nfds, &readfds, &writefds, NULL, NULL);
534       if ((ret < 0 && errno == EINTR) || ret == 0)
535         continue;
536       if (ret < 0)
537         {
538           g_warning ("%s: child select failed: %s", __func__,
539                      strerror (errno));
540           rc = -1;
541           goto client_free;
542         }
543 
544       /* Read any data from the client. */
545       if (client_connection->socket > 0
546           && FD_ISSET (client_connection->socket, &readfds))
547         {
548           buffer_size_t initial_start = from_client_end;
549 
550           switch (read_from_client (client_connection))
551             {
552               case  0:       /* Read everything. */
553                 break;
554               case -1:       /* Error. */
555                 rc = -1;
556                 goto client_free;
557               case -2:       /* from_client buffer full. */
558                 /* There may be more to read. */
559                 break;
560               case -3:       /* End of file. */
561                 g_debug ("   EOF reading from client");
562                 if (client_connection->socket > 0
563                     && FD_ISSET (client_connection->socket, &writefds))
564                   /* Write rest of to_client to client, so that the client gets
565                    * any buffered output and the response to the error. */
566                   write_to_client (client_connection);
567                 rc = 0;
568                 goto client_free;
569               default:       /* Programming error. */
570                 assert (0);
571             }
572 
573           /* This check prevents output in the "asynchronous network
574            * error" case. */
575           if (from_client_end > initial_start)
576             {
577               if (g_strstr_len (from_client + initial_start,
578                                 from_client_end - initial_start,
579                                 "<password>"))
580                 g_debug ("<= client  Input may contain password, suppressed");
581               else
582                 g_debug ("<= client  \"%.*s\"",
583                         from_client_end - initial_start,
584                         from_client + initial_start);
585             }
586 
587           ret = process_gmp_client_input ();
588           if (ret == 0)
589             /* Processed all input. */
590             ;
591           else if (ret == -1 || ret == -4)
592             {
593               /* Error.  Write rest of to_client to client, so that the
594                * client gets any buffered output and the response to the
595                * error. */
596               write_to_client (client_connection);
597               rc = -1;
598               goto client_free;
599             }
600           else
601             {
602               /* Programming error. */
603               assert (0);
604             }
605         }
606 
607       /* Write any data to the client. */
608       if (client_connection->socket > 0
609           && FD_ISSET (client_connection->socket, &writefds))
610         {
611           /* Write as much as possible to the client. */
612 
613           switch (write_to_client (client_connection))
614             {
615               case  0:      /* Wrote everything in to_client. */
616                 break;
617               case -1:      /* Error. */
618                 rc = -1;
619                 goto client_free;
620               case -2:      /* Wrote as much as client was willing to accept. */
621                 break;
622               default:      /* Programming error. */
623                 assert (0);
624             }
625         }
626     } /* while (1) */
627 
628 client_free:
629   gvm_connection_free (client_connection);
630   return rc;
631 }
632