From: Peter Xu <peterx@redhat.com>
To: qemu-devel@nongnu.org
Cc: Leonardo Bras Soares Passos <lsoaresp@redhat.com>,
"Daniel P . Berrange" <berrange@redhat.com>,
"Dr . David Alan Gilbert" <dgilbert@redhat.com>,
peterx@redhat.com, Juan Quintela <quintela@redhat.com>
Subject: [PATCH v5 04/21] tests: add migration tests of TLS with x509 credentials
Date: Mon, 25 Apr 2022 19:38:30 -0400 [thread overview]
Message-ID: <20220425233847.10393-5-peterx@redhat.com> (raw)
In-Reply-To: <20220425233847.10393-1-peterx@redhat.com>
From: Daniel P. Berrangé <berrange@redhat.com>
This validates that we correctly handle migration success and failure
scenarios when using TLS with x509 certificates. There are quite a few
different scenarios that matter in relation to hostname validation.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
meson.build | 1 +
tests/qtest/meson.build | 5 +
tests/qtest/migration-test.c | 382 ++++++++++++++++++++++++++++++++++-
3 files changed, 386 insertions(+), 2 deletions(-)
diff --git a/meson.build b/meson.build
index d083c6b7bf..d1231b23ae 100644
--- a/meson.build
+++ b/meson.build
@@ -1565,6 +1565,7 @@ config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
config_host_data.set('CONFIG_GETTID', has_gettid)
config_host_data.set('CONFIG_GNUTLS', gnutls.found())
config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
+config_host_data.set('CONFIG_TASN1', tasn1.found())
config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
config_host_data.set('CONFIG_NETTLE', nettle.found())
config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index ec14559e73..af7c31d611 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -274,6 +274,11 @@ 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 = {
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index f733aa352e..c730697f74 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -29,6 +29,9 @@
#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 */
@@ -736,6 +739,234 @@ test_migrate_tls_psk_finish(QTestState *from,
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,
@@ -1020,6 +1251,21 @@ static void test_precopy_unix_plain(void)
test_precopy_common(&args);
}
+static void test_precopy_unix_dirty_ring(void)
+{
+ g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+ MigrateCommon args = {
+ .start = {
+ .use_dirty_ring = true,
+ },
+ .listen_uri = uri,
+ .connect_uri = uri,
+ };
+
+ 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);
@@ -1033,19 +1279,38 @@ static void test_precopy_unix_tls_psk(void)
test_precopy_common(&args);
}
-static void test_precopy_unix_dirty_ring(void)
+#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 = {
- .use_dirty_ring = true,
+ .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 */
@@ -1172,6 +1437,97 @@ static void test_precopy_tcp_tls_psk_mismatch(void)
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,
@@ -1640,6 +1996,12 @@ int main(int argc, char **argv)
#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);
@@ -1648,6 +2010,22 @@ int main(int argc, char **argv)
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); */
--
2.32.0
next prev parent reply other threads:[~2022-04-25 23:45 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-25 23:38 [PATCH v5 00/21] migration: Postcopy Preemption Peter Xu
2022-04-25 23:38 ` [PATCH v5 01/21] tests: fix encoding of IP addresses in x509 certs Peter Xu
2022-04-25 23:38 ` [PATCH v5 02/21] tests: add more helper macros for creating TLS " Peter Xu
2022-04-25 23:38 ` [PATCH v5 03/21] tests: add migration tests of TLS with PSK credentials Peter Xu
2022-04-25 23:38 ` Peter Xu [this message]
2022-04-25 23:38 ` [PATCH v5 05/21] tests: convert XBZRLE migration test to use common helper Peter Xu
2022-04-25 23:38 ` [PATCH v5 06/21] tests: convert multifd migration tests " Peter Xu
2022-04-25 23:38 ` [PATCH v5 07/21] tests: add multifd migration tests of TLS with PSK credentials Peter Xu
2022-04-25 23:38 ` [PATCH v5 08/21] tests: add multifd migration tests of TLS with x509 credentials Peter Xu
2022-04-25 23:38 ` [PATCH v5 09/21] tests: ensure migration status isn't reported as failed Peter Xu
2022-04-25 23:38 ` [PATCH v5 10/21] migration: Add postcopy-preempt capability Peter Xu
2022-04-25 23:38 ` [PATCH v5 11/21] migration: Postcopy preemption preparation on channel creation Peter Xu
2022-05-11 17:08 ` manish.mishra
2022-05-12 16:36 ` Peter Xu
2022-04-25 23:38 ` [PATCH v5 12/21] migration: Postcopy preemption enablement Peter Xu
2022-04-25 23:38 ` [PATCH v5 13/21] migration: Postcopy recover with preempt enabled Peter Xu
2022-05-16 13:31 ` manish.mishra
2022-05-16 14:11 ` Peter Xu
2022-05-16 14:51 ` manish.mishra
2022-05-16 15:32 ` manish.mishra
2022-05-16 15:58 ` Peter Xu
2022-04-25 23:38 ` [PATCH v5 14/21] migration: Create the postcopy preempt channel asynchronously Peter Xu
2022-05-12 17:35 ` Dr. David Alan Gilbert
2022-05-16 15:02 ` manish.mishra
2022-05-16 16:21 ` Peter Xu
2022-04-25 23:38 ` [PATCH v5 15/21] migration: Parameter x-postcopy-preempt-break-huge Peter Xu
2022-05-12 17:42 ` Dr. David Alan Gilbert
2022-05-16 15:20 ` manish.mishra
2022-04-25 23:38 ` [PATCH v5 16/21] migration: Add helpers to detect TLS capability Peter Xu
2022-05-12 17:46 ` Dr. David Alan Gilbert
2022-04-25 23:38 ` [PATCH v5 17/21] migration: Export tls-[creds|hostname|authz] params to cmdline too Peter Xu
2022-05-12 18:03 ` Dr. David Alan Gilbert
2022-05-12 19:05 ` Daniel P. Berrangé
2022-05-12 20:07 ` Peter Xu
2022-04-25 23:38 ` [PATCH v5 18/21] migration: Enable TLS for preempt channel Peter Xu
2022-04-25 23:38 ` [PATCH v5 19/21] tests: Add postcopy tls migration test Peter Xu
2022-04-25 23:38 ` [PATCH v5 20/21] tests: Add postcopy tls recovery " Peter Xu
2022-04-25 23:38 ` [PATCH v5 21/21] tests: Add postcopy preempt tests Peter Xu
2022-05-16 15:25 ` [PATCH v5 00/21] migration: Postcopy Preemption manish.mishra
2022-05-16 16:06 ` Peter Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220425233847.10393-5-peterx@redhat.com \
--to=peterx@redhat.com \
--cc=berrange@redhat.com \
--cc=dgilbert@redhat.com \
--cc=lsoaresp@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=quintela@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.