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@xxxxxxxxxx> - */ - -#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@xxxxxxxxxx> - */ - -#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@xxxxxxxxxx> + */ + +#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@xxxxxxxxxx> + */ + +#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 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list