mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
Move encryption lookup back into qemu driver file
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.
This commit is contained in:
parent
1cfd5a00eb
commit
4604c18f0b
@ -349,6 +349,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
|
static int
|
||||||
qemuConnectMonitor(virDomainObjPtr vm, int reconnect)
|
qemuConnectMonitor(virDomainObjPtr vm, int reconnect)
|
||||||
{
|
{
|
||||||
@ -359,6 +466,9 @@ qemuConnectMonitor(virDomainObjPtr vm, int reconnect)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qemuMonitorRegisterDiskSecretLookup(priv->mon,
|
||||||
|
findVolumeQcowPassphrase);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ struct _qemuMonitor {
|
|||||||
virDomainObjPtr vm;
|
virDomainObjPtr vm;
|
||||||
|
|
||||||
qemuMonitorEOFNotify eofCB;
|
qemuMonitorEOFNotify eofCB;
|
||||||
|
qemuMonitorDiskSecretLookup secretCB;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Return -1 for error, 1 to continue reading and 0 for success */
|
/* Return -1 for error, 1 to continue reading and 0 for success */
|
||||||
@ -322,6 +323,7 @@ qemuMonitorOpen(virDomainObjPtr vm,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return mon;
|
return mon;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@ -344,6 +346,13 @@ void qemuMonitorClose(qemuMonitorPtr mon)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void qemuMonitorRegisterDiskSecretLookup(qemuMonitorPtr mon,
|
||||||
|
qemuMonitorDiskSecretLookup secretCB)
|
||||||
|
{
|
||||||
|
mon->secretCB = secretCB;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int qemuMonitorWrite(qemuMonitorPtr mon,
|
int qemuMonitorWrite(qemuMonitorPtr mon,
|
||||||
const char *data,
|
const char *data,
|
||||||
size_t len)
|
size_t len)
|
||||||
@ -410,3 +419,16 @@ retry:
|
|||||||
}
|
}
|
||||||
return 0;
|
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);
|
||||||
|
}
|
||||||
|
@ -36,12 +36,27 @@ typedef void (*qemuMonitorEOFNotify)(qemuMonitorPtr mon,
|
|||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
int withError);
|
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,
|
qemuMonitorPtr qemuMonitorOpen(virDomainObjPtr vm,
|
||||||
int reconnect,
|
int reconnect,
|
||||||
qemuMonitorEOFNotify eofCB);
|
qemuMonitorEOFNotify eofCB);
|
||||||
|
|
||||||
void qemuMonitorClose(qemuMonitorPtr mon);
|
void qemuMonitorClose(qemuMonitorPtr mon);
|
||||||
|
|
||||||
|
void qemuMonitorRegisterDiskSecretLookup(qemuMonitorPtr mon,
|
||||||
|
qemuMonitorDiskSecretLookup secretCB);
|
||||||
|
|
||||||
int qemuMonitorWrite(qemuMonitorPtr mon,
|
int qemuMonitorWrite(qemuMonitorPtr mon,
|
||||||
const char *data,
|
const char *data,
|
||||||
size_t len);
|
size_t len);
|
||||||
@ -57,5 +72,10 @@ int qemuMonitorRead(qemuMonitorPtr mon,
|
|||||||
|
|
||||||
int qemuMonitorWaitForInput(qemuMonitorPtr mon);
|
int qemuMonitorWaitForInput(qemuMonitorPtr mon);
|
||||||
|
|
||||||
|
int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
|
||||||
|
virConnectPtr conn,
|
||||||
|
const char *path,
|
||||||
|
char **secret,
|
||||||
|
size_t *secretLen);
|
||||||
|
|
||||||
#endif /* QEMU_MONITOR_H */
|
#endif /* QEMU_MONITOR_H */
|
||||||
|
@ -336,101 +336,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
|
static int
|
||||||
qemuMonitorSendVolumePassphrase(const virDomainObjPtr vm,
|
qemuMonitorSendVolumePassphrase(const virDomainObjPtr vm,
|
||||||
const char *buf,
|
const char *buf,
|
||||||
@ -438,7 +343,8 @@ qemuMonitorSendVolumePassphrase(const virDomainObjPtr vm,
|
|||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
virConnectPtr conn = data;
|
virConnectPtr conn = data;
|
||||||
char *passphrase, *path;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
char *passphrase = NULL, *path;
|
||||||
const char *prompt_path;
|
const char *prompt_path;
|
||||||
size_t path_len, passphrase_len = 0;
|
size_t path_len, passphrase_len = 0;
|
||||||
int res;
|
int res;
|
||||||
@ -458,9 +364,10 @@ qemuMonitorSendVolumePassphrase(const virDomainObjPtr vm,
|
|||||||
memcpy(path, prompt_path, path_len);
|
memcpy(path, prompt_path, path_len);
|
||||||
path[path_len] = '\0';
|
path[path_len] = '\0';
|
||||||
|
|
||||||
passphrase = findVolumeQcowPassphrase(conn, vm, path, &passphrase_len);
|
res = qemuMonitorGetDiskSecret(priv->mon, conn, path,
|
||||||
|
&passphrase, &passphrase_len);
|
||||||
VIR_FREE(path);
|
VIR_FREE(path);
|
||||||
if (passphrase == NULL)
|
if (res < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
res = qemuMonitorSend(vm, passphrase, -1);
|
res = qemuMonitorSend(vm, passphrase, -1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user