aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2016-02-10 18:41:13 +0000
committerPaolo Bonzini <pbonzini@redhat.com>2016-02-16 17:17:42 +0100
commit145614a112a8e67d6c84b26faaf2b2002e17d9be (patch)
treefa7204b2f7957acfe349a3bb3345fc7ddb38ae2b
parent75822a12c046646684bc8cad6296842b60e7b6bb (diff)
downloadqemu-145614a112a8e67d6c84b26faaf2b2002e17d9be.zip
qemu-145614a112a8e67d6c84b26faaf2b2002e17d9be.tar.gz
qemu-145614a112a8e67d6c84b26faaf2b2002e17d9be.tar.bz2
nbd: enable use of TLS with qemu-nbd server
This modifies the qemu-nbd program so that it is possible to request the use of TLS with the server. It simply adds a new command line option --tls-creds which is used to provide the ID of a QCryptoTLSCreds object previously created via the --object command line option. For example qemu-nbd --object tls-creds-x509,id=tls0,endpoint=server,\ dir=/home/berrange/security/qemutls \ --tls-creds tls0 \ --exportname default TLS requires the new style NBD protocol, so if no export name is set (via --export-name), then we use the default NBD protocol export name "" TLS is only supported when using an IPv4/IPv6 socket listener. It is not possible to use with UNIX sockets, which includes when connecting the NBD server to a host device. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> Message-Id: <1455129674-17255-16-git-send-email-berrange@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--qemu-nbd.c62
-rw-r--r--qemu-nbd.texi9
2 files changed, 68 insertions, 3 deletions
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 8acd515..933ca4a 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -42,6 +42,7 @@
#define QEMU_NBD_OPT_DISCARD 3
#define QEMU_NBD_OPT_DETECT_ZEROES 4
#define QEMU_NBD_OPT_OBJECT 5
+#define QEMU_NBD_OPT_TLSCREDS 6
static NBDExport *exp;
static bool newproto;
@@ -54,6 +55,7 @@ static int shared = 1;
static int nb_fds;
static QIOChannelSocket *server_ioc;
static int server_watch = -1;
+static QCryptoTLSCreds *tlscreds;
static void usage(const char *name)
{
@@ -342,7 +344,7 @@ static gboolean nbd_accept(QIOChannel *ioc, GIOCondition cond, gpointer opaque)
nb_fds++;
nbd_update_server_watch();
nbd_client_new(newproto ? NULL : exp, cioc,
- NULL, NULL, nbd_client_closed);
+ tlscreds, NULL, nbd_client_closed);
object_unref(OBJECT(cioc));
return TRUE;
@@ -402,6 +404,37 @@ static QemuOptsList qemu_object_opts = {
};
+
+static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp)
+{
+ Object *obj;
+ QCryptoTLSCreds *creds;
+
+ obj = object_resolve_path_component(
+ object_get_objects_root(), id);
+ if (!obj) {
+ error_setg(errp, "No TLS credentials with id '%s'",
+ id);
+ return NULL;
+ }
+ creds = (QCryptoTLSCreds *)
+ object_dynamic_cast(obj, TYPE_QCRYPTO_TLS_CREDS);
+ if (!creds) {
+ error_setg(errp, "Object with id '%s' is not TLS credentials",
+ id);
+ return NULL;
+ }
+
+ if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
+ error_setg(errp,
+ "Expecting TLS credentials with a server endpoint");
+ return NULL;
+ }
+ object_ref(obj);
+ return creds;
+}
+
+
int main(int argc, char **argv)
{
BlockBackend *blk;
@@ -441,6 +474,7 @@ int main(int argc, char **argv)
{ "verbose", 0, NULL, 'v' },
{ "object", 1, NULL, QEMU_NBD_OPT_OBJECT },
{ "export-name", 1, NULL, 'x' },
+ { "tls-creds", 1, NULL, QEMU_NBD_OPT_TLSCREDS },
{ NULL, 0, NULL, 0 }
};
int ch;
@@ -458,6 +492,7 @@ int main(int argc, char **argv)
BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF;
QDict *options = NULL;
const char *export_name = NULL;
+ const char *tlscredsid = NULL;
/* The client thread uses SIGTERM to interrupt the server. A signal
* handler ensures that "qemu-nbd -v -c" exits with a nice status code.
@@ -634,6 +669,9 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
} break;
+ case QEMU_NBD_OPT_TLSCREDS:
+ tlscredsid = optarg;
+ break;
}
}
@@ -650,6 +688,28 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
+ if (tlscredsid) {
+ if (sockpath) {
+ error_report("TLS is only supported with IPv4/IPv6");
+ exit(EXIT_FAILURE);
+ }
+ if (device) {
+ error_report("TLS is not supported with a host device");
+ exit(EXIT_FAILURE);
+ }
+ if (!export_name) {
+ /* Set the default NBD protocol export name, since
+ * we *must* use new style protocol for TLS */
+ export_name = "";
+ }
+ tlscreds = nbd_get_tls_creds(tlscredsid, &local_err);
+ if (local_err) {
+ error_report("Failed to get TLS creds %s",
+ error_get_pretty(local_err));
+ exit(EXIT_FAILURE);
+ }
+ }
+
if (disconnect) {
int nbdfd = open(argv[optind], O_RDWR);
if (nbdfd < 0) {
diff --git a/qemu-nbd.texi b/qemu-nbd.texi
index 874481d..227a73c 100644
--- a/qemu-nbd.texi
+++ b/qemu-nbd.texi
@@ -21,9 +21,10 @@ Export a QEMU disk image using the NBD protocol.
@item --object type,id=@var{id},...props...
Define a new instance of the @var{type} object class identified by @var{id}.
See the @code{qemu(1)} manual page for full details of the properties
-supported. The common object type that it makes sense to define is the
+supported. The common object types that it makes sense to define are the
@code{secret} object, which is used to supply passwords and/or encryption
-keys.
+keys, and the @code{tls-creds} object, which is used to supply TLS
+credentials for the qemu-nbd server.
@item -p, --port=@var{port}
The TCP port to listen on (default @samp{10809})
@item -o, --offset=@var{offset}
@@ -76,6 +77,10 @@ Don't exit on the last connection
@item -x NAME, --export-name=NAME
Set the NBD volume export name. This switches the server to use
the new style NBD protocol negotiation
+@item --tls-creds=ID
+Enable mandatory TLS encryption for the server by setting the ID
+of the TLS credentials object previously created with the --object
+option.
@item -v, --verbose
Display extra debugging information
@item -h, --help