[libvirt] [PATCH 2/7] Move storage encryption code to src/util

Mark McLoughlin markmc at redhat.com
Fri Sep 25 13:27:28 UTC 2009


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@/src/util/buf.c \
 	    @top_srcdir@/src/util/logging.c \
             @top_srcdir@/src/util/memory.c \
+            @top_srcdir@/src/util/storage_encryption.c \
 	    @top_srcdir@/src/util/threads.c  \
             @top_srcdir@/src/util/util.c \
 	    @top_srcdir@/src/util/uuid.c \
             @top_srcdir@/src/util/virterror.c \
             @top_srcdir@/src/conf/capabilities.c \
-            @top_srcdir@/src/conf/storage_encryption_conf.c \
             @top_srcdir@/src/conf/domain_conf.c \
             @top_srcdir@/src/xen/xend_internal.c \
 	    @top_srcdir@/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 at 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 at 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 at 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 at 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




More information about the libvir-list mailing list