Greenbone Vulnerability Management Libraries  10.0.0
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 
221 static void
222 set_cert_pub_mem (const char *data)
223 {
224  if (cert_pub_mem)
225  g_free (cert_pub_mem);
226  cert_pub_mem = g_strdup (data);
227 }
228 
233 static void
234 set_cert_priv_mem (const char *data)
235 {
236  if (cert_priv_mem)
237  g_free (cert_priv_mem);
238  cert_priv_mem = g_strdup (data);
239 }
240 
245 static const char *
247 {
248  return cert_priv_mem;
249 }
250 
255 static const char *
257 {
258  return cert_pub_mem;
259 }
260 
274 static int
275 client_cert_callback (gnutls_session_t session,
276  const gnutls_datum_t *req_ca_rdn, int nreqs,
277  const gnutls_pk_algorithm_t *sign_algos,
278  int sign_algos_length, gnutls_retr2_st *st)
279 {
280  int ret;
281  gnutls_datum_t data;
282  static gnutls_x509_crt_t crt;
283  static gnutls_x509_privkey_t key;
284 
285  (void) session;
286  (void) req_ca_rdn;
287  (void) nreqs;
288  (void) sign_algos;
289  (void) sign_algos_length;
290  data.data = (unsigned char *) g_strdup (get_cert_pub_mem ());
291  data.size = strlen (get_cert_pub_mem ());
292  gnutls_x509_crt_init (&crt);
293  ret = gnutls_x509_crt_import (crt, &data, GNUTLS_X509_FMT_PEM);
294  g_free (data.data);
295  if (ret)
296  return ret;
297  st->cert.x509 = &crt;
298  st->cert_type = GNUTLS_CRT_X509;
299  st->ncerts = 1;
300 
301  data.data = (unsigned char *) g_strdup (get_cert_priv_mem ());
302  data.size = strlen (get_cert_priv_mem ());
303  gnutls_x509_privkey_init (&key);
304  ret = gnutls_x509_privkey_import (key, &data, GNUTLS_X509_FMT_PEM);
305  g_free (data.data);
306  if (ret)
307  return ret;
308  st->key.x509 = key;
309  st->key_type = GNUTLS_PRIVKEY_X509;
310  return 0;
311 }
312 
326 int
327 gvm_server_open_verify (gnutls_session_t *session, const char *host, int port,
328  const char *ca_mem, const char *pub_mem,
329  const char *priv_mem, int verify)
330 {
331  int ret;
332  int server_socket;
333  struct addrinfo address_hints;
334  struct addrinfo *addresses, *address;
335  gchar *port_string;
336  int host_type;
337 
338  gnutls_certificate_credentials_t credentials;
339 
340  /* Ensure that host and port have sane values. */
341  if (port < 1 || port > 65535)
342  {
343  g_warning ("Failed to create client TLS session. "
344  "Invalid port %d",
345  port);
346  return -1;
347  }
348  host_type = gvm_get_host_type (host);
350  || host_type == HOST_TYPE_IPV6))
351  {
352  g_warning ("Failed to create client TLS session. Invalid host %s", host);
353  return -1;
354  }
355 
359  if (gvm_server_new_mem (GNUTLS_CLIENT, ca_mem, pub_mem, priv_mem, session,
360  &credentials))
361  {
362  g_warning ("Failed to create client TLS session.");
363  return -1;
364  }
365 
366  if (ca_mem && pub_mem && priv_mem)
367  {
368  set_cert_pub_mem (pub_mem);
369  set_cert_priv_mem (priv_mem);
370 
371  gnutls_certificate_set_retrieve_function (credentials,
373  }
374 
375  /* Create the port string. */
376 
377  port_string = g_strdup_printf ("%i", port);
378 
379  /* Get all possible addresses. */
380 
381  memset (&address_hints, 0, sizeof (address_hints));
382  address_hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6. */
383  address_hints.ai_socktype = SOCK_STREAM;
384  address_hints.ai_protocol = 0;
385 
386  if (getaddrinfo (host, port_string, &address_hints, &addresses))
387  {
388  g_free (port_string);
389  g_warning ("Failed to get server addresses for %s: %s", host,
390  gai_strerror (errno));
391  gnutls_deinit (*session);
392  gnutls_certificate_free_credentials (credentials);
393  return -1;
394  }
395  g_free (port_string);
396 
397  /* Try to connect to each address in turn. */
398 
399  for (address = addresses; address; address = address->ai_next)
400  {
401  /* Make server socket. */
402 
403  if (address->ai_family == AF_INET6)
404  server_socket = socket (PF_INET6, SOCK_STREAM, 0);
405  else
406  server_socket = socket (PF_INET, SOCK_STREAM, 0);
407  if (server_socket == -1)
408  {
409  g_warning ("Failed to create server socket");
410  freeaddrinfo (addresses);
411  gnutls_deinit (*session);
412  gnutls_certificate_free_credentials (credentials);
413  return -1;
414  }
415 
416  /* Connect to server. */
417 
418  if (connect (server_socket, address->ai_addr, address->ai_addrlen) == -1)
419  {
420  close (server_socket);
421  continue;
422  }
423  break;
424  }
425 
426  freeaddrinfo (addresses);
427 
428  if (address == NULL)
429  {
430  g_warning ("Failed to connect to server");
431  gnutls_deinit (*session);
432  gnutls_certificate_free_credentials (credentials);
433  return -1;
434  }
435 
436  g_debug (" Connected to server '%s' port %d.", host, port);
437 
438  /* Complete setup of server session. */
439  ret = server_attach_internal (server_socket, session, host, port);
440  if (ret)
441  {
442  if (ret == -2)
443  {
444  close (server_socket);
445  gnutls_deinit (*session);
446  gnutls_certificate_free_credentials (credentials);
447  }
448  close (server_socket);
449  return -1;
450  }
451  if (verify && gvm_server_verify (*session))
452  {
453  close (server_socket);
454  return -1;
455  }
456 
457  return server_socket;
458 }
459 
474 int
475 gvm_server_open_with_cert (gnutls_session_t *session, const char *host,
476  int port, const char *ca_mem, const char *pub_mem,
477  const char *priv_mem)
478 {
479  return gvm_server_open_verify (session, host, port, ca_mem, pub_mem, priv_mem,
480  ca_mem && pub_mem && priv_mem);
481 }
482 
492 int
493 gvm_server_open (gnutls_session_t *session, const char *host, int port)
494 {
495  return gvm_server_open_with_cert (session, host, port, NULL, NULL, NULL);
496 }
497 
506 int
507 gvm_server_close (int socket, gnutls_session_t session)
508 {
509  return gvm_server_free (socket, session, NULL);
510 }
511 
519 void
521 {
522  gvm_connection_free (connection);
523 }
524 
536 static int
537 server_attach_internal (int socket, gnutls_session_t *session, const char *host,
538  int port)
539 {
540  unsigned int retries;
541 
542  gnutls_transport_set_ptr (*session,
543  (gnutls_transport_ptr_t) GSIZE_TO_POINTER (socket));
544 
545  retries = 0;
546  while (1)
547  {
548  int ret = gnutls_handshake (*session);
549  if (ret >= 0)
550  break;
551  if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
552  {
553  if (retries > 10)
554  usleep (MIN ((retries - 10) * 10000, 5000000));
555  retries++;
556  continue;
557  }
558  if (host)
559  g_debug ("Failed to shake hands with server '%s' port %d: %s", host,
560  port, gnutls_strerror (ret));
561  else
562  g_debug ("Failed to shake hands with peer: %s", gnutls_strerror (ret));
563  if (shutdown (socket, SHUT_RDWR) == -1)
564  g_debug ("Failed to shutdown server socket");
565  return -2;
566  }
567  if (host)
568  g_debug (" Shook hands with server '%s' port %d.", host, port);
569  else
570  g_debug (" Shook hands with peer.");
571 
572  return 0;
573 }
574 
584 int
585 gvm_server_attach (int socket, gnutls_session_t *session)
586 {
587  int ret;
588 
589  ret = server_attach_internal (socket, session, NULL, 0);
590  return ret ? -1 : 0;
591 }
592 
604 static int
605 gvm_server_vsendf_internal (gnutls_session_t *session, const char *fmt,
606  va_list ap, int quiet)
607 {
608  char *sref, *string;
609  int rc = 0, left;
610 
611  left = vasprintf (&string, fmt, ap);
612  if (left == -1)
613  string = NULL;
614 
615  sref = string;
616  while (left > 0)
617  {
618  ssize_t count;
619 
620  if (quiet == 0)
621  g_debug (" send %d from %.*s[...]", left, left < 30 ? left : 30,
622  string);
623  count = gnutls_record_send (*session, string, left);
624  if (count < 0)
625  {
626  if (count == GNUTLS_E_INTERRUPTED)
627  /* Interrupted, try write again. */
628  continue;
629  if (count == GNUTLS_E_REHANDSHAKE)
630  {
631  /* \todo Rehandshake. */
632  if (quiet == 0)
633  g_message (" %s rehandshake", __FUNCTION__);
634  continue;
635  }
636  g_warning ("Failed to write to server: %s", gnutls_strerror (count));
637  rc = -1;
638  goto out;
639  }
640  if (count == 0)
641  {
642  /* Server closed connection. */
643  if (quiet == 0)
644  g_debug ("= server closed");
645  rc = 1;
646  goto out;
647  }
648  if (quiet == 0)
649  g_debug ("=> %.*s", (int) count, string);
650  string += count;
651  left -= count;
652  }
653  if (quiet == 0)
654  g_debug ("=> done");
655 
656 out:
657  g_free (sref);
658  return rc;
659 }
660 
672 static int
673 unix_vsendf_internal (int socket, const char *fmt, va_list ap, int quiet)
674 {
675  char *string_start, *string;
676  int rc = 0, left;
677 
678  left = vasprintf (&string, fmt, ap);
679  if (left == -1)
680  string = NULL;
681 
682  string_start = string;
683  while (left > 0)
684  {
685  ssize_t count;
686 
687  if (quiet == 0)
688  g_debug (" send %d from %.*s[...]", left, left < 30 ? left : 30,
689  string);
690  count = write (socket, string, left);
691  if (count < 0)
692  {
693  if (errno == EINTR || errno == EAGAIN)
694  continue;
695  g_warning ("Failed to write to server: %s", strerror (errno));
696  rc = -1;
697  goto out;
698  }
699  if (quiet == 0)
700  g_debug ("=> %.*s", (int) count, string);
701 
702  string += count;
703  left -= count;
704  }
705  if (quiet == 0)
706  g_debug ("=> done");
707 
708 out:
709  g_free (string_start);
710  return rc;
711 }
712 
724 static int
725 gvm_connection_vsendf_internal (gvm_connection_t *connection, const char *fmt,
726  va_list ap, int quiet)
727 {
728  if (connection->tls)
729  return gvm_server_vsendf_internal (&connection->session, fmt, ap, quiet);
730  return unix_vsendf_internal (connection->socket, fmt, ap, quiet);
731 }
732 
742 int
743 gvm_server_vsendf (gnutls_session_t *session, const char *fmt, va_list ap)
744 {
745  return gvm_server_vsendf_internal (session, fmt, ap, 0);
746 }
747 
757 int
758 gvm_socket_vsendf (int socket, const char *fmt, va_list ap)
759 {
760  return unix_vsendf_internal (socket, fmt, ap, 0);
761 }
762 
772 int
773 gvm_connection_vsendf (gvm_connection_t *connection, const char *fmt,
774  va_list ap)
775 {
776  return gvm_connection_vsendf_internal (connection, fmt, ap, 0);
777 }
778 
788 int
789 gvm_server_vsendf_quiet (gnutls_session_t *session, const char *fmt, va_list ap)
790 {
791  return gvm_server_vsendf_internal (session, fmt, ap, 1);
792 }
793 
803 int
804 gvm_connection_vsendf_quiet (gvm_connection_t *connection, const char *fmt,
805  va_list ap)
806 {
807  return gvm_connection_vsendf_internal (connection, fmt, ap, 1);
808 }
809 
818 int
819 gvm_server_sendf (gnutls_session_t *session, const char *format, ...)
820 {
821  va_list ap;
822  int rc;
823 
824  va_start (ap, format);
825  rc = gvm_server_vsendf (session, format, ap);
826  va_end (ap);
827  return rc;
828 }
829 
838 int
839 gvm_connection_sendf (gvm_connection_t *connection, const char *format, ...)
840 {
841  va_list ap;
842  int rc;
843 
844  va_start (ap, format);
845  rc = gvm_connection_vsendf (connection, format, ap);
846  va_end (ap);
847  return rc;
848 }
849 
858 int
859 gvm_server_sendf_quiet (gnutls_session_t *session, const char *format, ...)
860 {
861  va_list ap;
862  int rc;
863 
864  va_start (ap, format);
865  rc = gvm_server_vsendf_quiet (session, format, ap);
866  va_end (ap);
867  return rc;
868 }
869 
878 int
879 gvm_connection_sendf_quiet (gvm_connection_t *connection, const char *format,
880  ...)
881 {
882  va_list ap;
883  int rc;
884 
885  va_start (ap, format);
886  rc = gvm_connection_vsendf_quiet (connection, format, ap);
887  va_end (ap);
888  return rc;
889 }
890 
901 int
902 gvm_server_sendf_xml (gnutls_session_t *session, const char *format, ...)
903 {
904  va_list ap;
905  gchar *msg;
906  int rc;
907 
908  va_start (ap, format);
909  msg = g_markup_vprintf_escaped (format, ap);
910  rc = gvm_server_sendf (session, "%s", msg);
911  g_free (msg);
912  va_end (ap);
913  return rc;
914 }
915 
926 int
927 gvm_connection_sendf_xml (gvm_connection_t *connection, const char *format, ...)
928 {
929  va_list ap;
930  gchar *msg;
931  int rc;
932 
933  va_start (ap, format);
934  msg = g_markup_vprintf_escaped (format, ap);
935  rc = gvm_connection_sendf (connection, "%s", msg);
936  g_free (msg);
937  va_end (ap);
938  return rc;
939 }
940 
953 int
954 gvm_server_sendf_xml_quiet (gnutls_session_t *session, const char *format, ...)
955 {
956  va_list ap;
957  gchar *msg;
958  int rc;
959 
960  va_start (ap, format);
961  msg = g_markup_vprintf_escaped (format, ap);
962  rc = gvm_server_sendf_quiet (session, "%s", msg);
963  g_free (msg);
964  va_end (ap);
965  return rc;
966 }
967 
980 int
982  const char *format, ...)
983 {
984  va_list ap;
985  gchar *msg;
986  int rc;
987 
988  va_start (ap, format);
989  msg = g_markup_vprintf_escaped (format, ap);
990  rc = gvm_connection_sendf_quiet (connection, "%s", msg);
991  g_free (msg);
992  va_end (ap);
993  return rc;
994 }
995 
1001 static int
1002 server_new_gnutls_init (gnutls_certificate_credentials_t *server_credentials)
1003 {
1004  /* Turn off use of /dev/random, as this can block. */
1005  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
1006 
1007  /* Initialize security library. */
1008  if (gnutls_global_init ())
1009  {
1010  g_warning ("Failed to initialize GNUTLS.");
1011  return -1;
1012  }
1013  /* Setup server session. */
1014  if (gnutls_certificate_allocate_credentials (server_credentials))
1015  {
1016  g_warning ("%s: failed to allocate server credentials\n", __FUNCTION__);
1017  return -1;
1018  }
1019  return 0;
1020 }
1021 
1031 static int
1032 server_new_gnutls_set (unsigned int end_type, const char *priority,
1033  gnutls_session_t *server_session,
1034  gnutls_certificate_credentials_t *server_credentials)
1035 {
1036  int err_gnutls;
1037 
1038  if (gnutls_init (server_session, end_type))
1039  {
1040  g_warning ("%s: failed to initialise server session\n", __FUNCTION__);
1041  return -1;
1042  }
1043 
1044  /* Depending on gnutls version different priority strings are
1045  possible. At least from 3.0 this is an option:
1046  "NONE:+VERS-TLS1.0:+CIPHER-ALL:+COMP-ALL:+RSA:+DHE-RSA:+DHE-DSS:+MAC-ALL"
1047  But in fact this function is only for internal
1048  purposes, not for scanning abilities. So, the conservative "NORMAL"
1049  is chosen.
1050  */
1051 
1052  if ((err_gnutls = gnutls_priority_set_direct (
1053  *server_session, priority ? priority : "NORMAL", NULL)))
1054  {
1055  g_warning ("%s: failed to set tls priorities: %s\n", __FUNCTION__,
1056  gnutls_strerror (err_gnutls));
1057  gnutls_deinit (*server_session);
1058  return -1;
1059  }
1060 
1061  if (gnutls_credentials_set (*server_session, GNUTLS_CRD_CERTIFICATE,
1062  *server_credentials))
1063  {
1064  g_warning ("%s: failed to set server credentials\n", __FUNCTION__);
1065  gnutls_deinit (*server_session);
1066  return -1;
1067  }
1068 
1069  if (end_type == GNUTLS_SERVER)
1070  gnutls_certificate_server_set_request (*server_session,
1071  GNUTLS_CERT_REQUEST);
1072  return 0;
1073 }
1074 
1089 static int
1090 server_new_internal (unsigned int end_type, const char *priority,
1091  const gchar *ca_cert_file, const gchar *cert_file,
1092  const gchar *key_file, gnutls_session_t *server_session,
1093  gnutls_certificate_credentials_t *server_credentials)
1094 {
1095  if (server_new_gnutls_init (server_credentials))
1096  return -1;
1097 
1098  if (cert_file && key_file)
1099  {
1100  int ret;
1101 
1102  ret = gnutls_certificate_set_x509_key_file (
1103  *server_credentials, cert_file, key_file, GNUTLS_X509_FMT_PEM);
1104  if (ret < 0)
1105  {
1106  g_warning ("%s: failed to set credentials key file: %s\n",
1107  __FUNCTION__, gnutls_strerror (ret));
1108  g_warning ("%s: cert file: %s\n", __FUNCTION__, cert_file);
1109  g_warning ("%s: key file : %s\n", __FUNCTION__, key_file);
1110  gnutls_certificate_free_credentials (*server_credentials);
1111  return -1;
1112  }
1113  }
1114 
1115  if (ca_cert_file)
1116  {
1117  int ret;
1118 
1119  ret = gnutls_certificate_set_x509_trust_file (
1120  *server_credentials, ca_cert_file, GNUTLS_X509_FMT_PEM);
1121  if (ret < 0)
1122  {
1123  g_warning ("%s: failed to set credentials trust file: %s\n",
1124  __FUNCTION__, gnutls_strerror (ret));
1125  g_warning ("%s: trust file: %s\n", __FUNCTION__, ca_cert_file);
1126  gnutls_certificate_free_credentials (*server_credentials);
1127  return -1;
1128  }
1129  }
1130 
1131  if (server_new_gnutls_set (end_type, priority, server_session,
1132  server_credentials))
1133  {
1134  gnutls_certificate_free_credentials (*server_credentials);
1135  return -1;
1136  }
1137 
1138  return 0;
1139 }
1140 
1154 int
1155 gvm_server_new (unsigned int end_type, gchar *ca_cert_file, gchar *cert_file,
1156  gchar *key_file, gnutls_session_t *server_session,
1157  gnutls_certificate_credentials_t *server_credentials)
1158 {
1159  return server_new_internal (end_type, NULL, ca_cert_file, cert_file, key_file,
1160  server_session, server_credentials);
1161 }
1162 
1176 int
1177 gvm_server_new_mem (unsigned int end_type, const char *ca_cert,
1178  const char *pub_key, const char *priv_key,
1179  gnutls_session_t *session,
1180  gnutls_certificate_credentials_t *credentials)
1181 {
1182  if (server_new_gnutls_init (credentials))
1183  return -1;
1184 
1185  if (pub_key && priv_key)
1186  {
1187  int ret;
1188  gnutls_datum_t pub, priv;
1189 
1190  pub.data = (void *) pub_key;
1191  pub.size = strlen (pub_key);
1192  priv.data = (void *) priv_key;
1193  priv.size = strlen (priv_key);
1194 
1195  ret = gnutls_certificate_set_x509_key_mem (*credentials, &pub, &priv,
1196  GNUTLS_X509_FMT_PEM);
1197  if (ret < 0)
1198  {
1199  g_warning ("%s: %s\n", __FUNCTION__, gnutls_strerror (ret));
1200  return -1;
1201  }
1202  }
1203 
1204  if (ca_cert)
1205  {
1206  int ret;
1207  gnutls_datum_t data;
1208 
1209  data.data = (void *) ca_cert;
1210  data.size = strlen (ca_cert);
1211  ret = gnutls_certificate_set_x509_trust_mem (*credentials, &data,
1212  GNUTLS_X509_FMT_PEM);
1213  if (ret < 0)
1214  {
1215  g_warning ("%s: %s\n", __FUNCTION__, gnutls_strerror (ret));
1216  gnutls_certificate_free_credentials (*credentials);
1217  return -1;
1218  }
1219  }
1220 
1221  if (server_new_gnutls_set (end_type, NULL, session, credentials))
1222  {
1223  gnutls_certificate_free_credentials (*credentials);
1224  return -1;
1225  }
1226 
1227  return 0;
1228 }
1229 
1238 int
1239 set_gnutls_dhparams (gnutls_certificate_credentials_t creds,
1240  const char *dhparams_file)
1241 {
1242  int ret;
1243  gnutls_datum_t data;
1244 
1245  if (!creds || !dhparams_file)
1246  return -1;
1247 
1248  if (load_gnutls_file (dhparams_file, &data))
1249  return -1;
1250  gnutls_dh_params_t params = g_malloc0 (sizeof (gnutls_dh_params_t));
1251  ret = gnutls_dh_params_import_pkcs3 (params, &data, GNUTLS_X509_FMT_PEM);
1252  unload_gnutls_file (&data);
1253  if (ret)
1254  return -1;
1255  else
1256  gnutls_certificate_set_dh_params (creds, params);
1257  return 0;
1258 }
1259 
1272 int
1273 gvm_server_free (int server_socket, gnutls_session_t server_session,
1274  gnutls_certificate_credentials_t server_credentials)
1275 {
1276  /* Turn off blocking. */
1277  // FIX get flags first
1278  if (fcntl (server_socket, F_SETFL, O_NONBLOCK) == -1)
1279  {
1280  g_warning ("%s: failed to set server socket flag: %s\n", __FUNCTION__,
1281  strerror (errno));
1282  return -1;
1283  }
1284 
1285  while (1)
1286  {
1287  int ret = gnutls_bye (server_session, GNUTLS_SHUT_WR);
1288  if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
1289  {
1290  continue;
1291  }
1292  if (ret)
1293  {
1294  g_debug (" Failed to gnutls_bye: %s\n",
1295  gnutls_strerror ((int) ret));
1296  /* Carry on successfully anyway, as this often fails, perhaps
1297  * because the server is closing the connection first. */
1298  break;
1299  }
1300  break;
1301  }
1302 
1303  /* The former separate code in gvm_server_close and here
1304  differed in the order the TLS session and socket was closed. The
1305  way we do it here seems to be the right thing but for full
1306  backward compatibility we do it for calls from
1307  gvm_server_close in the old way. We can distinguish the two
1308  modes by the existence of server_credentials. */
1309  if (server_credentials)
1310  {
1311  if (close (server_socket) == -1)
1312  {
1313  g_warning ("%s: failed to close server socket: %s\n", __FUNCTION__,
1314  strerror (errno));
1315  return -1;
1316  }
1317  gnutls_deinit (server_session);
1318  gnutls_certificate_free_credentials (server_credentials);
1319  }
1320  else
1321  {
1322  gnutls_deinit (server_session);
1323  close (server_socket);
1324  }
1325 
1326  gnutls_global_deinit ();
1327 
1328  return 0;
1329 }
static char * cert_pub_mem
Definition: serverutils.c:214
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:537
void gvm_connection_close(gvm_connection_t *connection)
Close a server connection and its socket.
Definition: serverutils.c:520
static int close_unix(gvm_connection_t *client_connection)
Close UNIX socket connection.
Definition: serverutils.c:76
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:725
gnutls_session_t session
Session.
Definition: serverutils.h:47
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
static const char * get_cert_pub_mem()
Get public certificate from cert_pub_mem.
Definition: serverutils.c:256
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:954
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:1090
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:1032
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:1273
int gvm_connection_sendf(gvm_connection_t *connection, const char *format,...)
Format and send a string to the server.
Definition: serverutils.c:839
static int unix_vsendf_internal(int socket, const char *fmt, va_list ap, int quiet)
Send a string to the server.
Definition: serverutils.c:673
int socket
Socket.
Definition: serverutils.h:46
int gvm_get_host_type(const gchar *str_stripped)
Determines the host type in a buffer.
Definition: hosts.c:768
static char * cert_priv_mem
Definition: serverutils.c:215
int gvm_connection_sendf_xml(gvm_connection_t *connection, const char *format,...)
Format and send an XML string to the server.
Definition: serverutils.c:927
static void set_cert_priv_mem(const char *data)
Save cert_priv_mem with private certificate.
Definition: serverutils.c:234
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:605
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:981
int gvm_socket_vsendf(int socket, const char *fmt, va_list ap)
Send a string to the server.
Definition: serverutils.c:758
void gvm_connection_free(gvm_connection_t *client_connection)
Free connection.
Definition: serverutils.c:111
int gvm_server_verify(gnutls_session_t session)
Verify certificate.
Definition: serverutils.c:130
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:493
static int server_new_gnutls_init(gnutls_certificate_credentials_t *server_credentials)
Initialize a server session.
Definition: serverutils.c:1002
int gvm_server_sendf_quiet(gnutls_session_t *session, const char *format,...)
Format and send a string to the server.
Definition: serverutils.c:859
int gvm_connection_sendf_quiet(gvm_connection_t *connection, const char *format,...)
Format and send a string to the server.
Definition: serverutils.c:879
int gvm_server_sendf_xml(gnutls_session_t *session, const char *format,...)
Format and send an XML string to the server.
Definition: serverutils.c:902
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:804
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:1155
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:1177
int set_gnutls_dhparams(gnutls_certificate_credentials_t creds, const char *dhparams_file)
Set a gnutls session's Diffie-Hellman parameters.
Definition: serverutils.c:1239
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:327
static const char * get_cert_priv_mem()
Get private certificate from cert_priv_mem.
Definition: serverutils.c:246
struct sockaddr_in address
Server address.
Definition: serverutils.c:57
host_type
Definition: hosts.h:36
int gvm_connection_vsendf(gvm_connection_t *connection, const char *fmt, va_list ap)
Send a string to the server.
Definition: serverutils.c:773
Connection.
Definition: serverutils.h:43
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:475
int tls
Whether uses TCP-TLS (vs UNIX socket).
Definition: serverutils.h:45
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:275
int gvm_server_close(int socket, gnutls_session_t session)
Close a server connection and its socket.
Definition: serverutils.c:507
int gvm_server_vsendf(gnutls_session_t *session, const char *fmt, va_list ap)
Send a string to the server.
Definition: serverutils.c:743
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:789
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:585
gnutls_certificate_credentials_t credentials
Credentials.
Definition: serverutils.h:48
int gvm_server_sendf(gnutls_session_t *session, const char *format,...)
Format and send a string to the server.
Definition: serverutils.c:819
static void set_cert_pub_mem(const char *data)
Save cert_pub_mem with public certificate.
Definition: serverutils.c:222
GnuTLS based functions for server communication - header file.
void unload_gnutls_file(gnutls_datum_t *data)
Unloads a gnutls_datum_t struct's data.
Definition: serverutils.c:208