redhat-based EL9 distros not supported?
by Harry Bryson
Prior to Enterprise Linux 9, it seems some Red Hat based distros returned "redhat-based" for inspect-get-distro
This allowed things like "virt-customize --firstboot-command" to work as this matched the supported distro list, e.g.
| "fedora"|"rhel"|"centos"|"scientificlinux"|"oraclelinux"|"redhat-based"
However, it seems some distros, e.g. Rocky9 and AlmaLinux9 are now returning "rocky"/"almalinux" for inspect-get-distro
When using virt-install and then virt-customize, I am seeing issues like the following:
[Rocky9]$ virt-customize -a disk.qcow2 --firstboot-command /tmp/bootstrap
[ 0.0] Examining the guest ...
[ 17.1] Setting a random seed
[ 17.3] Installing firstboot command: /tmp/bootstrap
virt-customize: error: guest type rocky is not supported
Is there some way to return "redhat-based" again for inspect-get-distro or does the distro list matching need to be updated?
I possibly updated the OS database (osinfo-query os) to support newer OS - is this related to this problem?
Harry
Harry Bryson | Software Engineer
Harry.Bryson(a)corero.com <mailto:Harry.Bryson@corero.com>
53 Hanover Street, Edinburgh, EH2 2PJ United Kingdom
Access Corero Network Security?s Privacy Policy here <www.corero.com/privacy>.
We are Corero Network Security plc (?Corero?), registered in England and Wales, with registered company number 02662978, registered office address Regus House Highbridge, Oxford Road, Uxbridge, Middlesex, UB8 1HR. Corero is the parent company for Corero Network Security, Inc. and Corero Network Security (UK) Ltd (a company registered in England and Wales with registered number 04047090, with the same registered office address as above) For information about how we process your data, or to manage your data preferences, click here <info.corero.com/data-preferences.html>.
2 years, 1 month
[libnbd PATCH] api: Add nbd_[aio_]opt_starttls
by Eric Blake
Very similar to the recent addition of nbd_opt_structured_reply, with
the new nbd_opt_starttls() finally giving us fine-grained control over
NBD_OPT_STARTTLS, and allowing productive handshaking with a server in
SELECTIVETLS mode.
With this patch, it is now easy to reproduce the scenario of nbdkit's
CVE-2021-3716, where a plaintext meddler-in-the-middle attacker could
cause client denial of service when a --tls=on server failed to reset
state after NBD_OPT_STARTTLS. This also exposed the fact that nbdkit
was not gracefully handling NBD_OPT_INFO from a plaintext client
connecting to a --tls=require server; the testsuite is skipped unless
using a fixed nbdkit (v1.33.2 or later).
---
generator/API.ml | 98 +++++++++++--
generator/states-newstyle-opt-starttls.c | 40 ++++--
generator/states-newstyle.c | 3 +
lib/opt.c | 50 +++++++
tests/Makefile.am | 5 +
tests/opt-starttls.c | 166 +++++++++++++++++++++++
.gitignore | 1 +
7 files changed, 343 insertions(+), 20 deletions(-)
create mode 100644 tests/opt-starttls.c
diff --git a/generator/API.ml b/generator/API.ml
index 69849102..8301ec9f 100644
--- a/generator/API.ml
+++ b/generator/API.ml
@@ -599,7 +599,11 @@ "set_tls", {
=item C<LIBNBD_TLS_DISABLE>
Disable TLS. (The default setting, unless using L<nbd_connect_uri(3)> with
-a URI that requires TLS)
+a URI that requires TLS).
+
+This setting is also useful during integration testing when using
+L<nbd_set_opt_mode(3)> and L<nbd_opt_starttls(3)> for manual
+control over when to request TLS negotiation.
=item C<LIBNBD_TLS_ALLOW>
@@ -632,7 +636,8 @@ "set_tls", {
test whether this is the case with L<nbd_supports_tls(3)>.";
example = Some "examples/encryption.c";
see_also = [SectionLink "ENCRYPTION AND AUTHENTICATION";
- Link "get_tls"; Link "get_tls_negotiated"];
+ Link "get_tls"; Link "get_tls_negotiated";
+ Link "opt_starttls"];
};
"get_tls", {
@@ -657,7 +662,7 @@ "get_tls_negotiated", {
After connecting you may call this to find out if the
connection is using TLS.
-This is only really useful if you set the TLS request mode
+This is normally useful only if you set the TLS request mode
to C<LIBNBD_TLS_ALLOW> (see L<nbd_set_tls(3)>), because in this
mode we try to use TLS but fall back to unencrypted if it was
not available. This function will tell you if TLS was
@@ -665,8 +670,14 @@ "get_tls_negotiated", {
In C<LIBNBD_TLS_REQUIRE> mode (the most secure) the connection
would have failed if TLS could not be negotiated, and in
-C<LIBNBD_TLS_DISABLE> mode TLS is not tried.";
- see_also = [Link "set_tls"; Link "get_tls"];
+C<LIBNBD_TLS_DISABLE> mode TLS is not tried automatically.
+
+However, when doing manual integration testing of server
+behavior, when you use L<nbd_set_opt_mode(3)> along with TLS
+request mode C<LIBNBD_TLS_DISABLE> before triggering the TLS
+handshake with L<nbd_opt_starttls(3)>, then this will report
+the result of that manual effort.";
+ see_also = [Link "set_tls"; Link "get_tls"; Link "opt_starttls"];
};
"set_tls_certificates", {
@@ -1092,11 +1103,12 @@ "set_opt_mode", {
newstyle server. This setting has no effect when connecting to an
oldstyle server.
-Note that libnbd defaults to attempting
+Note that libnbd defaults to attempting C<NBD_OPT_STARTTLS> and
C<NBD_OPT_STRUCTURED_REPLY> before letting you control remaining
-negotiation steps; if you need control over this step as well,
-first set L<nbd_set_request_structured_replies(3)> to false before
-starting the connection attempt.
+negotiation steps; if you need control over these steps as well,
+first set L<nbd_set_tls(3)> to C<LIBNBD_TLS_DISABLE> and
+L<nbd_set_request_structured_replies(3)> to false before starting
+the connection attempt.
When option mode is enabled, you have fine-grained control over which
options are negotiated, compared to the default of the server
@@ -1110,9 +1122,9 @@ "set_opt_mode", {
see_also = [Link "get_opt_mode"; Link "aio_is_negotiating";
Link "opt_abort"; Link "opt_go"; Link "opt_list";
Link "opt_info"; Link "opt_list_meta_context";
- Link "opt_set_meta_context";
+ Link "opt_set_meta_context"; Link "opt_starttls";
Link "opt_structured_reply";
- Link "set_request_structured_replies";
+ Link "set_tls"; Link "set_request_structured_replies";
Link "aio_connect"];
};
@@ -1166,6 +1178,44 @@ "opt_abort", {
see_also = [Link "set_opt_mode"; Link "aio_opt_abort"; Link "opt_go"];
};
+ "opt_starttls", {
+ default_call with
+ args = []; ret = RBool;
+ permitted_states = [ Negotiating ];
+ shortdesc = "request the server to initiate TLS";
+ longdesc = "\
+Request that the server initiate a secure TLS connection, by
+sending C<NBD_OPT_STARTTLS>. This can only be used if
+L<nbd_set_opt_mode(3)> enabled option mode; furthermore, if you
+use L<nbd_set_tls(3)> to request anything other than the default
+of C<LIBNBD_TLS_DISABLE>, then libnbd will have already attempted
+a TLS connection prior to allowing you control over option
+negotiation. This command is disabled if L<nbd_supports_tls(3)>
+reports false.
+
+This function is mainly useful for integration testing of corner
+cases in server handling; in particular, misuse of this function
+when coupled with a server that is not careful about resetting
+stateful commands such as L<nbd_opt_structured_reply(3)> could
+result in a security hole (see CVE-2021-3716 against nbdkit, for
+example). Thus, when security is a concern, you should instead
+prefer to use L<nbd_set_tls(3)> with C<LIBNBD_TLS_REQUIRE> and
+let libnbd negotiate TLS automatically.
+
+This function returns true if the server replies with success,
+false if the server replies with an error, and fails only if
+the server does not reply (such as for a loss of connection,
+which can include when the server rejects credentials supplied
+during the TLS handshake). Note that the NBD protocol documents
+that requesting TLS after it is already enabled is a client
+error; most servers will gracefully fail a second request, but
+that does not downgrade a TLS session that has already been
+established, as reported by L<nbd_get_tls_negotiated(3)>.";
+ see_also = [Link "set_opt_mode"; Link "aio_opt_starttls";
+ Link "set_tls"; Link "get_tls_negotiated";
+ Link "supports_tls"]
+ };
+
"opt_structured_reply", {
default_call with
args = []; ret = RBool;
@@ -2815,6 +2865,30 @@ "aio_opt_abort", {
see_also = [Link "set_opt_mode"; Link "opt_abort"];
};
+ "aio_opt_starttls", {
+ default_call with
+ args = [];
+ optargs = [ OClosure completion_closure ];
+ ret = RErr;
+ permitted_states = [ Negotiating ];
+ shortdesc = "request the server to initiate TLS";
+ longdesc = "\
+Request that the server initiate a secure TLS connection, by
+sending C<NBD_OPT_STARTTLS>. This behaves like the synchronous
+counterpart L<nbd_opt_starttls(3)>, except that it does
+not wait for the server's response.
+
+To determine when the request completes, wait for
+L<nbd_aio_is_connecting(3)> to return false. Or supply the optional
+C<completion_callback> which will be invoked as described in
+L<libnbd(3)/Completion callbacks>, except that it is automatically
+retired regardless of return value. Note that detecting whether the
+server returns an error (as is done by the return value of the
+synchronous counterpart) is only possible with a completion
+callback.";
+ see_also = [Link "set_opt_mode"; Link "opt_starttls"];
+ };
+
"aio_opt_structured_reply", {
default_call with
args = [];
@@ -3744,6 +3818,8 @@ let first_version =
"aio_opt_set_meta_context_queries", (1, 16);
"opt_structured_reply", (1, 16);
"aio_opt_structured_reply", (1, 16);
+ "opt_starttls", (1, 16);
+ "aio_opt_starttls", (1, 16);
(* These calls are proposed for a future version of libnbd, but
* have not been added to any released version so far.
diff --git a/generator/states-newstyle-opt-starttls.c b/generator/states-newstyle-opt-starttls.c
index 1233263b..fc72c43c 100644
--- a/generator/states-newstyle-opt-starttls.c
+++ b/generator/states-newstyle-opt-starttls.c
@@ -21,10 +21,15 @@
STATE_MACHINE {
NEWSTYLE.OPT_STARTTLS.START:
assert (h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE);
- /* If TLS was not requested we skip this option and go to the next one. */
- if (h->tls == LIBNBD_TLS_DISABLE) {
- SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
- return 0;
+ if (h->opt_current == NBD_OPT_STARTTLS)
+ assert (h->opt_mode);
+ else {
+ /* If TLS was not requested we skip this option and go to the next one. */
+ if (h->tls == LIBNBD_TLS_DISABLE) {
+ SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
+ return 0;
+ }
+ assert (CALLBACK_IS_NULL (h->opt_cb.completion));
}
h->sbuf.option.version = htobe64 (NBD_NEW_VERSION);
@@ -68,12 +73,14 @@ NEWSTYLE.OPT_STARTTLS.RECV_REPLY_PAYLOAD:
NEWSTYLE.OPT_STARTTLS.CHECK_REPLY:
uint32_t reply;
struct socket *new_sock;
+ int err = ENOTSUP;
reply = be32toh (h->sbuf.or.option_reply.reply);
switch (reply) {
case NBD_REP_ACK:
nbd_internal_reset_size_and_flags (h);
h->structured_replies = false;
+ h->meta_valid = false;
new_sock = nbd_internal_crypto_create_session (h, h->sock);
if (new_sock == NULL) {
SET_NEXT_STATE (%.DEAD);
@@ -86,6 +93,9 @@ NEWSTYLE.OPT_STARTTLS.CHECK_REPLY:
SET_NEXT_STATE (%TLS_HANDSHAKE_WRITE);
return 0;
+ case NBD_REP_ERR_INVALID:
+ err = EINVAL;
+ /* fallthrough */
default:
if (handle_reply_error (h) == -1) {
SET_NEXT_STATE (%.DEAD);
@@ -102,10 +112,16 @@ NEWSTYLE.OPT_STARTTLS.CHECK_REPLY:
return 0;
}
- debug (h,
- "server refused TLS (%s), continuing with unencrypted connection",
- reply == NBD_REP_ERR_POLICY ? "policy" : "not supported");
- SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
+ debug (h, "server refused TLS (%s)",
+ reply == NBD_REP_ERR_POLICY ? "policy" :
+ reply == NBD_REP_ERR_INVALID ? "invalid request" : "not supported");
+ CALL_CALLBACK (h->opt_cb.completion, &err);
+ if (h->opt_current == NBD_OPT_STARTTLS)
+ SET_NEXT_STATE (%.NEGOTIATING);
+ else {
+ debug (h, "continuing with unencrypted connection");
+ SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
+ }
return 0;
}
return 0;
@@ -149,12 +165,18 @@ NEWSTYLE.OPT_STARTTLS.TLS_HANDSHAKE_WRITE:
return 0;
NEWSTYLE.OPT_STARTTLS.TLS_HANDSHAKE_DONE:
+ int err = 0;
+
/* Finished handshake. */
h->tls_negotiated = true;
nbd_internal_crypto_debug_tls_enabled (h);
+ CALL_CALLBACK (h->opt_cb.completion, &err);
/* Continue with option negotiation. */
- SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
+ if (h->opt_current == NBD_OPT_STARTTLS)
+ SET_NEXT_STATE (%.NEGOTIATING);
+ else
+ SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
return 0;
} /* END STATE MACHINE */
diff --git a/generator/states-newstyle.c b/generator/states-newstyle.c
index 4652bc21..c88430e2 100644
--- a/generator/states-newstyle.c
+++ b/generator/states-newstyle.c
@@ -146,6 +146,9 @@ NEWSTYLE.START:
case NBD_OPT_STRUCTURED_REPLY:
SET_NEXT_STATE (%OPT_STRUCTURED_REPLY.START);
return 0;
+ case NBD_OPT_STARTTLS:
+ SET_NEXT_STATE (%OPT_STARTTLS.START);
+ return 0;
case 0:
break;
default:
diff --git a/lib/opt.c b/lib/opt.c
index 18bb4086..4ebb689e 100644
--- a/lib/opt.c
+++ b/lib/opt.c
@@ -139,6 +139,31 @@ nbd_unlocked_opt_abort (struct nbd_handle *h)
return wait_for_option (h);
}
+/* Issue NBD_OPT_STARTTLS and wait for the reply. */
+int
+nbd_unlocked_opt_starttls (struct nbd_handle *h)
+{
+ int err;
+ nbd_completion_callback c = { .callback = go_complete, .user_data = &err };
+ int r = nbd_unlocked_aio_opt_starttls (h, &c);
+
+ if (r == -1)
+ return r;
+
+ r = wait_for_option (h);
+ if (r == 0) {
+ if (nbd_internal_is_state_negotiating (get_next_state (h)))
+ r = err == 0;
+ else {
+ assert (nbd_internal_is_state_dead (get_next_state (h)));
+ set_error (err,
+ "failed to get response to opt_starttls request");
+ r = -1;
+ }
+ }
+ return r;
+}
+
/* Issue NBD_OPT_STRUCTURED_REPLY and wait for the reply. */
int
nbd_unlocked_opt_structured_reply (struct nbd_handle *h)
@@ -336,6 +361,31 @@ nbd_unlocked_aio_opt_abort (struct nbd_handle *h)
return 0;
}
+/* Issue NBD_OPT_STARTTLS without waiting. */
+int
+nbd_unlocked_aio_opt_starttls (struct nbd_handle *h,
+ nbd_completion_callback *complete)
+{
+ if ((h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE) == 0) {
+ set_error (ENOTSUP, "server is not using fixed newstyle protocol");
+ return -1;
+ }
+
+#ifndef HAVE_GNUTLS
+ set_error (ENOTSUP, "libnbd was compiled without TLS support");
+ return -1;
+
+#else
+ h->opt_current = NBD_OPT_STARTTLS;
+ h->opt_cb.completion = *complete;
+ SET_CALLBACK_TO_NULL (*complete);
+
+ if (nbd_internal_run (h, cmd_issue) == -1)
+ debug (h, "option queued, ignoring state machine failure");
+ return 0;
+#endif
+}
+
/* Issue NBD_OPT_STRUCTURED_REPLY without waiting. */
int
nbd_unlocked_aio_opt_structured_reply (struct nbd_handle *h,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 49ea6864..dd157518 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -658,12 +658,14 @@ if HAVE_PSKTOOL
check_PROGRAMS += \
connect-tls-psk \
+ opt-starttls \
aio-parallel-tls \
aio-parallel-load-tls \
synch-parallel-tls \
$(NULL)
TESTS += \
connect-tls-psk \
+ opt-starttls \
aio-parallel-tls.sh \
aio-parallel-load-tls.sh \
synch-parallel-tls.sh \
@@ -677,6 +679,9 @@ connect_tls_psk_CPPFLAGS = \
$(NULL)
connect_tls_psk_LDADD = $(top_builddir)/lib/libnbd.la
+opt_starttls_SOURCES = opt-starttls.c requires.c requires.h
+opt_starttls_LDADD = $(top_builddir)/lib/libnbd.la
+
aio_parallel_tls_SOURCES = aio-parallel.c
aio_parallel_tls_CPPFLAGS = \
$(AM_CPPFLAGS) \
diff --git a/tests/opt-starttls.c b/tests/opt-starttls.c
new file mode 100644
index 00000000..b90a0dcd
--- /dev/null
+++ b/tests/opt-starttls.c
@@ -0,0 +1,166 @@
+/* NBD client library in userspace
+ * Copyright (C) 2013-2022 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Test nbd_opt_starttls to nbdkit in permissive mode. */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <libnbd.h>
+
+#include "requires.h"
+
+struct expected {
+ int first_opt_sr;
+ int64_t first_size;
+ int first_opt_tls;
+ int first_get_sr;
+ int second_opt_sr;
+ int second_opt_tls;
+ int get_tls;
+ int second_get_sr;
+ int64_t second_size;
+};
+
+#define check(got, exp) do_check (#got, got, exp)
+
+static void
+do_check (const char *act, int64_t got, int64_t exp)
+{
+ fprintf (stderr, "trying %s\n", act);
+ if (got == -1)
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ else
+ fprintf (stderr, "succeeded, result %" PRId64 "\n", got);
+ if (got != exp) {
+ fprintf (stderr, "got %" PRId64 ", but expected %" PRId64 "\n", got, exp);
+ exit (EXIT_FAILURE);
+ }
+}
+
+static void
+do_test (const char *server_tls, struct expected exp)
+{
+ struct nbd_handle *nbd = nbd_create ();
+
+ if (nbd == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ if (nbd_supports_tls (nbd) != 1) {
+ fprintf (stderr, "SKIP: missing TLS support in libnbd\n");
+ exit (77);
+ }
+
+ if (nbd_set_opt_mode (nbd, true) == -1 ||
+ nbd_set_request_structured_replies (nbd, false) == -1 ||
+ nbd_set_tls_username (nbd, "alice") == -1 ||
+ nbd_set_tls_psk_file (nbd, "keys.psk") == -1) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ /* Run nbdkit as a subprocess. */
+ const char *args[] = { "nbdkit", "-sv", "--exit-with-parent", server_tls,
+ "--tls-verify-peer", "--tls-psk=keys.psk",
+ "--filter=tls-fallback", "pattern",
+ "size=1M", "tlsreadme=fallback", NULL };
+
+ if (nbd_connect_command (nbd, (char **) args) == -1) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ check (nbd_opt_structured_reply (nbd), exp.first_opt_sr);
+ check (nbd_opt_info (nbd), exp.first_size > 0 ? 0 : -1);
+ check (nbd_get_size (nbd), exp.first_size);
+ check (nbd_opt_starttls (nbd), exp.first_opt_tls);
+ check (nbd_get_structured_replies_negotiated (nbd), exp.first_get_sr);
+ check (nbd_opt_structured_reply (nbd), exp.second_opt_sr);
+ check (nbd_opt_starttls (nbd), exp.second_opt_tls);
+ check (nbd_get_tls_negotiated (nbd), exp.get_tls);
+ check (nbd_get_structured_replies_negotiated (nbd), exp.second_get_sr);
+ check (nbd_opt_info (nbd), 0);
+ check (nbd_get_size (nbd), exp.second_size);
+ check (nbd_opt_abort (nbd), 0);
+
+ nbd_close (nbd);
+}
+
+int
+main (int argc, char *argv[])
+{
+ /* Check --tls-verify-peer option is supported. */
+ requires ("nbdkit --tls-verify-peer -U - null --run 'exit 0'");
+ /* Check for nbdkit tls-fallback filter. */
+ requires ("nbdkit --filter=tls-fallback null --dump-plugin");
+
+ /* Reject older nbdkit that chokes on NBD_OPT_INFO to --tls=require */
+ requires ("test 0 = \"$(nbdkit --tls=require --tls-psk=keys.psk -U - null "
+ "--run 'nbdinfo \"nbd+unix://?socket=$unixsocket\"' 2>&1 |"
+ "grep -c 'nbdkit.*unknown option version')\"");
+
+ /* Behavior of a server with no TLS support */
+ do_test ("--tls=no", (struct expected) {
+ .first_opt_sr = 1, /* Structured reply succeeds */
+ .first_size = 512, /* Sees the tls-fallback safe size */
+ .first_opt_tls = 0, /* Server lacks TLS, but connection stays up */
+ .first_get_sr = 1, /* Structured reply still good */
+ .second_opt_sr = 0, /* Server rejects second SR as redundant */
+ .second_opt_tls = 0, /* Server still lacks TLS */
+ .get_tls = 0, /* Final state of TLS - not secure */
+ .second_get_sr = 1, /* Structured reply still good */
+ .second_size = 512, /* Still the tls-fallback safe size */
+ });
+
+ /* Behavior of a server with opportunistic TLS support */
+ do_test ("--tls=on", (struct expected) {
+ .first_opt_sr = 1, /* Structured reply succeeds */
+ .first_size = 512, /* Sees the tls-fallback safe size */
+ .first_opt_tls = 1, /* Server takes TLS */
+ .first_get_sr = 0, /* Structured reply wiped by TLS */
+ .second_opt_sr = 1, /* Server accepts second SR */
+ .second_opt_tls = 0, /* Server rejects second TLS as redundant */
+ .get_tls = 1, /* Final state of TLS - secure */
+ .second_get_sr = 1, /* Structured reply still good */
+ .second_size = 1024*1024, /* Sees the actual size */
+ });
+
+ /* Behavior of a server that requires TLS support */
+ do_test ("--tls=require", (struct expected) {
+ .first_opt_sr = 0, /* Structured reply fails without TLS first */
+ .first_size = -1, /* Cannot request info */
+ .first_opt_tls = 1, /* Server takes TLS */
+ .first_get_sr = 0, /* Structured reply hasn't been requested */
+ .second_opt_sr = 1, /* Server accepts second SR */
+ .second_opt_tls = 0, /* Server rejects second TLS as redundant */
+ .get_tls = 1, /* Final state of TLS - secure */
+ .second_get_sr = 1, /* Structured reply still good */
+ .second_size = 1024*1024, /* Sees the actual size */
+ });
+
+ exit (EXIT_SUCCESS);
+}
diff --git a/.gitignore b/.gitignore
index 37166b73..fe929d6d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -236,6 +236,7 @@ Makefile.in
/tests/opt-list-meta-queries
/tests/opt-set-meta
/tests/opt-set-meta-queries
+/tests/opt-starttls
/tests/opt-structured-twice
/tests/pki/
/tests/pread-initialize
--
2.37.3
2 years, 1 month
[libnbd PATCH] RFC: fuzzing: Break up handshake into more steps
by Eric Blake
Give the fuzzer a few more points to experiment with added branching
by explicitly using opt mode.
---
I'm not quite sure whether the fuzzer is able to synthesize specific
API calls from the client side; but if it can, letting the client
specifically enter the NEGOTIATING state may allow the fuzzer to spot
other nbd_opt_* API call chains that could provoke odd interactions,
which would be completely missed when sticking with the default of
skipping opt mode.
fuzzing/libnbd-fuzz-wrapper.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/fuzzing/libnbd-fuzz-wrapper.c b/fuzzing/libnbd-fuzz-wrapper.c
index 7e390558..e7cf7fe9 100644
--- a/fuzzing/libnbd-fuzz-wrapper.c
+++ b/fuzzing/libnbd-fuzz-wrapper.c
@@ -200,7 +200,10 @@ client (int sock)
nbd_add_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION);
/* This tests the handshake phase. */
+ nbd_set_opt_mode (nbd, true);
nbd_connect_socket (nbd, sock);
+ nbd_opt_info (nbd);
+ nbd_opt_go (nbd);
length = nbd_get_size (nbd);
--
2.37.3
2 years, 1 month
Parameter 'encrypt.key-secret' is required for cipher for virt-ls
by Do Re
Hello all,
background: One of my VM stopped working - on startup, I get the message
"No bootable device" in the virtual machine.
I would like to inspect the corresponding image with libguestfs-tools.
However, I don't know how to pass the encryption key to the tool. For
example:
virt-ls -a /opt/vm_witherror/machine1.qcow2 /
libguestfs: trace: set_verbose true
libguestfs: trace: set_verbose = 0
libguestfs: create: flags = 0, handle = 0x5645c40d6b00, program = virt-ls
libguestfs: trace: add_drive "/opt/vm_witherror/machine1.qcow2"
"readonly:true"
libguestfs: creating COW overlay to protect original drive content
libguestfs: trace: get_tmpdir
libguestfs: trace: get_tmpdir = "/tmp"
libguestfs: trace: disk_create "/tmp/libguestfsxECmri/overlay1.qcow2"
"qcow2" -1 "backingfile:/opt/vm_witherror/machine1.qcow2"
libguestfs: command: run: qemu-img
libguestfs: command: run: \ create
libguestfs: command: run: \ -f qcow2
libguestfs: command: run: \ -o backing_file=/opt/vm_witherror/machine1.qcow2
libguestfs: command: run: \ /tmp/libguestfsxECmri/overlay1.qcow2
qemu-img: /tmp/libguestfsxECmri/overlay1.qcow2: Parameter
'encrypt.key-secret' is required for cipher
Could not open backing image.
libguestfs: error: qemu-img: /tmp/libguestfsxECmri/overlay1.qcow2: qemu-img
exited with error status 1, see debug messages above
libguestfs: trace: disk_create = -1 (error)
libguestfs: trace: add_drive = -1 (error)
libguestfs: trace: close
libguestfs: closing guestfs handle 0x5645c40d6b00 (state 0)
libguestfs: command: run: rm
libguestfs: command: run: \ -rf /tmp/libguestfsxECmri
Could you please provide an example on how to get such an encrypted disk
mounted?
Thanks in advance
Kind regards
Dominik
2 years, 1 month
[nbdkit PATCH] tls: Gracefully handle early NBD_OPT_ payload
by Eric Blake
When using --tls=require, we need to consume any payload sent by the
client on an option other than NBD_OPT_STARTTLS (for example,
NBD_OPT_INFO); otherwise we will be out of sync and unable to read the
next NBD_OPT_, most likely preventing us from being able to establish
TLS if the client next attempts NBD_OPT_STARTTLS. Also, if the client
sends NBD_OPT_EXPORT_NAME, they are expecting us to disconnect on
failure, rather than trying to reply with an error (most clients use
NBD_OPT_GO these days because of that).
While it is unfortunate that a MitM proxy attacker can use this
weakness in nbdkit to prevent a TLS connection, it is not quite the
same as the prior fix for CVE-2021-3716 (commit 09a13daf) where a
plaintext NBD_OPT_STRUCTURED_REPLY could confuse a client; this is
because failure to establish TLS is easily detected at the client as a
proxy attack, and not a situation where the plaintext injection can
break client behavior without detection.
This bug has been latent for some time; that is because most people do
not try to connect a plaintext client to a server that requires TLS;
and even if it is done accidentally, clients like qemu or libnbd that
give a payload-free option request of NBD_OPT_STRUCTURED_REPLY first
don't tickle the problem, especially if they disconnect on getting the
NBD_REP_ERR_TLS_REQD rather than trying to proceed with another
NBD_OPT_*. But with an upcoming libnbd release adding a new API
nbd_opt_starttls() to write a SELECTIVETLS client, it becomes easier
to tickle. See also qemu commit d1129a8a.
Fixes: c5e76492 ("Add TLS support.", v1.1.15)
---
server/protocol-handshake-newstyle.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/server/protocol-handshake-newstyle.c b/server/protocol-handshake-newstyle.c
index 5ac45efa..4e16b72c 100644
--- a/server/protocol-handshake-newstyle.c
+++ b/server/protocol-handshake-newstyle.c
@@ -424,8 +424,16 @@ negotiate_handshake_newstyle_options (void)
*/
if (tls == 2 && !conn->using_tls &&
!(option == NBD_OPT_ABORT || option == NBD_OPT_STARTTLS)) {
+ if (option == NBD_OPT_EXPORT_NAME) {
+ debug ("newstyle negotiation: can't reply NBD_REP_ERR_TLS_REQD to %s",
+ name_of_nbd_opt (option));
+ return -1;
+ }
if (send_newstyle_option_reply (option, NBD_REP_ERR_TLS_REQD))
return -1;
+ if (conn_recv_full (data, optlen,
+ "waiting for starttls: %m") == -1)
+ return -1;
continue;
}
--
2.37.3
2 years, 1 month