Greenbone Vulnerability Management Libraries: util/serverutils.c Source File

Greenbone Vulnerability Management Libraries 23.1.2

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
41 server_attach_internal (int, gnutls_session_t *, const char *, int);
42static 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
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
92gvm_connection_free (gvm_connection_t *client_connection)
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)
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
160int
161load_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
188void
189unload_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
203static void
204set_cert_pub_mem (const char *data)
205{
206 g_free (cert_pub_mem);
207 cert_pub_mem = g_strdup (data);
208}
209
215static void
216set_cert_priv_mem (const char *data)
217{
218 if (cert_priv_mem)
219 g_free (cert_priv_mem);
220 cert_priv_mem = g_strdup (data);
221}
222
228static const char *
229get_cert_priv_mem ()
230{
231 return cert_priv_mem;
232}
233
239static const char *
240get_cert_pub_mem ()
241{
242 return cert_pub_mem;
243}
244
260static int
261client_cert_callback (gnutls_session_t session,
262 const gnutls_datum_t *req_ca_rdn, int nreqs,
263 const gnutls_pk_algorithm_t *sign_algos,
264 int sign_algos_length, gnutls_retr2_st *st)
265{
266 int ret;
267 gnutls_datum_t data;
268 static gnutls_x509_crt_t crt;
269 static gnutls_x509_privkey_t key;
270
271 (void) session;
272 (void) req_ca_rdn;
273 (void) nreqs;
274 (void) sign_algos;
275 (void) sign_algos_length;
276 data.data = (unsigned char *) g_strdup (get_cert_pub_mem ());
277 data.size = strlen (get_cert_pub_mem ());
278 gnutls_x509_crt_init (&crt);
279 ret = gnutls_x509_crt_import (crt, &data, GNUTLS_X509_FMT_PEM);
280 g_free (data.data);
281 if (ret)
282 return ret;
283 st->cert.x509 = &crt;
284 st->cert_type = GNUTLS_CRT_X509;
285 st->ncerts = 1;
286
287 data.data = (unsigned char *) g_strdup (get_cert_priv_mem ());
288 data.size = strlen (get_cert_priv_mem ());
289 gnutls_x509_privkey_init (&key);
290 ret = gnutls_x509_privkey_import (key, &data, GNUTLS_X509_FMT_PEM);
291 g_free (data.data);
292 if (ret)
293 return ret;
294 st->key.x509 = key;
295 st->key_type = GNUTLS_PRIVKEY_X509;
296 return 0;
297}
298
312int
313gvm_server_open_verify (gnutls_session_t *session, const char *host, int port,
314 const char *ca_mem, const char *pub_mem,
315 const char *priv_mem, int verify)
316{
317 int ret;
318 int server_socket;
319 struct addrinfo address_hints;
320 struct addrinfo *addresses, *address;
321 gchar *port_string;
322 int host_type;
323
324 gnutls_certificate_credentials_t credentials;
325
326 /* Ensure that host and port have sane values. */
327 if (port < 1 || port > 65535)
328 {
329 g_warning ("Failed to create client TLS session. "
330 "Invalid port %d",
331 port);
332 return -1;
333 }
334 host_type = gvm_get_host_type (host);
335 if (!(host_type == HOST_TYPE_NAME || host_type == HOST_TYPE_IPV4
336 || host_type == HOST_TYPE_IPV6))
337 {
338 g_warning ("Failed to create client TLS session. Invalid host %s", host);
339 return -1;
340 }
341
344
345 if (gvm_server_new_mem (GNUTLS_CLIENT, ca_mem, pub_mem, priv_mem, session,
346 &credentials))
347 {
348 g_warning ("Failed to create client TLS session.");
349 return -1;
350 }
351
352 if (ca_mem && pub_mem && priv_mem)
353 {
354 set_cert_pub_mem (pub_mem);
355 set_cert_priv_mem (priv_mem);
356
357 gnutls_certificate_set_retrieve_function (credentials,
358 client_cert_callback);
359 }
360
361 /* Create the port string. */
362
363 port_string = g_strdup_printf ("%i", port);
364
365 /* Get all possible addresses. */
366
367 memset (&address_hints, 0, sizeof (address_hints));
368 address_hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6. */
369 address_hints.ai_socktype = SOCK_STREAM;
370 address_hints.ai_protocol = 0;
371
372 if (getaddrinfo (host, port_string, &address_hints, &addresses))
373 {
374 g_free (port_string);
375 g_warning ("Failed to get server addresses for %s: %s", host,
376 gai_strerror (errno));
377 gnutls_deinit (*session);
378 gnutls_certificate_free_credentials (credentials);
379 return -1;
380 }
381 g_free (port_string);
382
383 /* Try to connect to each address in turn. */
384
385 for (address = addresses; address; address = address->ai_next)
386 {
387 /* Make server socket. */
388
389 if (address->ai_family == AF_INET6)
390 server_socket = socket (PF_INET6, SOCK_STREAM, 0);
391 else
392 server_socket = socket (PF_INET, SOCK_STREAM, 0);
393 if (server_socket == -1)
394 {
395 g_warning ("Failed to create server socket");
396 freeaddrinfo (addresses);
397 gnutls_deinit (*session);
398 gnutls_certificate_free_credentials (credentials);
399 return -1;
400 }
401
402 /* Connect to server. */
403
404 if (connect (server_socket, address->ai_addr, address->ai_addrlen) == -1)
405 {
406 close (server_socket);
407 continue;
408 }
409 break;
410 }
411
412 freeaddrinfo (addresses);
413
414 if (address == NULL)
415 {
416 g_warning ("Failed to connect to server");
417 gnutls_deinit (*session);
418 gnutls_certificate_free_credentials (credentials);
419 return -1;
420 }
421
422 g_debug (" Connected to server '%s' port %d.", host, port);
423
424 /* Complete setup of server session. */
425 ret = server_attach_internal (server_socket, session, host, port);
426 if (ret)
427 {
428 if (ret == -2)
429 {
430 close (server_socket);
431 gnutls_deinit (*session);
432 gnutls_certificate_free_credentials (credentials);
433 }
434 close (server_socket);
435 return -1;
436 }
437 if (verify && gvm_server_verify (*session))
438 {
439 close (server_socket);
440 return -1;
441 }
442
443 return server_socket;
444}
445
460int
461gvm_server_open_with_cert (gnutls_session_t *session, const char *host,
462 int port, const char *ca_mem, const char *pub_mem,
463 const char *priv_mem)
464{
465 return gvm_server_open_verify (session, host, port, ca_mem, pub_mem, priv_mem,
466 ca_mem && pub_mem && priv_mem);
467}
468
478int
479gvm_server_open (gnutls_session_t *session, const char *host, int port)
480{
481 return gvm_server_open_with_cert (session, host, port, NULL, NULL, NULL);
482}
483
492int
493gvm_server_close (int socket, gnutls_session_t session)
494{
495 return gvm_server_free (socket, session, NULL);
496}
497
503void
504gvm_connection_close (gvm_connection_t *connection)
505{
506 gvm_connection_free (connection);
507}
508
520static int
521server_attach_internal (int socket, gnutls_session_t *session, const char *host,
522 int port)
523{
524 unsigned int retries;
525
526 gnutls_transport_set_ptr (*session,
527 (gnutls_transport_ptr_t) GSIZE_TO_POINTER (socket));
528
529 retries = 0;
530 while (1)
531 {
532 int ret = gnutls_handshake (*session);
533 if (ret >= 0)
534 break;
535 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
536 {
537 if (retries > 10)
538 usleep (MIN ((retries - 10) * 10000, 5000000));
539 retries++;
540 continue;
541 }
542 if (host)
543 g_debug ("Failed to shake hands with server '%s' port %d: %s", host,
544 port, gnutls_strerror (ret));
545 else
546 g_debug ("Failed to shake hands with peer: %s", gnutls_strerror (ret));
547 if (shutdown (socket, SHUT_RDWR) == -1)
548 g_debug ("Failed to shutdown server socket");
549 return -2;
550 }
551 if (host)
552 g_debug (" Shook hands with server '%s' port %d.", host, port);
553 else
554 g_debug (" Shook hands with peer.");
555
556 return 0;
557}
558
568int
569gvm_server_attach (int socket, gnutls_session_t *session)
570{
571 int ret;
572
573 ret = server_attach_internal (socket, session, NULL, 0);
574 return ret ? -1 : 0;
575}
576
588static int
589gvm_server_vsendf_internal (gnutls_session_t *session, const char *fmt,
590 va_list ap, int quiet)
591{
592 char *sref, *string;
593 int rc = 0, left;
594
595 left = vasprintf (&string, fmt, ap);
596 if (left == -1)
597 string = NULL;
598
599 sref = string;
600 while (left > 0)
601 {
602 ssize_t count;
603
604 if (quiet == 0)
605 g_debug (" send %d from %.*s[...]", left, left < 30 ? left : 30,
606 string);
607 count = gnutls_record_send (*session, string, left);
608 if (count < 0)
609 {
610 if (count == GNUTLS_E_INTERRUPTED)
611 /* Interrupted, try write again. */
612 continue;
613 if (count == GNUTLS_E_REHANDSHAKE)
614 {
615 /* \todo Rehandshake. */
616 if (quiet == 0)
617 g_message (" %s rehandshake", __func__);
618 continue;
619 }
620 g_warning ("Failed to write to server: %s", gnutls_strerror (count));
621 rc = -1;
622 goto out;
623 }
624 if (count == 0)
625 {
626 /* Server closed connection. */
627 if (quiet == 0)
628 g_debug ("= server closed");
629 rc = 1;
630 goto out;
631 }
632 if (quiet == 0)
633 g_debug ("=> %.*s", (int) count, string);
634 string += count;
635 left -= count;
636 }
637 if (quiet == 0)
638 g_debug ("=> done");
639
640out:
641 g_free (sref);
642 return rc;
643}
644
656static int
657unix_vsendf_internal (int socket, const char *fmt, va_list ap, int quiet)
658{
659 char *string_start, *string;
660 int rc = 0, left;
661
662 left = vasprintf (&string, fmt, ap);
663 if (left == -1)
664 string = NULL;
665
666 string_start = string;
667 while (left > 0)
668 {
669 ssize_t count;
670
671 if (quiet == 0)
672 g_debug (" send %d from %.*s[...]", left, left < 30 ? left : 30,
673 string);
674 count = write (socket, string, left);
675 if (count < 0)
676 {
677 if (errno == EINTR || errno == EAGAIN)
678 continue;
679 g_warning ("Failed to write to server: %s", strerror (errno));
680 rc = -1;
681 goto out;
682 }
683 if (quiet == 0)
684 g_debug ("=> %.*s", (int) count, string);
685
686 string += count;
687 left -= count;
688 }
689 if (quiet == 0)
690 g_debug ("=> done");
691
692out:
693 g_free (string_start);
694 return rc;
695}
696
708static int
709gvm_connection_vsendf_internal (gvm_connection_t *connection, const char *fmt,
710 va_list ap, int quiet)
711{
712 if (connection->tls)
713 return gvm_server_vsendf_internal (&connection->session, fmt, ap, quiet);
714 return unix_vsendf_internal (connection->socket, fmt, ap, quiet);
715}
716
726int
727gvm_server_vsendf (gnutls_session_t *session, const char *fmt, va_list ap)
728{
729 return gvm_server_vsendf_internal (session, fmt, ap, 0);
730}
731
741int
742gvm_socket_vsendf (int socket, const char *fmt, va_list ap)
743{
744 return unix_vsendf_internal (socket, fmt, ap, 0);
745}
746
756static int
757gvm_connection_vsendf (gvm_connection_t *connection, const char *fmt,
758 va_list ap)
759{
760 return gvm_connection_vsendf_internal (connection, fmt, ap, 0);
761}
762
772static int
773gvm_server_vsendf_quiet (gnutls_session_t *session, const char *fmt, va_list ap)
774{
775 return gvm_server_vsendf_internal (session, fmt, ap, 1);
776}
777
787static int
788gvm_connection_vsendf_quiet (gvm_connection_t *connection, const char *fmt,
789 va_list ap)
790{
791 return gvm_connection_vsendf_internal (connection, fmt, ap, 1);
792}
793
802int
803gvm_server_sendf (gnutls_session_t *session, const char *format, ...)
804{
805 va_list ap;
806 int rc;
807
808 va_start (ap, format);
809 rc = gvm_server_vsendf (session, format, ap);
810 va_end (ap);
811 return rc;
812}
813
822int
823gvm_connection_sendf (gvm_connection_t *connection, const char *format, ...)
824{
825 va_list ap;
826 int rc;
827
828 va_start (ap, format);
829 rc = gvm_connection_vsendf (connection, format, ap);
830 va_end (ap);
831 return rc;
832}
833
842static int
843gvm_server_sendf_quiet (gnutls_session_t *session, const char *format, ...)
844{
845 va_list ap;
846 int rc;
847
848 va_start (ap, format);
849 rc = gvm_server_vsendf_quiet (session, format, ap);
850 va_end (ap);
851 return rc;
852}
853
862static int
863gvm_connection_sendf_quiet (gvm_connection_t *connection, const char *format,
864 ...)
865{
866 va_list ap;
867 int rc;
868
869 va_start (ap, format);
870 rc = gvm_connection_vsendf_quiet (connection, format, ap);
871 va_end (ap);
872 return rc;
873}
874
885int
886gvm_server_sendf_xml (gnutls_session_t *session, const char *format, ...)
887{
888 va_list ap;
889 gchar *msg;
890 int rc;
891
892 va_start (ap, format);
893 msg = g_markup_vprintf_escaped (format, ap);
894 rc = gvm_server_sendf (session, "%s", msg);
895 g_free (msg);
896 va_end (ap);
897 return rc;
898}
899
910int
911gvm_connection_sendf_xml (gvm_connection_t *connection, const char *format, ...)
912{
913 va_list ap;
914 gchar *msg;
915 int rc;
916
917 va_start (ap, format);
918 msg = g_markup_vprintf_escaped (format, ap);
919 rc = gvm_connection_sendf (connection, "%s", msg);
920 g_free (msg);
921 va_end (ap);
922 return rc;
923}
924
937int
938gvm_server_sendf_xml_quiet (gnutls_session_t *session, const char *format, ...)
939{
940 va_list ap;
941 gchar *msg;
942 int rc;
943
944 va_start (ap, format);
945 msg = g_markup_vprintf_escaped (format, ap);
946 rc = gvm_server_sendf_quiet (session, "%s", msg);
947 g_free (msg);
948 va_end (ap);
949 return rc;
950}
951
964int
965gvm_connection_sendf_xml_quiet (gvm_connection_t *connection,
966 const char *format, ...)
967{
968 va_list ap;
969 gchar *msg;
970 int rc;
971
972 va_start (ap, format);
973 msg = g_markup_vprintf_escaped (format, ap);
974 rc = gvm_connection_sendf_quiet (connection, "%s", msg);
975 g_free (msg);
976 va_end (ap);
977 return rc;
978}
979
987static int
988server_new_gnutls_init (gnutls_certificate_credentials_t *server_credentials)
989{
990 /* Turn off use of /dev/random, as this can block. */
991 gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
992
993 /* Initialize security library. */
994 if (gnutls_global_init ())
995 {
996 g_warning ("Failed to initialize GNUTLS.");
997 return -1;
998 }
999 /* Setup server session. */
1000 if (gnutls_certificate_allocate_credentials (server_credentials))
1001 {
1002 g_warning ("%s: failed to allocate server credentials\n", __func__);
1003 return -1;
1004 }
1005 return 0;
1006}
1007
1019static int
1020server_new_gnutls_set (unsigned int end_type, const char *priority,
1021 gnutls_session_t *server_session,
1022 gnutls_certificate_credentials_t *server_credentials)
1023{
1024 int err;
1025
1026 if (gnutls_init (server_session, end_type))
1027 {
1028 g_warning ("%s: failed to initialise server session\n", __func__);
1029 return -1;
1030 }
1031
1032 /* Depending on gnutls version different priority strings are
1033 possible. At least from 3.0 this is an option:
1034 "NONE:+VERS-TLS1.0:+CIPHER-ALL:+COMP-ALL:+RSA:+DHE-RSA:+DHE-DSS:+MAC-ALL"
1035 But in fact this function is only for internal
1036 purposes, not for scanning abilities. So, the conservative "NORMAL"
1037 is chosen.
1038 */
1039
1040 err = gnutls_priority_set_direct (*server_session,
1041 priority ? priority : "NORMAL", NULL);
1042 if (err)
1043 {
1044 g_warning ("%s: failed to set tls priorities: %s\n", __func__,
1045 gnutls_strerror (err));
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
1078static int
1079server_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
1143int
1144gvm_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
1165int
1166gvm_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
1227int
1228set_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
1270int
1271gvm_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_get_host_type
int gvm_get_host_type(const gchar *str_stripped)
Determines the host type in a buffer.
Definition hosts.c:814
hosts.h
Protos and data structures for Hosts collections and single hosts objects.
host_type
host_type
Definition hosts.h:34
HOST_TYPE_NAME
@ HOST_TYPE_NAME
Definition hosts.h:35
HOST_TYPE_IPV6
@ HOST_TYPE_IPV6
Definition hosts.h:40
HOST_TYPE_IPV4
@ HOST_TYPE_IPV4
Definition hosts.h:36
close_unix
static int close_unix(gvm_connection_t *client_connection)
Close UNIX socket connection.
Definition serverutils.c:57
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
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
get_cert_pub_mem
static const char * get_cert_pub_mem()
Get public certificate from cert_pub_mem.
Definition serverutils.c:240
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_sendf
int gvm_connection_sendf(gvm_connection_t *connection, const char *format,...)
Format and send a string to the server.
Definition serverutils.c:823
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:461
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:938
set_cert_priv_mem
static void set_cert_priv_mem(const char *data)
Save cert_priv_mem with private certificate.
Definition serverutils.c:216
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:727
get_cert_priv_mem
static const char * get_cert_priv_mem()
Get private certificate from cert_priv_mem.
Definition serverutils.c:229
gvm_server_close
int gvm_server_close(int socket, gnutls_session_t session)
Close a server connection and its socket.
Definition serverutils.c:493
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:479
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:709
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:261
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:911
cert_pub_mem
static char * cert_pub_mem
Definition serverutils.c:195
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:843
gvm_connection_close
void gvm_connection_close(gvm_connection_t *connection)
Close a server connection and its socket.
Definition serverutils.c:504
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:521
server_new_gnutls_init
static int server_new_gnutls_init(gnutls_certificate_credentials_t *server_credentials)
Initialize a server session.
Definition serverutils.c:988
gvm_socket_vsendf
int gvm_socket_vsendf(int socket, const char *fmt, va_list ap)
Send a string to the server.
Definition serverutils.c:742
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_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
cert_priv_mem
static char * cert_priv_mem
Definition serverutils.c:196
gvm_connection_free
void gvm_connection_free(gvm_connection_t *client_connection)
Free connection.
Definition serverutils.c:92
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:886
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:863
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:657
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 credentials.
Definition serverutils.c:1020
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:757
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_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:788
gvm_server_verify
int gvm_server_verify(gnutls_session_t session)
Verify certificate.
Definition serverutils.c:111
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:589
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:773
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:803
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_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:569
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:313
set_cert_pub_mem
static void set_cert_pub_mem(const char *data)
Save cert_pub_mem with public certificate.
Definition serverutils.c:204
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:965
serverutils.h
GnuTLS based functions for server communication - header file.
gvm_connection_t
Connection.
Definition serverutils.h:30
gvm_connection_t::tls
int tls
Whether uses TCP-TLS (vs UNIX socket).
Definition serverutils.h:31
gvm_connection_t::credentials
gnutls_certificate_credentials_t credentials
Credentials.
Definition serverutils.h:34
gvm_connection_t::socket
int socket
Socket.
Definition serverutils.h:32
gvm_connection_t::session
gnutls_session_t session
Session.
Definition serverutils.h:33