In the case of TLS-PSK-enabled migration, Libvirt manages the lifecycle
of the pre-shared key. Add a new test scenario to the migration cookie
test suite to validate the generation of pre-shared key when the
QEMU_MIGRATION_COOKIE_TLS_PSK flag is set. In addition, the test also
checks the length and the hexadecimal encoding of the pre-shared key.

Signed-off-by: Abhisek Panda <[email protected]>
---
 tests/qemumigrationcookiexmltest.c | 123 +++++++++++++++++++++++++++++
 tests/testutilsqemu.c              |  12 +++
 2 files changed, 135 insertions(+)

diff --git a/tests/qemumigrationcookiexmltest.c 
b/tests/qemumigrationcookiexmltest.c
index adf2eb4d08..0914793974 100644
--- a/tests/qemumigrationcookiexmltest.c
+++ b/tests/qemumigrationcookiexmltest.c
@@ -16,6 +16,7 @@
 
 #include <config.h>
 
+#include <stddef.h>
 #include <unistd.h>
 
 #include <sys/types.h>
@@ -92,6 +93,99 @@ testQemuMigrationCookieDataFree(struct 
testQemuMigrationCookieData *data)
 }
 
 
+static int
+testQemuMigrationCookiePSKValidate(const char *key)
+{
+    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(&driver);
+    size_t expected_key_len = 2 * cfg->migrateTLSPSKLength; /* The pre-shared 
key's length is 2 * PSK length */
+    size_t i;
+
+    if (!key) {
+        VIR_TEST_DEBUG("\nThe pre-shared key is not present in the migration 
cookie.");
+        return -1;
+    }
+
+    if (strlen(key) != expected_key_len) {
+        VIR_TEST_DEBUG("\nThe length of the pre-shared key is incorrect.");
+        return -1;
+    }
+
+    /* Check the characters of the key */
+    for (i = 0; i < expected_key_len; i++) {
+        if (!g_ascii_isxdigit(key[i])) {
+            VIR_TEST_DEBUG("\nThe key contains non-hex characters");
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+static int
+testQemuMigrationCookiePSKAttribute(const void *opaque)
+{
+    struct testQemuMigrationCookieData *data = (struct 
testQemuMigrationCookieData *) opaque;
+    g_autoptr(qemuMigrationCookie) cookie = NULL;
+    qemuDomainObjPrivate *priv;
+
+    /* if the VM object parsing step failed there's nothing this test can do */
+    if (!data->vm) {
+        VIR_TEST_DEBUG("\nmissing VM object\n");
+        return -1;
+    }
+    priv = data->vm->privateData;
+
+    if (!(cookie = qemuMigrationCookieNew(data->vm->def, NULL)))
+        return -1;
+
+    g_free(cookie->localHostname);
+    cookie->localHostname = g_strdup("hostname2");
+
+    if (virUUIDParse("8b3f4dc4-6a8e-5f9b-94a5-4c35babd8d95", 
cookie->localHostuuid) < 0) {
+        VIR_TEST_DEBUG("\nfailed to parse fake UUID");
+        return -1;
+    }
+
+    /* Format the migration cookie at the source */
+    if (qemuMigrationCookieFormat(cookie,
+                                  &driver,
+                                  data->vm,
+                                  data->cookiePopulateParty,
+                                  &data->xmlstr,
+                                  &data->xmlstrlen,
+                                  data->cookiePopulateFlags) < 0) {
+        VIR_TEST_DEBUG("\nfailed to populate and format qemu migration 
cookie");
+        return -1;
+    }
+
+    /* Check for the <migration-key> element in the generated migration cookie 
XML */
+    if (!strstr(data->xmlstr, "<migration-key>")) {
+        VIR_TEST_DEBUG("\nthe migration cookie is missing the migration-key 
element:\n%s\n",
+                    data->xmlstr);
+        return -1;
+    }
+
+    /* Parse the migration cookie at the destination */
+    if (!(data->cookie = qemuMigrationCookieParse(&driver,
+                                                  data->vm,
+                                                  data->vm->def,
+                                                  NULL,
+                                                  priv->qemuCaps,
+                                                  data->xmlstr,
+                                                  data->xmlstrlen,
+                                                  data->cookieParseFlags))) {
+        VIR_TEST_DEBUG("\nfailed to parse qemu migration cookie:\n%s\n", 
data->xmlstr);
+        return -1;
+    }
+
+    if (testQemuMigrationCookiePSKValidate(data->cookie->tlsPSK) < 0)
+        return -1;
+
+    return 0;
+}
+
+
 static int
 testQemuMigrationCookiePopulate(const void *opaque)
 {
@@ -418,6 +512,32 @@ testQemuMigrationCookieXML2XMLBitmaps(const char *name,
     return ret;
 }
 
+/* tests the generation and persistence of the pre-shared keys */
+static int
+testQemuMigrationCookiePSK(const char *domxml)
+{
+    struct testQemuMigrationCookieData *data = g_new0(struct 
testQemuMigrationCookieData, 1);
+    int ret = 0;
+
+    data->cookiePopulateFlags = QEMU_MIGRATION_COOKIE_TLS_PSK;
+    data->cookiePopulateParty = QEMU_MIGRATION_SOURCE;
+    data->cookieParseFlags = QEMU_MIGRATION_COOKIE_TLS_PSK;
+    data->inStatus = g_strconcat(abs_srcdir, "/", domxml, NULL);
+
+    /* load status XML as domain object */
+    if (testQemuMigrationCookieDomInit(data) < 0)
+        ret = -1;
+
+    /* test PSK generation and persistence */
+    if (virTestRun("qemumigrationcookie-psk-lifecycle",
+                   testQemuMigrationCookiePSKAttribute, data) < 0)
+        ret = -1;
+
+    testQemuMigrationCookieDataFree(data);
+
+    return ret;
+}
+
 
 static int
 mymain(void)
@@ -448,6 +568,9 @@ mymain(void)
     if (testQemuMigrationCookieXML2XMLBitmaps("nbd-bitmaps", 
"qemustatusxml2xmldata/migration-out-nbd-bitmaps-in.xml", 0) < 0)
         ret = -1;
 
+    if (testQemuMigrationCookiePSK("qemustatusxml2xmldata/modern-in.xml") < 0)
+        ret = -1;
+
     virBufferFreeAndReset(&testnamebuf);
 
  cleanup:
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
index e5e3342b53..b0e0d41895 100644
--- a/tests/testutilsqemu.c
+++ b/tests/testutilsqemu.c
@@ -297,6 +297,7 @@ qemuTestCapsCacheInsert(virFileCache *cache,
 
 #define STATEDIRTEMPLATE abs_builddir "/qemustatedir-XXXXXX"
 #define CONFIGDIRTEMPLATE abs_builddir "/qemuconfigdir-XXXXXX"
+#define TLSPSKDIRTEMPLATE abs_builddir "/pskstatedir-XXXXXX"
 
 int qemuTestDriverInit(virQEMUDriver *driver)
 {
@@ -304,6 +305,7 @@ int qemuTestDriverInit(virQEMUDriver *driver)
     virSecurityManager *mgr = NULL;
     char statedir[] = STATEDIRTEMPLATE;
     char configdir[] = CONFIGDIRTEMPLATE;
+    char tlspskdir[] = TLSPSKDIRTEMPLATE;
 
     memset(driver, 0, sizeof(*driver));
 
@@ -328,6 +330,7 @@ int qemuTestDriverInit(virQEMUDriver *driver)
      * dirs. */
     VIR_FREE(cfg->stateDir);
     VIR_FREE(cfg->configDir);
+    VIR_FREE(cfg->tlsPSKStateDir);
 
     /* Override paths to ensure predictable output
      *
@@ -367,6 +370,13 @@ int qemuTestDriverInit(virQEMUDriver *driver)
 
     cfg->configDir = g_strdup(configdir);
 
+    if (!g_mkdtemp(tlspskdir)) {
+        fprintf(stderr, "Cannot create fake tlsPSKStateDir");
+        goto error;
+    }
+
+    cfg->tlsPSKStateDir = g_strdup(tlspskdir);
+
     driver->caps = testQemuCapsInit();
     if (!driver->caps)
         goto error;
@@ -433,6 +443,8 @@ int qemuTestDriverInit(virQEMUDriver *driver)
 
     cfg->dumpGuestCore = false;
 
+    cfg->migrateTLSPSKLength = 32;
+
     driver->privileged = true;
 
     return 0;
-- 
2.43.7

Reply via email to