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 <[email protected]> Signed-off-by: Abhisek Panda <[email protected]> --- src/qemu/qemu_alias.c | 11 +++++ src/qemu/qemu_alias.h | 3 ++ src/qemu/qemu_hotplug.c | 59 +++++++++++++++++++++++--- src/qemu/qemu_hotplug.h | 15 ++++++- src/qemu/qemu_migration_params.c | 73 ++++++++++++++++++++++++++++++-- src/qemu/qemu_migration_params.h | 9 ++++ 6 files changed, 159 insertions(+), 11 deletions(-) diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index 9133389df1..4d61d7d2fe 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_tlsx5090", 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_tlspsk0", 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 9e7055f5da..296da1f195 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,49 @@ 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 *username, + const char *alias, + virJSONValue **tlsPSKProps) +{ + if (qemuBuildTLSPSKBackendProps(tlsPSKdir, tlsListen, username, alias, tlsPSKProps) < 0) + return -1; + + return 0; +} + + static int qemuDomainAttachRedirdevDevice(virQEMUDriver *driver, virDomainObj *vm, @@ -1941,7 +1988,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 +2287,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 +2392,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..835f57ded1 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,18 @@ qemuDomainGetTLSx509Objects(qemuDomainSecretInfo *secinfo, virJSONValue **tlsProps, virJSONValue **secProps); +int +qemuDomainAddTLSPSKObjects(virDomainObj *vm, + virDomainAsyncJob asyncJob, + virJSONValue **tlsPSKProps); + +int +qemuDomainGetTLSPSKObjects(const char *tlsPSKdir, + bool tlsListen, + const char *username, + 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..1c6ab6fc8a 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,69 @@ 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 + * @username: hostname of the migration destination + * @tls_psk_directory: directory containing the TLS-PSK key file + * @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, + const char *username, + qemuMigrationParams *migParams) +{ + qemuDomainJobPrivate *jobPriv = vm->job->privateData; + g_autoptr(virJSONValue) tlsPSKProps = NULL; + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + + if (!cfg->migrateTLSPSKdir) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("host migration TLS-PSK directory not configured")); + return -1; + } + + 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(cfg->migrateTLSPSKdir, tlsListen, + username, *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 between now and perform . */ + 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 +1344,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 +1355,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 +1365,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..07f5812065 100644 --- a/src/qemu/qemu_migration_params.h +++ b/src/qemu/qemu_migration_params.h @@ -123,6 +123,15 @@ qemuMigrationParamsEnableTLSx509(virQEMUDriver *driver, const char *hostname, qemuMigrationParams *migParams); +int +qemuMigrationParamsEnableTLSPSK(virQEMUDriver *driver, + virDomainObj *vm, + bool tlsListen, + int asyncJob, + char **tlsPSKAlias, + const char *username, + qemuMigrationParams *migParams); + int qemuMigrationParamsDisableTLS(virDomainObj *vm, qemuMigrationParams *migParams); -- 2.39.3
