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_DISCARD 3
|
||||||
#define QEMU_NBD_OPT_DETECT_ZEROES 4
|
#define QEMU_NBD_OPT_DETECT_ZEROES 4
|
||||||
#define QEMU_NBD_OPT_OBJECT 5
|
#define QEMU_NBD_OPT_OBJECT 5
|
||||||
|
#define QEMU_NBD_OPT_TLSCREDS 6
|
||||||
|
|
||||||
static NBDExport *exp;
|
static NBDExport *exp;
|
||||||
static bool newproto;
|
static bool newproto;
|
||||||
@ -54,6 +55,7 @@ static int shared = 1;
|
|||||||
static int nb_fds;
|
static int nb_fds;
|
||||||
static QIOChannelSocket *server_ioc;
|
static QIOChannelSocket *server_ioc;
|
||||||
static int server_watch = -1;
|
static int server_watch = -1;
|
||||||
|
static QCryptoTLSCreds *tlscreds;
|
||||||
|
|
||||||
static void usage(const char *name)
|
static void usage(const char *name)
|
||||||
{
|
{
|
||||||
@ -342,7 +344,7 @@ static gboolean nbd_accept(QIOChannel *ioc, GIOCondition cond, gpointer opaque)
|
|||||||
nb_fds++;
|
nb_fds++;
|
||||||
nbd_update_server_watch();
|
nbd_update_server_watch();
|
||||||
nbd_client_new(newproto ? NULL : exp, cioc,
|
nbd_client_new(newproto ? NULL : exp, cioc,
|
||||||
NULL, NULL, nbd_client_closed);
|
tlscreds, NULL, nbd_client_closed);
|
||||||
object_unref(OBJECT(cioc));
|
object_unref(OBJECT(cioc));
|
||||||
|
|
||||||
return TRUE;
|
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)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
@ -441,6 +474,7 @@ int main(int argc, char **argv)
|
|||||||
{ "verbose", 0, NULL, 'v' },
|
{ "verbose", 0, NULL, 'v' },
|
||||||
{ "object", 1, NULL, QEMU_NBD_OPT_OBJECT },
|
{ "object", 1, NULL, QEMU_NBD_OPT_OBJECT },
|
||||||
{ "export-name", 1, NULL, 'x' },
|
{ "export-name", 1, NULL, 'x' },
|
||||||
|
{ "tls-creds", 1, NULL, QEMU_NBD_OPT_TLSCREDS },
|
||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
int ch;
|
int ch;
|
||||||
@ -458,6 +492,7 @@ int main(int argc, char **argv)
|
|||||||
BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF;
|
BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF;
|
||||||
QDict *options = NULL;
|
QDict *options = NULL;
|
||||||
const char *export_name = NULL;
|
const char *export_name = NULL;
|
||||||
|
const char *tlscredsid = NULL;
|
||||||
|
|
||||||
/* The client thread uses SIGTERM to interrupt the server. A signal
|
/* The client thread uses SIGTERM to interrupt the server. A signal
|
||||||
* handler ensures that "qemu-nbd -v -c" exits with a nice status code.
|
* 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);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case QEMU_NBD_OPT_TLSCREDS:
|
||||||
|
tlscredsid = optarg;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,6 +688,28 @@ int main(int argc, char **argv)
|
|||||||
exit(EXIT_FAILURE);
|
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) {
|
if (disconnect) {
|
||||||
int nbdfd = open(argv[optind], O_RDWR);
|
int nbdfd = open(argv[optind], O_RDWR);
|
||||||
if (nbdfd < 0) {
|
if (nbdfd < 0) {
|
||||||
|
@ -21,9 +21,10 @@ Export a QEMU disk image using the NBD protocol.
|
|||||||
@item --object type,id=@var{id},...props...
|
@item --object type,id=@var{id},...props...
|
||||||
Define a new instance of the @var{type} object class identified by @var{id}.
|
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
|
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
|
@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}
|
@item -p, --port=@var{port}
|
||||||
The TCP port to listen on (default @samp{10809})
|
The TCP port to listen on (default @samp{10809})
|
||||||
@item -o, --offset=@var{offset}
|
@item -o, --offset=@var{offset}
|
||||||
@ -76,6 +77,10 @@ Don't exit on the last connection
|
|||||||
@item -x NAME, --export-name=NAME
|
@item -x NAME, --export-name=NAME
|
||||||
Set the NBD volume export name. This switches the server to use
|
Set the NBD volume export name. This switches the server to use
|
||||||
the new style NBD protocol negotiation
|
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
|
@item -v, --verbose
|
||||||
Display extra debugging information
|
Display extra debugging information
|
||||||
@item -h, --help
|
@item -h, --help
|
||||||
|
Loading…
Reference in New Issue
Block a user