To enable TLS-PSK-based authentication scheme, add support for instantiating the tls-creds-psk object through QEMU monitor. In order to remove the TLS-related objects from a QEMU instance, augment the qemuDomainDelTLSObjects handler to also consider the TLS-PSK object. Suggested-by: Tejus GK <tejus.gk@nutanix.com> Signed-off-by: Abhisek Panda <abhisek.panda1@nutanix.com> --- src/qemu/qemu_alias.c | 11 +++++ src/qemu/qemu_alias.h | 3 ++ src/qemu/qemu_hotplug.c | 58 ++++++++++++++++++++++++--- src/qemu/qemu_hotplug.h | 14 ++++++- src/qemu/qemu_migration_params.c | 69 ++++++++++++++++++++++++++++++-- src/qemu/qemu_migration_params.h | 8 ++++ 6 files changed, 152 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index b41794a5fa..a4894a681f 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -883,6 +883,17 @@ qemuAliasTLSx509ObjFromSrcAlias(const char *srcAlias) return g_strdup_printf("obj%s_tlsx509_0", srcAlias); } +/* qemuAliasTLSPSKObjFromSrcAlias + * @srcAlias: Pointer to a source alias string + * + * Generate and return a string to be used as the TLS PSK object alias + */ +char * +qemuAliasTLSPSKObjFromSrcAlias(const char *srcAlias) +{ + return g_strdup_printf("obj%s_tlspsk_0", srcAlias); +} + /* qemuAliasChardevFromDevAlias: * @devAlias: pointer do device alias diff --git a/src/qemu/qemu_alias.h b/src/qemu/qemu_alias.h index dd7bfdcc0f..2a0c7ca7c3 100644 --- a/src/qemu/qemu_alias.h +++ b/src/qemu/qemu_alias.h @@ -92,6 +92,9 @@ char *qemuAliasForSecret(const char *parentalias, char *qemuAliasTLSx509ObjFromSrcAlias(const char *srcAlias) ATTRIBUTE_NONNULL(1); +char *qemuAliasTLSPSKObjFromSrcAlias(const char *srcAlias) + ATTRIBUTE_NONNULL(1); + char *qemuAliasChardevFromDevAlias(const char *devAlias) ATTRIBUTE_NONNULL(1); diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index d2add3f656..75a2c75edf 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1702,12 +1702,13 @@ void qemuDomainDelTLSObjects(virDomainObj *vm, virDomainAsyncJob asyncJob, const char *secAlias, - const char *tlsx509Alias) + const char *tlsx509Alias, + const char *tlsPSKAlias) { qemuDomainObjPrivate *priv = vm->privateData; virErrorPtr orig_err; - if (!tlsx509Alias && !secAlias) + if (!tlsx509Alias && !secAlias && !tlsPSKAlias) return; virErrorPreserveLast(&orig_err); @@ -1721,6 +1722,9 @@ qemuDomainDelTLSObjects(virDomainObj *vm, if (secAlias) ignore_value(qemuMonitorDelObject(priv->mon, secAlias, false)); + if (tlsPSKAlias) + ignore_value(qemuMonitorDelObject(priv->mon, tlsPSKAlias, false)); + qemuDomainObjExitMonitor(vm); cleanup: @@ -1759,7 +1763,7 @@ qemuDomainAddTLSx509Objects(virDomainObj *vm, virErrorPreserveLast(&orig_err); qemuDomainObjExitMonitor(vm); virErrorRestore(&orig_err); - qemuDomainDelTLSObjects(vm, asyncJob, secAlias, NULL); + qemuDomainDelTLSObjects(vm, asyncJob, secAlias, NULL, NULL); return -1; } @@ -1881,6 +1885,48 @@ qemuDomainDelChardevTLSObjects(virQEMUDriver *driver, } +int +qemuDomainAddTLSPSKObjects(virDomainObj *vm, + virDomainAsyncJob asyncJob, + virJSONValue **tlsPSKProps) +{ + qemuDomainObjPrivate *priv = vm->privateData; + virErrorPtr orig_err; + + if (!tlsPSKProps) + return 0; + + if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0) + return -1; + + if (tlsPSKProps && *tlsPSKProps && + qemuMonitorAddObject(priv->mon, tlsPSKProps, NULL) < 0) + goto error; + + qemuDomainObjExitMonitor(vm); + return 0; + + error: + virErrorPreserveLast(&orig_err); + qemuDomainObjExitMonitor(vm); + virErrorRestore(&orig_err); + return -1; +} + + +int +qemuDomainGetTLSPSKObjects(const char *tlsPSKdir, + bool tlsListen, + const char *alias, + virJSONValue **tlsPSKProps) +{ + if (qemuBuildTLSPSKBackendProps(tlsPSKdir, tlsListen, alias, tlsPSKProps) < 0) + return -1; + + return 0; +} + + static int qemuDomainAttachRedirdevDevice(virQEMUDriver *driver, virDomainObj *vm, @@ -1941,7 +1987,7 @@ qemuDomainAttachRedirdevDevice(virQEMUDriver *driver, ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias)); qemuDomainObjExitMonitor(vm); virErrorRestore(&orig_err); - qemuDomainDelTLSObjects(vm, VIR_ASYNC_JOB_NONE, secAlias, tlsx509Alias); + qemuDomainDelTLSObjects(vm, VIR_ASYNC_JOB_NONE, secAlias, tlsx509Alias, NULL); goto audit; } @@ -2240,7 +2286,7 @@ qemuDomainAttachChrDevice(virQEMUDriver *driver, qemuDomainObjExitMonitor(vm); virErrorRestore(&orig_err); - qemuDomainDelTLSObjects(vm, VIR_ASYNC_JOB_NONE, secAlias, tlsx509Alias); + qemuDomainDelTLSObjects(vm, VIR_ASYNC_JOB_NONE, secAlias, tlsx509Alias, NULL); goto audit; } @@ -2345,7 +2391,7 @@ qemuDomainAttachRNGDevice(virQEMUDriver *driver, qemuDomainObjExitMonitor(vm); virErrorRestore(&orig_err); - qemuDomainDelTLSObjects(vm, VIR_ASYNC_JOB_NONE, secAlias, tlsx509Alias); + qemuDomainDelTLSObjects(vm, VIR_ASYNC_JOB_NONE, secAlias, tlsx509Alias, NULL); goto audit; } diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index 2d9b10204c..984d3098a6 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -28,7 +28,8 @@ void qemuDomainDelTLSObjects(virDomainObj *vm, virDomainAsyncJob asyncJob, const char *secAlias, - const char *tlsx509Alias); + const char *tlsx509Alias, + const char *tlsPSKAlias); int qemuDomainAddTLSx509Objects(virDomainObj *vm, @@ -46,6 +47,17 @@ qemuDomainGetTLSx509Objects(qemuDomainSecretInfo *secinfo, virJSONValue **tlsProps, virJSONValue **secProps); +int +qemuDomainAddTLSPSKObjects(virDomainObj *vm, + virDomainAsyncJob asyncJob, + virJSONValue **tlsPSKProps); + +int +qemuDomainGetTLSPSKObjects(const char *tlsPSKdir, + bool tlsListen, + const char *alias, + virJSONValue **tlsPSKProps); + int qemuDomainAttachDiskGeneric(virDomainObj *vm, virDomainDiskDef *disk, diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c index c91ae89c9b..846d97b4d1 100644 --- a/src/qemu/qemu_migration_params.c +++ b/src/qemu/qemu_migration_params.c @@ -1216,7 +1216,7 @@ qemuMigrationParamsEnableTLSx509(virQEMUDriver *driver, * This should prevent any issues just in case some cleanup wasn't * properly completed (both src and dst use the same alias) or * some other error path between now and perform . */ - qemuDomainDelTLSObjects(vm, asyncJob, secAlias, *tlsx509Alias); + qemuDomainDelTLSObjects(vm, asyncJob, secAlias, *tlsx509Alias, NULL); if (qemuDomainAddTLSx509Objects(vm, asyncJob, &secProps, &tlsx509Props) < 0) return -1; @@ -1237,6 +1237,65 @@ qemuMigrationParamsEnableTLSx509(virQEMUDriver *driver, } +/* qemuMigrationParamsEnableTLSPSK + * @driver: pointer to qemu driver + * @vm: domain object + * @tlsListen: server or client + * @asyncJob: Migration job to join + * @tlsPSKAlias: alias to be generated for TLS-PSK object + * @migParams: migration parameters to set + * + * Create the TLS PSK objects for the migration and set the migParams value. + * + * Returns 0 on success, -1 on failure + */ +int +qemuMigrationParamsEnableTLSPSK(virQEMUDriver *driver, + virDomainObj *vm, + bool tlsListen, + int asyncJob, + char **tlsPSKAlias, + qemuMigrationParams *migParams) +{ + qemuDomainJobPrivate *jobPriv = vm->job->privateData; + g_autoptr(virJSONValue) tlsPSKProps = NULL; + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + char uuidstr[VIR_UUID_STRING_BUFLEN]; + g_autofree char *dir_path = NULL; + + virUUIDFormat(vm->def->uuid, uuidstr); + dir_path = g_strdup_printf("%s/%s", cfg->stateDir, uuidstr); + + if (!jobPriv->migParams->params[QEMU_MIGRATION_PARAM_TLS_CREDS].set) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("TLS migration is not supported with this QEMU binary")); + return -1; + } + + if (!(*tlsPSKAlias = qemuAliasTLSPSKObjFromSrcAlias(QEMU_MIGRATION_TLS_ALIAS_BASE))) + return -1; + + if (qemuDomainGetTLSPSKObjects(dir_path, tlsListen, + *tlsPSKAlias, &tlsPSKProps) < 0) + return -1; + + /* Ensure the domain doesn't already have the TLS-PSK objects defined. + * This should prevent any issues just in case some cleanup wasn't + * properly completed (both src and dst use the same alias) or + * some other error path. */ + qemuDomainDelTLSObjects(vm, asyncJob, NULL, NULL, *tlsPSKAlias); + + if (qemuDomainAddTLSPSKObjects(vm, asyncJob, &tlsPSKProps) < 0) + return -1; + + if (qemuMigrationParamsSetString(migParams, QEMU_MIGRATION_PARAM_TLS_CREDS, + *tlsPSKAlias) < 0) + return -1; + + return 0; +} + + /* qemuMigrationParamsDisableTLS * @vm: domain object * @migParams: Pointer to a migration parameters block @@ -1281,8 +1340,8 @@ qemuMigrationParamsTLSHostnameIsSet(qemuMigrationParams *migParams) * @asyncJob: migration job to join * @apiFlags: API flags used to start the migration * - * Deconstruct all the setup possibly done for TLS - delete the TLS and - * security objects and free the secinfo + * Deconstruct all the setup possibly done for TLS - delete the TLS X.509, TLS-PSK + * and security objects and free the secinfo */ static void qemuMigrationParamsResetTLS(virDomainObj *vm, @@ -1292,6 +1351,7 @@ qemuMigrationParamsResetTLS(virDomainObj *vm, { g_autofree char *tlsx509Alias = NULL; g_autofree char *secAlias = NULL; + g_autofree char *tlsPSKAlias = NULL; /* There's nothing to do if QEMU does not support TLS migration or we were * not asked to enable it. */ @@ -1301,8 +1361,9 @@ qemuMigrationParamsResetTLS(virDomainObj *vm, tlsx509Alias = qemuAliasTLSx509ObjFromSrcAlias(QEMU_MIGRATION_TLS_ALIAS_BASE); secAlias = qemuAliasForSecret(QEMU_MIGRATION_TLS_ALIAS_BASE, NULL, 0); + tlsPSKAlias = qemuAliasTLSPSKObjFromSrcAlias(QEMU_MIGRATION_TLS_ALIAS_BASE); - qemuDomainDelTLSObjects(vm, asyncJob, secAlias, tlsx509Alias); + qemuDomainDelTLSObjects(vm, asyncJob, secAlias, tlsx509Alias, tlsPSKAlias); g_clear_pointer(&QEMU_DOMAIN_PRIVATE(vm)->migSecinfo, qemuDomainSecretInfoFree); } diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h index b578cf5091..ad65c7933e 100644 --- a/src/qemu/qemu_migration_params.h +++ b/src/qemu/qemu_migration_params.h @@ -123,6 +123,14 @@ qemuMigrationParamsEnableTLSx509(virQEMUDriver *driver, const char *hostname, qemuMigrationParams *migParams); +int +qemuMigrationParamsEnableTLSPSK(virQEMUDriver *driver, + virDomainObj *vm, + bool tlsListen, + int asyncJob, + char **tlsPSKAlias, + qemuMigrationParams *migParams); + int qemuMigrationParamsDisableTLS(virDomainObj *vm, qemuMigrationParams *migParams); -- 2.43.7