Greenbone Vulnerability Management Libraries  22.8.0
serverutils.c
Go to the documentation of this file.
1 /* SPDX-FileCopyrightText: 2009-2023 Greenbone AG
2  *
3  * SPDX-License-Identifier: GPL-2.0-or-later
4  */
5 
14 #define _GNU_SOURCE
15 
16 #include "serverutils.h"
17 
18 #include "../base/hosts.h" /* for is_hostname, is_ipv4_address, is_ipv6_add.. */
19 
20 #include <arpa/inet.h>
21 #include <errno.h> /* for errno, ENOTCONN, EAGAIN */
22 #include <fcntl.h> /* for fcntl, F_SETFL, O_NONBLOCK */
23 #include <gcrypt.h> /* for gcry_control */
24 #include <glib.h> /* for g_warning, g_free, g_debug, gchar, g_markup... */
25 #include <gnutls/x509.h> /* for gnutls_x509_crt_..., gnutls_x509_privkey_... */
26 #include <netdb.h> /* for addrinfo, freeaddrinfo, gai_strerror, getad... */
27 #include <signal.h> /* for sigaction, SIGPIPE, sigemptyset, SIG_IGN */
28 #include <stdio.h> /* for fclose, FILE, SEEK_END, SEEK_SET */
29 #include <string.h> /* for strerror, strlen, memset */
30 #include <sys/socket.h> /* for shutdown, connect, socket, SHUT_RDWR, SOCK_... */
31 #include <sys/types.h>
32 #include <unistd.h> /* for close, ssize_t, usleep */
33 
34 #undef G_LOG_DOMAIN
35 
38 #define G_LOG_DOMAIN "libgvm util"
39 
40 static int
41 server_attach_internal (int, gnutls_session_t *, const char *, int);
42 static int
43 server_new_internal (unsigned int, const char *, const gchar *, const gchar *,
44  const gchar *, gnutls_session_t *,
45  gnutls_certificate_credentials_t *);
46 
47 /* Connections. */
48 
56 static int
57 close_unix (gvm_connection_t *client_connection)
58 {
59  /* Turn off blocking. */
60  if (fcntl (client_connection->socket, F_SETFL, O_NONBLOCK) == -1)
61  {
62  g_warning ("%s: failed to set server socket flag: %s\n", __func__,
63  strerror (errno));
64  return -1;
65  }
66 
67  if (shutdown (client_connection->socket, SHUT_RDWR) == -1)
68  {
69  if (errno == ENOTCONN)
70  return 0;
71  g_warning ("%s: failed to shutdown server socket: %s\n", __func__,
72  strerror (errno));
73  return -1;
74  }
75 
76  if (close (client_connection->socket) == -1)
77  {
78  g_warning ("%s: failed to close server socket: %s\n", __func__,
79  strerror (errno));
80  return -1;
81  }
82 
83  return 0;
84 }
85 
91 void
93 {
94  if (client_connection->tls)
95  gvm_server_free (client_connection->socket, client_connection->session,
96  client_connection->credentials);
97  else
98  close_unix (client_connection);
99 }
100 
101 /* Certificate verification. */
102 
110 int
111 gvm_server_verify (gnutls_session_t session)
112 {
113  unsigned int status;
114  int ret;
115 
116  ret = gnutls_certificate_verify_peers2 (session, &status);
117  if (ret < 0)
118  {
119  g_warning ("%s: failed to verify peers: %s", __func__,
120  gnutls_strerror (ret));
121  return -1;
122  }
123 
124  if (status & GNUTLS_CERT_INVALID)
125  g_warning ("%s: the certificate is not trusted", __func__);
126 
127  if (status & GNUTLS_CERT_SIGNER_NOT_CA)
128  g_warning ("%s: the certificate's issuer is not a CA", __func__);
129 
130  if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
131  g_warning ("%s: the certificate was signed using an insecure algorithm",
132  __func__);
133 
134  if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
135  g_warning ("%s: the certificate hasn't got a known issuer", __func__);
136 
137  if (status & GNUTLS_CERT_REVOKED)
138  g_warning ("%s: the certificate has been revoked", __func__);
139 
140  if (status & GNUTLS_CERT_EXPIRED)
141  g_warning ("%s: the certificate has expired", __func__);
142 
143  if (status & GNUTLS_CERT_NOT_ACTIVATED)
144  g_warning ("%s: the certificate is not yet activated", __func__);
145 
146  if (status)
147  return 1;
148 
149  return 0;
150 }
151 
160 int
161 load_gnutls_file (const char *file, gnutls_datum_t *loaded_file)
162 {
163  FILE *f = NULL;
164  int64_t filelen;
165  void *ptr;
166 
167  if (!(f = fopen (file, "r")) || fseek (f, 0, SEEK_END) != 0
168  || (filelen = ftell (f)) < 0 || fseek (f, 0, SEEK_SET) != 0
169  || !(ptr = g_malloc0 ((size_t) filelen))
170  || fread (ptr, 1, (size_t) filelen, f) < (size_t) filelen)
171  {
172  if (f)
173  fclose (f);
174  return -1;
175  }
176 
177  loaded_file->data = ptr;
178  loaded_file->size = filelen;
179  fclose (f);
180  return 0;
181 }
182 
188 void
189 unload_gnutls_file (gnutls_datum_t *data)
190 {
191  if (data)
192  g_free (data->data);
193 }
194 
195 static char *cert_pub_mem = NULL;
196 static char *cert_priv_mem = NULL;
197 
203 static void
204 set_cert_pub_mem (const char *data)
205 {
206  if (cert_pub_mem)
207  g_free (cert_pub_mem);
208  cert_pub_mem = g_strdup (data);
209 }
210 
216 static void
217 set_cert_priv_mem (const char *data)
218 {
219  if (cert_priv_mem)
220  g_free (cert_priv_mem);
221  cert_priv_mem = g_strdup (data);
222 }
223 
229 static const char *
231 {
232  return cert_priv_mem;
233 }
234 
240 static const char *
242 {
243  return cert_pub_mem;
244 }
245 
261 static int
262 client_cert_callback (gnutls_session_t session,
263  const gnutls_datum_t *req_ca_rdn, int nreqs,
264  const gnutls_pk_algorithm_t *sign_algos,
265  int sign_algos_length, gnutls_retr2_st *st)
266 {
267  int ret;
268  gnutls_datum_t data;
269  static gnutls_x509_crt_t crt;
270  static gnutls_x509_privkey_t key;
271 
272  (void) session;
273  (void) req_ca_rdn;
274  (void) nreqs;
275  (void) sign_algos;
276  (void) sign_algos_length;
277  data.data = (unsigned char *) g_strdup (get_cert_pub_mem ());
278  data.size = strlen (get_cert_pub_mem ());
279  gnutls_x509_crt_init (&crt);
280  ret = gnutls_x509_crt_import (crt, &data, GNUTLS_X509_FMT_PEM);
281  g_free (data.data);
282  if (ret)
283  return ret;
284  st->cert.x509 = &crt;
285  st->cert_type = GNUTLS_CRT_X509;
286  st->ncerts = 1;
287 
288  data.data = (unsigned char *) g_strdup (get_cert_priv_mem ());
289  data.size = strlen (get_cert_priv_mem ());
290  gnutls_x509_privkey_init (&key);
291  ret = gnutls_x509_privkey_import (key, &data, GNUTLS_X509_FMT_PEM);
292  g_free (data.data);
293  if (ret)
294  return ret;
295  st->key.x509 = key;
296  st->key_type = GNUTLS_PRIVKEY_X509;
297  return 0;
298 }
299 
313 int
314 gvm_server_open_verify (gnutls_session_t *session, const char *host, int port,
315  const char *ca_mem, const char *pub_mem,
316  const char *priv_mem, int verify)
317 {
318  int ret;
319  int server_socket;
320  struct addrinfo address_hints;
321  struct addrinfo *addresses, *address;
322  gchar *port_string;
323  int host_type;
324 
325  gnutls_certificate_credentials_t credentials;
326 
327  /* Ensure that host and port have sane values. */
328  if (port < 1 || port > 65535)
329  {
330  g_warning ("Failed to create client TLS session. "
331  "Invalid port %d",
332  port);
333  return -1;
334  }
335  host_type = gvm_get_host_type (host);
337  || host_type == HOST_TYPE_IPV6))
338  {
339  g_warning ("Failed to create client TLS session. Invalid host %s", host);
340  return -1;
341  }
342 
346  if (gvm_server_new_mem (GNUTLS_CLIENT, ca_mem, pub_mem, priv_mem, session,
347  &credentials))
348  {
349  g_warning ("Failed to create client TLS session.");
350  return -1;
351  }
352 
353  if (ca_mem && pub_mem && priv_mem)
354  {
355  set_cert_pub_mem (pub_mem);
356  set_cert_priv_mem (priv_mem);
357 
358  gnutls_certificate_set_retrieve_function (credentials,
360  }
361 
362  /* Create the port string. */
363 
364  port_string = g_strdup_printf ("%i", port);
365 
366  /* Get all possible addresses. */
367 
368  memset (&address_hints, 0, sizeof (address_hints));
369  address_hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6. */
370  address_hints.ai_socktype = SOCK_STREAM;
371  address_hints.ai_protocol = 0;
372 
373  if (getaddrinfo (host, port_string, &address_hints, &addresses))
374  {
375  g_free (port_string);
376  g_warning ("Failed to get server addresses for %s: %s", host,
377  gai_strerror (errno));
378  gnutls_deinit (*session);
379  gnutls_certificate_free_credentials (credentials);
380  return -1;
381  }
382  g_free (port_string);
383 
384  /* Try to connect to each address in turn. */
385 
386  for (address = addresses; address; address = address->ai_next)
387  {
388  /* Make server socket. */
389 
390  if (address->ai_family == AF_INET6)
391  server_socket = socket (PF_INET6, SOCK_STREAM, 0);
392  else
393  server_socket = socket (PF_INET, SOCK_STREAM, 0);
394  if (server_socket == -1)
395  {
396  g_warning ("Failed to create server socket");
397  freeaddrinfo (addresses);
398  gnutls_deinit (*session);
399  gnutls_certificate_free_credentials (credentials);
400  return -1;
401  }
402 
403  /* Connect to server. */
404 
405  if (connect (server_socket, address->ai_addr, address->ai_addrlen) == -1)
406  {
407  close (server_socket);
408  continue;
409  }
410  break;
411  }
412 
413  freeaddrinfo (addresses);
414 
415  if (address == NULL)
416  {
417  g_warning ("Failed to connect to server");
418  gnutls_deinit (*session);
419  gnutls_certificate_free_credentials (credentials);
420  return -1;
421  }
422 
423  g_debug (" Connected to server '%s' port %d.", host, port);
424 
425  /* Complete setup of server session. */
426  ret = server_attach_internal (server_socket, session, host, port);
427  if (ret)
428  {
429  if (ret == -2)
430  {
431  close (server_socket);
432  gnutls_deinit (*session);
433  gnutls_certificate_free_credentials (credentials);
434  }
435  close (server_socket);
436  return -1;
437  }
438  if (verify && gvm_server_verify (*session))
439  {
440  close (server_socket);
441  return -1;
442  }
443 
444  return server_socket;
445 }
446 
461 int
462 gvm_server_open_with_cert (gnutls_session_t *session, const char *host,
463  int port, const char *ca_mem, const char *pub_mem,
464  const char *priv_mem)
465 {
466  return gvm_server_open_verify (session, host, port, ca_mem, pub_mem, priv_mem,
467  ca_mem && pub_mem && priv_mem);
468 }
469 
479 int
480 gvm_server_open (gnutls_session_t *session, const char *host, int port)
481 {
482  return gvm_server_open_with_cert (session, host, port, NULL, NULL, NULL);
483 }
484 
493 int
494 gvm_server_close (int socket, gnutls_session_t session)
495 {
496  return gvm_server_free (socket, session, NULL);
497 }
498 
504 void
506 {
507  gvm_connection_free (connection);
508 }
509 
521 static int
522 server_attach_internal (int socket, gnutls_session_t *session, const char *host,
523  int port)
524 {
525  unsigned int retries;
526 
527  gnutls_transport_set_ptr (*session,
528  (gnutls_transport_ptr_t) GSIZE_TO_POINTER (socket));
529 
530  retries = 0;
531  while (1)
532  {
533  int ret = gnutls_handshake (*session);
534  if (ret >= 0)
535  break;
536  if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
537  {
538  if (retries > 10)
539  usleep (MIN ((retries - 10) * 10000, 5000000));
540  retries++;
541  continue;
542  }
543  if (host)
544  g_debug ("Failed to shake hands with server '%s' port %d: %s", host,
545  port, gnutls_strerror (ret));
546  else
547  g_debug ("Failed to shake hands with peer: %s", gnutls_strerror (ret));
548  if (shutdown (socket, SHUT_RDWR) == -1)
549  g_debug ("Failed to shutdown server socket");
550  return -2;
551  }
552  if (host)
553  g_debug (" Shook hands with server '%s' port %d.", host, port);
554  else
555  g_debug (" Shook hands with peer.");
556 
557  return 0;
558 }
559 
569 int
570 gvm_server_attach (int socket, gnutls_session_t *session)
571 {
572  int ret;
573 
574  ret = server_attach_internal (socket, session, NULL, 0);
575  return ret ? -1 : 0;
576 }
577 
589 static int
590 gvm_server_vsendf_internal (gnutls_session_t *session, const char *fmt,
591  va_list ap, int quiet)
592 {
593  char *sref, *string;
594  int rc = 0, left;
595 
596  left = vasprintf (&string, fmt, ap);
597  if (left == -1)
598  string = NULL;
599 
600  sref = string;
601  while (left > 0)
602  {
603  ssize_t count;
604 
605  if (quiet == 0)
606  g_debug (" send %d from %.*s[...]", left, left < 30 ? left : 30,
607  string);
608  count = gnutls_record_send (*session, string, left);
609  if (count < 0)
610  {
611  if (count == GNUTLS_E_INTERRUPTED)
612  /* Interrupted, try write again. */
613  continue;
614  if (count == GNUTLS_E_REHANDSHAKE)
615  {
616  /* \todo Rehandshake. */
617  if (quiet == 0)
618  g_message (" %s rehandshake", __func__);
619  continue;
620  }
621  g_warning ("Failed to write to server: %s", gnutls_strerror (count));
622  rc = -1;
623  goto out;
624  }
625  if (count == 0)
626  {
627  /* Server closed connection. */
628  if (quiet == 0)
629  g_debug ("= server closed");
630  rc = 1;
631  goto out;
632  }
633  if (quiet == 0)
634  g_debug ("=> %.*s", (int) count, string);
635  string += count;
636  left -= count;
637  }
638  if (quiet == 0)
639  g_debug ("=> done");
640 
641 out:
642  g_free (sref);
643  return rc;
644 }
645 
657 static int
658 unix_vsendf_internal (int socket, const char *fmt, va_list ap, int quiet)
659 {
660  char *string_start, *string;
661  int rc = 0, left;
662 
663  left = vasprintf (&string, fmt, ap);
664  if (left == -1)
665  string = NULL;
666 
667  string_start = string;
668  while (left > 0)
669  {
670  ssize_t count;
671 
672  if (quiet == 0)
673  g_debug (" send %d from %.*s[...]", left, left < 30 ? left : 30,
674  string);
675  count = write (socket, string, left);
676  if (count < 0)
677  {
678  if (errno == EINTR || errno == EAGAIN)
679  continue;
680  g_warning ("Failed to write to server: %s", strerror (errno));
681  rc = -1;
682  goto out;
683  }
684  if (quiet == 0)
685  g_debug ("=> %.*s", (int) count, string);
686 
687  string += count;
688  left -= count;
689  }
690  if (quiet == 0)
691  g_debug ("=> done");
692 
693 out:
694  g_free (string_start);
695  return rc;
696 }
697 
709 static int
710 gvm_connection_vsendf_internal (gvm_connection_t *connection, const char *fmt,
711  va_list ap, int quiet)
712 {
713  if (connection->tls)
714  return gvm_server_vsendf_internal (&connection->session, fmt, ap, quiet);
715  return unix_vsendf_internal (connection->socket, fmt, ap, quiet);
716 }
717 
727 int
728 gvm_server_vsendf (gnutls_session_t *session, const char *fmt, va_list ap)
729 {
730  return gvm_server_vsendf_internal (session, fmt, ap, 0);
731 }
732 
742 int
743 gvm_socket_vsendf (int socket, const char *fmt, va_list ap)
744 {
745  return unix_vsendf_internal (socket, fmt, ap, 0);
746 }
747 
757 static int
758 gvm_connection_vsendf (gvm_connection_t *connection, const char *fmt,
759  va_list ap)
760 {
761  return gvm_connection_vsendf_internal (connection, fmt, ap, 0);
762 }
763 
773 static int
774 gvm_server_vsendf_quiet (gnutls_session_t *session, const char *fmt, va_list ap)
775 {
776  return gvm_server_vsendf_internal (session, fmt, ap, 1);
777 }
778 
788 static int
789 gvm_connection_vsendf_quiet (gvm_connection_t *connection, const char *fmt,
790  va_list ap)
791 {
792  return gvm_connection_vsendf_internal (connection, fmt, ap, 1);
793 }
794 
803 int
804 gvm_server_sendf (gnutls_session_t *session, const char *format, ...)
805 {
806  va_list ap;
807  int rc;
808 
809  va_start (ap, format);
810  rc = gvm_server_vsendf (session, format, ap);
811  va_end (ap);
812  return rc;
813 }
814 
823 int
824 gvm_connection_sendf (gvm_connection_t *connection, const char *format, ...)
825 {
826  va_list ap;
827  int rc;
828 
829  va_start (ap, format);
830  rc = gvm_connection_vsendf (connection, format, ap);
831  va_end (ap);
832  return rc;
833 }
834 
843 static int
844 gvm_server_sendf_quiet (gnutls_session_t *session, const char *format, ...)
845 {
846  va_list ap;
847  int rc;
848 
849  va_start (ap, format);
850  rc = gvm_server_vsendf_quiet (session, format, ap);
851  va_end (ap);
852  return rc;
853 }
854 
863 static int
864 gvm_connection_sendf_quiet (gvm_connection_t *connection, const char *format,
865  ...)
866 {
867  va_list ap;
868  int rc;
869 
870  va_start (ap, format);
871  rc = gvm_connection_vsendf_quiet (connection, format, ap);
872  va_end (ap);
873  return rc;
874 }
875 
886 int
887 gvm_server_sendf_xml (gnutls_session_t *session, const char *format, ...)
888 {
889  va_list ap;
890  gchar *msg;
891  int rc;
892 
893  va_start (ap, format);
894  msg = g_markup_vprintf_escaped (format, ap);
895  rc = gvm_server_sendf (session, "%s", msg);
896  g_free (msg);
897  va_end (ap);
898  return rc;
899 }
900 
911 int
912 gvm_connection_sendf_xml (gvm_connection_t *connection, const char *format, ...)
913 {
914  va_list ap;
915  gchar *msg;
916  int rc;
917 
918  va_start (ap, format);
919  msg = g_markup_vprintf_escaped (format, ap);
920  rc = gvm_connection_sendf (connection, "%s", msg);
921  g_free (msg);
922  va_end (ap);
923  return rc;
924 }
925 
938 int
939 gvm_server_sendf_xml_quiet (gnutls_session_t *session, const char *format, ...)
940 {
941  va_list ap;
942  gchar *msg;
943  int rc;
944 
945  va_start (ap, format);
946  msg = g_markup_vprintf_escaped (format, ap);
947  rc = gvm_server_sendf_quiet (session, "%s", msg);
948  g_free (msg);
949  va_end (ap);
950  return rc;
951 }
952 
965 int
967  const char *format, ...)
968 {
969  va_list ap;
970  gchar *msg;
971  int rc;
972 
973  va_start (ap, format);
974  msg = g_markup_vprintf_escaped (format, ap);
975  rc = gvm_connection_sendf_quiet (connection, "%s", msg);
976  g_free (msg);
977  va_end (ap);
978  return rc;
979 }
980 
988 static int
989 server_new_gnutls_init (gnutls_certificate_credentials_t *server_credentials)
990 {
991  /* Turn off use of /dev/random, as this can block. */
992  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
993 
994  /* Initialize security library. */
995  if (gnutls_global_init ())
996  {
997  g_warning ("Failed to initialize GNUTLS.");
998  return -1;
999  }
1000  /* Setup server session. */
1001  if (gnutls_certificate_allocate_credentials (server_credentials))
1002  {
1003  g_warning ("%s: failed to allocate server credentials\n", __func__);
1004  return -1;
1005  }
1006  return 0;
1007 }
1008 
1020 static int
1021 server_new_gnutls_set (unsigned int end_type, const char *priority,
1022  gnutls_session_t *server_session,
1023  gnutls_certificate_credentials_t *server_credentials)
1024 {
1025  int err_gnutls;
1026 
1027  if (gnutls_init (server_session, end_type))
1028  {
1029  g_warning ("%s: failed to initialise server session\n", __func__);
1030  return -1;
1031  }
1032 
1033  /* Depending on gnutls version different priority strings are
1034  possible. At least from 3.0 this is an option:
1035  "NONE:+VERS-TLS1.0:+CIPHER-ALL:+COMP-ALL:+RSA:+DHE-RSA:+DHE-DSS:+MAC-ALL"
1036  But in fact this function is only for internal
1037  purposes, not for scanning abilities. So, the conservative "NORMAL"
1038  is chosen.
1039  */
1040 
1041  if ((err_gnutls = gnutls_priority_set_direct (
1042  *server_session, priority ? priority : "NORMAL", NULL)))
1043  {
1044  g_warning ("%s: failed to set tls priorities: %s\n", __func__,
1045  gnutls_strerror (err_gnutls));
1046  gnutls_deinit (*server_session);
1047  return -1;
1048  }
1049 
1050  if (gnutls_credentials_set (*server_session, GNUTLS_CRD_CERTIFICATE,
1051  *server_credentials))
1052  {
1053  g_warning ("%s: failed to set server credentials\n", __func__);
1054  gnutls_deinit (*server_session);
1055  return -1;
1056  }
1057 
1058  if (end_type == GNUTLS_SERVER)
1059  gnutls_certificate_server_set_request (*server_session,
1060  GNUTLS_CERT_REQUEST);
1061  return 0;
1062 }
1063 
1078 static int
1079 server_new_internal (unsigned int end_type, const char *priority,
1080  const gchar *ca_cert_file, const gchar *cert_file,
1081  const gchar *key_file, gnutls_session_t *server_session,
1082  gnutls_certificate_credentials_t *server_credentials)
1083 {
1084  if (server_new_gnutls_init (server_credentials))
1085  return -1;
1086 
1087  if (cert_file && key_file)
1088  {
1089  int ret;
1090 
1091  ret = gnutls_certificate_set_x509_key_file (
1092  *server_credentials, cert_file, key_file, GNUTLS_X509_FMT_PEM);
1093  if (ret < 0)
1094  {
1095  g_warning ("%s: failed to set credentials key file: %s\n", __func__,
1096  gnutls_strerror (ret));
1097  g_warning ("%s: cert file: %s\n", __func__, cert_file);
1098  g_warning ("%s: key file : %s\n", __func__, key_file);
1099  gnutls_certificate_free_credentials (*server_credentials);
1100  return -1;
1101  }
1102  }
1103 
1104  if (ca_cert_file)
1105  {
1106  int ret;
1107 
1108  ret = gnutls_certificate_set_x509_trust_file (
1109  *server_credentials, ca_cert_file, GNUTLS_X509_FMT_PEM);
1110  if (ret < 0)
1111  {
1112  g_warning ("%s: failed to set credentials trust file: %s\n", __func__,
1113  gnutls_strerror (ret));
1114  g_warning ("%s: trust file: %s\n", __func__, ca_cert_file);
1115  gnutls_certificate_free_credentials (*server_credentials);
1116  return -1;
1117  }
1118  }
1119 
1120  if (server_new_gnutls_set (end_type, priority, server_session,
1121  server_credentials))
1122  {
1123  gnutls_certificate_free_credentials (*server_credentials);
1124  return -1;
1125  }
1126 
1127  return 0;
1128 }
1129 
1143 int
1144 gvm_server_new (unsigned int end_type, gchar *ca_cert_file, gchar *cert_file,
1145  gchar *key_file, gnutls_session_t *server_session,
1146  gnutls_certificate_credentials_t *server_credentials)
1147 {
1148  return server_new_internal (end_type, NULL, ca_cert_file, cert_file, key_file,
1149  server_session, server_credentials);
1150 }
1151 
1165 int
1166 gvm_server_new_mem (unsigned int end_type, const char *ca_cert,
1167  const char *pub_key, const char *priv_key,
1168  gnutls_session_t *session,
1169  gnutls_certificate_credentials_t *credentials)
1170 {
1171  if (server_new_gnutls_init (credentials))
1172  return -1;
1173 
1174  if (pub_key && priv_key)
1175  {
1176  int ret;
1177  gnutls_datum_t pub, priv;
1178 
1179  pub.data = (void *) pub_key;
1180  pub.size = strlen (pub_key);
1181  priv.data = (void *) priv_key;
1182  priv.size = strlen (priv_key);
1183 
1184  ret = gnutls_certificate_set_x509_key_mem (*credentials, &pub, &priv,
1185  GNUTLS_X509_FMT_PEM);
1186  if (ret < 0)
1187  {
1188  g_warning ("%s: %s\n", __func__, gnutls_strerror (ret));
1189  return -1;
1190  }
1191  }
1192 
1193  if (ca_cert)
1194  {
1195  int ret;
1196  gnutls_datum_t data;
1197 
1198  data.data = (void *) ca_cert;
1199  data.size = strlen (ca_cert);
1200  ret = gnutls_certificate_set_x509_trust_mem (*credentials, &data,
1201  GNUTLS_X509_FMT_PEM);
1202  if (ret < 0)
1203  {
1204  g_warning ("%s: %s\n", __func__, gnutls_strerror (ret));
1205  gnutls_certificate_free_credentials (*credentials);
1206  return -1;
1207  }
1208  }
1209 
1210  if (server_new_gnutls_set (end_type, NULL, session, credentials))
1211  {
1212  gnutls_certificate_free_credentials (*credentials);
1213  return -1;
1214  }
1215 
1216  return 0;
1217 }
1218 
1227 int
1228 set_gnutls_dhparams (gnutls_certificate_credentials_t creds,
1229  const char *dhparams_file)
1230 {
1231  int ret;
1232  gnutls_datum_t data;
1233 
1234  if (!creds || !dhparams_file)
1235  return -1;
1236 
1237  if (load_gnutls_file (dhparams_file, &data))
1238  return -1;
1239 
1240 /* Disable false positive warning about potential leak of memory */
1241 #ifndef __clang_analyzer__
1242 
1243  gnutls_dh_params_t params = g_malloc0 (sizeof (gnutls_dh_params_t));
1244  ret = gnutls_dh_params_import_pkcs3 (params, &data, GNUTLS_X509_FMT_PEM);
1245  unload_gnutls_file (&data);
1246  if (ret)
1247  {
1248  g_free (params);
1249  return -1;
1250  }
1251  else
1252  gnutls_certificate_set_dh_params (creds, params);
1253  return 0;
1254 
1255 #endif
1256 }
1257 
1270 int
1271 gvm_server_free (int server_socket, gnutls_session_t server_session,
1272  gnutls_certificate_credentials_t server_credentials)
1273 {
1274  /* Turn off blocking. */
1275  // FIX get flags first
1276  if (fcntl (server_socket, F_SETFL, O_NONBLOCK) == -1)
1277  {
1278  g_warning ("%s: failed to set server socket flag: %s\n", __func__,
1279  strerror (errno));
1280  return -1;
1281  }
1282 
1283  while (1)
1284  {
1285  int ret = gnutls_bye (server_session, GNUTLS_SHUT_WR);
1286  if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
1287  {
1288  continue;
1289  }
1290  if (ret)
1291  {
1292  g_debug (" Failed to gnutls_bye: %s\n",
1293  gnutls_strerror ((int) ret));
1294  /* Carry on successfully anyway, as this often fails, perhaps
1295  * because the server is closing the connection first. */
1296  break;
1297  }
1298  break;
1299  }
1300 
1301  /* The former separate code in gvm_server_close and here
1302  differed in the order the TLS session and socket was closed. The
1303  way we do it here seems to be the right thing but for full
1304  backward compatibility we do it for calls from
1305  gvm_server_close in the old way. We can distinguish the two
1306  modes by the existence of server_credentials. */
1307  if (server_credentials)
1308  {
1309  if (close (server_socket) == -1)
1310  {
1311  g_warning ("%s: failed to close server socket: %s\n", __func__,
1312  strerror (errno));
1313  return -1;
1314  }
1315  gnutls_deinit (server_session);
1316  gnutls_certificate_free_credentials (server_credentials);
1317  }
1318  else
1319  {
1320  gnutls_deinit (server_session);
1321  close (server_socket);
1322  }
1323 
1324  gnutls_global_deinit ();
1325 
1326  return 0;
1327 }
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:1166
gvm_connection_vsendf_quiet
static 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:789
gvm_server_close
int gvm_server_close(int socket, gnutls_session_t session)
Close a server connection and its socket.
Definition: serverutils.c:494
gvm_connection_vsendf
static int gvm_connection_vsendf(gvm_connection_t *connection, const char *fmt, va_list ap)
Send a string to the server.
Definition: serverutils.c:758
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:912
gvm_server_verify
int gvm_server_verify(gnutls_session_t session)
Verify certificate.
Definition: serverutils.c:111
unload_gnutls_file
void unload_gnutls_file(gnutls_datum_t *data)
Unloads a gnutls_datum_t struct's data.
Definition: serverutils.c:189
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:824
gvm_server_sendf_quiet
static int gvm_server_sendf_quiet(gnutls_session_t *session, const char *format,...)
Format and send a string to the server.
Definition: serverutils.c:844
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:1079
gvm_connection_sendf_quiet
static int gvm_connection_sendf_quiet(gvm_connection_t *connection, const char *format,...)
Format and send a string to the server.
Definition: serverutils.c:864
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:480
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:887
HOST_TYPE_IPV6
@ HOST_TYPE_IPV6
Definition: hosts.h:40
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:522
close_unix
static int close_unix(gvm_connection_t *client_connection)
Close UNIX socket connection.
Definition: serverutils.c:57
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:658
server_new_gnutls_init
static int server_new_gnutls_init(gnutls_certificate_credentials_t *server_credentials)
Initialize a server session.
Definition: serverutils.c:989
HOST_TYPE_IPV4
@ HOST_TYPE_IPV4
Definition: hosts.h:36
gvm_get_host_type
int gvm_get_host_type(const gchar *str_stripped)
Determines the host type in a buffer.
Definition: hosts.c:810
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:462
gvm_connection_t::socket
int socket
Socket.
Definition: serverutils.h:32
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:590
cert_pub_mem
static char * cert_pub_mem
Definition: serverutils.c:195
gvm_connection_t::tls
int tls
Whether uses TCP-TLS (vs UNIX socket).
Definition: serverutils.h:31
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:161
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:1271
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:728
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:966
gvm_connection_close
void gvm_connection_close(gvm_connection_t *connection)
Close a server connection and its socket.
Definition: serverutils.c:505
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:314
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:262
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:1144
gvm_connection_t::credentials
gnutls_certificate_credentials_t credentials
Credentials.
Definition: serverutils.h:34
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:710
gvm_connection_free
void gvm_connection_free(gvm_connection_t *client_connection)
Free connection.
Definition: serverutils.c:92
get_cert_pub_mem
static const char * get_cert_pub_mem()
Get public certificate from cert_pub_mem.
Definition: serverutils.c:241
cert_priv_mem
static char * cert_priv_mem
Definition: serverutils.c:196
host_type
host_type
Definition: hosts.h:34
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:939
gvm_server_vsendf_quiet
static 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:774
gvm_socket_vsendf
int gvm_socket_vsendf(int socket, const char *fmt, va_list ap)
Send a string to the server.
Definition: serverutils.c:743
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:570
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:1228
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:1021
get_cert_priv_mem
static const char * get_cert_priv_mem()
Get private certificate from cert_priv_mem.
Definition: serverutils.c:230
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:804
HOST_TYPE_NAME
@ HOST_TYPE_NAME
Definition: hosts.h:35
gvm_connection_t::session
gnutls_session_t session
Session.
Definition: serverutils.h:33
gvm_connection_t
Connection.
Definition: serverutils.h:30
set_cert_priv_mem
static void set_cert_priv_mem(const char *data)
Save cert_priv_mem with private certificate.
Definition: serverutils.c:217
set_cert_pub_mem
static void set_cert_pub_mem(const char *data)
Save cert_pub_mem with public certificate.
Definition: serverutils.c:204