[libvirt] [PATCH 15/20] Provide missing passphrase when creating a volume.

Daniel P. Berrange berrange at redhat.com
Thu Aug 27 17:13:04 UTC 2009


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 :|




More information about the libvir-list mailing list