=head1 NAME

nbd_set_tls - enable or require TLS (authentication and encryption)

=head1 SYNOPSIS

 #include <libnbd.h>

 int nbd_set_tls (
       struct nbd_handle *h, int tls
     );

=head1 DESCRIPTION

Enable or require TLS
(authenticated and encrypted connections) to the
NBD server.  The possible settings are:

=over 4

=item C<LIBNBD_TLS_DISABLE>

Disable TLS.  (The default setting, unless using L<nbd_connect_uri(3)> with
a URI that requires TLS).

This setting is also necessary if you use L<nbd_set_opt_mode(3)>
and want to interact in plaintext with a server that implements
the NBD protocol's C<SELECTIVETLS> mode, prior to enabling TLS
with L<nbd_opt_starttls(3)>.  Most NBD servers with TLS support
prefer the NBD protocol's C<FORCEDTLS> mode, so this sort of
manual interaction tends to be useful mainly during integration
testing.

=item C<LIBNBD_TLS_ALLOW>

Enable TLS if possible.

This option is insecure (or best effort) in that in some cases
it will fall back to an unencrypted and/or unauthenticated
connection if TLS could not be established.  Use
C<LIBNBD_TLS_REQUIRE> below if the connection must be
encrypted.

Some servers will drop the connection if TLS fails
so fallback may not be possible.

=item C<LIBNBD_TLS_REQUIRE>

Require an encrypted and authenticated TLS connection.
Always fail to connect if the connection is not encrypted
and authenticated.

=back

As well as calling this you may also need to supply
the path to the certificates directory (L<nbd_set_tls_certificates(3)>),
the username (L<nbd_set_tls_username(3)>) and/or
the Pre-Shared Keys (PSK) file (L<nbd_set_tls_psk_file(3)>).  For now,
when using L<nbd_connect_uri(3)>, any URI query parameters related to
TLS are not handled automatically.  Setting the level higher than
zero will fail if libnbd was not compiled against gnutls; you can
test whether this is the case with L<nbd_supports_tls(3)>.

=head1 RETURN VALUE

If the call is successful the function returns C<0>.

=head1 ERRORS

On error C<-1> is returned.

Refer to L<libnbd(3)/ERROR HANDLING>
for how to get further details of the error.

The following parameters must not be NULL: C<h>.
For more information see L<libnbd(3)/Non-NULL parameters>.

=head1 HANDLE STATE

nbd_set_tls
can be called when the handle is in the following state:

 ┌─────────────────────────────────────┬─────────────────────────┐
 │ Handle created, before connecting   │ ✅ allowed              │
 │ Connecting                          │ ❌ error                │
 │ Connecting & handshaking (opt_mode) │ ❌ error                │
 │ Connected to the server             │ ❌ error                │
 │ Connection shut down                │ ❌ error                │
 │ Handle dead                         │ ❌ error                │
 └─────────────────────────────────────┴─────────────────────────┘

=head1 VERSION

This function first appeared in libnbd 1.0.

If you need to test if this function is available at compile time
check if the following macro is defined:

 #define LIBNBD_HAVE_NBD_SET_TLS 1

=head1 EXAMPLE

This example is also available as F<examples/encryption.c>
in the libnbd source code.

 /* An example showing how to connect to a server which is
  * using TLS encryption.
  *
  * This requires nbdkit, and psktool from gnutls.
  *
  * Both libnbd and nbdkit support TLS-PSK which is a
  * simpler-to-deploy form of encryption.  (Of course
  * certificate-based encryption is also supported, but
  * it’s harder to make a self-contained example).
  */

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>

 #include <libnbd.h>

 #define TMPDIR "/tmp/XXXXXX"
 #define KEYS "keys.psk"
 #define USERNAME "alice"

 static char dir[] = TMPDIR;
 static char keys[] = TMPDIR "/" KEYS;
 static char cmd[] =
   "psktool -u " USERNAME " -p " TMPDIR "/" KEYS;

 /* Remove the temporary keys file when the program
  * exits.
  */
 static void
 cleanup_keys (void)
 {
   unlink (keys);
   rmdir (dir);
 }

 /* Create the temporary keys file to share with the
  * server.
  */
 static void
 create_keys (void)
 {
   size_t i;

   if (mkdtemp (dir) == NULL) {
     perror ("mkdtemp");
     exit (EXIT_FAILURE);
   }
   i = strlen (cmd) - strlen (TMPDIR) - strlen (KEYS) - 1;
   memcpy (&cmd[i], dir, strlen (TMPDIR));
   memcpy (keys, dir, strlen (TMPDIR));

   if (system (cmd) != 0) {
     fprintf (stderr, "psktool command failed\n");
     exit (EXIT_FAILURE);
   }

   atexit (cleanup_keys);
 }

 int
 main (int argc, char *argv[])
 {
   struct nbd_handle *nbd;
   char buf[512];

   create_keys ();

   /* Create the libnbd handle. */
   nbd = nbd_create ();
   if (nbd == NULL) {
     fprintf (stderr, "%s\n", nbd_get_error ());
     exit (EXIT_FAILURE);
   }

   /* Enable TLS in the client. */
   if (nbd_set_tls (nbd, LIBNBD_TLS_REQUIRE) == -1) {
     fprintf (stderr, "%s\n", nbd_get_error ());
     exit (EXIT_FAILURE);
   }

   /* Enable TLS-PSK and pass the keys filename. */
   if (nbd_set_tls_psk_file (nbd, keys) == -1) {
     fprintf (stderr, "%s\n", nbd_get_error ());
     exit (EXIT_FAILURE);
   }

   /* Set the local username for authentication. */
   if (nbd_set_tls_username (nbd, USERNAME) == -1) {
     fprintf (stderr, "%s\n", nbd_get_error ());
     exit (EXIT_FAILURE);
   }

   /* Run nbdkit as a subprocess, enabling and requiring
    * TLS-PSK encryption.
    */
   char *args[] = {
     "nbdkit", "-s", "--exit-with-parent",
     "--tls", "require", "--tls-psk", keys,
     "pattern", "size=1M", NULL
   };
   if (nbd_connect_command (nbd, args) == -1) {
     fprintf (stderr, "%s\n", nbd_get_error ());
     exit (EXIT_FAILURE);
   }

   /* Read the first sector. */
   if (nbd_pread (nbd, buf, sizeof buf, 0, 0) == -1) {
     fprintf (stderr, "%s\n", nbd_get_error ());
     exit (EXIT_FAILURE);
   }

   /* TLS connections must be shut down. */
   if (nbd_shutdown (nbd, 0) == -1) {
     fprintf (stderr, "%s\n", nbd_get_error ());
     exit (EXIT_FAILURE);
   }

   /* Close the libnbd handle. */
   nbd_close (nbd);

   exit (EXIT_SUCCESS);
 }

=head1 SEE ALSO

L<nbd_connect_uri(3)>,
L<nbd_create(3)>,
L<nbd_get_tls(3)>,
L<nbd_get_tls_negotiated(3)>,
L<nbd_opt_starttls(3)>,
L<nbd_set_opt_mode(3)>,
L<nbd_set_tls_certificates(3)>,
L<nbd_set_tls_priority(3)>,
L<nbd_set_tls_psk_file(3)>,
L<nbd_set_tls_username(3)>,
L<nbd_supports_tls(3)>,
L<libnbd(3)/ENCRYPTION AND AUTHENTICATION>,
L<libnbd(3)>.

=head1 AUTHORS

Eric Blake

Richard W.M. Jones

=head1 COPYRIGHT

Copyright Red Hat
