[libvirt] [PATCH 14/21] Move encryption lookup back into qemu driver file

Daniel P. Berrange berrange at redhat.com
Fri Oct 23 13:05:43 UTC 2009


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       |  113 ++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor.c      |   24 +++++++++
 src/qemu/qemu_monitor.h      |   20 +++++++
 src/qemu/qemu_monitor_text.c |  103 ++------------------------------------
 4 files changed, 162 insertions(+), 98 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index d25afb9..9c4783a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -356,6 +356,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;
+}
+
 /*
  * Open an existing VM's monitor, re-detect VCPU threads
  * and re-reserve the security labels in use
@@ -376,6 +483,9 @@ qemuReconnectDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaq
         goto error;
     }
 
+    qemuMonitorRegisterDiskSecretLookup(priv->mon,
+                                        findVolumeQcowPassphrase);
+
     if (qemuUpdateActivePciHostdevs(driver, obj->def) < 0) {
         goto error;
     }
@@ -1005,6 +1115,9 @@ qemudWaitForMonitor(virConnectPtr conn,
         return -1;
     }
 
+    qemuMonitorRegisterDiskSecretLookup(priv->mon,
+                                        findVolumeQcowPassphrase);
+
     return 0;
 }
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 5f7e20c..0906e33 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,18 @@ 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);
-- 
1.6.2.5




More information about the libvir-list mailing list