From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39045) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTZi3-0006yX-Ls for qemu-devel@nongnu.org; Wed, 10 Feb 2016 13:41:54 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aTZi2-0005rl-KK for qemu-devel@nongnu.org; Wed, 10 Feb 2016 13:41:51 -0500 From: "Daniel P. Berrange" Date: Wed, 10 Feb 2016 18:41:13 +0000 Message-Id: <1455129674-17255-16-git-send-email-berrange@redhat.com> In-Reply-To: <1455129674-17255-1-git-send-email-berrange@redhat.com> References: <1455129674-17255-1-git-send-email-berrange@redhat.com> Subject: [Qemu-devel] [PATCH v6 15/16] nbd: enable use of TLS with qemu-nbd server List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Paolo Bonzini , qemu-block@nongnu.org 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 --- qemu-nbd.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- qemu-nbd.texi | 4 ++++ 2 files changed, 65 insertions(+), 1 deletion(-) 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 2516963..417f9c6 100644 --- a/qemu-nbd.texi +++ b/qemu-nbd.texi @@ -76,6 +76,10 @@ Don't exit on the last connection @item -x NAME, --export-name=NAME Set the NDB 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 -- 2.5.0