Greenbone Vulnerability Management Libraries 23.9.3
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
13
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
38#define G_LOG_DOMAIN "libgvm util"
39
40static int
41server_attach_internal (int, gnutls_session_t *, const char *, int);
42static int
43server_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
56static int
57close_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
91void
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
110int
111gvm_server_verify (gnutls_session_t session, const char *host)
112{
113 unsigned int status;
114 int ret;
115
116 ret = gnutls_certificate_verify_peers3 (session, host, &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_UNEXPECTED_OWNER)
125 g_warning ("%s: the certificate's host does not match the actual host",
126 __func__);
127
128 if (status & GNUTLS_CERT_INVALID)
129 g_warning ("%s: the certificate is not trusted", __func__);
130
131 if (status & GNUTLS_CERT_SIGNER_NOT_CA)
132 g_warning ("%s: the certificate's issuer is not a CA", __func__);
133
134 if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
135 g_warning ("%s: the certificate was signed using an insecure algorithm",
136 __func__);
137
138 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
139 g_warning ("%s: the certificate hasn't got a known issuer", __func__);
140
141 if (status & GNUTLS_CERT_REVOKED)
142 g_warning ("%s: the certificate has been revoked", __func__);
143
144 if (status & GNUTLS_CERT_EXPIRED)
145 g_warning ("%s: the certificate has expired", __func__);
146
147 if (status & GNUTLS_CERT_NOT_ACTIVATED)
148 g_warning ("%s: the certificate is not yet activated", __func__);
149
150 if (status)
151 return 1;
152
153 return 0;
154}
155
164int
165load_gnutls_file (const char *file, gnutls_datum_t *loaded_file)
166{
167 FILE *f = NULL;
168 int64_t filelen;
169 void *ptr;
170
171 if (!(f = fopen (file, "r")) || fseek (f, 0, SEEK_END) != 0
172 || (filelen = ftell (f)) < 0 || fseek (f, 0, SEEK_SET) != 0
173 || !(ptr = g_malloc0 ((size_t) filelen))
174 || fread (ptr, 1, (size_t) filelen, f) < (size_t) filelen)
175 {
176 if (f)
177 fclose (f);
178 return -1;
179 }
180
181 loaded_file->data = ptr;
182 loaded_file->size = filelen;
183 fclose (f);
184 return 0;
185}
186
192void
193unload_gnutls_file (gnutls_datum_t *data)
194{
195 if (data)
196 g_free (data->data);
197}
198
199static char *cert_pub_mem = NULL;
200static char *cert_priv_mem = NULL;
201
207static void
208set_cert_pub_mem (const char *data)
209{
210 g_free (cert_pub_mem);
211 cert_pub_mem = g_strdup (data);
212}
213
219static void
220set_cert_priv_mem (const char *data)
221{
222 if (cert_priv_mem)
223 g_free (cert_priv_mem);
224 cert_priv_mem = g_strdup (data);
225}
226
232static const char *
234{
235 return cert_priv_mem;
236}
237
243static const char *
245{
246 return cert_pub_mem;
247}
248
264static int
265client_cert_callback (gnutls_session_t session,
266 const gnutls_datum_t *req_ca_rdn, int nreqs,
267 const gnutls_pk_algorithm_t *sign_algos,
268 int sign_algos_length, gnutls_retr2_st *st)
269{
270 int ret;
271 gnutls_datum_t data;
272 static gnutls_x509_crt_t crt;
273 static gnutls_x509_privkey_t key;
274
275 (void) session;
276 (void) req_ca_rdn;
277 (void) nreqs;
278 (void) sign_algos;
279 (void) sign_algos_length;
280 data.data = (unsigned char *) g_strdup (get_cert_pub_mem ());
281 data.size = strlen (get_cert_pub_mem ());
282 gnutls_x509_crt_init (&crt);
283 ret = gnutls_x509_crt_import (crt, &data, GNUTLS_X509_FMT_PEM);
284 g_free (data.data);
285 if (ret)
286 return ret;
287 st->cert.x509 = &crt;
288 st->cert_type = GNUTLS_CRT_X509;
289 st->ncerts = 1;
290
291 data.data = (unsigned char *) g_strdup (get_cert_priv_mem ());
292 data.size = strlen (get_cert_priv_mem ());
293 gnutls_x509_privkey_init (&key);
294 ret = gnutls_x509_privkey_import (key, &data, GNUTLS_X509_FMT_PEM);
295 g_free (data.data);
296 if (ret)
297 return ret;
298 st->key.x509 = key;
299 st->key_type = GNUTLS_PRIVKEY_X509;
300 return 0;
301}
302
316int
317gvm_server_open_verify (gnutls_session_t *session, const char *host, int port,
318 const char *ca_mem, const char *pub_mem,
319 const char *priv_mem, int verify)
320{
321 int ret;
322 int server_socket;
323 struct addrinfo address_hints;
324 struct addrinfo *addresses, *address;
325 gchar *port_string;
326 int host_type;
327
328 gnutls_certificate_credentials_t credentials;
329
330 /* Ensure that host and port have sane values. */
331 if (port < 1 || port > 65535)
332 {
333 g_warning ("Failed to create client TLS session. "
334 "Invalid port %d",
335 port);
336 return -1;
337 }
341 {
342 g_warning ("Failed to create client TLS session. Invalid host %s", host);
343 return -1;
344 }
345
348
349 if (gvm_server_new_mem (GNUTLS_CLIENT, ca_mem, pub_mem, priv_mem, session,
350 &credentials))
351 {
352 g_warning ("Failed to create client TLS session.");
353 return -1;
354 }
355
356 if (ca_mem && pub_mem && priv_mem)
357 {
358 set_cert_pub_mem (pub_mem);
359 set_cert_priv_mem (priv_mem);
360
361 gnutls_certificate_set_retrieve_function (credentials,
363 }
364
365 /* Create the port string. */
366
367 port_string = g_strdup_printf ("%i", port);
368
369 /* Get all possible addresses. */
370
371 memset (&address_hints, 0, sizeof (address_hints));
372 address_hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6. */
373 address_hints.ai_socktype = SOCK_STREAM;
374 address_hints.ai_protocol = 0;
375
376 if (getaddrinfo (host, port_string, &address_hints, &addresses))
377 {
378 g_free (port_string);
379 g_warning ("Failed to get server addresses for %s: %s", host,
380 gai_strerror (errno));
381 gnutls_deinit (*session);
382 gnutls_certificate_free_credentials (credentials);
383 return -1;
384 }
385 g_free (port_string);
386
387 /* Try to connect to each address in turn. */
388
389 for (address = addresses; address; address = address->ai_next)
390 {
391 /* Make server socket. */
392
393 if (address->ai_family == AF_INET6)
394 server_socket = socket (PF_INET6, SOCK_STREAM, 0);
395 else
396 server_socket = socket (PF_INET, SOCK_STREAM, 0);
397 if (server_socket == -1)
398 {
399 g_warning ("Failed to create server socket");
400 freeaddrinfo (addresses);
401 gnutls_deinit (*session);
402 gnutls_certificate_free_credentials (credentials);
403 return -1;
404 }
405
406 /* Connect to server. */
407
408 if (connect (server_socket, address->ai_addr, address->ai_addrlen) == -1)
409 {
410 close (server_socket);
411 continue;
412 }
413 break;
414 }
415
416 freeaddrinfo (addresses);
417
418 if (address == NULL)
419 {
420 g_warning ("Failed to connect to server");
421 gnutls_deinit (*session);
422 gnutls_certificate_free_credentials (credentials);
423 return -1;
424 }
425
426 g_debug (" Connected to server '%s' port %d.", host, port);
427
428 /* Complete setup of server session. */
429 ret = server_attach_internal (server_socket, session, host, port);
430 if (ret)
431 {
432 if (ret == -2)
433 {
434 close (server_socket);
435 gnutls_deinit (*session);
436 gnutls_certificate_free_credentials (credentials);
437 }
438 close (server_socket);
439 return -1;
440 }
441 if (verify && gvm_server_verify (*session, host))
442 {
443 close (server_socket);
444 return -1;
445 }
446
447 return server_socket;
448}
449
464int
465gvm_server_open_with_cert (gnutls_session_t *session, const char *host,
466 int port, const char *ca_mem, const char *pub_mem,
467 const char *priv_mem)
468{
469 return gvm_server_open_verify (session, host, port, ca_mem, pub_mem, priv_mem,
470 ca_mem && pub_mem && priv_mem);
471}
472
482int
483gvm_server_open (gnutls_session_t *session, const char *host, int port)
484{
485 return gvm_server_open_with_cert (session, host, port, NULL, NULL, NULL);
486}
487
496int
497gvm_server_close (int socket, gnutls_session_t session)
498{
499 return gvm_server_free (socket, session, NULL);
500}
501
507void
509{
510 gvm_connection_free (connection);
511}
512
524static int
525server_attach_internal (int socket, gnutls_session_t *session, const char *host,
526 int port)
527{
528 unsigned int retries;
529
530 gnutls_transport_set_ptr (*session,
531 (gnutls_transport_ptr_t) GSIZE_TO_POINTER (socket));
532
533 retries = 0;
534 while (1)
535 {
536 int ret = gnutls_handshake (*session);
537 if (ret >= 0)
538 break;
539 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
540 {
541 if (retries > 10)
542 usleep (MIN ((retries - 10) * 10000, 5000000));
543 retries++;
544 continue;
545 }
546 if (host)
547 g_debug ("Failed to shake hands with server '%s' port %d: %s", host,
548 port, gnutls_strerror (ret));
549 else
550 g_debug ("Failed to shake hands with peer: %s", gnutls_strerror (ret));
551 if (shutdown (socket, SHUT_RDWR) == -1)
552 g_debug ("Failed to shutdown server socket");
553 return -2;
554 }
555 if (host)
556 g_debug (" Shook hands with server '%s' port %d.", host, port);
557 else
558 g_debug (" Shook hands with peer.");
559
560 return 0;
561}
562
572int
573gvm_server_attach (int socket, gnutls_session_t *session)
574{
575 int ret;
576
577 ret = server_attach_internal (socket, session, NULL, 0);
578 return ret ? -1 : 0;
579}
580
592static int
593gvm_server_vsendf_internal (gnutls_session_t *session, const char *fmt,
594 va_list ap, int quiet)
595{
596 char *sref, *string;
597 int rc = 0, left;
598
599 left = vasprintf (&string, fmt, ap);
600 if (left == -1)
601 string = NULL;
602
603 sref = string;
604 while (left > 0)
605 {
606 ssize_t count;
607
608 if (quiet == 0)
609 g_debug (" send %d from %.*s[...]", left, left < 30 ? left : 30,
610 string);
611 count = gnutls_record_send (*session, string, left);
612 if (count < 0)
613 {
614 if (count == GNUTLS_E_INTERRUPTED)
615 /* Interrupted, try write again. */
616 continue;
617 if (count == GNUTLS_E_REHANDSHAKE)
618 {
619 /* \todo Rehandshake. */
620 if (quiet == 0)
621 g_message (" %s rehandshake", __func__);
622 continue;
623 }
624 g_warning ("Failed to write to server: %s", gnutls_strerror (count));
625 rc = -1;
626 goto out;
627 }
628 if (count == 0)
629 {
630 /* Server closed connection. */
631 if (quiet == 0)
632 g_debug ("= server closed");
633 rc = 1;
634 goto out;
635 }
636 if (quiet == 0)
637 g_debug ("=> %.*s", (int) count, string);
638 string += count;
639 left -= count;
640 }
641 if (quiet == 0)
642 g_debug ("=> done");
643
644out:
645 g_free (sref);
646 return rc;
647}
648
660static int
661unix_vsendf_internal (int socket, const char *fmt, va_list ap, int quiet)
662{
663 char *string_start, *string;
664 int rc = 0, left;
665
666 left = vasprintf (&string, fmt, ap);
667 if (left == -1)
668 string = NULL;
669
670 string_start = string;
671 while (left > 0)
672 {
673 ssize_t count;
674
675 if (quiet == 0)
676 g_debug (" send %d from %.*s[...]", left, left < 30 ? left : 30,
677 string);
678 count = write (socket, string, left);
679 if (count < 0)
680 {
681 if (errno == EINTR || errno == EAGAIN)
682 continue;
683 g_warning ("Failed to write to server: %s", strerror (errno));
684 rc = -1;
685 goto out;
686 }
687 if (quiet == 0)
688 g_debug ("=> %.*s", (int) count, string);
689
690 string += count;
691 left -= count;
692 }
693 if (quiet == 0)
694 g_debug ("=> done");
695
696out:
697 g_free (string_start);
698 return rc;
699}
700
712static int
714 va_list ap, int quiet)
715{
716 if (connection->tls)
717 return gvm_server_vsendf_internal (&connection->session, fmt, ap, quiet);
718 return unix_vsendf_internal (connection->socket, fmt, ap, quiet);
719}
720
730int
731gvm_server_vsendf (gnutls_session_t *session, const char *fmt, va_list ap)
732{
733 return gvm_server_vsendf_internal (session, fmt, ap, 0);
734}
735
745int
746gvm_socket_vsendf (int socket, const char *fmt, va_list ap)
747{
748 return unix_vsendf_internal (socket, fmt, ap, 0);
749}
750
760static int
761gvm_connection_vsendf (gvm_connection_t *connection, const char *fmt,
762 va_list ap)
763{
764 return gvm_connection_vsendf_internal (connection, fmt, ap, 0);
765}
766
776static int
777gvm_server_vsendf_quiet (gnutls_session_t *session, const char *fmt, va_list ap)
778{
779 return gvm_server_vsendf_internal (session, fmt, ap, 1);
780}
781
791static int
792gvm_connection_vsendf_quiet (gvm_connection_t *connection, const char *fmt,
793 va_list ap)
794{
795 return gvm_connection_vsendf_internal (connection, fmt, ap, 1);
796}
797
806int
807gvm_server_sendf (gnutls_session_t *session, const char *format, ...)
808{
809 va_list ap;
810 int rc;
811
812 va_start (ap, format);
813 rc = gvm_server_vsendf (session, format, ap);
814 va_end (ap);
815 return rc;
816}
817
826int
827gvm_connection_sendf (gvm_connection_t *connection, const char *format, ...)
828{
829 va_list ap;
830 int rc;
831
832 va_start (ap, format);
833 rc = gvm_connection_vsendf (connection, format, ap);
834 va_end (ap);
835 return rc;
836}
837
846static int
847gvm_server_sendf_quiet (gnutls_session_t *session, const char *format, ...)
848{
849 va_list ap;
850 int rc;
851
852 va_start (ap, format);
853 rc = gvm_server_vsendf_quiet (session, format, ap);
854 va_end (ap);
855 return rc;
856}
857
866static int
867gvm_connection_sendf_quiet (gvm_connection_t *connection, const char *format,
868 ...)
869{
870 va_list ap;
871 int rc;
872
873 va_start (ap, format);
874 rc = gvm_connection_vsendf_quiet (connection, format, ap);
875 va_end (ap);
876 return rc;
877}
878
889int
890gvm_server_sendf_xml (gnutls_session_t *session, const char *format, ...)
891{
892 va_list ap;
893 gchar *msg;
894 int rc;
895
896 va_start (ap, format);
897 msg = g_markup_vprintf_escaped (format, ap);
898 rc = gvm_server_sendf (session, "%s", msg);
899 g_free (msg);
900 va_end (ap);
901 return rc;
902}
903
914int
915gvm_connection_sendf_xml (gvm_connection_t *connection, const char *format, ...)
916{
917 va_list ap;
918 gchar *msg;
919 int rc;
920
921 va_start (ap, format);
922 msg = g_markup_vprintf_escaped (format, ap);
923 rc = gvm_connection_sendf (connection, "%s", msg);
924 g_free (msg);
925 va_end (ap);
926 return rc;
927}
928
941int
942gvm_server_sendf_xml_quiet (gnutls_session_t *session, const char *format, ...)
943{
944 va_list ap;
945 gchar *msg;
946 int rc;
947
948 va_start (ap, format);
949 msg = g_markup_vprintf_escaped (format, ap);
950 rc = gvm_server_sendf_quiet (session, "%s", msg);
951 g_free (msg);
952 va_end (ap);
953 return rc;
954}
955
968int
970 const char *format, ...)
971{
972 va_list ap;
973 gchar *msg;
974 int rc;
975
976 va_start (ap, format);
977 msg = g_markup_vprintf_escaped (format, ap);
978 rc = gvm_connection_sendf_quiet (connection, "%s", msg);
979 g_free (msg);
980 va_end (ap);
981 return rc;
982}
983
991static int
992server_new_gnutls_init (gnutls_certificate_credentials_t *server_credentials)
993{
994 /* Turn off use of /dev/random, as this can block. */
995 gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
996
997 /* Initialize security library. */
998 if (gnutls_global_init ())
999 {
1000 g_warning ("Failed to initialize GNUTLS.");
1001 return -1;
1002 }
1003 /* Setup server session. */
1004 if (gnutls_certificate_allocate_credentials (server_credentials))
1005 {
1006 g_warning ("%s: failed to allocate server credentials\n", __func__);
1007 return -1;
1008 }
1009 return 0;
1010}
1011
1023static int
1024server_new_gnutls_set (unsigned int end_type, const char *priority,
1025 gnutls_session_t *server_session,
1026 gnutls_certificate_credentials_t *server_credentials)
1027{
1028 int err;
1029
1030 if (gnutls_init (server_session, end_type))
1031 {
1032 g_warning ("%s: failed to initialise server session\n", __func__);
1033 return -1;
1034 }
1035
1036 /* Depending on gnutls version different priority strings are
1037 possible. At least from 3.0 this is an option:
1038 "NONE:+VERS-TLS1.0:+CIPHER-ALL:+COMP-ALL:+RSA:+DHE-RSA:+DHE-DSS:+MAC-ALL"
1039 But in fact this function is only for internal
1040 purposes, not for scanning abilities. So, the conservative "NORMAL"
1041 is chosen.
1042 */
1043
1044 err = gnutls_priority_set_direct (*server_session,
1045 priority ? priority : "NORMAL", NULL);
1046 if (err)
1047 {
1048 g_warning ("%s: failed to set tls priorities: %s\n", __func__,
1049 gnutls_strerror (err));
1050 gnutls_deinit (*server_session);
1051 return -1;
1052 }
1053
1054 if (gnutls_credentials_set (*server_session, GNUTLS_CRD_CERTIFICATE,
1055 *server_credentials))
1056 {
1057 g_warning ("%s: failed to set server credentials\n", __func__);
1058 gnutls_deinit (*server_session);
1059 return -1;
1060 }
1061
1062 if (end_type == GNUTLS_SERVER)
1063 gnutls_certificate_server_set_request (*server_session,
1064 GNUTLS_CERT_REQUEST);
1065 return 0;
1066}
1067
1082static int
1083server_new_internal (unsigned int end_type, const char *priority,
1084 const gchar *ca_cert_file, const gchar *cert_file,
1085 const gchar *key_file, gnutls_session_t *server_session,
1086 gnutls_certificate_credentials_t *server_credentials)
1087{
1088 if (server_new_gnutls_init (server_credentials))
1089 return -1;
1090
1091 if (cert_file && key_file)
1092 {
1093 int ret;
1094
1095 ret = gnutls_certificate_set_x509_key_file (
1096 *server_credentials, cert_file, key_file, GNUTLS_X509_FMT_PEM);
1097 if (ret < 0)
1098 {
1099 g_warning ("%s: failed to set credentials key file: %s\n", __func__,
1100 gnutls_strerror (ret));
1101 g_warning ("%s: cert file: %s\n", __func__, cert_file);
1102 g_warning ("%s: key file : %s\n", __func__, key_file);
1103 gnutls_certificate_free_credentials (*server_credentials);
1104 return -1;
1105 }
1106 }
1107
1108 if (ca_cert_file)
1109 {
1110 int ret;
1111
1112 ret = gnutls_certificate_set_x509_trust_file (
1113 *server_credentials, ca_cert_file, GNUTLS_X509_FMT_PEM);
1114 if (ret < 0)
1115 {
1116 g_warning ("%s: failed to set credentials trust file: %s\n", __func__,
1117 gnutls_strerror (ret));
1118 g_warning ("%s: trust file: %s\n", __func__, ca_cert_file);
1119 gnutls_certificate_free_credentials (*server_credentials);
1120 return -1;
1121 }
1122 }
1123
1124 if (server_new_gnutls_set (end_type, priority, server_session,
1125 server_credentials))
1126 {
1127 gnutls_certificate_free_credentials (*server_credentials);
1128 return -1;
1129 }
1130
1131 return 0;
1132}
1133
1147int
1148gvm_server_new (unsigned int end_type, gchar *ca_cert_file, gchar *cert_file,
1149 gchar *key_file, gnutls_session_t *server_session,
1150 gnutls_certificate_credentials_t *server_credentials)
1151{
1152 return server_new_internal (end_type, NULL, ca_cert_file, cert_file, key_file,
1153 server_session, server_credentials);
1154}
1155
1169int
1170gvm_server_new_mem (unsigned int end_type, const char *ca_cert,
1171 const char *pub_key, const char *priv_key,
1172 gnutls_session_t *session,
1173 gnutls_certificate_credentials_t *credentials)
1174{
1175 if (server_new_gnutls_init (credentials))
1176 return -1;
1177
1178 if (pub_key && priv_key)
1179 {
1180 int ret;
1181 gnutls_datum_t pub, priv;
1182
1183 pub.data = (void *) pub_key;
1184 pub.size = strlen (pub_key);
1185 priv.data = (void *) priv_key;
1186 priv.size = strlen (priv_key);
1187
1188 ret = gnutls_certificate_set_x509_key_mem (*credentials, &pub, &priv,
1189 GNUTLS_X509_FMT_PEM);
1190 if (ret < 0)
1191 {
1192 g_warning ("%s: %s\n", __func__, gnutls_strerror (ret));
1193 return -1;
1194 }
1195 }
1196
1197 if (ca_cert)
1198 {
1199 int ret;
1200 gnutls_datum_t data;
1201
1202 data.data = (void *) ca_cert;
1203 data.size = strlen (ca_cert);
1204 ret = gnutls_certificate_set_x509_trust_mem (*credentials, &data,
1205 GNUTLS_X509_FMT_PEM);
1206 if (ret < 0)
1207 {
1208 g_warning ("%s: %s\n", __func__, gnutls_strerror (ret));
1209 gnutls_certificate_free_credentials (*credentials);
1210 return -1;
1211 }
1212 }
1213
1214 if (server_new_gnutls_set (end_type, NULL, session, credentials))
1215 {
1216 gnutls_certificate_free_credentials (*credentials);
1217 return -1;
1218 }
1219
1220 return 0;
1221}
1222
1231int
1232set_gnutls_dhparams (gnutls_certificate_credentials_t creds,
1233 const char *dhparams_file)
1234{
1235 int ret;
1236 gnutls_datum_t data;
1237
1238 if (!creds || !dhparams_file)
1239 return -1;
1240
1241 if (load_gnutls_file (dhparams_file, &data))
1242 return -1;
1243
1244/* Disable false positive warning about potential leak of memory */
1245#ifndef __clang_analyzer__
1246
1247 gnutls_dh_params_t params = g_malloc0 (sizeof (gnutls_dh_params_t));
1248 ret = gnutls_dh_params_import_pkcs3 (params, &data, GNUTLS_X509_FMT_PEM);
1249 unload_gnutls_file (&data);
1250 if (ret)
1251 {
1252 g_free (params);
1253 return -1;
1254 }
1255 else
1256 gnutls_certificate_set_dh_params (creds, params);
1257 return 0;
1258
1259#endif
1260}
1261
1274int
1275gvm_server_free (int server_socket, gnutls_session_t server_session,
1276 gnutls_certificate_credentials_t server_credentials)
1277{
1278 /* Turn off blocking. */
1279 // FIX get flags first
1280 if (fcntl (server_socket, F_SETFL, O_NONBLOCK) == -1)
1281 {
1282 g_warning ("%s: failed to set server socket flag: %s\n", __func__,
1283 strerror (errno));
1284 return -1;
1285 }
1286
1287 while (1)
1288 {
1289 int ret = gnutls_bye (server_session, GNUTLS_SHUT_WR);
1290 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
1291 {
1292 continue;
1293 }
1294 if (ret)
1295 {
1296 g_debug (" Failed to gnutls_bye: %s\n",
1297 gnutls_strerror ((int) ret));
1298 /* Carry on successfully anyway, as this often fails, perhaps
1299 * because the server is closing the connection first. */
1300 break;
1301 }
1302 break;
1303 }
1304
1305 /* The former separate code in gvm_server_close and here
1306 differed in the order the TLS session and socket was closed. The
1307 way we do it here seems to be the right thing but for full
1308 backward compatibility we do it for calls from
1309 gvm_server_close in the old way. We can distinguish the two
1310 modes by the existence of server_credentials. */
1311 if (server_credentials)
1312 {
1313 if (close (server_socket) == -1)
1314 {
1315 g_warning ("%s: failed to close server socket: %s\n", __func__,
1316 strerror (errno));
1317 return -1;
1318 }
1319 gnutls_deinit (server_session);
1320 gnutls_certificate_free_credentials (server_credentials);
1321 }
1322 else
1323 {
1324 gnutls_deinit (server_session);
1325 close (server_socket);
1326 }
1327
1328 gnutls_global_deinit ();
1329
1330 return 0;
1331}
int gvm_get_host_type(const gchar *str_stripped)
Determines the host type in a buffer.
Definition hosts.c:814
Protos and data structures for Hosts collections and single hosts objects.
host_type
Definition hosts.h:34
@ HOST_TYPE_NAME
Definition hosts.h:35
@ HOST_TYPE_IPV6
Definition hosts.h:40
@ HOST_TYPE_IPV4
Definition hosts.h:36
static int close_unix(gvm_connection_t *client_connection)
Close UNIX socket connection.
Definition serverutils.c:57
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:1083
int set_gnutls_dhparams(gnutls_certificate_credentials_t creds, const char *dhparams_file)
Set a gnutls session's Diffie-Hellman parameters.
Definition serverutils.c:1232
static const char * get_cert_pub_mem()
Get public certificate from cert_pub_mem.
Definition serverutils.c:244
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:1148
int gvm_connection_sendf(gvm_connection_t *connection, const char *format,...)
Format and send a string to the server.
Definition serverutils.c:827
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:465
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:942
static void set_cert_priv_mem(const char *data)
Save cert_priv_mem with private certificate.
Definition serverutils.c:220
int gvm_server_vsendf(gnutls_session_t *session, const char *fmt, va_list ap)
Send a string to the server.
Definition serverutils.c:731
static const char * get_cert_priv_mem()
Get private certificate from cert_priv_mem.
Definition serverutils.c:233
int gvm_server_close(int socket, gnutls_session_t session)
Close a server connection and its socket.
Definition serverutils.c:497
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:483
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:713
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:265
int gvm_connection_sendf_xml(gvm_connection_t *connection, const char *format,...)
Format and send an XML string to the server.
Definition serverutils.c:915
static char * cert_pub_mem
Definition serverutils.c:199
static int gvm_server_sendf_quiet(gnutls_session_t *session, const char *format,...)
Format and send a string to the server.
Definition serverutils.c:847
void gvm_connection_close(gvm_connection_t *connection)
Close a server connection and its socket.
Definition serverutils.c:508
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:525
static int server_new_gnutls_init(gnutls_certificate_credentials_t *server_credentials)
Initialize a server session.
Definition serverutils.c:992
int gvm_socket_vsendf(int socket, const char *fmt, va_list ap)
Send a string to the server.
Definition serverutils.c:746
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:165
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:1170
static char * cert_priv_mem
Definition serverutils.c:200
void gvm_connection_free(gvm_connection_t *client_connection)
Free connection.
Definition serverutils.c:92
int gvm_server_verify(gnutls_session_t session, const char *host)
Verify certificate.
Definition serverutils.c:111
int gvm_server_sendf_xml(gnutls_session_t *session, const char *format,...)
Format and send an XML string to the server.
Definition serverutils.c:890
static int gvm_connection_sendf_quiet(gvm_connection_t *connection, const char *format,...)
Format and send a string to the server.
Definition serverutils.c:867
static int unix_vsendf_internal(int socket, const char *fmt, va_list ap, int quiet)
Send a string to the server.
Definition serverutils.c:661
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 credentials.
Definition serverutils.c:1024
static int gvm_connection_vsendf(gvm_connection_t *connection, const char *fmt, va_list ap)
Send a string to the server.
Definition serverutils.c:761
void unload_gnutls_file(gnutls_datum_t *data)
Unloads a gnutls_datum_t struct's data.
Definition serverutils.c:193
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:792
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:593
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:777
int gvm_server_sendf(gnutls_session_t *session, const char *format,...)
Format and send a string to the server.
Definition serverutils.c:807
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:1275
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:573
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:317
static void set_cert_pub_mem(const char *data)
Save cert_pub_mem with public certificate.
Definition serverutils.c:208
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:969
GnuTLS based functions for server communication - header file.
Connection.
Definition serverutils.h:30
int tls
Whether uses TCP-TLS (vs UNIX socket).
Definition serverutils.h:31
gnutls_certificate_credentials_t credentials
Credentials.
Definition serverutils.h:34
int socket
Socket.
Definition serverutils.h:32
gnutls_session_t session
Session.
Definition serverutils.h:33