"Fossies" - the Fresh Open Source Software Archive

Member "gvm-libs-11.0.1/util/serverutils.c" (12 May 2020, 37050 Bytes) of package /linux/misc/openvas/gvm-libs-11.0.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "serverutils.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 11.0.0_vs_11.0.1.

    1 /* Copyright (C) 2009-2019 Greenbone Networks GmbH
    2  *
    3  * SPDX-License-Identifier: GPL-2.0-or-later
    4  *
    5  * This program is free software; you can redistribute it and/or
    6  * modify it under the terms of the GNU General Public License
    7  * as published by the Free Software Foundation; either version 2
    8  * of the License, or (at your option) any later version.
    9  *
   10  * This program is distributed in the hope that it will be useful,
   11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  * GNU General Public License for more details.
   14  *
   15  * You should have received a copy of the GNU General Public License
   16  * along with this program; if not, write to the Free Software
   17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   18  */
   19 
   20 /**
   21  * @file
   22  * @brief GnuTLS based functions for server communication.
   23  *
   24  * This library supplies low-level communication functions for communication
   25  * with a server over GnuTLS.
   26  */
   27 
   28 #define _GNU_SOURCE
   29 
   30 #include "serverutils.h"
   31 
   32 #include "../base/hosts.h" /* for is_hostname, is_ipv4_address, is_ipv6_add.. */
   33 
   34 #include <arpa/inet.h>
   35 #include <errno.h>  /* for errno, ENOTCONN, EAGAIN */
   36 #include <fcntl.h>  /* for fcntl, F_SETFL, O_NONBLOCK */
   37 #include <gcrypt.h> /* for gcry_control */
   38 #include <glib.h>   /* for g_warning, g_free, g_debug, gchar, g_markup... */
   39 #include <gnutls/x509.h> /* for gnutls_x509_crt_..., gnutls_x509_privkey_... */
   40 #include <netdb.h>      /* for addrinfo, freeaddrinfo, gai_strerror, getad... */
   41 #include <signal.h>     /* for sigaction, SIGPIPE, sigemptyset, SIG_IGN */
   42 #include <stdio.h>      /* for fclose, FILE, SEEK_END, SEEK_SET */
   43 #include <string.h>     /* for strerror, strlen, memset */
   44 #include <sys/socket.h> /* for shutdown, connect, socket, SHUT_RDWR, SOCK_... */
   45 #include <sys/types.h>
   46 #include <unistd.h> /* for close, ssize_t, usleep */
   47 
   48 #undef G_LOG_DOMAIN
   49 /**
   50  * @brief GLib log domain.
   51  */
   52 #define G_LOG_DOMAIN "lib  serv"
   53 
   54 /**
   55  * @brief Server address.
   56  */
   57 struct sockaddr_in address;
   58 
   59 static int
   60 server_attach_internal (int, gnutls_session_t *, const char *, int);
   61 static int
   62 server_new_internal (unsigned int, const char *, const gchar *, const gchar *,
   63                      const gchar *, gnutls_session_t *,
   64                      gnutls_certificate_credentials_t *);
   65 
   66 /* Connections. */
   67 
   68 /**
   69  * @brief Close UNIX socket connection.
   70  *
   71  * @param[in]  client_connection  Client connection.
   72  *
   73  * @return 0 success, -1 error.
   74  */
   75 static int
   76 close_unix (gvm_connection_t *client_connection)
   77 {
   78   /* Turn off blocking. */
   79   if (fcntl (client_connection->socket, F_SETFL, O_NONBLOCK) == -1)
   80     {
   81       g_warning ("%s: failed to set server socket flag: %s\n", __FUNCTION__,
   82                  strerror (errno));
   83       return -1;
   84     }
   85 
   86   if (shutdown (client_connection->socket, SHUT_RDWR) == -1)
   87     {
   88       if (errno == ENOTCONN)
   89         return 0;
   90       g_warning ("%s: failed to shutdown server socket: %s\n", __FUNCTION__,
   91                  strerror (errno));
   92       return -1;
   93     }
   94 
   95   if (close (client_connection->socket) == -1)
   96     {
   97       g_warning ("%s: failed to close server socket: %s\n", __FUNCTION__,
   98                  strerror (errno));
   99       return -1;
  100     }
  101 
  102   return 0;
  103 }
  104 
  105 /**
  106  * @brief Free connection.
  107  *
  108  * @param[in]  client_connection  Connection.
  109  */
  110 void
  111 gvm_connection_free (gvm_connection_t *client_connection)
  112 {
  113   if (client_connection->tls)
  114     gvm_server_free (client_connection->socket, client_connection->session,
  115                      client_connection->credentials);
  116   else
  117     close_unix (client_connection);
  118 }
  119 
  120 /* Certificate verification. */
  121 
  122 /**
  123  * @brief Verify certificate.
  124  *
  125  * @param[in]  session  Pointer to GNUTLS session.
  126  *
  127  * @return 0 on success, 1 on failure, -1 on error.
  128  */
  129 int
  130 gvm_server_verify (gnutls_session_t session)
  131 {
  132   unsigned int status;
  133   int ret;
  134 
  135   ret = gnutls_certificate_verify_peers2 (session, &status);
  136   if (ret < 0)
  137     {
  138       g_warning ("%s: failed to verify peers: %s", __FUNCTION__,
  139                  gnutls_strerror (ret));
  140       return -1;
  141     }
  142 
  143   if (status & GNUTLS_CERT_INVALID)
  144     g_warning ("%s: the certificate is not trusted", __FUNCTION__);
  145 
  146   if (status & GNUTLS_CERT_SIGNER_NOT_CA)
  147     g_warning ("%s: the certificate's issuer is not a CA", __FUNCTION__);
  148 
  149   if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
  150     g_warning ("%s: the certificate was signed using an insecure algorithm",
  151                __FUNCTION__);
  152 
  153   if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
  154     g_warning ("%s: the certificate hasn't got a known issuer", __FUNCTION__);
  155 
  156   if (status & GNUTLS_CERT_REVOKED)
  157     g_warning ("%s: the certificate has been revoked", __FUNCTION__);
  158 
  159   if (status & GNUTLS_CERT_EXPIRED)
  160     g_warning ("%s: the certificate has expired", __FUNCTION__);
  161 
  162   if (status & GNUTLS_CERT_NOT_ACTIVATED)
  163     g_warning ("%s: the certificate is not yet activated", __FUNCTION__);
  164 
  165   if (status)
  166     return 1;
  167 
  168   return 0;
  169 }
  170 
  171 /**
  172  * @brief Loads a file's data into gnutls_datum_t struct.
  173  *
  174  * @param[in]   file          File to load.
  175  * @param[out]  loaded_file   Destination to load file into.
  176  *
  177  * @return 0 if success, -1 if error.
  178  */
  179 int
  180 load_gnutls_file (const char *file, gnutls_datum_t *loaded_file)
  181 {
  182   FILE *f = NULL;
  183   int64_t filelen;
  184   void *ptr;
  185 
  186   if (!(f = fopen (file, "r")) || fseek (f, 0, SEEK_END) != 0
  187       || (filelen = ftell (f)) < 0 || fseek (f, 0, SEEK_SET) != 0
  188       || !(ptr = g_malloc0 ((size_t) filelen))
  189       || fread (ptr, 1, (size_t) filelen, f) < (size_t) filelen)
  190     {
  191       if (f)
  192         fclose (f);
  193       return -1;
  194     }
  195 
  196   loaded_file->data = ptr;
  197   loaded_file->size = filelen;
  198   fclose (f);
  199   return 0;
  200 }
  201 
  202 /**
  203  * @brief Unloads a gnutls_datum_t struct's data.
  204  *
  205  * @param[in]  data     Pointer to gnutls_datum_t struct to be unloaded.
  206  */
  207 void
  208 unload_gnutls_file (gnutls_datum_t *data)
  209 {
  210   if (data)
  211     g_free (data->data);
  212 }
  213 
  214 static char *cert_pub_mem = NULL;
  215 static char *cert_priv_mem = NULL;
  216 
  217 /**
  218  * @brief  Save cert_pub_mem with public certificate.
  219  *
  220  * @param[in] data The DER or PEM encoded certificate.
  221  */
  222 static void
  223 set_cert_pub_mem (const char *data)
  224 {
  225   if (cert_pub_mem)
  226     g_free (cert_pub_mem);
  227   cert_pub_mem = g_strdup (data);
  228 }
  229 
  230 /**
  231  * @brief Save cert_priv_mem with private certificate.
  232  *
  233  * @param[in] data The DER or PEM encoded certificate.
  234  */
  235 static void
  236 set_cert_priv_mem (const char *data)
  237 {
  238   if (cert_priv_mem)
  239     g_free (cert_priv_mem);
  240   cert_priv_mem = g_strdup (data);
  241 }
  242 
  243 /**
  244  * @brief Get private certificate from @ref cert_priv_mem.
  245  *
  246  * @return The DER or PEM encoded certificate.
  247  */
  248 static const char *
  249 get_cert_priv_mem ()
  250 {
  251   return cert_priv_mem;
  252 }
  253 
  254 /**
  255  * @brief Get public certificate from @ref cert_pub_mem.
  256  *
  257  * @return The DER or PEM encoded certificate.
  258  */
  259 static const char *
  260 get_cert_pub_mem ()
  261 {
  262   return cert_pub_mem;
  263 }
  264 
  265 /**
  266  * @brief Callback function to be called in order to retrieve the
  267  *        certificate to be used in the handshake.
  268  *
  269  * @param[in] session Pointer to GNUTLS session. Not in used. Can be NULL.
  270  * @param[in] req_ca_rdn Contains a list with the CA names that
  271  *            the server considers trusted. Not in used. Can be NULL.
  272  * @param[in] nreqs Number of CA requested.  Not in used. Can be NULL.
  273  * @param[in] sign_algos contains a list with server's acceptable public key
  274  *            algorithms. Not in used. Can be NULL.
  275  * @param[in] sign_algos_length Algos list length. Not in used. Can be NULL.
  276  * @param[out] st Should contain the certificates and private keys
  277  *
  278  * @return 0 on success, non-null otherwise.
  279  */
  280 static int
  281 client_cert_callback (gnutls_session_t session,
  282                       const gnutls_datum_t *req_ca_rdn, int nreqs,
  283                       const gnutls_pk_algorithm_t *sign_algos,
  284                       int sign_algos_length, gnutls_retr2_st *st)
  285 {
  286   int ret;
  287   gnutls_datum_t data;
  288   static gnutls_x509_crt_t crt;
  289   static gnutls_x509_privkey_t key;
  290 
  291   (void) session;
  292   (void) req_ca_rdn;
  293   (void) nreqs;
  294   (void) sign_algos;
  295   (void) sign_algos_length;
  296   data.data = (unsigned char *) g_strdup (get_cert_pub_mem ());
  297   data.size = strlen (get_cert_pub_mem ());
  298   gnutls_x509_crt_init (&crt);
  299   ret = gnutls_x509_crt_import (crt, &data, GNUTLS_X509_FMT_PEM);
  300   g_free (data.data);
  301   if (ret)
  302     return ret;
  303   st->cert.x509 = &crt;
  304   st->cert_type = GNUTLS_CRT_X509;
  305   st->ncerts = 1;
  306 
  307   data.data = (unsigned char *) g_strdup (get_cert_priv_mem ());
  308   data.size = strlen (get_cert_priv_mem ());
  309   gnutls_x509_privkey_init (&key);
  310   ret = gnutls_x509_privkey_import (key, &data, GNUTLS_X509_FMT_PEM);
  311   g_free (data.data);
  312   if (ret)
  313     return ret;
  314   st->key.x509 = key;
  315   st->key_type = GNUTLS_PRIVKEY_X509;
  316   return 0;
  317 }
  318 
  319 /**
  320  * @brief Connect to the server using a given host, port and cert.
  321  *
  322  * @param[in]  session   Pointer to GNUTLS session.
  323  * @param[in]  host      Host to connect to.
  324  * @param[in]  port      Port to connect to.
  325  * @param[in]  ca_mem    CA cert.
  326  * @param[in]  pub_mem   Public key.
  327  * @param[in]  priv_mem  Private key.
  328  * @param[in]  verify    Whether to verify.
  329  *
  330  * @return 0 on success, -1 on error.
  331  */
  332 int
  333 gvm_server_open_verify (gnutls_session_t *session, const char *host, int port,
  334                         const char *ca_mem, const char *pub_mem,
  335                         const char *priv_mem, int verify)
  336 {
  337   int ret;
  338   int server_socket;
  339   struct addrinfo address_hints;
  340   struct addrinfo *addresses, *address;
  341   gchar *port_string;
  342   int host_type;
  343 
  344   gnutls_certificate_credentials_t credentials;
  345 
  346   /* Ensure that host and port have sane values. */
  347   if (port < 1 || port > 65535)
  348     {
  349       g_warning ("Failed to create client TLS session. "
  350                  "Invalid port %d",
  351                  port);
  352       return -1;
  353     }
  354   host_type = gvm_get_host_type (host);
  355   if (!(host_type == HOST_TYPE_NAME || host_type == HOST_TYPE_IPV4
  356         || host_type == HOST_TYPE_IPV6))
  357     {
  358       g_warning ("Failed to create client TLS session. Invalid host %s", host);
  359       return -1;
  360     }
  361 
  362   /** @warning On success we are leaking the credentials. We can't free
  363       them because the session only makes a shallow copy. */
  364 
  365   if (gvm_server_new_mem (GNUTLS_CLIENT, ca_mem, pub_mem, priv_mem, session,
  366                           &credentials))
  367     {
  368       g_warning ("Failed to create client TLS session.");
  369       return -1;
  370     }
  371 
  372   if (ca_mem && pub_mem && priv_mem)
  373     {
  374       set_cert_pub_mem (pub_mem);
  375       set_cert_priv_mem (priv_mem);
  376 
  377       gnutls_certificate_set_retrieve_function (credentials,
  378                                                 client_cert_callback);
  379     }
  380 
  381   /* Create the port string. */
  382 
  383   port_string = g_strdup_printf ("%i", port);
  384 
  385   /* Get all possible addresses. */
  386 
  387   memset (&address_hints, 0, sizeof (address_hints));
  388   address_hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6. */
  389   address_hints.ai_socktype = SOCK_STREAM;
  390   address_hints.ai_protocol = 0;
  391 
  392   if (getaddrinfo (host, port_string, &address_hints, &addresses))
  393     {
  394       g_free (port_string);
  395       g_warning ("Failed to get server addresses for %s: %s", host,
  396                  gai_strerror (errno));
  397       gnutls_deinit (*session);
  398       gnutls_certificate_free_credentials (credentials);
  399       return -1;
  400     }
  401   g_free (port_string);
  402 
  403   /* Try to connect to each address in turn. */
  404 
  405   for (address = addresses; address; address = address->ai_next)
  406     {
  407       /* Make server socket. */
  408 
  409       if (address->ai_family == AF_INET6)
  410         server_socket = socket (PF_INET6, SOCK_STREAM, 0);
  411       else
  412         server_socket = socket (PF_INET, SOCK_STREAM, 0);
  413       if (server_socket == -1)
  414         {
  415           g_warning ("Failed to create server socket");
  416           freeaddrinfo (addresses);
  417           gnutls_deinit (*session);
  418           gnutls_certificate_free_credentials (credentials);
  419           return -1;
  420         }
  421 
  422       /* Connect to server. */
  423 
  424       if (connect (server_socket, address->ai_addr, address->ai_addrlen) == -1)
  425         {
  426           close (server_socket);
  427           continue;
  428         }
  429       break;
  430     }
  431 
  432   freeaddrinfo (addresses);
  433 
  434   if (address == NULL)
  435     {
  436       g_warning ("Failed to connect to server");
  437       gnutls_deinit (*session);
  438       gnutls_certificate_free_credentials (credentials);
  439       return -1;
  440     }
  441 
  442   g_debug ("   Connected to server '%s' port %d.", host, port);
  443 
  444   /* Complete setup of server session. */
  445   ret = server_attach_internal (server_socket, session, host, port);
  446   if (ret)
  447     {
  448       if (ret == -2)
  449         {
  450           close (server_socket);
  451           gnutls_deinit (*session);
  452           gnutls_certificate_free_credentials (credentials);
  453         }
  454       close (server_socket);
  455       return -1;
  456     }
  457   if (verify && gvm_server_verify (*session))
  458     {
  459       close (server_socket);
  460       return -1;
  461     }
  462 
  463   return server_socket;
  464 }
  465 
  466 /**
  467  * @brief Connect to the server using a given host, port and cert.
  468  *
  469  * Verify if all cert args are given.
  470  *
  471  * @param[in]  session   Pointer to GNUTLS session.
  472  * @param[in]  host      Host to connect to.
  473  * @param[in]  port      Port to connect to.
  474  * @param[in]  ca_mem    CA cert.
  475  * @param[in]  pub_mem   Public key.
  476  * @param[in]  priv_mem  Private key.
  477  *
  478  * @return 0 on success, -1 on error.
  479  */
  480 int
  481 gvm_server_open_with_cert (gnutls_session_t *session, const char *host,
  482                            int port, const char *ca_mem, const char *pub_mem,
  483                            const char *priv_mem)
  484 {
  485   return gvm_server_open_verify (session, host, port, ca_mem, pub_mem, priv_mem,
  486                                  ca_mem && pub_mem && priv_mem);
  487 }
  488 
  489 /**
  490  * @brief Connect to the server using a given host and port.
  491  *
  492  * @param[in]  session  Pointer to GNUTLS session.
  493  * @param[in]  host     Host to connect to.
  494  * @param[in]  port     Port to connect to.
  495  *
  496  * @return 0 on success, -1 on error.
  497  */
  498 int
  499 gvm_server_open (gnutls_session_t *session, const char *host, int port)
  500 {
  501   return gvm_server_open_with_cert (session, host, port, NULL, NULL, NULL);
  502 }
  503 
  504 /**
  505  * @brief Close a server connection and its socket.
  506  *
  507  * @param[in]  socket   Socket connected to server.
  508  * @param[in]  session  GNUTLS session with server.
  509  *
  510  * @return 0 on success, -1 on error.
  511  */
  512 int
  513 gvm_server_close (int socket, gnutls_session_t session)
  514 {
  515   return gvm_server_free (socket, session, NULL);
  516 }
  517 
  518 /**
  519  * @brief Close a server connection and its socket.
  520  *
  521  * @param[in]  connection  Connection.
  522  *
  523  * @return 0 on success, -1 on error.
  524  */
  525 void
  526 gvm_connection_close (gvm_connection_t *connection)
  527 {
  528   gvm_connection_free (connection);
  529 }
  530 
  531 /**
  532  * @brief Attach a socket to a session, and shake hands with the peer.
  533  *
  534  * @param[in]  socket   Socket.
  535  * @param[in]  session  Pointer to GNUTLS session.
  536  * @param[in]  host     NULL or the name of the host for diagnostics
  537  * @param[in]  port     Port number for diagnostics; only used
  538  *                      if \a host is not NULL
  539  *
  540  * @return 0 on success, -1 on general error, -2 if the TLS handshake failed.
  541  */
  542 static int
  543 server_attach_internal (int socket, gnutls_session_t *session, const char *host,
  544                         int port)
  545 {
  546   unsigned int retries;
  547 
  548   gnutls_transport_set_ptr (*session,
  549                             (gnutls_transport_ptr_t) GSIZE_TO_POINTER (socket));
  550 
  551   retries = 0;
  552   while (1)
  553     {
  554       int ret = gnutls_handshake (*session);
  555       if (ret >= 0)
  556         break;
  557       if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
  558         {
  559           if (retries > 10)
  560             usleep (MIN ((retries - 10) * 10000, 5000000));
  561           retries++;
  562           continue;
  563         }
  564       if (host)
  565         g_debug ("Failed to shake hands with server '%s' port %d: %s", host,
  566                  port, gnutls_strerror (ret));
  567       else
  568         g_debug ("Failed to shake hands with peer: %s", gnutls_strerror (ret));
  569       if (shutdown (socket, SHUT_RDWR) == -1)
  570         g_debug ("Failed to shutdown server socket");
  571       return -2;
  572     }
  573   if (host)
  574     g_debug ("   Shook hands with server '%s' port %d.", host, port);
  575   else
  576     g_debug ("   Shook hands with peer.");
  577 
  578   return 0;
  579 }
  580 
  581 /**
  582  * @brief Attach a socket to a session, and shake hands with the peer.
  583  *
  584  * @param[in]  socket   Socket.
  585  * @param[in]  session  Pointer to GNUTLS session.
  586  *                      FIXME: Why is this a pointer to a session?
  587  *
  588  * @return 0 on success, -1 on error.
  589  */
  590 int
  591 gvm_server_attach (int socket, gnutls_session_t *session)
  592 {
  593   int ret;
  594 
  595   ret = server_attach_internal (socket, session, NULL, 0);
  596   return ret ? -1 : 0;
  597 }
  598 
  599 /**
  600  * @brief Send a string to the server.
  601  *
  602  * @param[in]  session  Pointer to GNUTLS session.
  603  * @param[in]  fmt      Format of string to send.
  604  * @param[in]  ap       Args for fmt.
  605  * @param[in]  quiet    Whether to log debug and info messages.  Useful for
  606  *                      hiding passwords.
  607  *
  608  * @return 0 on success, 1 if server closed connection, -1 on error.
  609  */
  610 static int
  611 gvm_server_vsendf_internal (gnutls_session_t *session, const char *fmt,
  612                             va_list ap, int quiet)
  613 {
  614   char *sref, *string;
  615   int rc = 0, left;
  616 
  617   left = vasprintf (&string, fmt, ap);
  618   if (left == -1)
  619     string = NULL;
  620 
  621   sref = string;
  622   while (left > 0)
  623     {
  624       ssize_t count;
  625 
  626       if (quiet == 0)
  627         g_debug ("   send %d from %.*s[...]", left, left < 30 ? left : 30,
  628                  string);
  629       count = gnutls_record_send (*session, string, left);
  630       if (count < 0)
  631         {
  632           if (count == GNUTLS_E_INTERRUPTED)
  633             /* Interrupted, try write again. */
  634             continue;
  635           if (count == GNUTLS_E_REHANDSHAKE)
  636             {
  637               /* \todo Rehandshake. */
  638               if (quiet == 0)
  639                 g_message ("   %s rehandshake", __FUNCTION__);
  640               continue;
  641             }
  642           g_warning ("Failed to write to server: %s", gnutls_strerror (count));
  643           rc = -1;
  644           goto out;
  645         }
  646       if (count == 0)
  647         {
  648           /* Server closed connection. */
  649           if (quiet == 0)
  650             g_debug ("=  server closed");
  651           rc = 1;
  652           goto out;
  653         }
  654       if (quiet == 0)
  655         g_debug ("=> %.*s", (int) count, string);
  656       string += count;
  657       left -= count;
  658     }
  659   if (quiet == 0)
  660     g_debug ("=> done");
  661 
  662 out:
  663   g_free (sref);
  664   return rc;
  665 }
  666 
  667 /**
  668  * @brief Send a string to the server.
  669  *
  670  * @param[in]  socket   Socket.
  671  * @param[in]  fmt      Format of string to send.
  672  * @param[in]  ap       Args for fmt.
  673  * @param[in]  quiet    Whether to log debug and info messages.  Useful for
  674  *                      hiding passwords.
  675  *
  676  * @return 0 on success, 1 if server closed connection, -1 on error.
  677  */
  678 static int
  679 unix_vsendf_internal (int socket, const char *fmt, va_list ap, int quiet)
  680 {
  681   char *string_start, *string;
  682   int rc = 0, left;
  683 
  684   left = vasprintf (&string, fmt, ap);
  685   if (left == -1)
  686     string = NULL;
  687 
  688   string_start = string;
  689   while (left > 0)
  690     {
  691       ssize_t count;
  692 
  693       if (quiet == 0)
  694         g_debug ("   send %d from %.*s[...]", left, left < 30 ? left : 30,
  695                  string);
  696       count = write (socket, string, left);
  697       if (count < 0)
  698         {
  699           if (errno == EINTR || errno == EAGAIN)
  700             continue;
  701           g_warning ("Failed to write to server: %s", strerror (errno));
  702           rc = -1;
  703           goto out;
  704         }
  705       if (quiet == 0)
  706         g_debug ("=> %.*s", (int) count, string);
  707 
  708       string += count;
  709       left -= count;
  710     }
  711   if (quiet == 0)
  712     g_debug ("=> done");
  713 
  714 out:
  715   g_free (string_start);
  716   return rc;
  717 }
  718 
  719 /**
  720  * @brief Send a string to the connection.
  721  *
  722  * @param[in]  connection  Connection.
  723  * @param[in]  fmt         Format of string to send.
  724  * @param[in]  ap          Args for fmt.
  725  * @param[in]  quiet       Whether to log debug and info messages.  Useful for
  726  *                         hiding passwords.
  727  *
  728  * @return 0 on success, 1 if server closed connection, -1 on error.
  729  */
  730 static int
  731 gvm_connection_vsendf_internal (gvm_connection_t *connection, const char *fmt,
  732                                 va_list ap, int quiet)
  733 {
  734   if (connection->tls)
  735     return gvm_server_vsendf_internal (&connection->session, fmt, ap, quiet);
  736   return unix_vsendf_internal (connection->socket, fmt, ap, quiet);
  737 }
  738 
  739 /**
  740  * @brief Send a string to the server.
  741  *
  742  * @param[in]  session  Pointer to GNUTLS session.
  743  * @param[in]  fmt      Format of string to send.
  744  * @param[in]  ap       Args for fmt.
  745  *
  746  * @return 0 on success, 1 if server closed connection, -1 on error.
  747  */
  748 int
  749 gvm_server_vsendf (gnutls_session_t *session, const char *fmt, va_list ap)
  750 {
  751   return gvm_server_vsendf_internal (session, fmt, ap, 0);
  752 }
  753 
  754 /**
  755  * @brief Send a string to the server.
  756  *
  757  * @param[in]  socket   Socket to send string through.
  758  * @param[in]  fmt      Format of string to send.
  759  * @param[in]  ap       Args for fmt.
  760  *
  761  * @return 0 on success, 1 if server closed connection, -1 on error.
  762  */
  763 int
  764 gvm_socket_vsendf (int socket, const char *fmt, va_list ap)
  765 {
  766   return unix_vsendf_internal (socket, fmt, ap, 0);
  767 }
  768 
  769 /**
  770  * @brief Send a string to the server.
  771  *
  772  * @param[in]  connection  Connection.
  773  * @param[in]  fmt         Format of string to send.
  774  * @param[in]  ap          Args for fmt.
  775  *
  776  * @return 0 on success, 1 if server closed connection, -1 on error.
  777  */
  778 int
  779 gvm_connection_vsendf (gvm_connection_t *connection, const char *fmt,
  780                        va_list ap)
  781 {
  782   return gvm_connection_vsendf_internal (connection, fmt, ap, 0);
  783 }
  784 
  785 /**
  786  * @brief Send a string to the server, refraining from logging besides warnings.
  787  *
  788  * @param[in]  session  Pointer to GNUTLS session.
  789  * @param[in]  fmt      Format of string to send.
  790  * @param[in]  ap       Args for fmt.
  791  *
  792  * @return 0 on success, 1 if server closed connection, -1 on error.
  793  */
  794 int
  795 gvm_server_vsendf_quiet (gnutls_session_t *session, const char *fmt, va_list ap)
  796 {
  797   return gvm_server_vsendf_internal (session, fmt, ap, 1);
  798 }
  799 
  800 /**
  801  * @brief Send a string to the server, refraining from logging besides warnings.
  802  *
  803  * @param[in]  connection  Connection.
  804  * @param[in]  fmt         Format of string to send.
  805  * @param[in]  ap          Args for fmt.
  806  *
  807  * @return 0 on success, 1 if server closed connection, -1 on error.
  808  */
  809 int
  810 gvm_connection_vsendf_quiet (gvm_connection_t *connection, const char *fmt,
  811                              va_list ap)
  812 {
  813   return gvm_connection_vsendf_internal (connection, fmt, ap, 1);
  814 }
  815 
  816 /**
  817  * @brief Format and send a string to the server.
  818  *
  819  * @param[in]  session  Pointer to GNUTLS session.
  820  * @param[in]  format   printf-style format string for message.
  821  *
  822  * @return 0 on success, -1 on error.
  823  */
  824 int
  825 gvm_server_sendf (gnutls_session_t *session, const char *format, ...)
  826 {
  827   va_list ap;
  828   int rc;
  829 
  830   va_start (ap, format);
  831   rc = gvm_server_vsendf (session, format, ap);
  832   va_end (ap);
  833   return rc;
  834 }
  835 
  836 /**
  837  * @brief Format and send a string to the server.
  838  *
  839  * @param[in]  connection  Connection.
  840  * @param[in]  format      printf-style format string for message.
  841  *
  842  * @return 0 on success, -1 on error.
  843  */
  844 int
  845 gvm_connection_sendf (gvm_connection_t *connection, const char *format, ...)
  846 {
  847   va_list ap;
  848   int rc;
  849 
  850   va_start (ap, format);
  851   rc = gvm_connection_vsendf (connection, format, ap);
  852   va_end (ap);
  853   return rc;
  854 }
  855 
  856 /**
  857  * @brief Format and send a string to the server.
  858  *
  859  * @param[in]  session  Pointer to GNUTLS session.
  860  * @param[in]  format   printf-style format string for message.
  861  *
  862  * @return 0 on success, -1 on error.
  863  */
  864 int
  865 gvm_server_sendf_quiet (gnutls_session_t *session, const char *format, ...)
  866 {
  867   va_list ap;
  868   int rc;
  869 
  870   va_start (ap, format);
  871   rc = gvm_server_vsendf_quiet (session, format, ap);
  872   va_end (ap);
  873   return rc;
  874 }
  875 
  876 /**
  877  * @brief Format and send a string to the server.
  878  *
  879  * @param[in]  connection  Connection.
  880  * @param[in]  format      printf-style format string for message.
  881  *
  882  * @return 0 on success, -1 on error.
  883  */
  884 int
  885 gvm_connection_sendf_quiet (gvm_connection_t *connection, const char *format,
  886                             ...)
  887 {
  888   va_list ap;
  889   int rc;
  890 
  891   va_start (ap, format);
  892   rc = gvm_connection_vsendf_quiet (connection, format, ap);
  893   va_end (ap);
  894   return rc;
  895 }
  896 
  897 /**
  898  * @brief Format and send an XML string to the server.
  899  *
  900  * Escape XML in string and character args.
  901  *
  902  * @param[in]  session  Pointer to GNUTLS session.
  903  * @param[in]  format   printf-style format string for message.
  904  *
  905  * @return 0 on success, -1 on error.
  906  */
  907 int
  908 gvm_server_sendf_xml (gnutls_session_t *session, const char *format, ...)
  909 {
  910   va_list ap;
  911   gchar *msg;
  912   int rc;
  913 
  914   va_start (ap, format);
  915   msg = g_markup_vprintf_escaped (format, ap);
  916   rc = gvm_server_sendf (session, "%s", msg);
  917   g_free (msg);
  918   va_end (ap);
  919   return rc;
  920 }
  921 
  922 /**
  923  * @brief Format and send an XML string to the server.
  924  *
  925  * Escape XML in string and character args.
  926  *
  927  * @param[in]  connection  Connection.
  928  * @param[in]  format      printf-style format string for message.
  929  *
  930  * @return 0 on success, -1 on error.
  931  */
  932 int
  933 gvm_connection_sendf_xml (gvm_connection_t *connection, const char *format, ...)
  934 {
  935   va_list ap;
  936   gchar *msg;
  937   int rc;
  938 
  939   va_start (ap, format);
  940   msg = g_markup_vprintf_escaped (format, ap);
  941   rc = gvm_connection_sendf (connection, "%s", msg);
  942   g_free (msg);
  943   va_end (ap);
  944   return rc;
  945 }
  946 
  947 /**
  948  * @brief Format and send an XML string to the server.
  949  *
  950  * Escape XML in string and character args.
  951  *
  952  * Quiet version, only logs warnings.
  953  *
  954  * @param[in]  session  Pointer to GNUTLS session.
  955  * @param[in]  format   printf-style format string for message.
  956  *
  957  * @return 0 on success, -1 on error.
  958  */
  959 int
  960 gvm_server_sendf_xml_quiet (gnutls_session_t *session, const char *format, ...)
  961 {
  962   va_list ap;
  963   gchar *msg;
  964   int rc;
  965 
  966   va_start (ap, format);
  967   msg = g_markup_vprintf_escaped (format, ap);
  968   rc = gvm_server_sendf_quiet (session, "%s", msg);
  969   g_free (msg);
  970   va_end (ap);
  971   return rc;
  972 }
  973 
  974 /**
  975  * @brief Format and send an XML string to the server.
  976  *
  977  * Escape XML in string and character args.
  978  *
  979  * Quiet version, only logs warnings.
  980  *
  981  * @param[in]  connection  Connection.
  982  * @param[in]  format      printf-style format string for message.
  983  *
  984  * @return 0 on success, -1 on error.
  985  */
  986 int
  987 gvm_connection_sendf_xml_quiet (gvm_connection_t *connection,
  988                                 const char *format, ...)
  989 {
  990   va_list ap;
  991   gchar *msg;
  992   int rc;
  993 
  994   va_start (ap, format);
  995   msg = g_markup_vprintf_escaped (format, ap);
  996   rc = gvm_connection_sendf_quiet (connection, "%s", msg);
  997   g_free (msg);
  998   va_end (ap);
  999   return rc;
 1000 }
 1001 
 1002 /**
 1003  * @brief Initialize a server session.
 1004  *
 1005  * @param[in]  server_credentials  Credentials to be allocated.
 1006  *
 1007  * @return 0 on success, -1 on error.
 1008  */
 1009 static int
 1010 server_new_gnutls_init (gnutls_certificate_credentials_t *server_credentials)
 1011 {
 1012   /* Turn off use of /dev/random, as this can block. */
 1013   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
 1014 
 1015   /* Initialize security library. */
 1016   if (gnutls_global_init ())
 1017     {
 1018       g_warning ("Failed to initialize GNUTLS.");
 1019       return -1;
 1020     }
 1021   /* Setup server session. */
 1022   if (gnutls_certificate_allocate_credentials (server_credentials))
 1023     {
 1024       g_warning ("%s: failed to allocate server credentials\n", __FUNCTION__);
 1025       return -1;
 1026     }
 1027   return 0;
 1028 }
 1029 
 1030 /**
 1031  * @brief Set the server credencials.
 1032  *
 1033  * @param[in]  end_type Connection end type.
 1034  * @param[in]  priority TLS priority to be set. If no one is given, NORMAL is
 1035  *             default.
 1036  * @param[in]  server_session GNUTLS session.
 1037  * @param[in]  server_credentials Credentials to be set.
 1038  *
 1039  * @return 0 on success, -1 on error.
 1040  */
 1041 static int
 1042 server_new_gnutls_set (unsigned int end_type, const char *priority,
 1043                        gnutls_session_t *server_session,
 1044                        gnutls_certificate_credentials_t *server_credentials)
 1045 {
 1046   int err_gnutls;
 1047 
 1048   if (gnutls_init (server_session, end_type))
 1049     {
 1050       g_warning ("%s: failed to initialise server session\n", __FUNCTION__);
 1051       return -1;
 1052     }
 1053 
 1054   /* Depending on gnutls version different priority strings are
 1055      possible. At least from 3.0 this is an option:
 1056      "NONE:+VERS-TLS1.0:+CIPHER-ALL:+COMP-ALL:+RSA:+DHE-RSA:+DHE-DSS:+MAC-ALL"
 1057      But in fact this function is only for internal
 1058      purposes, not for scanning abilities. So, the conservative "NORMAL"
 1059      is chosen.
 1060   */
 1061 
 1062   if ((err_gnutls = gnutls_priority_set_direct (
 1063          *server_session, priority ? priority : "NORMAL", NULL)))
 1064     {
 1065       g_warning ("%s: failed to set tls priorities: %s\n", __FUNCTION__,
 1066                  gnutls_strerror (err_gnutls));
 1067       gnutls_deinit (*server_session);
 1068       return -1;
 1069     }
 1070 
 1071   if (gnutls_credentials_set (*server_session, GNUTLS_CRD_CERTIFICATE,
 1072                               *server_credentials))
 1073     {
 1074       g_warning ("%s: failed to set server credentials\n", __FUNCTION__);
 1075       gnutls_deinit (*server_session);
 1076       return -1;
 1077     }
 1078 
 1079   if (end_type == GNUTLS_SERVER)
 1080     gnutls_certificate_server_set_request (*server_session,
 1081                                            GNUTLS_CERT_REQUEST);
 1082   return 0;
 1083 }
 1084 
 1085 /**
 1086  * @brief Make a session for connecting to a server.
 1087  *
 1088  * @param[in]   end_type            Connection end type (GNUTLS_SERVER or
 1089  *                                  GNUTLS_CLIENT).
 1090  * @param[in]   priority            Custom priority string or NULL.
 1091  * @param[in]   ca_cert_file        Certificate authority file.
 1092  * @param[in]   cert_file           Certificate file.
 1093  * @param[in]   key_file            Key file.
 1094  * @param[out]  server_session      The session with the server.
 1095  * @param[out]  server_credentials  Server credentials.
 1096  *
 1097  * @return 0 on success, -1 on error.
 1098  */
 1099 static int
 1100 server_new_internal (unsigned int end_type, const char *priority,
 1101                      const gchar *ca_cert_file, const gchar *cert_file,
 1102                      const gchar *key_file, gnutls_session_t *server_session,
 1103                      gnutls_certificate_credentials_t *server_credentials)
 1104 {
 1105   if (server_new_gnutls_init (server_credentials))
 1106     return -1;
 1107 
 1108   if (cert_file && key_file)
 1109     {
 1110       int ret;
 1111 
 1112       ret = gnutls_certificate_set_x509_key_file (
 1113         *server_credentials, cert_file, key_file, GNUTLS_X509_FMT_PEM);
 1114       if (ret < 0)
 1115         {
 1116           g_warning ("%s: failed to set credentials key file: %s\n",
 1117                      __FUNCTION__, gnutls_strerror (ret));
 1118           g_warning ("%s:   cert file: %s\n", __FUNCTION__, cert_file);
 1119           g_warning ("%s:   key file : %s\n", __FUNCTION__, key_file);
 1120           gnutls_certificate_free_credentials (*server_credentials);
 1121           return -1;
 1122         }
 1123     }
 1124 
 1125   if (ca_cert_file)
 1126     {
 1127       int ret;
 1128 
 1129       ret = gnutls_certificate_set_x509_trust_file (
 1130         *server_credentials, ca_cert_file, GNUTLS_X509_FMT_PEM);
 1131       if (ret < 0)
 1132         {
 1133           g_warning ("%s: failed to set credentials trust file: %s\n",
 1134                      __FUNCTION__, gnutls_strerror (ret));
 1135           g_warning ("%s: trust file: %s\n", __FUNCTION__, ca_cert_file);
 1136           gnutls_certificate_free_credentials (*server_credentials);
 1137           return -1;
 1138         }
 1139     }
 1140 
 1141   if (server_new_gnutls_set (end_type, priority, server_session,
 1142                              server_credentials))
 1143     {
 1144       gnutls_certificate_free_credentials (*server_credentials);
 1145       return -1;
 1146     }
 1147 
 1148   return 0;
 1149 }
 1150 
 1151 /**
 1152  * @brief Make a session for connecting to a server.
 1153  *
 1154  * @param[in]   end_type            Connection end type (GNUTLS_SERVER or
 1155  *                                  GNUTLS_CLIENT).
 1156  * @param[in]   ca_cert_file        Certificate authority file.
 1157  * @param[in]   cert_file           Certificate file.
 1158  * @param[in]   key_file            Key file.
 1159  * @param[out]  server_session      The session with the server.
 1160  * @param[out]  server_credentials  Server credentials.
 1161  *
 1162  * @return 0 on success, -1 on error.
 1163  */
 1164 int
 1165 gvm_server_new (unsigned int end_type, gchar *ca_cert_file, gchar *cert_file,
 1166                 gchar *key_file, gnutls_session_t *server_session,
 1167                 gnutls_certificate_credentials_t *server_credentials)
 1168 {
 1169   return server_new_internal (end_type, NULL, ca_cert_file, cert_file, key_file,
 1170                               server_session, server_credentials);
 1171 }
 1172 
 1173 /**
 1174  * @brief Make a session for connecting to a server, with certificates stored
 1175  *        in memory.
 1176  *
 1177  * @param[in]   end_type    Connecton end type: GNUTLS_SERVER or GNUTLS_CLIENT.
 1178  * @param[in]   ca_cert     Certificate authority public key.
 1179  * @param[in]   pub_key     Public key.
 1180  * @param[in]   priv_key    Private key.
 1181  * @param[out]  session     The session with the server.
 1182  * @param[out]  credentials Server credentials.
 1183  *
 1184  * @return 0 on success, -1 on error.
 1185  */
 1186 int
 1187 gvm_server_new_mem (unsigned int end_type, const char *ca_cert,
 1188                     const char *pub_key, const char *priv_key,
 1189                     gnutls_session_t *session,
 1190                     gnutls_certificate_credentials_t *credentials)
 1191 {
 1192   if (server_new_gnutls_init (credentials))
 1193     return -1;
 1194 
 1195   if (pub_key && priv_key)
 1196     {
 1197       int ret;
 1198       gnutls_datum_t pub, priv;
 1199 
 1200       pub.data = (void *) pub_key;
 1201       pub.size = strlen (pub_key);
 1202       priv.data = (void *) priv_key;
 1203       priv.size = strlen (priv_key);
 1204 
 1205       ret = gnutls_certificate_set_x509_key_mem (*credentials, &pub, &priv,
 1206                                                  GNUTLS_X509_FMT_PEM);
 1207       if (ret < 0)
 1208         {
 1209           g_warning ("%s: %s\n", __FUNCTION__, gnutls_strerror (ret));
 1210           return -1;
 1211         }
 1212     }
 1213 
 1214   if (ca_cert)
 1215     {
 1216       int ret;
 1217       gnutls_datum_t data;
 1218 
 1219       data.data = (void *) ca_cert;
 1220       data.size = strlen (ca_cert);
 1221       ret = gnutls_certificate_set_x509_trust_mem (*credentials, &data,
 1222                                                    GNUTLS_X509_FMT_PEM);
 1223       if (ret < 0)
 1224         {
 1225           g_warning ("%s: %s\n", __FUNCTION__, gnutls_strerror (ret));
 1226           gnutls_certificate_free_credentials (*credentials);
 1227           return -1;
 1228         }
 1229     }
 1230 
 1231   if (server_new_gnutls_set (end_type, NULL, session, credentials))
 1232     {
 1233       gnutls_certificate_free_credentials (*credentials);
 1234       return -1;
 1235     }
 1236 
 1237   return 0;
 1238 }
 1239 
 1240 /**
 1241  * @brief Set a gnutls session's  Diffie-Hellman parameters.
 1242  *
 1243  * @param[in]   creds           GnuTLS credentials.
 1244  * @param[in]   dhparams_file   Path to PEM file containing the DH parameters.
 1245  *
 1246  * @return 0 on success, -1 on error.
 1247  */
 1248 int
 1249 set_gnutls_dhparams (gnutls_certificate_credentials_t creds,
 1250                      const char *dhparams_file)
 1251 {
 1252   int ret;
 1253   gnutls_datum_t data;
 1254 
 1255   if (!creds || !dhparams_file)
 1256     return -1;
 1257 
 1258   if (load_gnutls_file (dhparams_file, &data))
 1259     return -1;
 1260   gnutls_dh_params_t params = g_malloc0 (sizeof (gnutls_dh_params_t));
 1261   ret = gnutls_dh_params_import_pkcs3 (params, &data, GNUTLS_X509_FMT_PEM);
 1262   unload_gnutls_file (&data);
 1263   if (ret)
 1264     return -1;
 1265   else
 1266     gnutls_certificate_set_dh_params (creds, params);
 1267   return 0;
 1268 }
 1269 
 1270 /**
 1271  * @brief Cleanup a server session.
 1272  *
 1273  * This shuts down the TLS session, closes the socket and releases the
 1274  * TLS resources.
 1275  *
 1276  * @param[in]  server_socket       The socket connected to the server.
 1277  * @param[in]  server_session      The session with the server.
 1278  * @param[in]  server_credentials  Credentials or NULL.
 1279  *
 1280  * @return 0 success, -1 error.
 1281  */
 1282 int
 1283 gvm_server_free (int server_socket, gnutls_session_t server_session,
 1284                  gnutls_certificate_credentials_t server_credentials)
 1285 {
 1286   /* Turn off blocking. */
 1287   // FIX get flags first
 1288   if (fcntl (server_socket, F_SETFL, O_NONBLOCK) == -1)
 1289     {
 1290       g_warning ("%s: failed to set server socket flag: %s\n", __FUNCTION__,
 1291                  strerror (errno));
 1292       return -1;
 1293     }
 1294 
 1295   while (1)
 1296     {
 1297       int ret = gnutls_bye (server_session, GNUTLS_SHUT_WR);
 1298       if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
 1299         {
 1300           continue;
 1301         }
 1302       if (ret)
 1303         {
 1304           g_debug ("   Failed to gnutls_bye: %s\n",
 1305                    gnutls_strerror ((int) ret));
 1306           /* Carry on successfully anyway, as this often fails, perhaps
 1307            * because the server is closing the connection first. */
 1308           break;
 1309         }
 1310       break;
 1311     }
 1312 
 1313   /* The former separate code in gvm_server_close and here
 1314      differed in the order the TLS session and socket was closed.  The
 1315      way we do it here seems to be the right thing but for full
 1316      backward compatibility we do it for calls from
 1317      gvm_server_close in the old way.  We can distinguish the two
 1318      modes by the existence of server_credentials.  */
 1319   if (server_credentials)
 1320     {
 1321       if (close (server_socket) == -1)
 1322         {
 1323           g_warning ("%s: failed to close server socket: %s\n", __FUNCTION__,
 1324                      strerror (errno));
 1325           return -1;
 1326         }
 1327       gnutls_deinit (server_session);
 1328       gnutls_certificate_free_credentials (server_credentials);
 1329     }
 1330   else
 1331     {
 1332       gnutls_deinit (server_session);
 1333       close (server_socket);
 1334     }
 1335 
 1336   gnutls_global_deinit ();
 1337 
 1338   return 0;
 1339 }