On Thu, Aug 20, 2009 at 08:18:13PM +0200, Miloslav Trma?? wrote:
If the <encryption format='qcow'> element does not
specify a secret
during volume creation, generate a suitable secret and add it to the
<encryption> tag. The caller can view the updated <encryption> tag
using virStorageVolGetXMLDesc().
Similarly, when <encryption format='default'/> is specified while
creating a qcow or qcow2-formatted volume, change the format to "qcow"
and generate a secret as described above.
Changes since the third submission:
- Add "flags" parameter to virSecretDefineXML(), virSecretGetXMLDesc(),
virSecretGetValue(), virSecretSetValue(), and all derived interfaces.
---
src/storage_backend.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 124 insertions(+), 3 deletions(-)
diff --git a/src/storage_backend.c b/src/storage_backend.c
index c818142..5fa0035 100644
--- a/src/storage_backend.c
+++ b/src/storage_backend.c
@@ -43,6 +43,7 @@
#include <selinux/selinux.h>
#endif
+#include "datatypes.h"
#include "virterror_internal.h"
#include "util.h"
#include "memory.h"
@@ -331,6 +332,118 @@ cleanup:
}
static int
+virStorageGenerateQcowEncryption(virConnectPtr conn,
+ virStorageVolDefPtr vol)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ virStorageEncryptionPtr enc;
+ virStorageEncryptionSecretPtr enc_secret = NULL;
+ virSecretPtr secret = NULL;
+ char *uuid = NULL, *xml;
+ unsigned char value[16];
+ int ret = -1, fd = -1;
+ size_t i;
+
+ if (conn->secretDriver == NULL || conn->secretDriver->defineXML == NULL ||
+ conn->secretDriver->setValue == NULL) {
+ virStorageReportError(conn, VIR_ERR_NO_SUPPORT, "%s",
+ _("secret storage not supported"));
+ goto cleanup;
+ }
+
+ enc = vol->target.encryption;
+ if (enc->nsecrets != 0) {
+ virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("secrets already defined"));
+ goto cleanup;
+ }
+
+ if (VIR_ALLOC(enc_secret) < 0 || VIR_REALLOC_N(enc->secrets, 1) < 0) {
+ virReportOOMError(conn);
+ goto cleanup;
+ }
+
+ virBufferAddLit(&buf, "<secret ephemeral='no'
private='no'>");
+ /* <uuid/> is chosen by the secret driver */
+ virBufferEscapeString(&buf,
+ "<description>qcow passphrase for
%s</description>",
+ vol->target.path);
+ virBufferEscapeString(&buf, "<volume>%s</volume>",
vol->target.path);
+ virBufferAddLit(&buf, "</secret>");
+ if (virBufferError(&buf)) {
+ virReportOOMError(conn);
+ goto cleanup;
+ }
+ xml = virBufferContentAndReset(&buf);
This is the first place where we should be just calling into an
internal secret_conf.h API for formatting XML from a struct,
rather than duplicating the XML formatting.
+ /* A qcow passphrase is up to 16 bytes, with any data following
a NUL
+ ignored. Prohibit control and non-ASCII characters to avoid possible
+ unpleasant surprises with the qemu monitor input mechanism. */
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd < 0) {
+ virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot open /dev/urandom"));
+ goto cleanup;
+ }
+ i = 0;
+ while (i < sizeof (value)) {
+ ssize_t r;
+
+ while ((r = read(fd, value + i, 1)) == -1 && errno == EINTR)
+ ;
+ if (r <= 0) {
+ virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot read from /dev/urandom"));
+ goto cleanup;
+ }
+ if (value[i] >= 0x20 && value[i] <= 0x7E)
+ i++; /* Got an acceptable character */
+ }
+ close(fd);
I reckon this snippet of code could usefully be put into the util.h file
as virFileGenerateRandomkey(), or alternatively perhaps secret_conf.h,
as virSecretGenerateRandomKey(unsigned char *buf, size_t buflen);
Regards,
Daniel
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|