Greenbone Vulnerability Management Libraries  11.0.1
serverutils.c
Go to the documentation of this file.
1 /* Copyright (C) 2009-2019 Greenbone Networks GmbH
2  *
3  * SPDX-License-Identifier: GPL-2.0-or-later
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the 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 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 
28 #define _GNU_SOURCE
29 
30 #include "serverutils.h"
31 
32 #include "../base/hosts.h" /* for is_hostname, is_ipv4_address, is_ipv6_add.. */
33 
34 #include <arpa/inet.h>
35 #include <errno.h> /* for errno, ENOTCONN, EAGAIN */
36 #include <fcntl.h> /* for fcntl, F_SETFL, O_NONBLOCK */
37 #include <gcrypt.h> /* for gcry_control */
38 #include <glib.h> /* for g_warning, g_free, g_debug, gchar, g_markup... */
39 #include <gnutls/x509.h> /* for gnutls_x509_crt_..., gnutls_x509_privkey_... */
40 #include <netdb.h> /* for addrinfo, freeaddrinfo, gai_strerror, getad... */
41 #include <signal.h> /* for sigaction, SIGPIPE, sigemptyset, SIG_IGN */
42 #include <stdio.h> /* for fclose, FILE, SEEK_END, SEEK_SET */
43 #include <string.h> /* for strerror, strlen, memset */
44 #include <sys/socket.h> /* for shutdown, connect, socket, SHUT_RDWR, SOCK_... */
45 #include <sys/types.h>
46 #include <unistd.h> /* for close, ssize_t, usleep */
47 
48 #undef G_LOG_DOMAIN
49 
52 #define G_LOG_DOMAIN "lib serv"
53 
57 struct sockaddr_in address;
58 
59 static int
60 server_attach_internal (int, gnutls_session_t *, const char *, int);
61 static int
62 server_new_internal (unsigned int, const char *, const gchar *, const gchar *,
63  const gchar *, gnutls_session_t *,
64  gnutls_certificate_credentials_t *);
65 
66 /* Connections. */
67 
75 static int
76 close_unix (gvm_connection_t *client_connection)
77 {
78  /* Turn off blocking. */
79  if (fcntl (client_connection->socket, F_SETFL, O_NONBLOCK) == -1)
80  {
81  g_warning ("%s: failed to set server socket flag: %s\n", __FUNCTION__,
82  strerror (errno));
83  return -1;
84  }
85 
86  if (shutdown (client_connection->socket, SHUT_RDWR) == -1)
87  {
88  if (errno == ENOTCONN)
89  return 0;
90  g_warning ("%s: failed to shutdown server socket: %s\n", __FUNCTION__,
91  strerror (errno));
92  return -1;
93  }
94 
95  if (close (client_connection->socket) == -1)
96  {
97  g_warning ("%s: failed to close server socket: %s\n", __FUNCTION__,
98  strerror (errno));
99  return -1;
100  }
101 
102  return 0;
103 }
104 
110 void
112 {
113  if (client_connection->tls)
114  gvm_server_free (client_connection->socket, client_connection->session,
115  client_connection->credentials);
116  else
117  close_unix (client_connection);
118 }
119 
120 /* Certificate verification. */
121 
129 int
130 gvm_server_verify (gnutls_session_t session)
131 {
132  unsigned int status;
133  int ret;
134 
135  ret = gnutls_certificate_verify_peers2 (session, &status);
136  if (ret < 0)
137  {
138  g_warning ("%s: failed to verify peers: %s", __FUNCTION__,
139  gnutls_strerror (ret));
140  return -1;
141  }
142 
143  if (status & GNUTLS_CERT_INVALID)
144  g_warning ("%s: the certificate is not trusted", __FUNCTION__);
145 
146  if (status & GNUTLS_CERT_SIGNER_NOT_CA)
147  g_warning ("%s: the certificate's issuer is not a CA", __FUNCTION__);
148 
149  if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
150  g_warning ("%s: the certificate was signed using an insecure algorithm",
151  __FUNCTION__);
152 
153  if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
154  g_warning ("%s: the certificate hasn't got a known issuer", __FUNCTION__);
155 
156  if (status & GNUTLS_CERT_REVOKED)
157  g_warning ("%s: the certificate has been revoked", __FUNCTION__);
158 
159  if (status & GNUTLS_CERT_EXPIRED)
160  g_warning ("%s: the certificate has expired", __FUNCTION__);
161 
162  if (status & GNUTLS_CERT_NOT_ACTIVATED)
163  g_warning ("%s: the certificate is not yet activated", __FUNCTION__);
164 
165  if (status)
166  return 1;
167 
168  return 0;
169 }
170 
179 int
180 load_gnutls_file (const char *file, gnutls_datum_t *loaded_file)
181 {
182  FILE *f = NULL;
183  int64_t filelen;
184  void *ptr;
185 
186  if (!(f = fopen (file, "r")) || fseek (f, 0, SEEK_END) != 0
187  || (filelen = ftell (f)) < 0 || fseek (f, 0, SEEK_SET) != 0
188  || !(ptr = g_malloc0 ((size_t) filelen))
189  || fread (ptr, 1, (size_t) filelen, f) < (size_t) filelen)
190  {
191  if (f)
192  fclose (f);
193  return -1;
194  }
195 
196  loaded_file->data = ptr;
197  loaded_file->size = filelen;
198  fclose (f);
199  return 0;
200 }
201 
207 void
208 unload_gnutls_file (gnutls_datum_t *data)
209 {
210  if (data)
211  g_free (data->data);
212 }
213 
214 static char *cert_pub_mem = NULL;
215 static char *cert_priv_mem = NULL;
216 
222 static void
223 set_cert_pub_mem (const char *data)
224 {
225  if (cert_pub_mem)
226  g_free (cert_pub_mem);
227  cert_pub_mem = g_strdup (data);
228 }
229 
235 static void
236 set_cert_priv_mem (const char *data)
237 {
238  if (cert_priv_mem)
239  g_free (cert_priv_mem);
240  cert_priv_mem = g_strdup (data);
241 }
242 
248 static const char *
250 {
251  return cert_priv_mem;
252 }
253 
259 static const char *
261 {
262  return cert_pub_mem;
263 }
264 
280 static int
281 client_cert_callback (gnutls_session_t session,
282  const gnutls_datum_t *req_ca_rdn, int nreqs,
283  const gnutls_pk_algorithm_t *sign_algos,
284  int sign_algos_length, gnutls_retr2_st *st)
285 {
286  int ret;
287  gnutls_datum_t data;
288  static gnutls_x509_crt_t crt;
289  static gnutls_x509_privkey_t key;
290 
291  (void) session;
292  (void) req_ca_rdn;
293  (void) nreqs;
294  (void) sign_algos;
295  (void) sign_algos_length;
296  data.data = (unsigned char *) g_strdup (get_cert_pub_mem ());
297  data.size = strlen (get_cert_pub_mem ());
298  gnutls_x509_crt_init (&crt);
299  ret = gnutls_x509_crt_import (crt, &data, GNUTLS_X509_FMT_PEM);
300  g_free (data.data);
301  if (ret)
302  return ret;
303  st->cert.x509 = &crt;
304  st->cert_type = GNUTLS_CRT_X509;
305  st->ncerts = 1;
306 
307  data.data = (unsigned char *) g_strdup (get_cert_priv_mem ());
308  data.size = strlen (get_cert_priv_mem ());
309  gnutls_x509_privkey_init (&key);
310  ret = gnutls_x509_privkey_import (key, &data, GNUTLS_X509_FMT_PEM);
311  g_free (data.data);
312  if (ret)
313  return ret;
314  st->key.x509 = key;
315  st->key_type = GNUTLS_PRIVKEY_X509;
316  return 0;
317 }
318 
332 int
333 gvm_server_open_verify (gnutls_session_t *session, const char *host, int port,
334  const char *ca_mem, const char *pub_mem,
335  const char *priv_mem, int verify)
336 {
337  int ret;
338  int server_socket;
339  struct addrinfo address_hints;
340  struct addrinfo *addresses, *address;
341  gchar *port_string;
342  int host_type;
343 
344  gnutls_certificate_credentials_t credentials;
345 
346  /* Ensure that host and port have sane values. */
347  if (port < 1 || port > 65535)
348  {
349  g_warning ("Failed to create client TLS session. "
350  "Invalid port %d",
351  port);
352  return -1;
353  }
354  host_type = gvm_get_host_type (host);
356  || host_type == HOST_TYPE_IPV6))
357  {
358  g_warning ("Failed to create client TLS session. Invalid host %s", host);
359  return -1;
360  }
361 
365  if (gvm_server_new_mem (GNUTLS_CLIENT, ca_mem, pub_mem, priv_mem, session,
366  &credentials))
367  {
368  g_warning ("Failed to create client TLS session.");
369  return -1;
370  }
371 
372  if (ca_mem && pub_mem && priv_mem)
373  {
374  set_cert_pub_mem (pub_mem);
375  set_cert_priv_mem (priv_mem);
376 
377  gnutls_certificate_set_retrieve_function (credentials,
379  }
380 
381  /* Create the port string. */
382 
383  port_string = g_strdup_printf ("%i", port);
384 
385  /* Get all possible addresses. */
386 
387  memset (&address_hints, 0, sizeof (address_hints));
388  address_hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6. */
389  address_hints.ai_socktype = SOCK_STREAM;
390  address_hints.ai_protocol = 0;
391 
392  if (getaddrinfo (host, port_string, &address_hints, &addresses))
393  {
394  g_free (port_string);
395  g_warning ("Failed to get server addresses for %s: %s", host,
396  gai_strerror (errno));
397  gnutls_deinit (*session);
398  gnutls_certificate_free_credentials (credentials);
399  return -1;
400  }
401  g_free (port_string);
402 
403  /* Try to connect to each address in turn. */
404 
405  for (address = addresses; address; address = address->ai_next)
406  {
407  /* Make server socket. */
408 
409  if (address->ai_family == AF_INET6)
410  server_socket = socket (PF_INET6, SOCK_STREAM, 0);
411  else
412  server_socket = socket (PF_INET, SOCK_STREAM, 0);
413  if (server_socket == -1)
414  {
415  g_warning ("Failed to create server socket");
416  freeaddrinfo (addresses);
417  gnutls_deinit (*session);
418  gnutls_certificate_free_credentials (credentials);
419  return -1;
420  }
421 
422  /* Connect to server. */
423 
424  if (connect (server_socket, address->ai_addr, address->ai_addrlen) == -1)
425  {
426  close (server_socket);
427  continue;
428  }
429  break;
430  }
431 
432  freeaddrinfo (addresses);
433 
434  if (address == NULL)
435  {
436  g_warning ("Failed to connect to server");
437  gnutls_deinit (*session);
438  gnutls_certificate_free_credentials (credentials);
439  return -1;
440  }
441 
442  g_debug (" Connected to server '%s' port %d.", host, port);
443 
444  /* Complete setup of server session. */
445  ret = server_attach_internal (server_socket, session, host, port);
446  if (ret)
447  {
448  if (ret == -2)
449  {
450  close (server_socket);
451  gnutls_deinit (*session);
452  gnutls_certificate_free_credentials (credentials);
453  }
454  close (server_socket);
455  return -1;
456  }
457  if (verify && gvm_server_verify (*session))
458  {
459  close (server_socket);
460  return -1;
461  }
462 
463  return server_socket;
464 }
465 
480 int
481 gvm_server_open_with_cert (gnutls_session_t *session, const char *host,
482  int port, const char *ca_mem, const char *pub_mem,
483  const char *priv_mem)
484 {
485  return gvm_server_open_verify (session, host, port, ca_mem, pub_mem, priv_mem,
486  ca_mem && pub_mem && priv_mem);
487 }
488 
498 int
499 gvm_server_open (gnutls_session_t *session, const char *host, int port)
500 {
501  return gvm_server_open_with_cert (session, host, port, NULL, NULL, NULL);
502 }
503 
512 int
513 gvm_server_close (int socket, gnutls_session_t session)
514 {
515  return gvm_server_free (socket, session, NULL);
516 }
517 
525 void
527 {
528  gvm_connection_free (connection);
529 }
530 
542 static int
543 server_attach_internal (int socket, gnutls_session_t *session, const char *host,
544  int port)
545 {
546  unsigned int retries;
547 
548  gnutls_transport_set_ptr (*session,
549  (gnutls_transport_ptr_t) GSIZE_TO_POINTER (socket));
550 
551  retries = 0;
552  while (1)
553  {
554  int ret = gnutls_handshake (*session);
555  if (ret >= 0)
556  break;
557  if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
558  {
559  if (retries > 10)
560  usleep (MIN ((retries - 10) * 10000, 5000000));
561  retries++;
562  continue;
563  }
564  if (host)
565  g_debug ("Failed to shake hands with server '%s' port %d: %s", host,
566  port, gnutls_strerror (ret));
567  else
568  g_debug ("Failed to shake hands with peer: %s", gnutls_strerror (ret));
569  if (shutdown (socket, SHUT_RDWR) == -1)
570  g_debug ("Failed to shutdown server socket");
571  return -2;
572  }
573  if (host)
574  g_debug (" Shook hands with server '%s' port %d.", host, port);
575  else
576  g_debug (" Shook hands with peer.");
577 
578  return 0;
579 }
580 
590 int
591 gvm_server_attach (int socket, gnutls_session_t *session)
592 {
593  int ret;
594 
595  ret = server_attach_internal (socket, session, NULL, 0);
596  return ret ? -1 : 0;
597 }
598 
610 static int
611 gvm_server_vsendf_internal (gnutls_session_t *session, const char *fmt,
612  va_list ap, int quiet)
613 {
614  char *sref, *string;
615  int rc = 0, left;
616 
617  left = vasprintf (&string, fmt, ap);
618  if (left == -1)
619  string = NULL;
620 
621  sref = string;
622  while (left > 0)
623  {
624  ssize_t count;
625 
626  if (quiet == 0)
627  g_debug (" send %d from %.*s[...]", left, left < 30 ? left : 30,
628  string);
629  count = gnutls_record_send (*session, string, left);
630  if (count < 0)
631  {
632  if (count == GNUTLS_E_INTERRUPTED)
633  /* Interrupted, try write again. */
634  continue;
635  if (count == GNUTLS_E_REHANDSHAKE)
636  {
637  /* \todo Rehandshake. */
638  if (quiet == 0)
639  g_message (" %s rehandshake", __FUNCTION__);
640  continue;
641  }
642  g_warning ("Failed to write to server: %s", gnutls_strerror (count));
643  rc = -1;
644  goto out;
645  }
646  if (count == 0)
647  {
648  /* Server closed connection. */
649  if (quiet == 0)
650  g_debug ("= server closed");
651  rc = 1;
652  goto out;
653  }
654  if (quiet == 0)
655  g_debug ("=> %.*s", (int) count, string);
656  string += count;
657  left -= count;
658  }
659  if (quiet == 0)
660  g_debug ("=> done");
661 
662 out:
663  g_free (sref);
664  return rc;
665 }
666 
678 static int
679 unix_vsendf_internal (int socket, const char *fmt, va_list ap, int quiet)
680 {
681  char *string_start, *string;
682  int rc = 0, left;
683 
684  left = vasprintf (&string, fmt, ap);
685  if (left == -1)
686  string = NULL;
687 
688  string_start = string;
689  while (left > 0)
690  {
691  ssize_t count;
692 
693  if (quiet == 0)
694  g_debug (" send %d from %.*s[...]", left, left < 30 ? left : 30,
695  string);
696  count = write (socket, string, left);
697  if (count < 0)
698  {
699  if (errno == EINTR || errno == EAGAIN)
700  continue;
701  g_warning ("Failed to write to server: %s", strerror (errno));
702  rc = -1;
703  goto out;
704  }
705  if (quiet == 0)
706  g_debug ("=> %.*s", (int) count, string);
707 
708  string += count;
709  left -= count;
710  }
711  if (quiet == 0)
712  g_debug ("=> done");
713 
714 out:
715  g_free (string_start);
716  return rc;
717 }
718 
730 static int
731 gvm_connection_vsendf_internal (gvm_connection_t *connection, const char *fmt,
732  va_list ap, int quiet)
733 {
734  if (connection->tls)
735  return gvm_server_vsendf_internal (&connection->session, fmt, ap, quiet);
736  return unix_vsendf_internal (connection->socket, fmt, ap, quiet);
737 }
738 
748 int
749 gvm_server_vsendf (gnutls_session_t *session, const char *fmt, va_list ap)
750 {
751  return gvm_server_vsendf_internal (session, fmt, ap, 0);
752 }
753 
763 int
764 gvm_socket_vsendf (int socket, const char *fmt, va_list ap)
765 {
766  return unix_vsendf_internal (socket, fmt, ap, 0);
767 }
768 
778 int
779 gvm_connection_vsendf (gvm_connection_t *connection, const char *fmt,
780  va_list ap)
781 {
782  return gvm_connection_vsendf_internal (connection, fmt, ap, 0);
783 }
784 
794 int
795 gvm_server_vsendf_quiet (gnutls_session_t *session, const char *fmt, va_list ap)
796 {
797  return gvm_server_vsendf_internal (session, fmt, ap, 1);
798 }
799 
809 int
810 gvm_connection_vsendf_quiet (gvm_connection_t *connection, const char *fmt,
811  va_list ap)
812 {
813  return gvm_connection_vsendf_internal (connection, fmt, ap, 1);
814 }
815 
824 int
825 gvm_server_sendf (gnutls_session_t *session, const char *format, ...)
826 {
827  va_list ap;
828  int rc;
829 
830  va_start (ap, format);
831  rc = gvm_server_vsendf (session, format, ap);
832  va_end (ap);
833  return rc;
834 }
835 
844 int
845 gvm_connection_sendf (gvm_connection_t *connection, const char *format, ...)
846 {
847  va_list ap;
848  int rc;
849 
850  va_start (ap, format);
851  rc = gvm_connection_vsendf (connection, format, ap);
852  va_end (ap);
853  return rc;
854 }
855 
864 int
865 gvm_server_sendf_quiet (gnutls_session_t *session, const char *format, ...)
866 {
867  va_list ap;
868  int rc;
869 
870  va_start (ap, format);
871  rc = gvm_server_vsendf_quiet (session, format, ap);
872  va_end (ap);
873  return rc;
874 }
875 
884 int
885 gvm_connection_sendf_quiet (gvm_connection_t *connection, const char *format,
886  ...)
887 {
888  va_list ap;
889  int rc;
890 
891  va_start (ap, format);
892  rc = gvm_connection_vsendf_quiet (connection, format, ap);
893  va_end (ap);
894  return rc;
895 }
896 
907 int
908 gvm_server_sendf_xml (gnutls_session_t *session, const char *format, ...)
909 {
910  va_list ap;
911  gchar *msg;
912  int rc;
913 
914  va_start (ap, format);
915  msg = g_markup_vprintf_escaped (format, ap);
916  rc = gvm_server_sendf (session, "%s", msg);
917  g_free (msg);
918  va_end (ap);
919  return rc;
920 }
921 
932 int
933 gvm_connection_sendf_xml (gvm_connection_t *connection, const char *format, ...)
934 {
935  va_list ap;
936  gchar *msg;
937  int rc;
938 
939  va_start (ap, format);
940  msg = g_markup_vprintf_escaped (format, ap);
941  rc = gvm_connection_sendf (connection, "%s", msg);
942  g_free (msg);
943  va_end (ap);
944  return rc;
945 }
946 
959 int
960 gvm_server_sendf_xml_quiet (gnutls_session_t *session, const char *format, ...)
961 {
962  va_list ap;
963  gchar *msg;
964  int rc;
965 
966  va_start (ap, format);
967  msg = g_markup_vprintf_escaped (format, ap);
968  rc = gvm_server_sendf_quiet (session, "%s", msg);
969  g_free (msg);
970  va_end (ap);
971  return rc;
972 }
973 
986 int
988  const char *format, ...)
989 {
990  va_list ap;
991  gchar *msg;
992  int rc;
993 
994  va_start (ap, format);
995  msg = g_markup_vprintf_escaped (format, ap);
996  rc = gvm_connection_sendf_quiet (connection, "%s", msg);
997  g_free (msg);
998  va_end (ap);
999  return rc;
1000 }
1001 
1009 static int
1010 server_new_gnutls_init (gnutls_certificate_credentials_t *server_credentials)
1011 {
1012  /* Turn off use of /dev/random, as this can block. */
1013  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
1014 
1015  /* Initialize security library. */
1016  if (gnutls_global_init ())
1017  {
1018  g_warning ("Failed to initialize GNUTLS.");
1019  return -1;
1020  }
1021  /* Setup server session. */
1022  if (gnutls_certificate_allocate_credentials (server_credentials))
1023  {
1024  g_warning ("%s: failed to allocate server credentials\n", __FUNCTION__);
1025  return -1;
1026  }
1027  return 0;
1028 }
1029 
1041 static int
1042 server_new_gnutls_set (unsigned int end_type, const char *priority,
1043  gnutls_session_t *server_session,
1044  gnutls_certificate_credentials_t *server_credentials)
1045 {
1046  int err_gnutls;
1047 
1048  if (gnutls_init (server_session, end_type))
1049  {
1050  g_warning ("%s: failed to initialise server session\n", __FUNCTION__);
1051  return -1;
1052  }
1053 
1054  /* Depending on gnutls version different priority strings are
1055  possible. At least from 3.0 this is an option:
1056  "NONE:+VERS-TLS1.0:+CIPHER-ALL:+COMP-ALL:+RSA:+DHE-RSA:+DHE-DSS:+MAC-ALL"
1057  But in fact this function is only for internal
1058  purposes, not for scanning abilities. So, the conservative "NORMAL"
1059  is chosen.
1060  */
1061 
1062  if ((err_gnutls = gnutls_priority_set_direct (
1063  *server_session, priority ? priority : "NORMAL", NULL)))
1064  {
1065  g_warning ("%s: failed to set tls priorities: %s\n", __FUNCTION__,
1066  gnutls_strerror (err_gnutls));
1067  gnutls_deinit (*server_session);
1068  return -1;
1069  }
1070 
1071  if (gnutls_credentials_set (*server_session, GNUTLS_CRD_CERTIFICATE,
1072  *server_credentials))
1073  {
1074  g_warning ("%s: failed to set server credentials\n", __FUNCTION__);
1075  gnutls_deinit (*server_session);
1076  return -1;
1077  }
1078 
1079  if (end_type == GNUTLS_SERVER)
1080  gnutls_certificate_server_set_request (*server_session,
1081  GNUTLS_CERT_REQUEST);
1082  return 0;
1083 }
1084 
1099 static int
1100 server_new_internal (unsigned int end_type, const char *priority,
1101  const gchar *ca_cert_file, const gchar *cert_file,
1102  const gchar *key_file, gnutls_session_t *server_session,
1103  gnutls_certificate_credentials_t *server_credentials)
1104 {
1105  if (server_new_gnutls_init (server_credentials))
1106  return -1;
1107 
1108  if (cert_file && key_file)
1109  {
1110  int ret;
1111 
1112  ret = gnutls_certificate_set_x509_key_file (
1113  *server_credentials, cert_file, key_file, GNUTLS_X509_FMT_PEM);
1114  if (ret < 0)
1115  {
1116  g_warning ("%s: failed to set credentials key file: %s\n",
1117  __FUNCTION__, gnutls_strerror (ret));
1118  g_warning ("%s: cert file: %s\n", __FUNCTION__, cert_file);
1119  g_warning ("%s: key file : %s\n", __FUNCTION__, key_file);
1120  gnutls_certificate_free_credentials (*server_credentials);
1121  return -1;
1122  }
1123  }
1124 
1125  if (ca_cert_file)
1126  {
1127  int ret;
1128 
1129  ret = gnutls_certificate_set_x509_trust_file (
1130  *server_credentials, ca_cert_file, GNUTLS_X509_FMT_PEM);
1131  if (ret < 0)
1132  {
1133  g_warning ("%s: failed to set credentials trust file: %s\n",
1134  __FUNCTION__, gnutls_strerror (ret));
1135  g_warning ("%s: trust file: %s\n", __FUNCTION__, ca_cert_file);
1136  gnutls_certificate_free_credentials (*server_credentials);
1137  return -1;
1138  }
1139  }
1140 
1141  if (server_new_gnutls_set (end_type, priority, server_session,
1142  server_credentials))
1143  {
1144  gnutls_certificate_free_credentials (*server_credentials);
1145  return -1;
1146  }
1147 
1148  return 0;
1149 }
1150 
1164 int
1165 gvm_server_new (unsigned int end_type, gchar *ca_cert_file, gchar *cert_file,
1166  gchar *key_file, gnutls_session_t *server_session,
1167  gnutls_certificate_credentials_t *server_credentials)
1168 {
1169  return server_new_internal (end_type, NULL, ca_cert_file, cert_file, key_file,
1170  server_session, server_credentials);
1171 }
1172 
1186 int
1187 gvm_server_new_mem (unsigned int end_type, const char *ca_cert,
1188  const char *pub_key, const char *priv_key,
1189  gnutls_session_t *session,
1190  gnutls_certificate_credentials_t *credentials)
1191 {
1192  if (server_new_gnutls_init (credentials))
1193  return -1;
1194 
1195  if (pub_key && priv_key)
1196  {
1197  int ret;
1198  gnutls_datum_t pub, priv;
1199 
1200  pub.data = (void *) pub_key;
1201  pub.size = strlen (pub_key);
1202  priv.data = (void *) priv_key;
1203  priv.size = strlen (priv_key);
1204 
1205  ret = gnutls_certificate_set_x509_key_mem (*credentials, &pub, &priv,
1206  GNUTLS_X509_FMT_PEM);
1207  if (ret < 0)
1208  {
1209  g_warning ("%s: %s\n", __FUNCTION__, gnutls_strerror (ret));
1210  return -1;
1211  }
1212  }
1213 
1214  if (ca_cert)
1215  {
1216  int ret;
1217  gnutls_datum_t data;
1218 
1219  data.data = (void *) ca_cert;
1220  data.size = strlen (ca_cert);
1221  ret = gnutls_certificate_set_x509_trust_mem (*credentials, &data,
1222  GNUTLS_X509_FMT_PEM);
1223  if (ret < 0)
1224  {
1225  g_warning ("%s: %s\n", __FUNCTION__, gnutls_strerror (ret));
1226  gnutls_certificate_free_credentials (*credentials);
1227  return -1;
1228  }
1229  }
1230 
1231  if (server_new_gnutls_set (end_type, NULL, session, credentials))
1232  {
1233  gnutls_certificate_free_credentials (*credentials);
1234  return -1;
1235  }
1236 
1237  return 0;
1238 }
1239 
1248 int
1249 set_gnutls_dhparams (gnutls_certificate_credentials_t creds,
1250  const char *dhparams_file)
1251 {
1252  int ret;
1253  gnutls_datum_t data;
1254 
1255  if (!creds || !dhparams_file)
1256  return -1;
1257 
1258  if (load_gnutls_file (dhparams_file, &data))
1259  return -1;
1260  gnutls_dh_params_t params = g_malloc0 (sizeof (gnutls_dh_params_t));
1261  ret = gnutls_dh_params_import_pkcs3 (params, &data, GNUTLS_X509_FMT_PEM);
1262  unload_gnutls_file (&data);
1263  if (ret)
1264  return -1;
1265  else
1266  gnutls_certificate_set_dh_params (creds, params);
1267  return 0;
1268 }
1269 
1282 int
1283 gvm_server_free (int server_socket, gnutls_session_t server_session,
1284  gnutls_certificate_credentials_t server_credentials)
1285 {
1286  /* Turn off blocking. */
1287  // FIX get flags first
1288  if (fcntl (server_socket, F_SETFL, O_NONBLOCK) == -1)
1289  {
1290  g_warning ("%s: failed to set server socket flag: %s\n", __FUNCTION__,
1291  strerror (errno));
1292  return -1;
1293  }
1294 
1295  while (1)
1296  {
1297  int ret = gnutls_bye (server_session, GNUTLS_SHUT_WR);
1298  if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
1299  {
1300  continue;
1301  }
1302  if (ret)
1303  {
1304  g_debug (" Failed to gnutls_bye: %s\n",
1305  gnutls_strerror ((int) ret));
1306  /* Carry on successfully anyway, as this often fails, perhaps
1307  * because the server is closing the connection first. */
1308  break;
1309  }
1310  break;
1311  }
1312 
1313  /* The former separate code in gvm_server_close and here
1314  differed in the order the TLS session and socket was closed. The
1315  way we do it here seems to be the right thing but for full
1316  backward compatibility we do it for calls from
1317  gvm_server_close in the old way. We can distinguish the two
1318  modes by the existence of server_credentials. */
1319  if (server_credentials)
1320  {
1321  if (close (server_socket) == -1)
1322  {
1323  g_warning ("%s: failed to close server socket: %s\n", __FUNCTION__,
1324  strerror (errno));
1325  return -1;
1326  }
1327  gnutls_deinit (server_session);
1328  gnutls_certificate_free_credentials (server_credentials);
1329  }
1330  else
1331  {
1332  gnutls_deinit (server_session);
1333  close (server_socket);
1334  }
1335 
1336  gnutls_global_deinit ();
1337 
1338  return 0;
1339 }
gvm_server_new_mem
int gvm_server_new_mem(unsigned int end_type, const char *ca_cert, const char *pub_key, const char *priv_key, gnutls_session_t *session, gnutls_certificate_credentials_t *credentials)
Make a session for connecting to a server, with certificates stored in memory.
Definition: serverutils.c:1187
gvm_server_close
int gvm_server_close(int socket, gnutls_session_t session)
Close a server connection and its socket.
Definition: serverutils.c:513
gvm_connection_sendf_xml
int gvm_connection_sendf_xml(gvm_connection_t *connection, const char *format,...)
Format and send an XML string to the server.
Definition: serverutils.c:933
gvm_server_verify
int gvm_server_verify(gnutls_session_t session)
Verify certificate.
Definition: serverutils.c:130
unload_gnutls_file
void unload_gnutls_file(gnutls_datum_t *data)
Unloads a gnutls_datum_t struct's data.
Definition: serverutils.c:208
gvm_connection_sendf
int gvm_connection_sendf(gvm_connection_t *connection, const char *format,...)
Format and send a string to the server.
Definition: serverutils.c:845
server_new_internal
static int server_new_internal(unsigned int, const char *, const gchar *, const gchar *, const gchar *, gnutls_session_t *, gnutls_certificate_credentials_t *)
Make a session for connecting to a server.
Definition: serverutils.c:1100
gvm_server_open
int gvm_server_open(gnutls_session_t *session, const char *host, int port)
Connect to the server using a given host and port.
Definition: serverutils.c:499
gvm_server_sendf_xml
int gvm_server_sendf_xml(gnutls_session_t *session, const char *format,...)
Format and send an XML string to the server.
Definition: serverutils.c:908
HOST_TYPE_IPV6
@ HOST_TYPE_IPV6
Definition: hosts.h:43
server_attach_internal
static int server_attach_internal(int, gnutls_session_t *, const char *, int)
Attach a socket to a session, and shake hands with the peer.
Definition: serverutils.c:543
close_unix
static int close_unix(gvm_connection_t *client_connection)
Close UNIX socket connection.
Definition: serverutils.c:76
unix_vsendf_internal
static int unix_vsendf_internal(int socket, const char *fmt, va_list ap, int quiet)
Send a string to the server.
Definition: serverutils.c:679
server_new_gnutls_init
static int server_new_gnutls_init(gnutls_certificate_credentials_t *server_credentials)
Initialize a server session.
Definition: serverutils.c:1010
HOST_TYPE_IPV4
@ HOST_TYPE_IPV4
Definition: hosts.h:39
gvm_get_host_type
int gvm_get_host_type(const gchar *str_stripped)
Determines the host type in a buffer.
Definition: hosts.c:771
gvm_server_open_with_cert
int gvm_server_open_with_cert(gnutls_session_t *session, const char *host, int port, const char *ca_mem, const char *pub_mem, const char *priv_mem)
Connect to the server using a given host, port and cert.
Definition: serverutils.c:481
gvm_connection_t::socket
int socket
Socket.
Definition: serverutils.h:46
gvm_server_vsendf_internal
static int gvm_server_vsendf_internal(gnutls_session_t *session, const char *fmt, va_list ap, int quiet)
Send a string to the server.
Definition: serverutils.c:611
cert_pub_mem
static char * cert_pub_mem
Definition: serverutils.c:214
gvm_connection_t::tls
int tls
Whether uses TCP-TLS (vs UNIX socket).
Definition: serverutils.h:45
load_gnutls_file
int load_gnutls_file(const char *file, gnutls_datum_t *loaded_file)
Loads a file's data into gnutls_datum_t struct.
Definition: serverutils.c:180
gvm_server_free
int gvm_server_free(int server_socket, gnutls_session_t server_session, gnutls_certificate_credentials_t server_credentials)
Cleanup a server session.
Definition: serverutils.c:1283
gvm_server_vsendf
int gvm_server_vsendf(gnutls_session_t *session, const char *fmt, va_list ap)
Send a string to the server.
Definition: serverutils.c:749
gvm_connection_sendf_xml_quiet
int gvm_connection_sendf_xml_quiet(gvm_connection_t *connection, const char *format,...)
Format and send an XML string to the server.
Definition: serverutils.c:987
gvm_connection_close
void gvm_connection_close(gvm_connection_t *connection)
Close a server connection and its socket.
Definition: serverutils.c:526
gvm_server_open_verify
int gvm_server_open_verify(gnutls_session_t *session, const char *host, int port, const char *ca_mem, const char *pub_mem, const char *priv_mem, int verify)
Connect to the server using a given host, port and cert.
Definition: serverutils.c:333
client_cert_callback
static int client_cert_callback(gnutls_session_t session, const gnutls_datum_t *req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t *sign_algos, int sign_algos_length, gnutls_retr2_st *st)
Callback function to be called in order to retrieve the certificate to be used in the handshake.
Definition: serverutils.c:281
gvm_server_new
int gvm_server_new(unsigned int end_type, gchar *ca_cert_file, gchar *cert_file, gchar *key_file, gnutls_session_t *server_session, gnutls_certificate_credentials_t *server_credentials)
Make a session for connecting to a server.
Definition: serverutils.c:1165
gvm_connection_t::credentials
gnutls_certificate_credentials_t credentials
Credentials.
Definition: serverutils.h:48
gvm_connection_vsendf_internal
static int gvm_connection_vsendf_internal(gvm_connection_t *connection, const char *fmt, va_list ap, int quiet)
Send a string to the connection.
Definition: serverutils.c:731
gvm_connection_free
void gvm_connection_free(gvm_connection_t *client_connection)
Free connection.
Definition: serverutils.c:111
get_cert_pub_mem
static const char * get_cert_pub_mem()
Get public certificate from cert_pub_mem.
Definition: serverutils.c:260
gvm_connection_vsendf_quiet
int gvm_connection_vsendf_quiet(gvm_connection_t *connection, const char *fmt, va_list ap)
Send a string to the server, refraining from logging besides warnings.
Definition: serverutils.c:810
gvm_server_vsendf_quiet
int gvm_server_vsendf_quiet(gnutls_session_t *session, const char *fmt, va_list ap)
Send a string to the server, refraining from logging besides warnings.
Definition: serverutils.c:795
cert_priv_mem
static char * cert_priv_mem
Definition: serverutils.c:215
host_type
host_type
Definition: hosts.h:36
gvm_server_sendf_xml_quiet
int gvm_server_sendf_xml_quiet(gnutls_session_t *session, const char *format,...)
Format and send an XML string to the server.
Definition: serverutils.c:960
gvm_socket_vsendf
int gvm_socket_vsendf(int socket, const char *fmt, va_list ap)
Send a string to the server.
Definition: serverutils.c:764
serverutils.h
GnuTLS based functions for server communication - header file.
gvm_server_attach
int gvm_server_attach(int socket, gnutls_session_t *session)
Attach a socket to a session, and shake hands with the peer.
Definition: serverutils.c:591
set_gnutls_dhparams
int set_gnutls_dhparams(gnutls_certificate_credentials_t creds, const char *dhparams_file)
Set a gnutls session's Diffie-Hellman parameters.
Definition: serverutils.c:1249
server_new_gnutls_set
static int server_new_gnutls_set(unsigned int end_type, const char *priority, gnutls_session_t *server_session, gnutls_certificate_credentials_t *server_credentials)
Set the server credencials.
Definition: serverutils.c:1042
get_cert_priv_mem
static const char * get_cert_priv_mem()
Get private certificate from cert_priv_mem.
Definition: serverutils.c:249
gvm_server_sendf
int gvm_server_sendf(gnutls_session_t *session, const char *format,...)
Format and send a string to the server.
Definition: serverutils.c:825
gvm_server_sendf_quiet
int gvm_server_sendf_quiet(gnutls_session_t *session, const char *format,...)
Format and send a string to the server.
Definition: serverutils.c:865
gvm_connection_sendf_quiet
int gvm_connection_sendf_quiet(gvm_connection_t *connection, const char *format,...)
Format and send a string to the server.
Definition: serverutils.c:885
HOST_TYPE_NAME
@ HOST_TYPE_NAME
Definition: hosts.h:38
address
struct sockaddr_in address
Server address.
Definition: serverutils.c:57
gvm_connection_t::session
gnutls_session_t session
Session.
Definition: serverutils.h:47
gvm_connection_t
Connection.
Definition: serverutils.h:43
gvm_connection_vsendf
int gvm_connection_vsendf(gvm_connection_t *connection, const char *fmt, va_list ap)
Send a string to the server.
Definition: serverutils.c:779
set_cert_priv_mem
static void set_cert_priv_mem(const char *data)
Save cert_priv_mem with private certificate.
Definition: serverutils.c:236
set_cert_pub_mem
static void set_cert_pub_mem(const char *data)
Save cert_pub_mem with public certificate.
Definition: serverutils.c:223