@@ -45,6 +45,7 @@
#define QEMU_NBD_OPT_DETECT_ZEROES 259
#define QEMU_NBD_OPT_OBJECT 260
#define QEMU_NBD_OPT_IMAGE_OPTS 261
+#define QEMU_NBD_OPT_TLSCREDS 262
static NBDExport *exp;
static bool newproto;
@@ -57,6 +58,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)
{
@@ -345,7 +347,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;
@@ -434,6 +436,37 @@ static int object_create(void *opaque, QemuOpts *opts, Error **errp)
return 0;
}
+
+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;
@@ -475,6 +508,7 @@ int main(int argc, char **argv)
{ "object", required_argument, NULL, QEMU_NBD_OPT_OBJECT },
{ "image-opts", no_argument, NULL, QEMU_NBD_OPT_IMAGE_OPTS },
{ "exportname", required_argument, NULL, 'x' },
+ { "tls-creds", required_argument, NULL, QEMU_NBD_OPT_TLSCREDS },
{ NULL, 0, NULL, 0 }
};
int ch;
@@ -494,6 +528,7 @@ int main(int argc, char **argv)
QemuOpts *opts;
bool imageOpts = false;
const char *exportname = 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.
@@ -669,6 +704,9 @@ int main(int argc, char **argv)
case QEMU_NBD_OPT_IMAGE_OPTS:
imageOpts = true;
break;
+ case QEMU_NBD_OPT_TLSCREDS:
+ tlscredsid = optarg;
+ break;
case '?':
error_report("Try `%s --help' for more information.", argv[0]);
exit(EXIT_FAILURE);
@@ -687,6 +725,27 @@ int main(int argc, char **argv)
exit(1);
}
+ if (tlscredsid) {
+ if (!exportname) {
+ error_report("Export name is required when using TLS");
+ exit(EXIT_FAILURE);
+ }
+ 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);
+ }
+ 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) {
@@ -66,6 +66,10 @@ Export QEMU disk image using NBD protocol.
@item -x NAME, --exportname=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
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 Note that it is mandatory to supply the --exportname argument when requesting TLS, since it requires use of the new style NBD protocol where the client requests a volume name explicitly. 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> --- qemu-nbd.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- qemu-nbd.texi | 4 ++++ 2 files changed, 64 insertions(+), 1 deletion(-)