nbd patches for 2022-03-07
- Dan Berrange: Allow qemu-nbd to support TLS over Unix sockets - Eric Blake: Minor cleanups related to 64-bit block operations -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEccLMIrHEYCkn0vOqp6FrSiUnQ2oFAmImtE8ACgkQp6FrSiUn Q2ovmgf/aksDqf2eNcahs++fez+8Qi9ll5OY/qGyjnzBgsatYKjrK+xF7OnjoJox eRX026lh81Q4EQK7oZBUnr2UCY4bncDBTI7MTLh603EV/tId5ZLwx007ERhzvtC1 mIsQHXNuO9X25LQG2eWnfunY9YztQpiT5r/g3khD2yPBqJWIvBfblzPLx6FkF7px /WM8xEKCihmGr1Wr3b+zGYL083YkaBWCvHoR8mJt3tEFUj+Qie8XcdV0OVyI0XUj 5goIFRcpVwBE8P2nLtfUKNzEXz22cmdonOJUX7E5IvGO21k5F/HrWlHdo8JnuSUZ t0w5L9yCxBrRpY1burz30b77J0WMCw== =C8Dd -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2022-03-07' into staging nbd patches for 2022-03-07 - Dan Berrange: Allow qemu-nbd to support TLS over Unix sockets - Eric Blake: Minor cleanups related to 64-bit block operations # gpg: Signature made Tue 08 Mar 2022 01:41:35 GMT # gpg: using RSA key 71C2CC22B1C4602927D2F3AAA7A16B4A2527436A # gpg: Good signature from "Eric Blake <eblake@redhat.com>" [full] # gpg: aka "Eric Blake (Free Software Programmer) <ebb9@byu.net>" [full] # gpg: aka "[jpeg image of size 6874]" [full] # Primary key fingerprint: 71C2 CC22 B1C4 6029 27D2 F3AA A7A1 6B4A 2527 436A * remotes/ericb/tags/pull-nbd-2022-03-07: qemu-io: Allow larger write zeroes under no fallback qemu-io: Utilize 64-bit status during map nbd/server: Minor cleanups tests/qemu-iotests: validate NBD TLS with UNIX sockets and PSK tests/qemu-iotests: validate NBD TLS with UNIX sockets tests/qemu-iotests: validate NBD TLS with hostname mismatch tests/qemu-iotests: convert NBD TLS test to use standard filters tests/qemu-iotests: introduce filter for qemu-nbd export list tests/qemu-iotests: expand _filter_nbd rules tests/qemu-iotests: add QEMU_IOTESTS_REGEN=1 to update reference file block/nbd: don't restrict TLS usage to IP sockets qemu-nbd: add --tls-hostname option for TLS certificate validation block/nbd: support override of hostname for TLS certificate validation block: pass desired TLS hostname through from block driver client crypto: mandate a hostname when checking x509 creds on a client Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
fdee2c9692
25
block/nbd.c
25
block/nbd.c
@ -90,9 +90,10 @@ typedef struct BDRVNBDState {
|
||||
uint32_t reconnect_delay;
|
||||
uint32_t open_timeout;
|
||||
SocketAddress *saddr;
|
||||
char *export, *tlscredsid;
|
||||
char *export;
|
||||
char *tlscredsid;
|
||||
QCryptoTLSCreds *tlscreds;
|
||||
const char *hostname;
|
||||
char *tlshostname;
|
||||
char *x_dirty_bitmap;
|
||||
bool alloc_depth;
|
||||
|
||||
@ -121,6 +122,8 @@ static void nbd_clear_bdrvstate(BlockDriverState *bs)
|
||||
s->export = NULL;
|
||||
g_free(s->tlscredsid);
|
||||
s->tlscredsid = NULL;
|
||||
g_free(s->tlshostname);
|
||||
s->tlshostname = NULL;
|
||||
g_free(s->x_dirty_bitmap);
|
||||
s->x_dirty_bitmap = NULL;
|
||||
}
|
||||
@ -1765,6 +1768,11 @@ static QemuOptsList nbd_runtime_opts = {
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "ID of the TLS credentials to use",
|
||||
},
|
||||
{
|
||||
.name = "tls-hostname",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Override hostname for validating TLS x509 certificate",
|
||||
},
|
||||
{
|
||||
.name = "x-dirty-bitmap",
|
||||
.type = QEMU_OPT_STRING,
|
||||
@ -1831,12 +1839,11 @@ static int nbd_process_options(BlockDriverState *bs, QDict *options,
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* TODO SOCKET_ADDRESS_KIND_FD where fd has AF_INET or AF_INET6 */
|
||||
if (s->saddr->type != SOCKET_ADDRESS_TYPE_INET) {
|
||||
error_setg(errp, "TLS only supported over IP sockets");
|
||||
goto error;
|
||||
s->tlshostname = g_strdup(qemu_opt_get(opts, "tls-hostname"));
|
||||
if (!s->tlshostname &&
|
||||
s->saddr->type == SOCKET_ADDRESS_TYPE_INET) {
|
||||
s->tlshostname = g_strdup(s->saddr->u.inet.host);
|
||||
}
|
||||
s->hostname = s->saddr->u.inet.host;
|
||||
}
|
||||
|
||||
s->x_dirty_bitmap = g_strdup(qemu_opt_get(opts, "x-dirty-bitmap"));
|
||||
@ -1876,7 +1883,8 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
s->conn = nbd_client_connection_new(s->saddr, true, s->export,
|
||||
s->x_dirty_bitmap, s->tlscreds);
|
||||
s->x_dirty_bitmap, s->tlscreds,
|
||||
s->tlshostname);
|
||||
|
||||
if (s->open_timeout) {
|
||||
nbd_client_connection_enable_retry(s->conn);
|
||||
@ -2037,6 +2045,7 @@ static const char *const nbd_strong_runtime_opts[] = {
|
||||
"port",
|
||||
"export",
|
||||
"tls-creds",
|
||||
"tls-hostname",
|
||||
"server.",
|
||||
|
||||
NULL
|
||||
|
@ -148,12 +148,6 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds,
|
||||
if (!nbd_server->tlscreds) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* TODO SOCKET_ADDRESS_TYPE_FD where fd has AF_INET or AF_INET6 */
|
||||
if (addr->type != SOCKET_ADDRESS_TYPE_INET) {
|
||||
error_setg(errp, "TLS is only supported with IPv4/IPv6");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
nbd_server->tlsauthz = g_strdup(tls_authz);
|
||||
|
@ -373,6 +373,12 @@ qcrypto_tls_session_check_certificate(QCryptoTLSSession *session,
|
||||
session->hostname);
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
if (session->creds->endpoint ==
|
||||
QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
|
||||
error_setg(errp, "No hostname for certificate validation");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -415,7 +415,8 @@ NBDClientConnection *nbd_client_connection_new(const SocketAddress *saddr,
|
||||
bool do_negotiation,
|
||||
const char *export_name,
|
||||
const char *x_dirty_bitmap,
|
||||
QCryptoTLSCreds *tlscreds);
|
||||
QCryptoTLSCreds *tlscreds,
|
||||
const char *tlshostname);
|
||||
void nbd_client_connection_release(NBDClientConnection *conn);
|
||||
|
||||
QIOChannel *coroutine_fn
|
||||
|
@ -33,6 +33,7 @@ struct NBDClientConnection {
|
||||
/* Initialization constants, never change */
|
||||
SocketAddress *saddr; /* address to connect to */
|
||||
QCryptoTLSCreds *tlscreds;
|
||||
char *tlshostname;
|
||||
NBDExportInfo initial_info;
|
||||
bool do_negotiation;
|
||||
bool do_retry;
|
||||
@ -77,7 +78,8 @@ NBDClientConnection *nbd_client_connection_new(const SocketAddress *saddr,
|
||||
bool do_negotiation,
|
||||
const char *export_name,
|
||||
const char *x_dirty_bitmap,
|
||||
QCryptoTLSCreds *tlscreds)
|
||||
QCryptoTLSCreds *tlscreds,
|
||||
const char *tlshostname)
|
||||
{
|
||||
NBDClientConnection *conn = g_new(NBDClientConnection, 1);
|
||||
|
||||
@ -85,6 +87,7 @@ NBDClientConnection *nbd_client_connection_new(const SocketAddress *saddr,
|
||||
*conn = (NBDClientConnection) {
|
||||
.saddr = QAPI_CLONE(SocketAddress, saddr),
|
||||
.tlscreds = tlscreds,
|
||||
.tlshostname = g_strdup(tlshostname),
|
||||
.do_negotiation = do_negotiation,
|
||||
|
||||
.initial_info.request_sizes = true,
|
||||
@ -107,6 +110,7 @@ static void nbd_client_connection_do_free(NBDClientConnection *conn)
|
||||
}
|
||||
error_free(conn->err);
|
||||
qapi_free_SocketAddress(conn->saddr);
|
||||
g_free(conn->tlshostname);
|
||||
object_unref(OBJECT(conn->tlscreds));
|
||||
g_free(conn->initial_info.x_dirty_bitmap);
|
||||
g_free(conn->initial_info.name);
|
||||
@ -120,6 +124,7 @@ static void nbd_client_connection_do_free(NBDClientConnection *conn)
|
||||
*/
|
||||
static int nbd_connect(QIOChannelSocket *sioc, SocketAddress *addr,
|
||||
NBDExportInfo *info, QCryptoTLSCreds *tlscreds,
|
||||
const char *tlshostname,
|
||||
QIOChannel **outioc, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
@ -140,7 +145,7 @@ static int nbd_connect(QIOChannelSocket *sioc, SocketAddress *addr,
|
||||
}
|
||||
|
||||
ret = nbd_receive_negotiate(NULL, QIO_CHANNEL(sioc), tlscreds,
|
||||
tlscreds ? addr->u.inet.host : NULL,
|
||||
tlshostname,
|
||||
outioc, info, errp);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
@ -183,7 +188,8 @@ static void *connect_thread_func(void *opaque)
|
||||
|
||||
ret = nbd_connect(conn->sioc, conn->saddr,
|
||||
conn->do_negotiation ? &conn->updated_info : NULL,
|
||||
conn->tlscreds, &conn->ioc, &local_err);
|
||||
conn->tlscreds, conn->tlshostname,
|
||||
&conn->ioc, &local_err);
|
||||
|
||||
/*
|
||||
* conn->updated_info will finally be returned to the user. Clear the
|
||||
|
11
nbd/server.c
11
nbd/server.c
@ -2085,11 +2085,10 @@ static void nbd_extent_array_convert_to_be(NBDExtentArray *ea)
|
||||
* Add extent to NBDExtentArray. If extent can't be added (no available space),
|
||||
* return -1.
|
||||
* For safety, when returning -1 for the first time, .can_add is set to false,
|
||||
* further call to nbd_extent_array_add() will crash.
|
||||
* (to avoid the situation, when after failing to add an extent (returned -1),
|
||||
* user miss this failure and add another extent, which is successfully added
|
||||
* (array is full, but new extent may be squashed into the last one), then we
|
||||
* have invalid array with skipped extent)
|
||||
* and further calls to nbd_extent_array_add() will crash.
|
||||
* (this avoids the situation where a caller ignores failure to add one extent,
|
||||
* where adding another extent that would squash into the last array entry
|
||||
* would result in an incorrect range reported to the client)
|
||||
*/
|
||||
static int nbd_extent_array_add(NBDExtentArray *ea,
|
||||
uint32_t length, uint32_t flags)
|
||||
@ -2648,7 +2647,7 @@ static coroutine_fn void nbd_trip(void *opaque)
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
/* It wans't -EIO, so, according to nbd_co_receive_request()
|
||||
/* It wasn't -EIO, so, according to nbd_co_receive_request()
|
||||
* semantics, we should return the error to the client. */
|
||||
Error *export_err = local_err;
|
||||
|
||||
|
@ -4079,6 +4079,8 @@
|
||||
#
|
||||
# @tls-creds: TLS credentials ID
|
||||
#
|
||||
# @tls-hostname: TLS hostname override for certificate validation (Since 7.0)
|
||||
#
|
||||
# @x-dirty-bitmap: A metadata context name such as "qemu:dirty-bitmap:NAME"
|
||||
# or "qemu:allocation-depth" to query in place of the
|
||||
# traditional "base:allocation" block status (see
|
||||
@ -4109,6 +4111,7 @@
|
||||
'data': { 'server': 'SocketAddress',
|
||||
'*export': 'str',
|
||||
'*tls-creds': 'str',
|
||||
'*tls-hostname': 'str',
|
||||
'*x-dirty-bitmap': { 'type': 'str', 'features': [ 'unstable' ] },
|
||||
'*reconnect-delay': 'uint32',
|
||||
'*open-timeout': 'uint32' } }
|
||||
|
@ -604,10 +604,6 @@ static int do_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
|
||||
.done = false,
|
||||
};
|
||||
|
||||
if (bytes > INT_MAX) {
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
co = qemu_coroutine_create(co_pwrite_zeroes_entry, &data);
|
||||
bdrv_coroutine_enter(blk_bs(blk), co);
|
||||
while (!data.done) {
|
||||
@ -1161,8 +1157,9 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
|
||||
if (count < 0) {
|
||||
print_cvtnum_err(count, argv[optind]);
|
||||
return count;
|
||||
} else if (count > BDRV_REQUEST_MAX_BYTES) {
|
||||
printf("length cannot exceed %" PRIu64 ", given %s\n",
|
||||
} else if (count > BDRV_REQUEST_MAX_BYTES &&
|
||||
!(flags & BDRV_REQ_NO_FALLBACK)) {
|
||||
printf("length cannot exceed %" PRIu64 " without -n, given %s\n",
|
||||
(uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1994,11 +1991,9 @@ static int map_is_allocated(BlockDriverState *bs, int64_t offset,
|
||||
int64_t bytes, int64_t *pnum)
|
||||
{
|
||||
int64_t num;
|
||||
int num_checked;
|
||||
int ret, firstret;
|
||||
|
||||
num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
|
||||
ret = bdrv_is_allocated(bs, offset, num_checked, &num);
|
||||
ret = bdrv_is_allocated(bs, offset, bytes, &num);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@ -2010,8 +2005,7 @@ static int map_is_allocated(BlockDriverState *bs, int64_t offset,
|
||||
offset += num;
|
||||
bytes -= num;
|
||||
|
||||
num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
|
||||
ret = bdrv_is_allocated(bs, offset, num_checked, &num);
|
||||
ret = bdrv_is_allocated(bs, offset, bytes, &num);
|
||||
if (ret == firstret && num) {
|
||||
*pnum += num;
|
||||
} else {
|
||||
|
23
qemu-nbd.c
23
qemu-nbd.c
@ -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;
|
||||
@ -802,7 +808,9 @@ int main(int argc, char **argv)
|
||||
|
||||
socket_activation = check_socket_activation();
|
||||
if (socket_activation == 0) {
|
||||
if (!sockpath) {
|
||||
setup_address_and_port(&bindto, &port);
|
||||
}
|
||||
} else {
|
||||
/* Using socket activation - check user didn't use -p etc. */
|
||||
const char *err_msg = socket_activation_validate_opts(device, sockpath,
|
||||
@ -823,10 +831,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
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);
|
||||
@ -835,6 +839,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 +853,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 +873,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
|
||||
|
@ -61,11 +61,13 @@ tls_x509_create_server "ca1" "server1"
|
||||
tls_x509_create_client "ca1" "client1"
|
||||
tls_x509_create_client "ca2" "client2"
|
||||
tls_x509_create_client "ca1" "client3"
|
||||
tls_psk_create_creds "psk1"
|
||||
tls_psk_create_creds "psk2"
|
||||
|
||||
echo
|
||||
echo "== preparing image =="
|
||||
_make_test_img 64M
|
||||
$QEMU_IO -c 'w -P 0x11 1m 1m' "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -c 'w -P 0x11 1m 1m' "$TEST_IMG" 2>&1 | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "== check TLS client to plain server fails =="
|
||||
@ -74,9 +76,9 @@ nbd_server_start_tcp_socket -f $IMGFMT "$TEST_IMG" 2> "$TEST_DIR/server.log"
|
||||
obj=tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0
|
||||
$QEMU_IMG info --image-opts --object $obj \
|
||||
driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \
|
||||
2>&1 | sed "s/$nbd_tcp_port/PORT/g"
|
||||
2>&1 | _filter_nbd
|
||||
$QEMU_NBD_PROG -L -b $nbd_tcp_addr -p $nbd_tcp_port --object $obj \
|
||||
--tls-creds=tls0
|
||||
--tls-creds=tls0 2>&1 | _filter_qemu_nbd_exports
|
||||
|
||||
nbd_server_stop
|
||||
|
||||
@ -88,8 +90,10 @@ nbd_server_start_tcp_socket \
|
||||
--tls-creds tls0 \
|
||||
-f $IMGFMT "$TEST_IMG" 2>> "$TEST_DIR/server.log"
|
||||
|
||||
$QEMU_IMG info nbd://localhost:$nbd_tcp_port 2>&1 | sed "s/$nbd_tcp_port/PORT/g"
|
||||
$QEMU_NBD_PROG -L -b $nbd_tcp_addr -p $nbd_tcp_port
|
||||
$QEMU_IMG info nbd://localhost:$nbd_tcp_port \
|
||||
2>&1 | _filter_nbd
|
||||
$QEMU_NBD_PROG -L -b $nbd_tcp_addr -p $nbd_tcp_port \
|
||||
2>&1 | _filter_qemu_nbd_exports
|
||||
|
||||
echo
|
||||
echo "== check TLS works =="
|
||||
@ -97,21 +101,39 @@ obj1=tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0
|
||||
obj2=tls-creds-x509,dir=${tls_dir}/client3,endpoint=client,id=tls0
|
||||
$QEMU_IMG info --image-opts --object $obj1 \
|
||||
driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \
|
||||
2>&1 | sed "s/$nbd_tcp_port/PORT/g"
|
||||
2>&1 | _filter_nbd
|
||||
$QEMU_IMG info --image-opts --object $obj2 \
|
||||
driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \
|
||||
2>&1 | sed "s/$nbd_tcp_port/PORT/g"
|
||||
2>&1 | _filter_nbd
|
||||
$QEMU_NBD_PROG -L -b $nbd_tcp_addr -p $nbd_tcp_port --object $obj1 \
|
||||
--tls-creds=tls0
|
||||
--tls-creds=tls0 2>&1 | _filter_qemu_nbd_exports
|
||||
|
||||
echo
|
||||
echo "== check TLS fail over TCP with mismatched hostname =="
|
||||
obj1=tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0
|
||||
$QEMU_IMG info --image-opts --object $obj1 \
|
||||
driver=nbd,host=localhost,port=$nbd_tcp_port,tls-creds=tls0 \
|
||||
2>&1 | _filter_nbd
|
||||
$QEMU_NBD_PROG -L -b localhost -p $nbd_tcp_port --object $obj1 \
|
||||
--tls-creds=tls0 | _filter_qemu_nbd_exports
|
||||
|
||||
echo
|
||||
echo "== check TLS works over TCP with mismatched hostname and override =="
|
||||
obj1=tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0
|
||||
$QEMU_IMG info --image-opts --object $obj1 \
|
||||
driver=nbd,host=localhost,port=$nbd_tcp_port,tls-creds=tls0,tls-hostname=127.0.0.1 \
|
||||
2>&1 | _filter_nbd
|
||||
$QEMU_NBD_PROG -L -b localhost -p $nbd_tcp_port --object $obj1 \
|
||||
--tls-creds=tls0 --tls-hostname=127.0.0.1 | _filter_qemu_nbd_exports
|
||||
|
||||
echo
|
||||
echo "== check TLS with different CA fails =="
|
||||
obj=tls-creds-x509,dir=${tls_dir}/client2,endpoint=client,id=tls0
|
||||
$QEMU_IMG info --image-opts --object $obj \
|
||||
driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \
|
||||
2>&1 | sed "s/$nbd_tcp_port/PORT/g"
|
||||
2>&1 | _filter_nbd
|
||||
$QEMU_NBD_PROG -L -b $nbd_tcp_addr -p $nbd_tcp_port --object $obj \
|
||||
--tls-creds=tls0
|
||||
--tls-creds=tls0 2>&1 | _filter_qemu_nbd_exports
|
||||
|
||||
echo
|
||||
echo "== perform I/O over TLS =="
|
||||
@ -121,7 +143,8 @@ $QEMU_IO -c 'r -P 0x11 1m 1m' -c 'w -P 0x22 1m 1m' --image-opts \
|
||||
driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \
|
||||
2>&1 | _filter_qemu_io
|
||||
|
||||
$QEMU_IO -f $IMGFMT -r -U -c 'r -P 0x22 1m 1m' "$TEST_IMG" | _filter_qemu_io
|
||||
$QEMU_IO -f $IMGFMT -r -U -c 'r -P 0x22 1m 1m' "$TEST_IMG" \
|
||||
2>&1 | _filter_qemu_io
|
||||
|
||||
echo
|
||||
echo "== check TLS with authorization =="
|
||||
@ -139,12 +162,62 @@ nbd_server_start_tcp_socket \
|
||||
$QEMU_IMG info --image-opts \
|
||||
--object tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0 \
|
||||
driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \
|
||||
2>&1 | sed "s/$nbd_tcp_port/PORT/g"
|
||||
2>&1 | _filter_nbd
|
||||
|
||||
$QEMU_IMG info --image-opts \
|
||||
--object tls-creds-x509,dir=${tls_dir}/client3,endpoint=client,id=tls0 \
|
||||
driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \
|
||||
2>&1 | sed "s/$nbd_tcp_port/PORT/g"
|
||||
2>&1 | _filter_nbd
|
||||
|
||||
nbd_server_stop
|
||||
|
||||
nbd_server_start_unix_socket \
|
||||
--object tls-creds-x509,dir=${tls_dir}/server1,endpoint=server,id=tls0,verify-peer=on \
|
||||
--tls-creds tls0 \
|
||||
-f $IMGFMT "$TEST_IMG" 2>> "$TEST_DIR/server.log"
|
||||
|
||||
echo
|
||||
echo "== check TLS fail over UNIX with no hostname =="
|
||||
obj1=tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0
|
||||
$QEMU_IMG info --image-opts --object $obj1 \
|
||||
driver=nbd,path=$nbd_unix_socket,tls-creds=tls0 2>&1 | _filter_nbd
|
||||
$QEMU_NBD_PROG -L -k $nbd_unix_socket --object $obj1 --tls-creds=tls0 \
|
||||
2>&1 | _filter_qemu_nbd_exports
|
||||
|
||||
echo
|
||||
echo "== check TLS works over UNIX with hostname override =="
|
||||
obj1=tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0
|
||||
$QEMU_IMG info --image-opts --object $obj1 \
|
||||
driver=nbd,path=$nbd_unix_socket,tls-creds=tls0,tls-hostname=127.0.0.1 \
|
||||
2>&1 | _filter_nbd
|
||||
$QEMU_NBD_PROG -L -k $nbd_unix_socket --object $obj1 \
|
||||
--tls-creds=tls0 --tls-hostname=127.0.0.1 2>&1 | _filter_qemu_nbd_exports
|
||||
|
||||
|
||||
echo
|
||||
echo "== check TLS works over UNIX with PSK =="
|
||||
nbd_server_stop
|
||||
|
||||
nbd_server_start_unix_socket \
|
||||
--object tls-creds-psk,dir=${tls_dir}/psk1,endpoint=server,id=tls0,verify-peer=on \
|
||||
--tls-creds tls0 \
|
||||
-f $IMGFMT "$TEST_IMG" 2>> "$TEST_DIR/server.log"
|
||||
|
||||
obj1=tls-creds-psk,dir=${tls_dir}/psk1,username=psk1,endpoint=client,id=tls0
|
||||
$QEMU_IMG info --image-opts --object $obj1 \
|
||||
driver=nbd,path=$nbd_unix_socket,tls-creds=tls0 \
|
||||
2>&1 | _filter_nbd
|
||||
$QEMU_NBD_PROG -L -k $nbd_unix_socket --object $obj1 \
|
||||
--tls-creds=tls0 2>&1 | _filter_qemu_nbd_exports
|
||||
|
||||
echo
|
||||
echo "== check TLS fails over UNIX with mismatch PSK =="
|
||||
obj1=tls-creds-psk,dir=${tls_dir}/psk2,username=psk2,endpoint=client,id=tls0
|
||||
$QEMU_IMG info --image-opts --object $obj1 \
|
||||
driver=nbd,path=$nbd_unix_socket,tls-creds=tls0 \
|
||||
2>&1 | _filter_nbd
|
||||
$QEMU_NBD_PROG -L -k $nbd_unix_socket --object $obj1 \
|
||||
--tls-creds=tls0 2>&1 | _filter_qemu_nbd_exports
|
||||
|
||||
echo
|
||||
echo "== final server log =="
|
||||
|
@ -7,6 +7,8 @@ Generating a signed certificate...
|
||||
Generating a signed certificate...
|
||||
Generating a signed certificate...
|
||||
Generating a signed certificate...
|
||||
Generating a random key for user 'psk1'
|
||||
Generating a random key for user 'psk2'
|
||||
|
||||
== preparing image ==
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
@ -17,15 +19,12 @@ wrote 1048576/1048576 bytes at offset 1048576
|
||||
qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': Denied by server for option 5 (starttls)
|
||||
server reported: TLS not configured
|
||||
qemu-nbd: Denied by server for option 5 (starttls)
|
||||
server reported: TLS not configured
|
||||
|
||||
== check plain client to TLS server fails ==
|
||||
qemu-img: Could not open 'nbd://localhost:PORT': TLS negotiation required before option 7 (go)
|
||||
Did you forget a valid tls-creds?
|
||||
server reported: Option 0x7 not permitted before TLS
|
||||
qemu-nbd: TLS negotiation required before option 3 (list)
|
||||
Did you forget a valid tls-creds?
|
||||
server reported: Option 0x3 not permitted before TLS
|
||||
|
||||
== check TLS works ==
|
||||
image: nbd://127.0.0.1:PORT
|
||||
@ -39,12 +38,21 @@ disk size: unavailable
|
||||
exports available: 1
|
||||
export: ''
|
||||
size: 67108864
|
||||
flags: 0xced ( flush fua trim zeroes df cache fast-zero )
|
||||
min block: 1
|
||||
opt block: 4096
|
||||
max block: 33554432
|
||||
available meta contexts: 1
|
||||
base:allocation
|
||||
|
||||
== check TLS fail over TCP with mismatched hostname ==
|
||||
qemu-img: Could not open 'driver=nbd,host=localhost,port=PORT,tls-creds=tls0': Certificate does not match the hostname localhost
|
||||
qemu-nbd: Certificate does not match the hostname localhost
|
||||
|
||||
== check TLS works over TCP with mismatched hostname and override ==
|
||||
image: nbd://localhost:PORT
|
||||
file format: nbd
|
||||
virtual size: 64 MiB (67108864 bytes)
|
||||
disk size: unavailable
|
||||
exports available: 1
|
||||
export: ''
|
||||
size: 67108864
|
||||
min block: 1
|
||||
|
||||
== check TLS with different CA fails ==
|
||||
qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': The certificate hasn't got a known issuer
|
||||
@ -62,9 +70,43 @@ read 1048576/1048576 bytes at offset 1048576
|
||||
qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': Failed to read option reply: Cannot read from TLS channel: Software caused connection abort
|
||||
qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': Failed to read option reply: Cannot read from TLS channel: Software caused connection abort
|
||||
|
||||
== check TLS fail over UNIX with no hostname ==
|
||||
qemu-img: Could not open 'driver=nbd,path=SOCK_DIR/qemu-nbd.sock,tls-creds=tls0': No hostname for certificate validation
|
||||
qemu-nbd: No hostname for certificate validation
|
||||
|
||||
== check TLS works over UNIX with hostname override ==
|
||||
image: nbd+unix://?socket=SOCK_DIR/qemu-nbd.sock
|
||||
file format: nbd
|
||||
virtual size: 64 MiB (67108864 bytes)
|
||||
disk size: unavailable
|
||||
exports available: 1
|
||||
export: ''
|
||||
size: 67108864
|
||||
min block: 1
|
||||
|
||||
== check TLS works over UNIX with PSK ==
|
||||
image: nbd+unix://?socket=SOCK_DIR/qemu-nbd.sock
|
||||
file format: nbd
|
||||
virtual size: 64 MiB (67108864 bytes)
|
||||
disk size: unavailable
|
||||
exports available: 1
|
||||
export: ''
|
||||
size: 67108864
|
||||
min block: 1
|
||||
|
||||
== check TLS fails over UNIX with mismatch PSK ==
|
||||
qemu-img: Could not open 'driver=nbd,path=SOCK_DIR/qemu-nbd.sock,tls-creds=tls0': TLS handshake failed: The TLS connection was non-properly terminated.
|
||||
qemu-nbd: TLS handshake failed: The TLS connection was non-properly terminated.
|
||||
|
||||
== final server log ==
|
||||
qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: Software caused connection abort
|
||||
qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: Software caused connection abort
|
||||
qemu-nbd: option negotiation failed: Verify failed: No certificate was found.
|
||||
qemu-nbd: option negotiation failed: Verify failed: No certificate was found.
|
||||
qemu-nbd: option negotiation failed: TLS x509 authz check for DISTINGUISHED-NAME is denied
|
||||
qemu-nbd: option negotiation failed: TLS x509 authz check for DISTINGUISHED-NAME is denied
|
||||
qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: Software caused connection abort
|
||||
qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: Software caused connection abort
|
||||
qemu-nbd: option negotiation failed: TLS handshake failed: An illegal parameter has been received.
|
||||
qemu-nbd: option negotiation failed: TLS handshake failed: An illegal parameter has been received.
|
||||
*** done
|
||||
|
@ -58,7 +58,7 @@ echo
|
||||
|
||||
nbd_server_start_unix_socket -f $IMGFMT "$TEST_IMG_FILE"
|
||||
|
||||
$QEMU_NBD_PROG --list -k $nbd_unix_socket | grep '\(size\|min\)'
|
||||
$QEMU_NBD_PROG --list -k $nbd_unix_socket | _filter_qemu_nbd_exports
|
||||
$QEMU_IMG map -f raw --output=json "$TEST_IMG" | _filter_qemu_img_map
|
||||
$QEMU_IO -f raw -c map "$TEST_IMG"
|
||||
nbd_server_stop
|
||||
@ -71,7 +71,7 @@ echo
|
||||
# sector alignment, here at the server.
|
||||
nbd_server_start_unix_socket "$TEST_IMG_FILE" 2> "$TEST_DIR/server.log"
|
||||
|
||||
$QEMU_NBD_PROG --list -k $nbd_unix_socket | grep '\(size\|min\)'
|
||||
$QEMU_NBD_PROG --list -k $nbd_unix_socket | _filter_qemu_nbd_exports
|
||||
$QEMU_IMG map -f raw --output=json "$TEST_IMG" | _filter_qemu_img_map
|
||||
$QEMU_IO -f raw -c map "$TEST_IMG"
|
||||
nbd_server_stop
|
||||
@ -84,7 +84,7 @@ echo
|
||||
# Now force sector alignment at the client.
|
||||
nbd_server_start_unix_socket -f $IMGFMT "$TEST_IMG_FILE"
|
||||
|
||||
$QEMU_NBD_PROG --list -k $nbd_unix_socket | grep '\(size\|min\)'
|
||||
$QEMU_NBD_PROG --list -k $nbd_unix_socket | _filter_qemu_nbd_exports
|
||||
$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
|
||||
$QEMU_IO -c map "$TEST_IMG"
|
||||
nbd_server_stop
|
||||
|
@ -2,6 +2,8 @@ QA output created by 241
|
||||
|
||||
=== Exporting unaligned raw image, natural alignment ===
|
||||
|
||||
exports available: 1
|
||||
export: ''
|
||||
size: 1024
|
||||
min block: 1
|
||||
[{ "start": 0, "length": 1000, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
|
||||
@ -10,6 +12,8 @@ QA output created by 241
|
||||
|
||||
=== Exporting unaligned raw image, forced server sector alignment ===
|
||||
|
||||
exports available: 1
|
||||
export: ''
|
||||
size: 1024
|
||||
min block: 512
|
||||
[{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET}]
|
||||
@ -20,6 +24,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
|
||||
|
||||
=== Exporting unaligned raw image, forced client sector alignment ===
|
||||
|
||||
exports available: 1
|
||||
export: ''
|
||||
size: 1024
|
||||
min block: 1
|
||||
[{ "start": 0, "length": 1000, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
|
||||
|
@ -301,10 +301,19 @@ _filter_nbd()
|
||||
# Filter out the TCP port number since this changes between runs.
|
||||
sed -e '/nbd\/.*\.c:/d' \
|
||||
-e 's#127\.0\.0\.1:[0-9]*#127.0.0.1:PORT#g' \
|
||||
-e 's#localhost:[0-9]*#localhost:PORT#g' \
|
||||
-e 's#host=127\.0\.0\.1,port=[0-9]*#host=127.0.0.1,port=PORT#g' \
|
||||
-e 's#host=localhost,port=[0-9]*#host=localhost,port=PORT#g' \
|
||||
-e "s#path=$SOCK_DIR#path=SOCK_DIR#g" \
|
||||
-e "s#?socket=$SOCK_DIR#?socket=SOCK_DIR#g" \
|
||||
-e 's#\(foo\|PORT/\?\|.sock\): Failed to .*$#\1#'
|
||||
}
|
||||
|
||||
_filter_qemu_nbd_exports()
|
||||
{
|
||||
grep '\(exports available\|export\|size\|min block\|qemu-nbd\):'
|
||||
}
|
||||
|
||||
_filter_qmp_empty_return()
|
||||
{
|
||||
grep -v '{"return": {}}'
|
||||
|
@ -24,6 +24,7 @@ tls_x509_cleanup()
|
||||
{
|
||||
rm -f "${tls_dir}"/*.pem
|
||||
rm -f "${tls_dir}"/*/*.pem
|
||||
rm -f "${tls_dir}"/*/*.psk
|
||||
rmdir "${tls_dir}"/*
|
||||
rmdir "${tls_dir}"
|
||||
}
|
||||
@ -40,6 +41,18 @@ tls_certtool()
|
||||
rm -f "${tls_dir}"/certtool.log
|
||||
}
|
||||
|
||||
tls_psktool()
|
||||
{
|
||||
psktool "$@" 1>"${tls_dir}"/psktool.log 2>&1
|
||||
if test "$?" = 0; then
|
||||
head -1 "${tls_dir}"/psktool.log
|
||||
else
|
||||
cat "${tls_dir}"/psktool.log
|
||||
fi
|
||||
rm -f "${tls_dir}"/psktool.log
|
||||
}
|
||||
|
||||
|
||||
tls_x509_init()
|
||||
{
|
||||
(certtool --help) >/dev/null 2>&1 || \
|
||||
@ -118,12 +131,13 @@ tls_x509_create_server()
|
||||
caname=$1
|
||||
name=$2
|
||||
|
||||
# We don't include 'localhost' in the cert, as
|
||||
# we want to keep it unlisted to let tests
|
||||
# validate hostname override
|
||||
mkdir -p "${tls_dir}/$name"
|
||||
cat > "${tls_dir}/cert.info" <<EOF
|
||||
organization = Cthulhu Dark Lord Enterprises $name
|
||||
cn = localhost
|
||||
dns_name = localhost
|
||||
dns_name = localhost.localdomain
|
||||
cn = iotests.qemu.org
|
||||
ip_address = 127.0.0.1
|
||||
ip_address = ::1
|
||||
tls_www_server
|
||||
@ -175,3 +189,14 @@ EOF
|
||||
|
||||
rm -f "${tls_dir}/cert.info"
|
||||
}
|
||||
|
||||
tls_psk_create_creds()
|
||||
{
|
||||
name=$1
|
||||
|
||||
mkdir -p "${tls_dir}/$name"
|
||||
|
||||
tls_psktool \
|
||||
--pskfile "${tls_dir}/$name/keys.psk" \
|
||||
--username "$name"
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import subprocess
|
||||
import contextlib
|
||||
import json
|
||||
import termios
|
||||
import shutil
|
||||
import sys
|
||||
from multiprocessing import Pool
|
||||
from contextlib import contextmanager
|
||||
@ -322,6 +323,11 @@ class TestRunner(ContextManager['TestRunner']):
|
||||
|
||||
diff = file_diff(str(f_reference), str(f_bad))
|
||||
if diff:
|
||||
if os.environ.get("QEMU_IOTESTS_REGEN", None) is not None:
|
||||
shutil.copyfile(str(f_bad), str(f_reference))
|
||||
print("########################################")
|
||||
print("##### REFERENCE FILE UPDATED #####")
|
||||
print("########################################")
|
||||
return TestResult(status='fail', elapsed=elapsed,
|
||||
description=f'output mismatch (see {f_bad})',
|
||||
diff=diff, casenotrun=casenotrun)
|
||||
|
Loading…
Reference in New Issue
Block a user