qemu-nbd: add --tls-hostname option for TLS certificate validation

When using the --list option, qemu-nbd acts as an NBD client rather
than a server. As such when using TLS, it has a need to validate
the server certificate. This adds a --tls-hostname option which can
be used to override the default hostname used for certificate
validation.

Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20220304193610.3293146-5-berrange@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2022-03-04 19:36:02 +00:00 committed by Eric Blake
parent a0cd6d2972
commit 003b2b2521
2 changed files with 29 additions and 1 deletions

View file

@ -169,6 +169,19 @@ driver options if ``--image-opts`` is specified.
option; or provide the credentials needed for connecting as a client
in list mode.
.. option:: --tls-hostname=hostname
When validating an x509 certificate received over a TLS connection,
the hostname that the NBD client used to connect will be checked
against information in the server provided certificate. Sometimes
it might be required to override the hostname used to perform this
check. For example, if the NBD client is using a tunnel from localhost
to connect to the remote server, the `--tls-hostname` option should
be used to set the officially expected hostname of the remote NBD
server. This can also be used if accessing NBD over a UNIX socket
where there is no inherent hostname available. This is only permitted
when acting as a NBD client with the `--list` option.
.. option:: --fork
Fork off the server process and exit the parent once the server is running.

View file

@ -69,6 +69,7 @@
#define QEMU_NBD_OPT_TLSAUTHZ 264
#define QEMU_NBD_OPT_PID_FILE 265
#define QEMU_NBD_OPT_SELINUX_LABEL 266
#define QEMU_NBD_OPT_TLSHOSTNAME 267
#define MBR_SIZE 512
@ -542,6 +543,7 @@ int main(int argc, char **argv)
{ "export-name", required_argument, NULL, 'x' },
{ "description", required_argument, NULL, 'D' },
{ "tls-creds", required_argument, NULL, QEMU_NBD_OPT_TLSCREDS },
{ "tls-hostname", required_argument, NULL, QEMU_NBD_OPT_TLSHOSTNAME },
{ "tls-authz", required_argument, NULL, QEMU_NBD_OPT_TLSAUTHZ },
{ "image-opts", no_argument, NULL, QEMU_NBD_OPT_IMAGE_OPTS },
{ "trace", required_argument, NULL, 'T' },
@ -568,6 +570,7 @@ int main(int argc, char **argv)
strList *bitmaps = NULL;
bool alloc_depth = false;
const char *tlscredsid = NULL;
const char *tlshostname = NULL;
bool imageOpts = false;
bool writethrough = false; /* Client will flush as needed. */
bool fork_process = false;
@ -747,6 +750,9 @@ int main(int argc, char **argv)
case QEMU_NBD_OPT_TLSCREDS:
tlscredsid = optarg;
break;
case QEMU_NBD_OPT_TLSHOSTNAME:
tlshostname = optarg;
break;
case QEMU_NBD_OPT_IMAGE_OPTS:
imageOpts = true;
break;
@ -835,6 +841,10 @@ int main(int argc, char **argv)
error_report("TLS authorization is incompatible with export list");
exit(EXIT_FAILURE);
}
if (tlshostname && !list) {
error_report("TLS hostname is only supported with export list");
exit(EXIT_FAILURE);
}
tlscreds = nbd_get_tls_creds(tlscredsid, list, &local_err);
if (local_err) {
error_reportf_err(local_err, "Failed to get TLS creds: ");
@ -845,6 +855,10 @@ int main(int argc, char **argv)
error_report("--tls-authz is not permitted without --tls-creds");
exit(EXIT_FAILURE);
}
if (tlshostname) {
error_report("--tls-hostname is not permitted without --tls-creds");
exit(EXIT_FAILURE);
}
}
if (selinux_label) {
@ -861,7 +875,8 @@ int main(int argc, char **argv)
if (list) {
saddr = nbd_build_socket_address(sockpath, bindto, port);
return qemu_nbd_client_list(saddr, tlscreds, bindto);
return qemu_nbd_client_list(saddr, tlscreds,
tlshostname ? tlshostname : bindto);
}
#if !HAVE_NBD_DEVICE