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>
This commit is contained in:
parent
75822a12c0
commit
145614a112
62
qemu-nbd.c
62
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) {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user