aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/qtest/meson.build12
-rw-r--r--tests/qtest/migration-helpers.c13
-rw-r--r--tests/qtest/migration-helpers.h1
-rw-r--r--tests/qtest/migration-test.c867
-rw-r--r--tests/unit/crypto-tls-psk-helpers.c18
-rw-r--r--tests/unit/crypto-tls-psk-helpers.h1
-rw-r--r--tests/unit/crypto-tls-x509-helpers.c16
-rw-r--r--tests/unit/crypto-tls-x509-helpers.h53
-rw-r--r--tests/unit/test-crypto-tlssession.c11
-rw-r--r--tests/unit/test-io-channel-socket.c1
10 files changed, 898 insertions, 95 deletions
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 3551b9c..b425484 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -273,13 +273,23 @@ endif
tpmemu_files = ['tpm-emu.c', 'tpm-util.c', 'tpm-tests.c']
+migration_files = [files('migration-helpers.c')]
+if gnutls.found()
+ migration_files += [files('../unit/crypto-tls-psk-helpers.c'), gnutls]
+
+ if tasn1.found()
+ migration_files += [files('../unit/crypto-tls-x509-helpers.c',
+ '../unit/pkix_asn1_tab.c'), tasn1]
+ endif
+endif
+
qtests = {
'bios-tables-test': [io, 'boot-sector.c', 'acpi-utils.c', 'tpm-emu.c'],
'cdrom-test': files('boot-sector.c'),
'dbus-vmstate-test': files('migration-helpers.c') + dbus_vmstate1,
'erst-test': files('erst-test.c'),
'ivshmem-test': [rt, '../../contrib/ivshmem-server/ivshmem-server.c'],
- 'migration-test': files('migration-helpers.c'),
+ 'migration-test': migration_files,
'pxe-test': files('boot-sector.c'),
'qos-test': [chardev, io, qos_test_ss.apply(config_host, strict: false).sources()],
'tpm-crb-swtpm-test': [io, tpmemu_files],
diff --git a/tests/qtest/migration-helpers.c b/tests/qtest/migration-helpers.c
index 4ee2601..a6aa59e 100644
--- a/tests/qtest/migration-helpers.c
+++ b/tests/qtest/migration-helpers.c
@@ -107,6 +107,19 @@ QDict *migrate_query(QTestState *who)
return wait_command(who, "{ 'execute': 'query-migrate' }");
}
+QDict *migrate_query_not_failed(QTestState *who)
+{
+ const char *status;
+ QDict *rsp = migrate_query(who);
+ status = qdict_get_str(rsp, "status");
+ if (g_str_equal(status, "failed")) {
+ g_printerr("query-migrate shows failed migration: %s\n",
+ qdict_get_str(rsp, "error-desc"));
+ }
+ g_assert(!g_str_equal(status, "failed"));
+ return rsp;
+}
+
/*
* Note: caller is responsible to free the returned object via
* g_free() after use
diff --git a/tests/qtest/migration-helpers.h b/tests/qtest/migration-helpers.h
index 2731399..78587c2 100644
--- a/tests/qtest/migration-helpers.h
+++ b/tests/qtest/migration-helpers.h
@@ -27,6 +27,7 @@ G_GNUC_PRINTF(3, 4)
void migrate_qmp(QTestState *who, const char *uri, const char *fmt, ...);
QDict *migrate_query(QTestState *who);
+QDict *migrate_query_not_failed(QTestState *who);
void wait_for_migration_status(QTestState *who,
const char *goal, const char **ungoals);
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index cba6023..d33e806 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -23,9 +23,16 @@
#include "qapi/qapi-visit-sockets.h"
#include "qapi/qobject-input-visitor.h"
#include "qapi/qobject-output-visitor.h"
+#include "crypto/tlscredspsk.h"
#include "migration-helpers.h"
#include "tests/migration/migration-test.h"
+#ifdef CONFIG_GNUTLS
+# include "tests/unit/crypto-tls-psk-helpers.h"
+# ifdef CONFIG_TASN1
+# include "tests/unit/crypto-tls-x509-helpers.h"
+# endif /* CONFIG_TASN1 */
+#endif /* CONFIG_GNUTLS */
/* For dirty ring test; so far only x86_64 is supported */
#if defined(__linux__) && defined(HOST_X86_64)
@@ -174,7 +181,7 @@ static int64_t read_ram_property_int(QTestState *who, const char *property)
QDict *rsp_return, *rsp_ram;
int64_t result;
- rsp_return = migrate_query(who);
+ rsp_return = migrate_query_not_failed(who);
if (!qdict_haskey(rsp_return, "ram")) {
/* Still in setup */
result = 0;
@@ -191,7 +198,7 @@ static int64_t read_migrate_property_int(QTestState *who, const char *property)
QDict *rsp_return;
int64_t result;
- rsp_return = migrate_query(who);
+ rsp_return = migrate_query_not_failed(who);
result = qdict_get_try_int(rsp_return, property, 0);
qobject_unref(rsp_return);
return result;
@@ -206,7 +213,7 @@ static void read_blocktime(QTestState *who)
{
QDict *rsp_return;
- rsp_return = migrate_query(who);
+ rsp_return = migrate_query_not_failed(who);
g_assert(qdict_haskey(rsp_return, "postcopy-blocktime"));
qobject_unref(rsp_return);
}
@@ -640,6 +647,328 @@ static void test_migrate_end(QTestState *from, QTestState *to, bool test_dest)
cleanup("dest_serial");
}
+#ifdef CONFIG_GNUTLS
+struct TestMigrateTLSPSKData {
+ char *workdir;
+ char *workdiralt;
+ char *pskfile;
+ char *pskfilealt;
+};
+
+static void *
+test_migrate_tls_psk_start_common(QTestState *from,
+ QTestState *to,
+ bool mismatch)
+{
+ struct TestMigrateTLSPSKData *data =
+ g_new0(struct TestMigrateTLSPSKData, 1);
+ QDict *rsp;
+
+ data->workdir = g_strdup_printf("%s/tlscredspsk0", tmpfs);
+ data->pskfile = g_strdup_printf("%s/%s", data->workdir,
+ QCRYPTO_TLS_CREDS_PSKFILE);
+ mkdir(data->workdir, 0700);
+ test_tls_psk_init(data->pskfile);
+
+ if (mismatch) {
+ data->workdiralt = g_strdup_printf("%s/tlscredspskalt0", tmpfs);
+ data->pskfilealt = g_strdup_printf("%s/%s", data->workdiralt,
+ QCRYPTO_TLS_CREDS_PSKFILE);
+ mkdir(data->workdiralt, 0700);
+ test_tls_psk_init_alt(data->pskfilealt);
+ }
+
+ rsp = wait_command(from,
+ "{ 'execute': 'object-add',"
+ " 'arguments': { 'qom-type': 'tls-creds-psk',"
+ " 'id': 'tlscredspsk0',"
+ " 'endpoint': 'client',"
+ " 'dir': %s,"
+ " 'username': 'qemu'} }",
+ data->workdir);
+ qobject_unref(rsp);
+
+ rsp = wait_command(to,
+ "{ 'execute': 'object-add',"
+ " 'arguments': { 'qom-type': 'tls-creds-psk',"
+ " 'id': 'tlscredspsk0',"
+ " 'endpoint': 'server',"
+ " 'dir': %s } }",
+ mismatch ? data->workdiralt : data->workdir);
+ qobject_unref(rsp);
+
+ migrate_set_parameter_str(from, "tls-creds", "tlscredspsk0");
+ migrate_set_parameter_str(to, "tls-creds", "tlscredspsk0");
+
+ return data;
+}
+
+static void *
+test_migrate_tls_psk_start_match(QTestState *from,
+ QTestState *to)
+{
+ return test_migrate_tls_psk_start_common(from, to, false);
+}
+
+static void *
+test_migrate_tls_psk_start_mismatch(QTestState *from,
+ QTestState *to)
+{
+ return test_migrate_tls_psk_start_common(from, to, true);
+}
+
+static void
+test_migrate_tls_psk_finish(QTestState *from,
+ QTestState *to,
+ void *opaque)
+{
+ struct TestMigrateTLSPSKData *data = opaque;
+
+ test_tls_psk_cleanup(data->pskfile);
+ if (data->pskfilealt) {
+ test_tls_psk_cleanup(data->pskfilealt);
+ }
+ rmdir(data->workdir);
+ if (data->workdiralt) {
+ rmdir(data->workdiralt);
+ }
+
+ g_free(data->workdiralt);
+ g_free(data->pskfilealt);
+ g_free(data->workdir);
+ g_free(data->pskfile);
+ g_free(data);
+}
+
+#ifdef CONFIG_TASN1
+typedef struct {
+ char *workdir;
+ char *keyfile;
+ char *cacert;
+ char *servercert;
+ char *serverkey;
+ char *clientcert;
+ char *clientkey;
+} TestMigrateTLSX509Data;
+
+typedef struct {
+ bool verifyclient;
+ bool clientcert;
+ bool hostileclient;
+ bool authzclient;
+ const char *certhostname;
+ const char *certipaddr;
+} TestMigrateTLSX509;
+
+static void *
+test_migrate_tls_x509_start_common(QTestState *from,
+ QTestState *to,
+ TestMigrateTLSX509 *args)
+{
+ TestMigrateTLSX509Data *data = g_new0(TestMigrateTLSX509Data, 1);
+ QDict *rsp;
+
+ data->workdir = g_strdup_printf("%s/tlscredsx5090", tmpfs);
+ data->keyfile = g_strdup_printf("%s/key.pem", data->workdir);
+
+ data->cacert = g_strdup_printf("%s/ca-cert.pem", data->workdir);
+ data->serverkey = g_strdup_printf("%s/server-key.pem", data->workdir);
+ data->servercert = g_strdup_printf("%s/server-cert.pem", data->workdir);
+ if (args->clientcert) {
+ data->clientkey = g_strdup_printf("%s/client-key.pem", data->workdir);
+ data->clientcert = g_strdup_printf("%s/client-cert.pem", data->workdir);
+ }
+
+ mkdir(data->workdir, 0700);
+
+ test_tls_init(data->keyfile);
+ g_assert(link(data->keyfile, data->serverkey) == 0);
+ if (args->clientcert) {
+ g_assert(link(data->keyfile, data->clientkey) == 0);
+ }
+
+ TLS_ROOT_REQ_SIMPLE(cacertreq, data->cacert);
+ if (args->clientcert) {
+ TLS_CERT_REQ_SIMPLE_CLIENT(servercertreq, cacertreq,
+ args->hostileclient ?
+ QCRYPTO_TLS_TEST_CLIENT_HOSTILE_NAME :
+ QCRYPTO_TLS_TEST_CLIENT_NAME,
+ data->clientcert);
+ }
+
+ TLS_CERT_REQ_SIMPLE_SERVER(clientcertreq, cacertreq,
+ data->servercert,
+ args->certhostname,
+ args->certipaddr);
+
+ rsp = wait_command(from,
+ "{ 'execute': 'object-add',"
+ " 'arguments': { 'qom-type': 'tls-creds-x509',"
+ " 'id': 'tlscredsx509client0',"
+ " 'endpoint': 'client',"
+ " 'dir': %s,"
+ " 'sanity-check': true,"
+ " 'verify-peer': true} }",
+ data->workdir);
+ qobject_unref(rsp);
+ migrate_set_parameter_str(from, "tls-creds", "tlscredsx509client0");
+ if (args->certhostname) {
+ migrate_set_parameter_str(from, "tls-hostname", args->certhostname);
+ }
+
+ rsp = wait_command(to,
+ "{ 'execute': 'object-add',"
+ " 'arguments': { 'qom-type': 'tls-creds-x509',"
+ " 'id': 'tlscredsx509server0',"
+ " 'endpoint': 'server',"
+ " 'dir': %s,"
+ " 'sanity-check': true,"
+ " 'verify-peer': %i} }",
+ data->workdir, args->verifyclient);
+ qobject_unref(rsp);
+ migrate_set_parameter_str(to, "tls-creds", "tlscredsx509server0");
+
+ if (args->authzclient) {
+ rsp = wait_command(to,
+ "{ 'execute': 'object-add',"
+ " 'arguments': { 'qom-type': 'authz-simple',"
+ " 'id': 'tlsauthz0',"
+ " 'identity': %s} }",
+ "CN=" QCRYPTO_TLS_TEST_CLIENT_NAME);
+ migrate_set_parameter_str(to, "tls-authz", "tlsauthz0");
+ }
+
+ return data;
+}
+
+/*
+ * The normal case: match server's cert hostname against
+ * whatever host we were telling QEMU to connect to (if any)
+ */
+static void *
+test_migrate_tls_x509_start_default_host(QTestState *from,
+ QTestState *to)
+{
+ TestMigrateTLSX509 args = {
+ .verifyclient = true,
+ .clientcert = true,
+ .certipaddr = "127.0.0.1"
+ };
+ return test_migrate_tls_x509_start_common(from, to, &args);
+}
+
+/*
+ * The unusual case: the server's cert is different from
+ * the address we're telling QEMU to connect to (if any),
+ * so we must give QEMU an explicit hostname to validate
+ */
+static void *
+test_migrate_tls_x509_start_override_host(QTestState *from,
+ QTestState *to)
+{
+ TestMigrateTLSX509 args = {
+ .verifyclient = true,
+ .clientcert = true,
+ .certhostname = "qemu.org",
+ };
+ return test_migrate_tls_x509_start_common(from, to, &args);
+}
+
+/*
+ * The unusual case: the server's cert is different from
+ * the address we're telling QEMU to connect to, and so we
+ * expect the client to reject the server
+ */
+static void *
+test_migrate_tls_x509_start_mismatch_host(QTestState *from,
+ QTestState *to)
+{
+ TestMigrateTLSX509 args = {
+ .verifyclient = true,
+ .clientcert = true,
+ .certipaddr = "10.0.0.1",
+ };
+ return test_migrate_tls_x509_start_common(from, to, &args);
+}
+
+static void *
+test_migrate_tls_x509_start_friendly_client(QTestState *from,
+ QTestState *to)
+{
+ TestMigrateTLSX509 args = {
+ .verifyclient = true,
+ .clientcert = true,
+ .authzclient = true,
+ .certipaddr = "127.0.0.1",
+ };
+ return test_migrate_tls_x509_start_common(from, to, &args);
+}
+
+static void *
+test_migrate_tls_x509_start_hostile_client(QTestState *from,
+ QTestState *to)
+{
+ TestMigrateTLSX509 args = {
+ .verifyclient = true,
+ .clientcert = true,
+ .hostileclient = true,
+ .authzclient = true,
+ .certipaddr = "127.0.0.1",
+ };
+ return test_migrate_tls_x509_start_common(from, to, &args);
+}
+
+/*
+ * The case with no client certificate presented,
+ * and no server verification
+ */
+static void *
+test_migrate_tls_x509_start_allow_anon_client(QTestState *from,
+ QTestState *to)
+{
+ TestMigrateTLSX509 args = {
+ .certipaddr = "127.0.0.1",
+ };
+ return test_migrate_tls_x509_start_common(from, to, &args);
+}
+
+/*
+ * The case with no client certificate presented,
+ * and server verification rejecting
+ */
+static void *
+test_migrate_tls_x509_start_reject_anon_client(QTestState *from,
+ QTestState *to)
+{
+ TestMigrateTLSX509 args = {
+ .verifyclient = true,
+ .certipaddr = "127.0.0.1",
+ };
+ return test_migrate_tls_x509_start_common(from, to, &args);
+}
+
+static void
+test_migrate_tls_x509_finish(QTestState *from,
+ QTestState *to,
+ void *opaque)
+{
+ TestMigrateTLSX509Data *data = opaque;
+
+ test_tls_cleanup(data->keyfile);
+ unlink(data->cacert);
+ unlink(data->servercert);
+ unlink(data->serverkey);
+ unlink(data->clientcert);
+ unlink(data->clientkey);
+ rmdir(data->workdir);
+
+ g_free(data->workdir);
+ g_free(data->keyfile);
+ g_free(data);
+}
+#endif /* CONFIG_TASN1 */
+#endif /* CONFIG_GNUTLS */
+
static int migrate_postcopy_prepare(QTestState **from_ptr,
QTestState **to_ptr,
MigrateStart *args)
@@ -845,6 +1174,9 @@ typedef struct {
/* This test should fail, dest qemu should fail with abnormal status */
MIG_TEST_FAIL_DEST_QUIT_ERR,
} result;
+
+ /* Optional: set number of migration passes to wait for */
+ unsigned int iterations;
} MigrateCommon;
static void test_precopy_common(MigrateCommon *args)
@@ -890,7 +1222,13 @@ static void test_precopy_common(MigrateCommon *args)
qtest_set_expected_status(to, 1);
}
} else {
- wait_for_migration_pass(from);
+ if (args->iterations) {
+ while (args->iterations--) {
+ wait_for_migration_pass(from);
+ }
+ } else {
+ wait_for_migration_pass(from);
+ }
migrate_set_parameter_int(from, "downtime-limit", CONVERGE_DOWNTIME);
@@ -911,7 +1249,7 @@ static void test_precopy_common(MigrateCommon *args)
test_migrate_end(from, to, args->result == MIG_TEST_SUCCEED);
}
-static void test_precopy_unix(void)
+static void test_precopy_unix_plain(void)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
MigrateCommon args = {
@@ -922,6 +1260,7 @@ static void test_precopy_unix(void)
test_precopy_common(&args);
}
+
static void test_precopy_unix_dirty_ring(void)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
@@ -936,6 +1275,53 @@ static void test_precopy_unix_dirty_ring(void)
test_precopy_common(&args);
}
+#ifdef CONFIG_GNUTLS
+static void test_precopy_unix_tls_psk(void)
+{
+ g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+ MigrateCommon args = {
+ .connect_uri = uri,
+ .listen_uri = uri,
+ .start_hook = test_migrate_tls_psk_start_match,
+ .finish_hook = test_migrate_tls_psk_finish,
+ };
+
+ test_precopy_common(&args);
+}
+
+#ifdef CONFIG_TASN1
+static void test_precopy_unix_tls_x509_default_host(void)
+{
+ g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+ MigrateCommon args = {
+ .start = {
+ .hide_stderr = true,
+ },
+ .connect_uri = uri,
+ .listen_uri = uri,
+ .start_hook = test_migrate_tls_x509_start_default_host,
+ .finish_hook = test_migrate_tls_x509_finish,
+ .result = MIG_TEST_FAIL_DEST_QUIT_ERR,
+ };
+
+ test_precopy_common(&args);
+}
+
+static void test_precopy_unix_tls_x509_override_host(void)
+{
+ g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+ MigrateCommon args = {
+ .connect_uri = uri,
+ .listen_uri = uri,
+ .start_hook = test_migrate_tls_x509_start_override_host,
+ .finish_hook = test_migrate_tls_x509_finish,
+ };
+
+ test_precopy_common(&args);
+}
+#endif /* CONFIG_TASN1 */
+#endif /* CONFIG_GNUTLS */
+
#if 0
/* Currently upset on aarch64 TCG */
static void test_ignore_shared(void)
@@ -973,68 +1359,161 @@ static void test_ignore_shared(void)
}
#endif
-static void test_xbzrle(const char *uri)
+static void *
+test_migrate_xbzrle_start(QTestState *from,
+ QTestState *to)
{
- MigrateStart args = {};
- QTestState *from, *to;
-
- if (test_migrate_start(&from, &to, uri, &args)) {
- return;
- }
-
- /*
- * We want to pick a speed slow enough that the test completes
- * quickly, but that it doesn't complete precopy even on a slow
- * machine, so also set the downtime.
- */
- /* 1 ms should make it not converge*/
- migrate_set_parameter_int(from, "downtime-limit", 1);
- /* 1GB/s */
- migrate_set_parameter_int(from, "max-bandwidth", 1000000000);
-
migrate_set_parameter_int(from, "xbzrle-cache-size", 33554432);
migrate_set_capability(from, "xbzrle", true);
migrate_set_capability(to, "xbzrle", true);
- /* Wait for the first serial output from the source */
- wait_for_serial("src_serial");
- migrate_qmp(from, uri, "{}");
+ return NULL;
+}
- wait_for_migration_pass(from);
- /* Make sure we have 2 passes, so the xbzrle cache gets a workout */
- wait_for_migration_pass(from);
+static void test_precopy_unix_xbzrle(void)
+{
+ g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+ MigrateCommon args = {
+ .connect_uri = uri,
+ .listen_uri = uri,
- /* 1000ms should converge */
- migrate_set_parameter_int(from, "downtime-limit", 1000);
+ .start_hook = test_migrate_xbzrle_start,
- if (!got_stop) {
- qtest_qmp_eventwait(from, "STOP");
- }
- qtest_qmp_eventwait(to, "RESUME");
+ .iterations = 2,
+ };
- wait_for_serial("dest_serial");
- wait_for_migration_complete(from);
+ test_precopy_common(&args);
+}
- test_migrate_end(from, to, true);
+static void test_precopy_tcp_plain(void)
+{
+ MigrateCommon args = {
+ .listen_uri = "tcp:127.0.0.1:0",
+ };
+
+ test_precopy_common(&args);
}
-static void test_xbzrle_unix(void)
+#ifdef CONFIG_GNUTLS
+static void test_precopy_tcp_tls_psk_match(void)
{
- g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+ MigrateCommon args = {
+ .listen_uri = "tcp:127.0.0.1:0",
+ .start_hook = test_migrate_tls_psk_start_match,
+ .finish_hook = test_migrate_tls_psk_finish,
+ };
- test_xbzrle(uri);
+ test_precopy_common(&args);
}
-static void test_precopy_tcp(void)
+static void test_precopy_tcp_tls_psk_mismatch(void)
{
MigrateCommon args = {
+ .start = {
+ .hide_stderr = true,
+ },
.listen_uri = "tcp:127.0.0.1:0",
+ .start_hook = test_migrate_tls_psk_start_mismatch,
+ .finish_hook = test_migrate_tls_psk_finish,
+ .result = MIG_TEST_FAIL,
};
test_precopy_common(&args);
}
+#ifdef CONFIG_TASN1
+static void test_precopy_tcp_tls_x509_default_host(void)
+{
+ MigrateCommon args = {
+ .listen_uri = "tcp:127.0.0.1:0",
+ .start_hook = test_migrate_tls_x509_start_default_host,
+ .finish_hook = test_migrate_tls_x509_finish,
+ };
+
+ test_precopy_common(&args);
+}
+
+static void test_precopy_tcp_tls_x509_override_host(void)
+{
+ MigrateCommon args = {
+ .listen_uri = "tcp:127.0.0.1:0",
+ .start_hook = test_migrate_tls_x509_start_override_host,
+ .finish_hook = test_migrate_tls_x509_finish,
+ };
+
+ test_precopy_common(&args);
+}
+
+static void test_precopy_tcp_tls_x509_mismatch_host(void)
+{
+ MigrateCommon args = {
+ .start = {
+ .hide_stderr = true,
+ },
+ .listen_uri = "tcp:127.0.0.1:0",
+ .start_hook = test_migrate_tls_x509_start_mismatch_host,
+ .finish_hook = test_migrate_tls_x509_finish,
+ .result = MIG_TEST_FAIL_DEST_QUIT_ERR,
+ };
+
+ test_precopy_common(&args);
+}
+
+static void test_precopy_tcp_tls_x509_friendly_client(void)
+{
+ MigrateCommon args = {
+ .listen_uri = "tcp:127.0.0.1:0",
+ .start_hook = test_migrate_tls_x509_start_friendly_client,
+ .finish_hook = test_migrate_tls_x509_finish,
+ };
+
+ test_precopy_common(&args);
+}
+
+static void test_precopy_tcp_tls_x509_hostile_client(void)
+{
+ MigrateCommon args = {
+ .start = {
+ .hide_stderr = true,
+ },
+ .listen_uri = "tcp:127.0.0.1:0",
+ .start_hook = test_migrate_tls_x509_start_hostile_client,
+ .finish_hook = test_migrate_tls_x509_finish,
+ .result = MIG_TEST_FAIL,
+ };
+
+ test_precopy_common(&args);
+}
+
+static void test_precopy_tcp_tls_x509_allow_anon_client(void)
+{
+ MigrateCommon args = {
+ .listen_uri = "tcp:127.0.0.1:0",
+ .start_hook = test_migrate_tls_x509_start_allow_anon_client,
+ .finish_hook = test_migrate_tls_x509_finish,
+ };
+
+ test_precopy_common(&args);
+}
+
+static void test_precopy_tcp_tls_x509_reject_anon_client(void)
+{
+ MigrateCommon args = {
+ .start = {
+ .hide_stderr = true,
+ },
+ .listen_uri = "tcp:127.0.0.1:0",
+ .start_hook = test_migrate_tls_x509_start_reject_anon_client,
+ .finish_hook = test_migrate_tls_x509_finish,
+ .result = MIG_TEST_FAIL,
+ };
+
+ test_precopy_common(&args);
+}
+#endif /* CONFIG_TASN1 */
+#endif /* CONFIG_GNUTLS */
+
static void *test_migrate_fd_start_hook(QTestState *from,
QTestState *to)
{
@@ -1261,26 +1740,12 @@ static void test_migrate_auto_converge(void)
test_migrate_end(from, to, true);
}
-static void test_multifd_tcp(const char *method)
+static void *
+test_migrate_precopy_tcp_multifd_start_common(QTestState *from,
+ QTestState *to,
+ const char *method)
{
- MigrateStart args = {};
- QTestState *from, *to;
QDict *rsp;
- g_autofree char *uri = NULL;
-
- if (test_migrate_start(&from, &to, "defer", &args)) {
- return;
- }
-
- /*
- * We want to pick a speed slow enough that the test completes
- * quickly, but that it doesn't complete precopy even on a slow
- * machine, so also set the downtime.
- */
- /* 1 ms should make it not converge*/
- migrate_set_parameter_int(from, "downtime-limit", 1);
- /* 1GB/s */
- migrate_set_parameter_int(from, "max-bandwidth", 1000000000);
migrate_set_parameter_int(from, "multifd-channels", 16);
migrate_set_parameter_int(to, "multifd-channels", 16);
@@ -1296,44 +1761,218 @@ static void test_multifd_tcp(const char *method)
" 'arguments': { 'uri': 'tcp:127.0.0.1:0' }}");
qobject_unref(rsp);
- /* Wait for the first serial output from the source */
- wait_for_serial("src_serial");
-
- uri = migrate_get_socket_address(to, "socket-address");
-
- migrate_qmp(from, uri, "{}");
-
- wait_for_migration_pass(from);
+ return NULL;
+}
- migrate_set_parameter_int(from, "downtime-limit", CONVERGE_DOWNTIME);
+static void *
+test_migrate_precopy_tcp_multifd_start(QTestState *from,
+ QTestState *to)
+{
+ return test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
+}
- if (!got_stop) {
- qtest_qmp_eventwait(from, "STOP");
- }
- qtest_qmp_eventwait(to, "RESUME");
+static void *
+test_migrate_precopy_tcp_multifd_zlib_start(QTestState *from,
+ QTestState *to)
+{
+ return test_migrate_precopy_tcp_multifd_start_common(from, to, "zlib");
+}
- wait_for_serial("dest_serial");
- wait_for_migration_complete(from);
- test_migrate_end(from, to, true);
+#ifdef CONFIG_ZSTD
+static void *
+test_migrate_precopy_tcp_multifd_zstd_start(QTestState *from,
+ QTestState *to)
+{
+ return test_migrate_precopy_tcp_multifd_start_common(from, to, "zstd");
}
+#endif /* CONFIG_ZSTD */
static void test_multifd_tcp_none(void)
{
- test_multifd_tcp("none");
+ MigrateCommon args = {
+ .listen_uri = "defer",
+ .start_hook = test_migrate_precopy_tcp_multifd_start,
+ };
+ test_precopy_common(&args);
}
static void test_multifd_tcp_zlib(void)
{
- test_multifd_tcp("zlib");
+ MigrateCommon args = {
+ .listen_uri = "defer",
+ .start_hook = test_migrate_precopy_tcp_multifd_zlib_start,
+ };
+ test_precopy_common(&args);
}
#ifdef CONFIG_ZSTD
static void test_multifd_tcp_zstd(void)
{
- test_multifd_tcp("zstd");
+ MigrateCommon args = {
+ .listen_uri = "defer",
+ .start_hook = test_migrate_precopy_tcp_multifd_zstd_start,
+ };
+ test_precopy_common(&args);
}
#endif
+#ifdef CONFIG_GNUTLS
+static void *
+test_migrate_multifd_tcp_tls_psk_start_match(QTestState *from,
+ QTestState *to)
+{
+ test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
+ return test_migrate_tls_psk_start_match(from, to);
+}
+
+static void *
+test_migrate_multifd_tcp_tls_psk_start_mismatch(QTestState *from,
+ QTestState *to)
+{
+ test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
+ return test_migrate_tls_psk_start_mismatch(from, to);
+}
+
+#ifdef CONFIG_TASN1
+static void *
+test_migrate_multifd_tls_x509_start_default_host(QTestState *from,
+ QTestState *to)
+{
+ test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
+ return test_migrate_tls_x509_start_default_host(from, to);
+}
+
+static void *
+test_migrate_multifd_tls_x509_start_override_host(QTestState *from,
+ QTestState *to)
+{
+ test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
+ return test_migrate_tls_x509_start_override_host(from, to);
+}
+
+static void *
+test_migrate_multifd_tls_x509_start_mismatch_host(QTestState *from,
+ QTestState *to)
+{
+ test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
+ return test_migrate_tls_x509_start_mismatch_host(from, to);
+}
+
+static void *
+test_migrate_multifd_tls_x509_start_allow_anon_client(QTestState *from,
+ QTestState *to)
+{
+ test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
+ return test_migrate_tls_x509_start_allow_anon_client(from, to);
+}
+
+static void *
+test_migrate_multifd_tls_x509_start_reject_anon_client(QTestState *from,
+ QTestState *to)
+{
+ test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
+ return test_migrate_tls_x509_start_reject_anon_client(from, to);
+}
+#endif /* CONFIG_TASN1 */
+
+static void test_multifd_tcp_tls_psk_match(void)
+{
+ MigrateCommon args = {
+ .listen_uri = "defer",
+ .start_hook = test_migrate_multifd_tcp_tls_psk_start_match,
+ .finish_hook = test_migrate_tls_psk_finish,
+ };
+ test_precopy_common(&args);
+}
+
+static void test_multifd_tcp_tls_psk_mismatch(void)
+{
+ MigrateCommon args = {
+ .start = {
+ .hide_stderr = true,
+ },
+ .listen_uri = "defer",
+ .start_hook = test_migrate_multifd_tcp_tls_psk_start_mismatch,
+ .finish_hook = test_migrate_tls_psk_finish,
+ .result = MIG_TEST_FAIL,
+ };
+ test_precopy_common(&args);
+}
+
+#ifdef CONFIG_TASN1
+static void test_multifd_tcp_tls_x509_default_host(void)
+{
+ MigrateCommon args = {
+ .listen_uri = "defer",
+ .start_hook = test_migrate_multifd_tls_x509_start_default_host,
+ .finish_hook = test_migrate_tls_x509_finish,
+ };
+ test_precopy_common(&args);
+}
+
+static void test_multifd_tcp_tls_x509_override_host(void)
+{
+ MigrateCommon args = {
+ .listen_uri = "defer",
+ .start_hook = test_migrate_multifd_tls_x509_start_override_host,
+ .finish_hook = test_migrate_tls_x509_finish,
+ };
+ test_precopy_common(&args);
+}
+
+static void test_multifd_tcp_tls_x509_mismatch_host(void)
+{
+ /*
+ * This has different behaviour to the non-multifd case.
+ *
+ * In non-multifd case when client aborts due to mismatched
+ * cert host, the server has already started trying to load
+ * migration state, and so it exits with I/O failure.
+ *
+ * In multifd case when client aborts due to mismatched
+ * cert host, the server is still waiting for the other
+ * multifd connections to arrive so hasn't started trying
+ * to load migration state, and thus just aborts the migration
+ * without exiting.
+ */
+ MigrateCommon args = {
+ .start = {
+ .hide_stderr = true,
+ },
+ .listen_uri = "defer",
+ .start_hook = test_migrate_multifd_tls_x509_start_mismatch_host,
+ .finish_hook = test_migrate_tls_x509_finish,
+ .result = MIG_TEST_FAIL,
+ };
+ test_precopy_common(&args);
+}
+
+static void test_multifd_tcp_tls_x509_allow_anon_client(void)
+{
+ MigrateCommon args = {
+ .listen_uri = "defer",
+ .start_hook = test_migrate_multifd_tls_x509_start_allow_anon_client,
+ .finish_hook = test_migrate_tls_x509_finish,
+ };
+ test_precopy_common(&args);
+}
+
+static void test_multifd_tcp_tls_x509_reject_anon_client(void)
+{
+ MigrateCommon args = {
+ .start = {
+ .hide_stderr = true,
+ },
+ .listen_uri = "defer",
+ .start_hook = test_migrate_multifd_tls_x509_start_reject_anon_client,
+ .finish_hook = test_migrate_tls_x509_finish,
+ .result = MIG_TEST_FAIL,
+ };
+ test_precopy_common(&args);
+}
+#endif /* CONFIG_TASN1 */
+#endif /* CONFIG_GNUTLS */
+
/*
* This test does:
* source target
@@ -1497,10 +2136,44 @@ int main(int argc, char **argv)
qtest_add_func("/migration/postcopy/unix", test_postcopy);
qtest_add_func("/migration/postcopy/recovery", test_postcopy_recovery);
qtest_add_func("/migration/bad_dest", test_baddest);
- qtest_add_func("/migration/precopy/unix", test_precopy_unix);
- qtest_add_func("/migration/precopy/tcp", test_precopy_tcp);
+ qtest_add_func("/migration/precopy/unix/plain", test_precopy_unix_plain);
+ qtest_add_func("/migration/precopy/unix/xbzrle", test_precopy_unix_xbzrle);
+#ifdef CONFIG_GNUTLS
+ qtest_add_func("/migration/precopy/unix/tls/psk",
+ test_precopy_unix_tls_psk);
+#ifdef CONFIG_TASN1
+ qtest_add_func("/migration/precopy/unix/tls/x509/default-host",
+ test_precopy_unix_tls_x509_default_host);
+ qtest_add_func("/migration/precopy/unix/tls/x509/override-host",
+ test_precopy_unix_tls_x509_override_host);
+#endif /* CONFIG_TASN1 */
+#endif /* CONFIG_GNUTLS */
+
+ qtest_add_func("/migration/precopy/tcp/plain", test_precopy_tcp_plain);
+#ifdef CONFIG_GNUTLS
+ qtest_add_func("/migration/precopy/tcp/tls/psk/match",
+ test_precopy_tcp_tls_psk_match);
+ qtest_add_func("/migration/precopy/tcp/tls/psk/mismatch",
+ test_precopy_tcp_tls_psk_mismatch);
+#ifdef CONFIG_TASN1
+ qtest_add_func("/migration/precopy/tcp/tls/x509/default-host",
+ test_precopy_tcp_tls_x509_default_host);
+ qtest_add_func("/migration/precopy/tcp/tls/x509/override-host",
+ test_precopy_tcp_tls_x509_override_host);
+ qtest_add_func("/migration/precopy/tcp/tls/x509/mismatch-host",
+ test_precopy_tcp_tls_x509_mismatch_host);
+ qtest_add_func("/migration/precopy/tcp/tls/x509/friendly-client",
+ test_precopy_tcp_tls_x509_friendly_client);
+ qtest_add_func("/migration/precopy/tcp/tls/x509/hostile-client",
+ test_precopy_tcp_tls_x509_hostile_client);
+ qtest_add_func("/migration/precopy/tcp/tls/x509/allow-anon-client",
+ test_precopy_tcp_tls_x509_allow_anon_client);
+ qtest_add_func("/migration/precopy/tcp/tls/x509/reject-anon-client",
+ test_precopy_tcp_tls_x509_reject_anon_client);
+#endif /* CONFIG_TASN1 */
+#endif /* CONFIG_GNUTLS */
+
/* qtest_add_func("/migration/ignore_shared", test_ignore_shared); */
- qtest_add_func("/migration/xbzrle/unix", test_xbzrle_unix);
qtest_add_func("/migration/fd_proto", test_migrate_fd_proto);
qtest_add_func("/migration/validate_uuid", test_validate_uuid);
qtest_add_func("/migration/validate_uuid_error", test_validate_uuid_error);
@@ -1510,12 +2183,34 @@ int main(int argc, char **argv)
test_validate_uuid_dst_not_set);
qtest_add_func("/migration/auto_converge", test_migrate_auto_converge);
- qtest_add_func("/migration/multifd/tcp/none", test_multifd_tcp_none);
- qtest_add_func("/migration/multifd/tcp/cancel", test_multifd_tcp_cancel);
- qtest_add_func("/migration/multifd/tcp/zlib", test_multifd_tcp_zlib);
+ qtest_add_func("/migration/multifd/tcp/plain/none",
+ test_multifd_tcp_none);
+ qtest_add_func("/migration/multifd/tcp/plain/cancel",
+ test_multifd_tcp_cancel);
+ qtest_add_func("/migration/multifd/tcp/plain/zlib",
+ test_multifd_tcp_zlib);
#ifdef CONFIG_ZSTD
- qtest_add_func("/migration/multifd/tcp/zstd", test_multifd_tcp_zstd);
+ qtest_add_func("/migration/multifd/tcp/plain/zstd",
+ test_multifd_tcp_zstd);
#endif
+#ifdef CONFIG_GNUTLS
+ qtest_add_func("/migration/multifd/tcp/tls/psk/match",
+ test_multifd_tcp_tls_psk_match);
+ qtest_add_func("/migration/multifd/tcp/tls/psk/mismatch",
+ test_multifd_tcp_tls_psk_mismatch);
+#ifdef CONFIG_TASN1
+ qtest_add_func("/migration/multifd/tcp/tls/x509/default-host",
+ test_multifd_tcp_tls_x509_default_host);
+ qtest_add_func("/migration/multifd/tcp/tls/x509/override-host",
+ test_multifd_tcp_tls_x509_override_host);
+ qtest_add_func("/migration/multifd/tcp/tls/x509/mismatch-host",
+ test_multifd_tcp_tls_x509_mismatch_host);
+ qtest_add_func("/migration/multifd/tcp/tls/x509/allow-anon-client",
+ test_multifd_tcp_tls_x509_allow_anon_client);
+ qtest_add_func("/migration/multifd/tcp/tls/x509/reject-anon-client",
+ test_multifd_tcp_tls_x509_reject_anon_client);
+#endif /* CONFIG_TASN1 */
+#endif /* CONFIG_GNUTLS */
if (kvm_dirty_ring_supported()) {
qtest_add_func("/migration/dirty_ring",
diff --git a/tests/unit/crypto-tls-psk-helpers.c b/tests/unit/crypto-tls-psk-helpers.c
index 4bea7c6..511e08c 100644
--- a/tests/unit/crypto-tls-psk-helpers.c
+++ b/tests/unit/crypto-tls-psk-helpers.c
@@ -24,7 +24,8 @@
#include "crypto-tls-psk-helpers.h"
#include "qemu/sockets.h"
-void test_tls_psk_init(const char *pskfile)
+static void
+test_tls_psk_init_common(const char *pskfile, const char *user, const char *key)
{
FILE *fp;
@@ -33,11 +34,22 @@ void test_tls_psk_init(const char *pskfile)
g_critical("Failed to create pskfile %s: %s", pskfile, strerror(errno));
abort();
}
- /* Don't do this in real applications! Use psktool. */
- fprintf(fp, "qemu:009d5638c40fde0c\n");
+ fprintf(fp, "%s:%s\n", user, key);
fclose(fp);
}
+void test_tls_psk_init(const char *pskfile)
+{
+ /* Don't hard code a key like this in real applications! Use psktool. */
+ test_tls_psk_init_common(pskfile, "qemu", "009d5638c40fde0c");
+}
+
+void test_tls_psk_init_alt(const char *pskfile)
+{
+ /* Don't hard code a key like this in real applications! Use psktool. */
+ test_tls_psk_init_common(pskfile, "qemu", "10ffa6a2c42f0388");
+}
+
void test_tls_psk_cleanup(const char *pskfile)
{
unlink(pskfile);
diff --git a/tests/unit/crypto-tls-psk-helpers.h b/tests/unit/crypto-tls-psk-helpers.h
index faa645c..67f8bdd 100644
--- a/tests/unit/crypto-tls-psk-helpers.h
+++ b/tests/unit/crypto-tls-psk-helpers.h
@@ -24,6 +24,7 @@
#include <gnutls/gnutls.h>
void test_tls_psk_init(const char *keyfile);
+void test_tls_psk_init_alt(const char *keyfile);
void test_tls_psk_cleanup(const char *keyfile);
#endif
diff --git a/tests/unit/crypto-tls-x509-helpers.c b/tests/unit/crypto-tls-x509-helpers.c
index fc609b3..e9937f6 100644
--- a/tests/unit/crypto-tls-x509-helpers.c
+++ b/tests/unit/crypto-tls-x509-helpers.c
@@ -168,9 +168,19 @@ test_tls_get_ipaddr(const char *addrstr,
hints.ai_flags = AI_NUMERICHOST;
g_assert(getaddrinfo(addrstr, NULL, &hints, &res) == 0);
- *datalen = res->ai_addrlen;
- *data = g_new(char, *datalen);
- memcpy(*data, res->ai_addr, *datalen);
+ if (res->ai_family == AF_INET) {
+ struct sockaddr_in *in = (struct sockaddr_in *)res->ai_addr;
+ *datalen = sizeof(in->sin_addr);
+ *data = g_new(char, *datalen);
+ memcpy(*data, &in->sin_addr, *datalen);
+ } else if (res->ai_family == AF_INET6) {
+ struct sockaddr_in6 *in = (struct sockaddr_in6 *)res->ai_addr;
+ *datalen = sizeof(in->sin6_addr);
+ *data = g_new(char, *datalen);
+ memcpy(*data, &in->sin6_addr, *datalen);
+ } else {
+ g_assert_not_reached();
+ }
freeaddrinfo(res);
}
diff --git a/tests/unit/crypto-tls-x509-helpers.h b/tests/unit/crypto-tls-x509-helpers.h
index cf6329e..247e716 100644
--- a/tests/unit/crypto-tls-x509-helpers.h
+++ b/tests/unit/crypto-tls-x509-helpers.h
@@ -26,6 +26,9 @@
#include <libtasn1.h>
+#define QCRYPTO_TLS_TEST_CLIENT_NAME "ACME QEMU Client"
+#define QCRYPTO_TLS_TEST_CLIENT_HOSTILE_NAME "ACME Hostile Client"
+
/*
* This contains parameter about how to generate
* certificates.
@@ -118,6 +121,56 @@ void test_tls_cleanup(const char *keyfile);
}; \
test_tls_generate_cert(&varname, NULL)
+# define TLS_ROOT_REQ_SIMPLE(varname, fname) \
+ QCryptoTLSTestCertReq varname = { \
+ .filename = fname, \
+ .cn = "qemu-CA", \
+ .basicConstraintsEnable = true, \
+ .basicConstraintsCritical = true, \
+ .basicConstraintsIsCA = true, \
+ .keyUsageEnable = true, \
+ .keyUsageCritical = true, \
+ .keyUsageValue = GNUTLS_KEY_KEY_CERT_SIGN, \
+ }; \
+ test_tls_generate_cert(&varname, NULL)
+
+# define TLS_CERT_REQ_SIMPLE_CLIENT(varname, cavarname, cname, fname) \
+ QCryptoTLSTestCertReq varname = { \
+ .filename = fname, \
+ .cn = cname, \
+ .basicConstraintsEnable = true, \
+ .basicConstraintsCritical = true, \
+ .basicConstraintsIsCA = false, \
+ .keyUsageEnable = true, \
+ .keyUsageCritical = true, \
+ .keyUsageValue = \
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, \
+ .keyPurposeEnable = true, \
+ .keyPurposeCritical = true, \
+ .keyPurposeOID1 = GNUTLS_KP_TLS_WWW_CLIENT, \
+ }; \
+ test_tls_generate_cert(&varname, cavarname.crt)
+
+# define TLS_CERT_REQ_SIMPLE_SERVER(varname, cavarname, fname, \
+ hostname, ipaddr) \
+ QCryptoTLSTestCertReq varname = { \
+ .filename = fname, \
+ .cn = hostname ? hostname : ipaddr, \
+ .altname1 = hostname, \
+ .ipaddr1 = ipaddr, \
+ .basicConstraintsEnable = true, \
+ .basicConstraintsCritical = true, \
+ .basicConstraintsIsCA = false, \
+ .keyUsageEnable = true, \
+ .keyUsageCritical = true, \
+ .keyUsageValue = \
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT, \
+ .keyPurposeEnable = true, \
+ .keyPurposeCritical = true, \
+ .keyPurposeOID1 = GNUTLS_KP_TLS_WWW_SERVER, \
+ }; \
+ test_tls_generate_cert(&varname, cavarname.crt)
+
extern const asn1_static_node pkix_asn1_tab[];
#endif
diff --git a/tests/unit/test-crypto-tlssession.c b/tests/unit/test-crypto-tlssession.c
index a266dc3..f222959 100644
--- a/tests/unit/test-crypto-tlssession.c
+++ b/tests/unit/test-crypto-tlssession.c
@@ -512,12 +512,19 @@ int main(int argc, char **argv)
false, true, "wiki.qemu.org", NULL);
TEST_SESS_REG(altname4, cacertreq.filename,
+ servercertalt1req.filename, clientcertreq.filename,
+ false, false, "192.168.122.1", NULL);
+ TEST_SESS_REG(altname5, cacertreq.filename,
+ servercertalt1req.filename, clientcertreq.filename,
+ false, false, "fec0::dead:beaf", NULL);
+
+ TEST_SESS_REG(altname6, cacertreq.filename,
servercertalt2req.filename, clientcertreq.filename,
false, true, "qemu.org", NULL);
- TEST_SESS_REG(altname5, cacertreq.filename,
+ TEST_SESS_REG(altname7, cacertreq.filename,
servercertalt2req.filename, clientcertreq.filename,
false, false, "www.qemu.org", NULL);
- TEST_SESS_REG(altname6, cacertreq.filename,
+ TEST_SESS_REG(altname8, cacertreq.filename,
servercertalt2req.filename, clientcertreq.filename,
false, false, "wiki.qemu.org", NULL);
diff --git a/tests/unit/test-io-channel-socket.c b/tests/unit/test-io-channel-socket.c
index c49eec1..6713886 100644
--- a/tests/unit/test-io-channel-socket.c
+++ b/tests/unit/test-io-channel-socket.c
@@ -444,6 +444,7 @@ static void test_io_channel_unix_fd_pass(void)
G_N_ELEMENTS(iosend),
fdsend,
G_N_ELEMENTS(fdsend),
+ 0,
&error_abort);
qio_channel_readv_full(dst,