This is so we can use it in the storage file probing code which is
also moving to src/util
The real code change is renaming virStorageReportError() to
virStorageEncryptionReportError()
* src/util/storage_encryption.[ch]: add
* src/conf/storage_encryption_conf.[ch]: remove
* src/conf/domain_conf.h, storage/conf/storage_conf.h: include
storage_encryption.h
* src/Makefile.am: build src/util/storage_encryption.[ch]; note
libvirt_lxc now needs to be linked with $(SELINUX_LIBS)
* proxy/Makefile.am: ditto
* po/POTFILES.in, src/libvirt_private.syms: update
---
po/POTFILES.in | 2 +-
proxy/Makefile.am | 2 +-
src/Makefile.am | 52 +++---
src/conf/domain_conf.h | 2 +-
src/conf/storage_conf.h | 2 +-
src/conf/storage_encryption_conf.c | 294 -----------------------------------
src/conf/storage_encryption_conf.h | 80 ----------
src/libvirt_private.syms | 2 +-
src/util/storage_encryption.c | 301 ++++++++++++++++++++++++++++++++++++
src/util/storage_encryption.h | 80 ++++++++++
10 files changed, 412 insertions(+), 405 deletions(-)
delete mode 100644 src/conf/storage_encryption_conf.c
delete mode 100644 src/conf/storage_encryption_conf.h
create mode 100644 src/util/storage_encryption.c
create mode 100644 src/util/storage_encryption.h
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 67769c8..9f21459 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -7,7 +7,6 @@ src/conf/network_conf.c
src/conf/node_device_conf.c
src/conf/secret_conf.c
src/conf/storage_conf.c
-src/conf/storage_encryption_conf.c
src/datatypes.c
src/interface/netcf_driver.c
src/libvirt.c
@@ -45,6 +44,7 @@ src/util/conf.c
src/util/iptables.c
src/util/logging.c
src/util/pci.c
+src/util/storage_encryption.c
src/util/util.c
src/util/uuid.c
src/util/virterror.c
diff --git a/proxy/Makefile.am b/proxy/Makefile.am
index 3e0050b..2ae6ef9 100644
--- a/proxy/Makefile.am
+++ b/proxy/Makefile.am
@@ -17,12 +17,12 @@ libvirt_proxy_SOURCES = libvirt_proxy.c \
@top_srcdir(a)/src/util/buf.c \
@top_srcdir(a)/src/util/logging.c \
@top_srcdir(a)/src/util/memory.c \
+ @top_srcdir(a)/src/util/storage_encryption.c \
@top_srcdir(a)/src/util/threads.c \
@top_srcdir(a)/src/util/util.c \
@top_srcdir(a)/src/util/uuid.c \
@top_srcdir(a)/src/util/virterror.c \
@top_srcdir(a)/src/conf/capabilities.c \
- @top_srcdir(a)/src/conf/storage_encryption_conf.c \
@top_srcdir(a)/src/conf/domain_conf.c \
@top_srcdir(a)/src/xen/xend_internal.c \
@top_srcdir(a)/src/xen/xen_hypervisor.c \
diff --git a/src/Makefile.am b/src/Makefile.am
index 9cbec47..5bddb58 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,26 +35,27 @@ mod_LTLIBRARIES =
# These files are not related to driver APIs. Simply generic
# helper APIs for various purposes
-UTIL_SOURCES = \
- util/bridge.c util/bridge.h \
- util/buf.c util/buf.h \
- util/conf.c util/conf.h \
- util/cgroup.c util/cgroup.h \
- util/event.c util/event.h \
- util/hash.c util/hash.h \
- util/iptables.c util/iptables.h \
- util/logging.c util/logging.h \
- util/memory.c util/memory.h \
- util/pci.c util/pci.h \
- util/hostusb.c util/hostusb.h \
- util/qparams.c util/qparams.h \
- util/stats_linux.c util/stats_linux.h \
- util/threads.c util/threads.h \
- util/threads-pthread.h \
- util/threads-win32.h \
- util/uuid.c util/uuid.h \
- util/util.c util/util.h \
- util/xml.c util/xml.h \
+UTIL_SOURCES = \
+ util/bridge.c util/bridge.h \
+ util/buf.c util/buf.h \
+ util/conf.c util/conf.h \
+ util/cgroup.c util/cgroup.h \
+ util/event.c util/event.h \
+ util/hash.c util/hash.h \
+ util/iptables.c util/iptables.h \
+ util/logging.c util/logging.h \
+ util/memory.c util/memory.h \
+ util/pci.c util/pci.h \
+ util/hostusb.c util/hostusb.h \
+ util/qparams.c util/qparams.h \
+ util/stats_linux.c util/stats_linux.h \
+ util/storage_encryption.c util/storage_encryption.h \
+ util/threads.c util/threads.h \
+ util/threads-pthread.h \
+ util/threads-win32.h \
+ util/uuid.c util/uuid.h \
+ util/util.c util/util.h \
+ util/xml.c util/xml.h \
util/virterror.c util/virterror_internal.h
EXTRA_DIST += util/threads-pthread.c util/threads-win32.c
@@ -98,16 +99,12 @@ SECRET_CONF_SOURCES = \
NODE_DEVICE_CONF_SOURCES = \
conf/node_device_conf.c conf/node_device_conf.h
-ENCRYPTION_CONF_SOURCES = \
- conf/storage_encryption_conf.c conf/storage_encryption_conf.h
-
CONF_SOURCES = \
$(DOMAIN_CONF_SOURCES) \
$(DOMAIN_EVENT_SOURCES) \
$(NETWORK_CONF_SOURCES) \
$(NODE_DEVICE_CONF_SOURCES) \
$(STORAGE_CONF_SOURCES) \
- $(ENCRYPTION_CONF_SOURCES) \
$(INTERFACE_CONF_SOURCES) \
$(SECRET_CONF_SOURCES)
@@ -779,10 +776,13 @@ libvirt_lxc_SOURCES = \
$(LXC_CONTROLLER_SOURCES) \
$(UTIL_SOURCES) \
$(NODE_INFO_SOURCES) \
- $(ENCRYPTION_CONF_SOURCES) \
$(DOMAIN_CONF_SOURCES)
libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(COVERAGE_LDCFLAGS) $(CAPNG_LIBS)
-libvirt_lxc_LDADD = $(LIBXML_LIBS) $(NUMACTL_LIBS) ../gnulib/lib/libgnu.la
+libvirt_lxc_LDADD = \
+ $(LIBXML_LIBS) \
+ $(NUMACTL_LIBS) \
+ $(SELINUX_LIBS) \
+ ../gnulib/lib/libgnu.la
libvirt_lxc_CFLAGS = \
$(LIBPARTED_CFLAGS) \
$(NUMACTL_CFLAGS) \
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 7c918a7..1db5b2b 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -30,7 +30,7 @@
#include "internal.h"
#include "capabilities.h"
-#include "storage_encryption_conf.h"
+#include "storage_encryption.h"
#include "util.h"
#include "threads.h"
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 421d305..00dd102 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -26,7 +26,7 @@
#include "internal.h"
#include "util.h"
-#include "storage_encryption_conf.h"
+#include "storage_encryption.h"
#include "threads.h"
#include <libxml/tree.h>
diff --git a/src/conf/storage_encryption_conf.c b/src/conf/storage_encryption_conf.c
deleted file mode 100644
index b97b989..0000000
--- a/src/conf/storage_encryption_conf.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * storage_encryption_conf.c: volume encryption information
- *
- * Copyright (C) 2009 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Red Hat Author: Miloslav Trmač <mitr(a)redhat.com>
- */
-
-#include <config.h>
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "internal.h"
-
-#include "buf.h"
-#include "memory.h"
-#include "storage_conf.h"
-#include "storage_encryption_conf.h"
-#include "util.h"
-#include "xml.h"
-#include "virterror_internal.h"
-#include "uuid.h"
-
-#define VIR_FROM_THIS VIR_FROM_STORAGE
-
-VIR_ENUM_IMPL(virStorageEncryptionSecretType,
- VIR_STORAGE_ENCRYPTION_SECRET_TYPE_LAST, "passphrase")
-
-VIR_ENUM_IMPL(virStorageEncryptionFormat,
- VIR_STORAGE_ENCRYPTION_FORMAT_LAST,
- "default", "qcow")
-
-static void
-virStorageEncryptionSecretFree(virStorageEncryptionSecretPtr secret)
-{
- if (!secret)
- return;
- VIR_FREE(secret);
-}
-
-void
-virStorageEncryptionFree(virStorageEncryptionPtr enc)
-{
- size_t i;
-
- if (!enc)
- return;
-
- for (i = 0; i < enc->nsecrets; i++)
- virStorageEncryptionSecretFree(enc->secrets[i]);
- VIR_FREE(enc->secrets);
- VIR_FREE(enc);
-}
-
-#ifndef PROXY
-
-static virStorageEncryptionSecretPtr
-virStorageEncryptionSecretParse(virConnectPtr conn, xmlXPathContextPtr ctxt,
- xmlNodePtr node)
-{
- xmlNodePtr old_node;
- virStorageEncryptionSecretPtr ret;
- char *type_str;
- int type;
- char *uuidstr = NULL;
-
- if (VIR_ALLOC(ret) < 0) {
- virReportOOMError(conn);
- return NULL;
- }
-
- old_node = ctxt->node;
- ctxt->node = node;
-
- type_str = virXPathString(conn, "string(./@type)", ctxt);
- if (type_str == NULL) {
- virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s",
- _("unknown volume encryption secret type"));
- goto cleanup;
- }
- type = virStorageEncryptionSecretTypeTypeFromString(type_str);
- if (type < 0) {
- virStorageReportError(conn, VIR_ERR_XML_ERROR,
- _("unknown volume encryption secret type %s"),
- type_str);
- VIR_FREE(type_str);
- goto cleanup;
- }
- VIR_FREE(type_str);
- ret->type = type;
-
- uuidstr = virXPathString(conn, "string(./@uuid)", ctxt);
- if (uuidstr) {
- if (virUUIDParse(uuidstr, ret->uuid) < 0) {
- virStorageReportError(conn, VIR_ERR_XML_ERROR,
- _("malformed volume encryption uuid
'%s'"),
- uuidstr);
- goto cleanup;
- }
- } else {
- virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s",
- _("missing volume encryption uuid"));
- goto cleanup;
- }
- ctxt->node = old_node;
- return ret;
-
- cleanup:
- virStorageEncryptionSecretFree(ret);
- VIR_FREE(uuidstr);
- ctxt->node = old_node;
- return NULL;
-}
-
-static virStorageEncryptionPtr
-virStorageEncryptionParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt)
-{
- xmlNodePtr *nodes = NULL;
- virStorageEncryptionPtr ret;
- char *format_str;
- int format, i, n;
-
- if (VIR_ALLOC(ret) < 0) {
- virReportOOMError(conn);
- return NULL;
- }
-
- format_str = virXPathString(conn, "string(./@format)", ctxt);
- if (format_str == NULL) {
- virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s",
- _("unknown volume encryption format"));
- goto cleanup;
- }
- format = virStorageEncryptionFormatTypeFromString(format_str);
- if (format < 0) {
- virStorageReportError(conn, VIR_ERR_XML_ERROR,
- _("unknown volume encryption format type %s"),
- format_str);
- VIR_FREE(format_str);
- goto cleanup;
- }
- VIR_FREE(format_str);
- ret->format = format;
-
- n = virXPathNodeSet(conn, "./secret", ctxt, &nodes);
- if (n < 0){
- virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot extract volume encryption secrets"));
- goto cleanup;
- }
- if (n != 0 && VIR_ALLOC_N(ret->secrets, n) < 0) {
- virReportOOMError(conn);
- goto cleanup;
- }
- ret->nsecrets = n;
- for (i = 0; i < n; i++) {
- ret->secrets[i] = virStorageEncryptionSecretParse(conn, ctxt, nodes[i]);
- if (ret->secrets[i] == NULL)
- goto cleanup;
- }
- VIR_FREE(nodes);
-
- return ret;
-
- cleanup:
- VIR_FREE(nodes);
- virStorageEncryptionFree(ret);
- return NULL;
-}
-
-virStorageEncryptionPtr
-virStorageEncryptionParseNode(virConnectPtr conn,
- xmlDocPtr xml, xmlNodePtr root)
-{
- xmlXPathContextPtr ctxt = NULL;
- virStorageEncryptionPtr enc = NULL;
-
- if (STRNEQ((const char *) root->name, "encryption")) {
- virStorageReportError(conn, VIR_ERR_XML_ERROR,
- "%s", _("unknown root element for volume
"
- "encryption information"));
- goto cleanup;
- }
-
- ctxt = xmlXPathNewContext(xml);
- if (ctxt == NULL) {
- virReportOOMError(conn);
- goto cleanup;
- }
-
- ctxt->node = root;
- enc = virStorageEncryptionParseXML(conn, ctxt);
-
- cleanup:
- xmlXPathFreeContext(ctxt);
- return enc;
-}
-#endif /* ! PROXY */
-
-
-static int
-virStorageEncryptionSecretFormat(virConnectPtr conn,
- virBufferPtr buf,
- virStorageEncryptionSecretPtr secret)
-{
- const char *type;
- char uuidstr[VIR_UUID_STRING_BUFLEN];
-
- type = virStorageEncryptionSecretTypeTypeToString(secret->type);
- if (!type) {
- virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
- _("unexpected volume encryption secret type"));
- return -1;
- }
-
- virUUIDFormat(secret->uuid, uuidstr);
- virBufferVSprintf(buf, " <secret type='%s'
uuid='%s'/>\n", type, uuidstr);
- return 0;
-}
-
-int
-virStorageEncryptionFormat(virConnectPtr conn,
- virBufferPtr buf,
- virStorageEncryptionPtr enc)
-{
- const char *format;
- size_t i;
-
- format = virStorageEncryptionFormatTypeToString(enc->format);
- if (!format) {
- virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
- "%s", _("unexpected encryption
format"));
- return -1;
- }
- virBufferVSprintf(buf, " <encryption format='%s'>\n",
format);
-
- for (i = 0; i < enc->nsecrets; i++) {
- if (virStorageEncryptionSecretFormat(conn, buf, enc->secrets[i]) < 0)
- return -1;
- }
-
- virBufferAddLit(buf, " </encryption>\n");
-
- return 0;
-}
-
-int
-virStorageGenerateQcowPassphrase(virConnectPtr conn, unsigned char *dest)
-{
- int fd;
- size_t i;
-
- /* 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"));
- return -1;
- }
- i = 0;
- while (i < VIR_STORAGE_QCOW_PASSPHRASE_SIZE) {
- ssize_t r;
-
- while ((r = read(fd, dest + i, 1)) == -1 && errno == EINTR)
- ;
- if (r <= 0) {
- virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
- _("Cannot read from /dev/urandom"));
- close(fd);
- return -1;
- }
- if (dest[i] >= 0x20 && dest[i] <= 0x7E)
- i++; /* Got an acceptable character */
- }
- close(fd);
- return 0;
-}
diff --git a/src/conf/storage_encryption_conf.h b/src/conf/storage_encryption_conf.h
deleted file mode 100644
index 5d0bc3c..0000000
--- a/src/conf/storage_encryption_conf.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * storage_encryption_conf.h: volume encryption information
- *
- * Copyright (C) 2009 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Red Hat Author: Miloslav Trmač <mitr(a)redhat.com>
- */
-
-#ifndef __VIR_STORAGE_ENCRYPTION_H__
-#define __VIR_STORAGE_ENCRYPTION_H__
-
-#include "internal.h"
-#include "buf.h"
-#include "util.h"
-
-#include <stdbool.h>
-#include <libxml/tree.h>
-
-enum virStorageEncryptionSecretType {
- VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE = 0,
-
- VIR_STORAGE_ENCRYPTION_SECRET_TYPE_LAST
-};
-VIR_ENUM_DECL(virStorageEncryptionSecretType)
-
-typedef struct _virStorageEncryptionSecret virStorageEncryptionSecret;
-typedef virStorageEncryptionSecret *virStorageEncryptionSecretPtr;
-struct _virStorageEncryptionSecret {
- int type; /* enum virStorageEncryptionSecretType */
- unsigned char uuid[VIR_UUID_BUFLEN];
-};
-
-enum virStorageEncryptionFormat {
- /* "default" is only valid for volume creation */
- VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT = 0,
- VIR_STORAGE_ENCRYPTION_FORMAT_QCOW, /* Both qcow and qcow2 */
-
- VIR_STORAGE_ENCRYPTION_FORMAT_LAST,
-};
-VIR_ENUM_DECL(virStorageEncryptionFormat)
-
-typedef struct _virStorageEncryption virStorageEncryption;
-typedef virStorageEncryption *virStorageEncryptionPtr;
-struct _virStorageEncryption {
- int format; /* enum virStorageEncryptionFormat */
-
- size_t nsecrets;
- virStorageEncryptionSecretPtr *secrets;
-};
-
-void virStorageEncryptionFree(virStorageEncryptionPtr enc);
-
-virStorageEncryptionPtr virStorageEncryptionParseNode(virConnectPtr conn,
- xmlDocPtr xml,
- xmlNodePtr root);
-int virStorageEncryptionFormat(virConnectPtr conn, virBufferPtr buf,
- virStorageEncryptionPtr enc);
-
-/* A helper for VIR_STORAGE_ENCRYPTION_FORMAT_QCOW */
-enum {
- VIR_STORAGE_QCOW_PASSPHRASE_SIZE = 16
-};
-
-int virStorageGenerateQcowPassphrase(virConnectPtr conn, unsigned char *dest);
-
-#endif /* __VIR_STORAGE_ENCRYPTION_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a6668f3..e42a5e4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -385,7 +385,7 @@ virStoragePartedFsTypeTypeToString;
virStoragePoolObjLock;
virStoragePoolObjUnlock;
-# storage_encryption_conf.h
+# storage_encryption.h
virStorageEncryptionFree;
virStorageEncryptionDropSecrets;
virStorageEncryptionParseNode;
diff --git a/src/util/storage_encryption.c b/src/util/storage_encryption.c
new file mode 100644
index 0000000..f9bef2d
--- /dev/null
+++ b/src/util/storage_encryption.c
@@ -0,0 +1,301 @@
+/*
+ * storage_encryption.c: volume encryption information
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Red Hat Author: Miloslav Trmač <mitr(a)redhat.com>
+ */
+
+#include <config.h>
+
+#include "storage_encryption.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "internal.h"
+#include "buf.h"
+#include "memory.h"
+#include "util.h"
+#include "xml.h"
+#include "virterror_internal.h"
+#include "uuid.h"
+
+#define VIR_FROM_THIS VIR_FROM_STORAGE
+
+#define virStorageEncryptionReportError(conn, code, fmt...) \
+ virReportErrorHelper(conn, VIR_FROM_STORAGE, code, __FILE__, \
+ __FUNCTION__, __LINE__, fmt)
+
+
+VIR_ENUM_IMPL(virStorageEncryptionSecretType,
+ VIR_STORAGE_ENCRYPTION_SECRET_TYPE_LAST, "passphrase")
+
+VIR_ENUM_IMPL(virStorageEncryptionFormat,
+ VIR_STORAGE_ENCRYPTION_FORMAT_LAST,
+ "default", "qcow")
+
+static void
+virStorageEncryptionSecretFree(virStorageEncryptionSecretPtr secret)
+{
+ if (!secret)
+ return;
+ VIR_FREE(secret);
+}
+
+void
+virStorageEncryptionFree(virStorageEncryptionPtr enc)
+{
+ size_t i;
+
+ if (!enc)
+ return;
+
+ for (i = 0; i < enc->nsecrets; i++)
+ virStorageEncryptionSecretFree(enc->secrets[i]);
+ VIR_FREE(enc->secrets);
+ VIR_FREE(enc);
+}
+
+#ifndef PROXY
+
+static virStorageEncryptionSecretPtr
+virStorageEncryptionSecretParse(virConnectPtr conn, xmlXPathContextPtr ctxt,
+ xmlNodePtr node)
+{
+ xmlNodePtr old_node;
+ virStorageEncryptionSecretPtr ret;
+ char *type_str;
+ int type;
+ char *uuidstr = NULL;
+
+ if (VIR_ALLOC(ret) < 0) {
+ virReportOOMError(conn);
+ return NULL;
+ }
+
+ old_node = ctxt->node;
+ ctxt->node = node;
+
+ type_str = virXPathString(conn, "string(./@type)", ctxt);
+ if (type_str == NULL) {
+ virStorageEncryptionReportError(conn, VIR_ERR_XML_ERROR, "%s",
+ _("unknown volume encryption "
+ "secret type"));
+ goto cleanup;
+ }
+ type = virStorageEncryptionSecretTypeTypeFromString(type_str);
+ if (type < 0) {
+ virStorageEncryptionReportError(conn, VIR_ERR_XML_ERROR,
+ _("unknown volume encryption "
+ "secret type %s"), type_str);
+ VIR_FREE(type_str);
+ goto cleanup;
+ }
+ VIR_FREE(type_str);
+ ret->type = type;
+
+ uuidstr = virXPathString(conn, "string(./@uuid)", ctxt);
+ if (uuidstr) {
+ if (virUUIDParse(uuidstr, ret->uuid) < 0) {
+ virStorageEncryptionReportError(conn, VIR_ERR_XML_ERROR,
+ _("malformed volume encryption "
+ "uuid '%s'"), uuidstr);
+ goto cleanup;
+ }
+ } else {
+ virStorageEncryptionReportError(conn, VIR_ERR_XML_ERROR, "%s",
+ _("missing volume encryption uuid"));
+ goto cleanup;
+ }
+ ctxt->node = old_node;
+ return ret;
+
+ cleanup:
+ virStorageEncryptionSecretFree(ret);
+ VIR_FREE(uuidstr);
+ ctxt->node = old_node;
+ return NULL;
+}
+
+static virStorageEncryptionPtr
+virStorageEncryptionParseXML(virConnectPtr conn, xmlXPathContextPtr ctxt)
+{
+ xmlNodePtr *nodes = NULL;
+ virStorageEncryptionPtr ret;
+ char *format_str;
+ int format, i, n;
+
+ if (VIR_ALLOC(ret) < 0) {
+ virReportOOMError(conn);
+ return NULL;
+ }
+
+ format_str = virXPathString(conn, "string(./@format)", ctxt);
+ if (format_str == NULL) {
+ virStorageEncryptionReportError(conn, VIR_ERR_XML_ERROR, "%s",
+ _("unknown volume encryption
format"));
+ goto cleanup;
+ }
+ format = virStorageEncryptionFormatTypeFromString(format_str);
+ if (format < 0) {
+ virStorageEncryptionReportError(conn, VIR_ERR_XML_ERROR,
+ _("unknown volume encryption format "
+ "type %s"), format_str);
+ VIR_FREE(format_str);
+ goto cleanup;
+ }
+ VIR_FREE(format_str);
+ ret->format = format;
+
+ n = virXPathNodeSet(conn, "./secret", ctxt, &nodes);
+ if (n < 0){
+ virStorageEncryptionReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot extract volume encryption "
+ "secrets"));
+ goto cleanup;
+ }
+ if (n != 0 && VIR_ALLOC_N(ret->secrets, n) < 0) {
+ virReportOOMError(conn);
+ goto cleanup;
+ }
+ ret->nsecrets = n;
+ for (i = 0; i < n; i++) {
+ ret->secrets[i] = virStorageEncryptionSecretParse(conn, ctxt, nodes[i]);
+ if (ret->secrets[i] == NULL)
+ goto cleanup;
+ }
+ VIR_FREE(nodes);
+
+ return ret;
+
+ cleanup:
+ VIR_FREE(nodes);
+ virStorageEncryptionFree(ret);
+ return NULL;
+}
+
+virStorageEncryptionPtr
+virStorageEncryptionParseNode(virConnectPtr conn,
+ xmlDocPtr xml, xmlNodePtr root)
+{
+ xmlXPathContextPtr ctxt = NULL;
+ virStorageEncryptionPtr enc = NULL;
+
+ if (STRNEQ((const char *) root->name, "encryption")) {
+ virStorageEncryptionReportError(conn, VIR_ERR_XML_ERROR, "%s",
+ _("unknown root element for volume "
+ "encryption information"));
+ goto cleanup;
+ }
+
+ ctxt = xmlXPathNewContext(xml);
+ if (ctxt == NULL) {
+ virReportOOMError(conn);
+ goto cleanup;
+ }
+
+ ctxt->node = root;
+ enc = virStorageEncryptionParseXML(conn, ctxt);
+
+ cleanup:
+ xmlXPathFreeContext(ctxt);
+ return enc;
+}
+#endif /* ! PROXY */
+
+
+static int
+virStorageEncryptionSecretFormat(virConnectPtr conn,
+ virBufferPtr buf,
+ virStorageEncryptionSecretPtr secret)
+{
+ const char *type;
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+ type = virStorageEncryptionSecretTypeTypeToString(secret->type);
+ if (!type) {
+ virStorageEncryptionReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("unexpected volume encryption "
+ "secret type"));
+ return -1;
+ }
+
+ virUUIDFormat(secret->uuid, uuidstr);
+ virBufferVSprintf(buf, " <secret type='%s'
uuid='%s'/>\n", type, uuidstr);
+ return 0;
+}
+
+int
+virStorageEncryptionFormat(virConnectPtr conn,
+ virBufferPtr buf,
+ virStorageEncryptionPtr enc)
+{
+ const char *format;
+ size_t i;
+
+ format = virStorageEncryptionFormatTypeToString(enc->format);
+ if (!format) {
+ virStorageEncryptionReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("unexpected encryption
format"));
+ return -1;
+ }
+ virBufferVSprintf(buf, " <encryption format='%s'>\n",
format);
+
+ for (i = 0; i < enc->nsecrets; i++) {
+ if (virStorageEncryptionSecretFormat(conn, buf, enc->secrets[i]) < 0)
+ return -1;
+ }
+
+ virBufferAddLit(buf, " </encryption>\n");
+
+ return 0;
+}
+
+int
+virStorageGenerateQcowPassphrase(virConnectPtr conn, unsigned char *dest)
+{
+ int fd;
+ size_t i;
+
+ /* 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) {
+ virStorageEncryptionReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot open /dev/urandom"));
+ return -1;
+ }
+ i = 0;
+ while (i < VIR_STORAGE_QCOW_PASSPHRASE_SIZE) {
+ ssize_t r;
+
+ while ((r = read(fd, dest + i, 1)) == -1 && errno == EINTR)
+ ;
+ if (r <= 0) {
+ virStorageEncryptionReportError(conn, VIR_ERR_INTERNAL_ERROR,
"%s",
+ _("Cannot read from
/dev/urandom"));
+ close(fd);
+ return -1;
+ }
+ if (dest[i] >= 0x20 && dest[i] <= 0x7E)
+ i++; /* Got an acceptable character */
+ }
+ close(fd);
+ return 0;
+}
diff --git a/src/util/storage_encryption.h b/src/util/storage_encryption.h
new file mode 100644
index 0000000..a6fe0f7
--- /dev/null
+++ b/src/util/storage_encryption.h
@@ -0,0 +1,80 @@
+/*
+ * storage_encryption.h: volume encryption information
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Red Hat Author: Miloslav Trmač <mitr(a)redhat.com>
+ */
+
+#ifndef __VIR_STORAGE_ENCRYPTION_H__
+#define __VIR_STORAGE_ENCRYPTION_H__
+
+#include "internal.h"
+#include "buf.h"
+#include "util.h"
+
+#include <stdbool.h>
+#include <libxml/tree.h>
+
+enum virStorageEncryptionSecretType {
+ VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE = 0,
+
+ VIR_STORAGE_ENCRYPTION_SECRET_TYPE_LAST
+};
+VIR_ENUM_DECL(virStorageEncryptionSecretType)
+
+typedef struct _virStorageEncryptionSecret virStorageEncryptionSecret;
+typedef virStorageEncryptionSecret *virStorageEncryptionSecretPtr;
+struct _virStorageEncryptionSecret {
+ int type; /* enum virStorageEncryptionSecretType */
+ unsigned char uuid[VIR_UUID_BUFLEN];
+};
+
+enum virStorageEncryptionFormat {
+ /* "default" is only valid for volume creation */
+ VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT = 0,
+ VIR_STORAGE_ENCRYPTION_FORMAT_QCOW, /* Both qcow and qcow2 */
+
+ VIR_STORAGE_ENCRYPTION_FORMAT_LAST,
+};
+VIR_ENUM_DECL(virStorageEncryptionFormat)
+
+typedef struct _virStorageEncryption virStorageEncryption;
+typedef virStorageEncryption *virStorageEncryptionPtr;
+struct _virStorageEncryption {
+ int format; /* enum virStorageEncryptionFormat */
+
+ size_t nsecrets;
+ virStorageEncryptionSecretPtr *secrets;
+};
+
+void virStorageEncryptionFree(virStorageEncryptionPtr enc);
+
+virStorageEncryptionPtr virStorageEncryptionParseNode(virConnectPtr conn,
+ xmlDocPtr xml,
+ xmlNodePtr root);
+int virStorageEncryptionFormat(virConnectPtr conn, virBufferPtr buf,
+ virStorageEncryptionPtr enc);
+
+/* A helper for VIR_STORAGE_ENCRYPTION_FORMAT_QCOW */
+enum {
+ VIR_STORAGE_QCOW_PASSPHRASE_SIZE = 16
+};
+
+int virStorageGenerateQcowPassphrase(virConnectPtr conn, unsigned char *dest);
+
+#endif /* __VIR_STORAGE_ENCRYPTION_H__ */
--
1.6.2.5