[libvirt] [PATCH 06/15] Move encryption lookup back into qemu driver file

Daniel Veillard veillard at redhat.com
Wed Nov 4 13:39:50 UTC 2009


On Tue, Nov 03, 2009 at 02:50:00PM -0500, Daniel P. Berrange wrote:
> Decouple the monitor code from the virDomainDefPtr structure
> by moving the disk encryption lookup code back into the
> qemu_driver.c file. Instead provide a function callback to
> the monitor code which can be invoked to retrieve encryption
> data as required.
> 
> * src/qemu/qemu_driver.c: Add findDomainDiskEncryption,
>   and findVolumeQcowPassphrase. Pass address of the method
>   findVolumeQcowPassphrase into qemuMonitorOpen()
> * src/qemu/qemu_monitor.c: Associate a disk
>   encryption function callback with the qemuMonitorPtr
>   object.
> * src/qemu/qemu_monitor_text.c: Remove findDomainDiskEncryption
>   and findVolumeQcowPassphrase.
> ---
>  src/qemu/qemu_driver.c       |  110 ++++++++++++++++++++++++++++++++++++++++++
>  src/qemu/qemu_monitor.c      |   22 ++++++++
>  src/qemu/qemu_monitor.h      |   20 ++++++++
>  src/qemu/qemu_monitor_text.c |  103 ++-------------------------------------
>  4 files changed, 157 insertions(+), 98 deletions(-)
> 
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index e985543..30cc66e 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -348,6 +348,113 @@ qemuHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
>  }
>  
>  
> +static virStorageEncryptionPtr
> +findDomainDiskEncryption(virConnectPtr conn, virDomainObjPtr vm,
> +                         const char *path)
> +{
> +    bool seen_volume;
> +    int i;
> +
> +    seen_volume = false;
> +    for (i = 0; i < vm->def->ndisks; i++) {
> +        virDomainDiskDefPtr disk;
> +
> +        disk = vm->def->disks[i];
> +        if (disk->src != NULL && STREQ(disk->src, path)) {
> +            seen_volume = true;
> +            if (disk->encryption != NULL)
> +                return disk->encryption;
> +        }
> +    }
> +    if (seen_volume)
> +        qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
> +                         _("missing <encryption> for volume %s"), path);
> +    else
> +        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
> +                         _("unexpected passphrase request for volume %s"),
> +                         path);
> +    return NULL;
> +}
> +
> +
> +static int
> +findVolumeQcowPassphrase(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
> +                         virConnectPtr conn,
> +                         virDomainObjPtr vm,
> +                         const char *path,
> +                         char **secretRet,
> +                         size_t *secretLen)
> +{
> +    virStorageEncryptionPtr enc;
> +    virSecretPtr secret;
> +    char *passphrase;
> +    unsigned char *data;
> +    size_t size;
> +
> +    if (!conn) {
> +        qemudReportError(NULL, NULL, NULL, VIR_ERR_NO_SUPPORT,
> +                         "%s", _("cannot find secrets without a connection"));
> +        return -1;
> +    }
> +
> +    if (conn->secretDriver == NULL ||
> +        conn->secretDriver->lookupByUUID == NULL ||
> +        conn->secretDriver->getValue == NULL) {
> +        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT, "%s",
> +                         _("secret storage not supported"));
> +        return -1;
> +    }
> +
> +    enc = findDomainDiskEncryption(conn, vm, path);
> +    if (enc == NULL)
> +        return -1;
> +
> +    if (enc->format != VIR_STORAGE_ENCRYPTION_FORMAT_QCOW ||
> +        enc->nsecrets != 1 ||
> +        enc->secrets[0]->type !=
> +        VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE) {
> +        qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
> +                         _("invalid <encryption> for volume %s"), path);
> +        return -1;
> +    }
> +
> +    secret = conn->secretDriver->lookupByUUID(conn,
> +                                              enc->secrets[0]->uuid);
> +    if (secret == NULL)
> +        return -1;
> +    data = conn->secretDriver->getValue(secret, &size,
> +                                        VIR_SECRET_GET_VALUE_INTERNAL_CALL);
> +    virUnrefSecret(secret);
> +    if (data == NULL)
> +        return -1;
> +
> +    if (memchr(data, '\0', size) != NULL) {
> +        memset(data, 0, size);
> +        VIR_FREE(data);
> +        qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_SECRET,
> +                         _("format='qcow' passphrase for %s must not contain a "
> +                           "'\\0'"), path);
> +        return -1;
> +    }
> +
> +    if (VIR_ALLOC_N(passphrase, size + 1) < 0) {
> +        memset(data, 0, size);
> +        VIR_FREE(data);
> +        virReportOOMError(conn);
> +        return -1;
> +    }
> +    memcpy(passphrase, data, size);
> +    passphrase[size] = '\0';
> +
> +    memset(data, 0, size);
> +    VIR_FREE(data);
> +
> +    *secretRet = passphrase;
> +    *secretLen = size;
> +
> +    return 0;
> +}
> +
>  static int
>  qemuConnectMonitor(virDomainObjPtr vm, int reconnect)
>  {
> @@ -358,6 +465,9 @@ qemuConnectMonitor(virDomainObjPtr vm, int reconnect)
>          return -1;
>      }
>  
> +    qemuMonitorRegisterDiskSecretLookup(priv->mon,
> +                                        findVolumeQcowPassphrase);
> +
>      return 0;
>  }
>  
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index 5f7e20c..352328d 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -45,6 +45,7 @@ struct _qemuMonitor {
>      virDomainObjPtr vm;
>  
>      qemuMonitorEOFNotify eofCB;
> +    qemuMonitorDiskSecretLookup secretCB;
>  };
>  
>  /* Return -1 for error, 1 to continue reading and 0 for success */
> @@ -322,6 +323,7 @@ qemuMonitorOpen(virDomainObjPtr vm,
>          goto cleanup;
>      }
>  
> +
>      return mon;
>  
>  cleanup:
> @@ -344,6 +346,13 @@ void qemuMonitorClose(qemuMonitorPtr mon)
>  }
>  
>  
> +void qemuMonitorRegisterDiskSecretLookup(qemuMonitorPtr mon,
> +                                         qemuMonitorDiskSecretLookup secretCB)
> +{
> +    mon->secretCB = secretCB;
> +}
> +
> +
>  int qemuMonitorWrite(qemuMonitorPtr mon,
>                       const char *data,
>                       size_t len)
> @@ -410,3 +419,16 @@ retry:
>      }
>      return 0;
>  }
> +
> +
> +int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
> +                             virConnectPtr conn,
> +                             const char *path,
> +                             char **secret,
> +                             size_t *secretLen)
> +{
> +    *secret = NULL;
> +    *secretLen = 0;
> +
> +    return mon->secretCB(mon, conn, mon->vm, path, secret, secretLen);
> +}
> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
> index e863e20..6fb99a9 100644
> --- a/src/qemu/qemu_monitor.h
> +++ b/src/qemu/qemu_monitor.h
> @@ -36,12 +36,27 @@ typedef void (*qemuMonitorEOFNotify)(qemuMonitorPtr mon,
>                                       virDomainObjPtr vm,
>                                       int withError);
>  
> +/* XXX we'd really like to avoid virCOnnectPtr here
> + * It is required so the callback can find the active
> + * secret driver. Need to change this to work like the
> + * security drivers do, to avoid this
> + */
> +typedef int (*qemuMonitorDiskSecretLookup)(qemuMonitorPtr mon,
> +                                           virConnectPtr conn,
> +                                           virDomainObjPtr vm,
> +                                           const char *path,
> +                                           char **secret,
> +                                           size_t *secretLen);
> +
>  qemuMonitorPtr qemuMonitorOpen(virDomainObjPtr vm,
>                                 int reconnect,
>                                 qemuMonitorEOFNotify eofCB);
>  
>  void qemuMonitorClose(qemuMonitorPtr mon);
>  
> +void qemuMonitorRegisterDiskSecretLookup(qemuMonitorPtr mon,
> +                                         qemuMonitorDiskSecretLookup secretCB);
> +
>  int qemuMonitorWrite(qemuMonitorPtr mon,
>                       const char *data,
>                       size_t len);
> @@ -57,5 +72,10 @@ int qemuMonitorRead(qemuMonitorPtr mon,
>  
>  int qemuMonitorWaitForInput(qemuMonitorPtr mon);
>  
> +int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
> +                             virConnectPtr conn,
> +                             const char *path,
> +                             char **secret,
> +                             size_t *secretLen);
>  
>  #endif /* QEMU_MONITOR_H */
> diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
> index fa17971..a0146ae 100644
> --- a/src/qemu/qemu_monitor_text.c
> +++ b/src/qemu/qemu_monitor_text.c
> @@ -334,101 +334,6 @@ qemuMonitorCommand(const virDomainObjPtr vm,
>  }
>  
>  
> -
> -static virStorageEncryptionPtr
> -findDomainDiskEncryption(virConnectPtr conn, virDomainObjPtr vm,
> -                         const char *path)
> -{
> -    bool seen_volume;
> -    int i;
> -
> -    seen_volume = false;
> -    for (i = 0; i < vm->def->ndisks; i++) {
> -        virDomainDiskDefPtr disk;
> -
> -        disk = vm->def->disks[i];
> -        if (disk->src != NULL && STREQ(disk->src, path)) {
> -            seen_volume = true;
> -            if (disk->encryption != NULL)
> -                return disk->encryption;
> -        }
> -    }
> -    if (seen_volume)
> -        qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
> -                         _("missing <encryption> for volume %s"), path);
> -    else
> -        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
> -                         _("unexpected passphrase request for volume %s"),
> -                         path);
> -    return NULL;
> -}
> -
> -static char *
> -findVolumeQcowPassphrase(virConnectPtr conn, virDomainObjPtr vm,
> -                         const char *path, size_t *passphrase_len)
> -{
> -    virStorageEncryptionPtr enc;
> -    virSecretPtr secret;
> -    char *passphrase;
> -    unsigned char *data;
> -    size_t size;
> -
> -    if (conn->secretDriver == NULL ||
> -        conn->secretDriver->lookupByUUID == NULL ||
> -        conn->secretDriver->getValue == NULL) {
> -        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT, "%s",
> -                         _("secret storage not supported"));
> -        return NULL;
> -    }
> -
> -    enc = findDomainDiskEncryption(conn, vm, path);
> -    if (enc == NULL)
> -        return NULL;
> -
> -    if (enc->format != VIR_STORAGE_ENCRYPTION_FORMAT_QCOW ||
> -        enc->nsecrets != 1 ||
> -        enc->secrets[0]->type !=
> -        VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE) {
> -        qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
> -                         _("invalid <encryption> for volume %s"), path);
> -        return NULL;
> -    }
> -
> -    secret = conn->secretDriver->lookupByUUID(conn,
> -                                              enc->secrets[0]->uuid);
> -    if (secret == NULL)
> -        return NULL;
> -    data = conn->secretDriver->getValue(secret, &size,
> -                                        VIR_SECRET_GET_VALUE_INTERNAL_CALL);
> -    virUnrefSecret(secret);
> -    if (data == NULL)
> -        return NULL;
> -
> -    if (memchr(data, '\0', size) != NULL) {
> -        memset(data, 0, size);
> -        VIR_FREE(data);
> -        qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_SECRET,
> -                         _("format='qcow' passphrase for %s must not contain a "
> -                           "'\\0'"), path);
> -        return NULL;
> -    }
> -
> -    if (VIR_ALLOC_N(passphrase, size + 1) < 0) {
> -        memset(data, 0, size);
> -        VIR_FREE(data);
> -        virReportOOMError(conn);
> -        return NULL;
> -    }
> -    memcpy(passphrase, data, size);
> -    passphrase[size] = '\0';
> -
> -    memset(data, 0, size);
> -    VIR_FREE(data);
> -
> -    *passphrase_len = size;
> -    return passphrase;
> -}
> -
>  static int
>  qemuMonitorSendVolumePassphrase(const virDomainObjPtr vm,
>                                  const char *buf,
> @@ -436,7 +341,8 @@ qemuMonitorSendVolumePassphrase(const virDomainObjPtr vm,
>                                  void *data)
>  {
>      virConnectPtr conn = data;
> -    char *passphrase, *path;
> +    qemuDomainObjPrivatePtr priv = vm->privateData;
> +    char *passphrase = NULL, *path;
>      const char *prompt_path;
>      size_t path_len, passphrase_len = 0;
>      int res;
> @@ -456,9 +362,10 @@ qemuMonitorSendVolumePassphrase(const virDomainObjPtr vm,
>      memcpy(path, prompt_path, path_len);
>      path[path_len] = '\0';
>  
> -    passphrase = findVolumeQcowPassphrase(conn, vm, path, &passphrase_len);
> +    res = qemuMonitorGetDiskSecret(priv->mon, conn, path,
> +                                   &passphrase, &passphrase_len);
>      VIR_FREE(path);
> -    if (passphrase == NULL)
> +    if (res < 0)
>          return -1;
>  
>      res = qemuMonitorSend(vm, passphrase, -1);

  ACK,

Daniel

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list