[libvirt] [PATCH v2 0/6] Some patches for native TLS encrypted chardev TCP support

v1: http://www.redhat.com/archives/libvir-list/2016-June/msg00824.html Based on Dan's review from patch 4, alter the methodology to use the libvirt qemu config file to add support for a 'default' and (at first) a 'chartcp' (I could use chardev, but I was concerned that would imply more options - udp, unix, etc.). I have started on the authentication portion of this (e.g. a passwordid= parameter pointing at a secret object), but I'm a bit held up by the need to have the secret key patches. I've separated those out and will post a separate set shortly as well to hopefully get some traction. For the chartcp, I went with the 'default' location for the /etc/pki path - that will at least test patch 1. I also tested those locally by removing the code in qemuxml2xmltest.c to specify the specific -vnc or -spice paths as the test has. John Ferlan (6): conf: Add new default TLS X.509 certificate default directory conf: Introduce chartcp_tls_x509_cert_dir qemu: Make qemuBuildShmemBackendStr private qemu: Add cfg pointer to various command line helpers qemu: Add support for TLS X.509 path to TCP chardev backend qemu: Add the ability to hotplug the TLS X.509 environment src/conf/domain_conf.h | 1 + src/qemu/libvirtd_qemu.aug | 9 +- src/qemu/qemu.conf | 52 ++++--- src/qemu/qemu_command.c | 158 ++++++++++++++++++--- src/qemu/qemu_command.h | 12 +- src/qemu/qemu_conf.c | 45 +++++- src/qemu/qemu_conf.h | 5 + src/qemu/qemu_hotplug.c | 29 +++- src/qemu/qemu_monitor_json.c | 9 ++ src/qemu/test_libvirtd_qemu.aug.in | 3 + .../qemuxml2argv-serial-tcp-tlsx509-chardev.args | 33 +++++ .../qemuxml2argv-serial-tcp-tlsx509-chardev.xml | 41 ++++++ tests/qemuxml2argvtest.c | 6 + .../qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml | 50 +++++++ tests/qemuxml2xmltest.c | 1 + 15 files changed, 399 insertions(+), 55 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml -- 2.5.5

Rather that specify perhaps multiple TLS X.509 certificate directories, let's create a "default" directory which can then be used if the service (e.g. for now vnc and spice) does not supply a default directory. Since the default for vnc and spice may have existed before without being supplied, the default check will first check if the service specific path exists and if so, set the cfg entry to that; otherwise, the default will be set to the (now) new defaultTLSx509certdir. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/libvirtd_qemu.aug | 5 ++++- src/qemu/qemu.conf | 36 ++++++++++++++++----------------- src/qemu/qemu_conf.c | 41 ++++++++++++++++++++++++++++++++------ src/qemu/qemu_conf.h | 2 ++ src/qemu/test_libvirtd_qemu.aug.in | 1 + 5 files changed, 60 insertions(+), 25 deletions(-) diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index 8bc23ba..39b3a34 100644 --- a/src/qemu/libvirtd_qemu.aug +++ b/src/qemu/libvirtd_qemu.aug @@ -24,6 +24,8 @@ module Libvirtd_qemu = (* Config entry grouped by function - same order as example config *) + let default_tls_entry = str_entry "default_tls_x509_cert_dir" + let vnc_entry = str_entry "vnc_listen" | bool_entry "vnc_auto_unix_socket" | bool_entry "vnc_tls" @@ -93,7 +95,8 @@ module Libvirtd_qemu = let nvram_entry = str_array_entry "nvram" (* Each entry in the config is one of the following ... *) - let entry = vnc_entry + let entry = default_tls_entry + | vnc_entry | spice_entry | nogfx_entry | remote_display_entry diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index 7964273..72acdfb 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -2,6 +2,16 @@ # All settings described here are optional - if omitted, sensible # defaults are used. +# Use of TLS requires that x509 certificates be issued. The default is +# to keep them in /etc/pki/libvirt-default. This directory must contain +# +# ca-cert.pem - the CA master certificate +# server-cert.pem - the server certificate signed with ca-cert.pem +# server-key.pem - the server private key +# +#default_tls_x509_cert_dir = "/etc/pki/libvirt-default" + + # VNC is configured to listen on 127.0.0.1 by default. # To make it listen on all public interfaces, uncomment # this next option. @@ -32,15 +42,10 @@ #vnc_tls = 1 -# Use of TLS requires that x509 certificates be issued. The -# default it to keep them in /etc/pki/libvirt-vnc. This directory -# must contain -# -# ca-cert.pem - the CA master certificate -# server-cert.pem - the server certificate signed with ca-cert.pem -# server-key.pem - the server private key -# -# This option allows the certificate directory to be changed +# In order to override the default TLS certificate location for +# vnc certificates, supply a valid path to the certificate directory. +# If the provided path does not exist then the default_tls_x509_cert_dir +# path will be used. # #vnc_tls_x509_cert_dir = "/etc/pki/libvirt-vnc" @@ -117,15 +122,10 @@ #spice_tls = 1 -# Use of TLS requires that x509 certificates be issued. The -# default it to keep them in /etc/pki/libvirt-spice. This directory -# must contain -# -# ca-cert.pem - the CA master certificate -# server-cert.pem - the server certificate signed with ca-cert.pem -# server-key.pem - the server private key -# -# This option allows the certificate directory to be changed. +# In order to override the default TLS certificate location for +# spice certificates, supply a valid path to the certificate directory. +# If the provided path does not exist then the default_tls_x509_cert_dir +# path will be used. # #spice_tls_x509_cert_dir = "/etc/pki/libvirt-spice" diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 6dfa738..118ca63 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -236,19 +236,44 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged) if (virAsprintf(&cfg->autostartDir, "%s/qemu/autostart", cfg->configBaseDir) < 0) goto error; - - if (VIR_STRDUP(cfg->vncListen, "127.0.0.1") < 0) + /* Set the default directory to find TLS X.509 certificates. + * This will then be used as a fallback if the service specific + * directory doesn't exist (although we don't check if this exists). + */ + if (VIR_STRDUP(cfg->defaultTLSx509certdir, + SYSCONFDIR "/pki/libvirt-default") < 0) goto error; - if (VIR_STRDUP(cfg->vncTLSx509certdir, SYSCONFDIR "/pki/libvirt-vnc") < 0) + if (VIR_STRDUP(cfg->vncListen, "127.0.0.1") < 0) goto error; if (VIR_STRDUP(cfg->spiceListen, "127.0.0.1") < 0) goto error; - if (VIR_STRDUP(cfg->spiceTLSx509certdir, - SYSCONFDIR "/pki/libvirt-spice") < 0) - goto error; + /* + * If a "SYSCONFDIR" + "pki/libvirt-<val>" exists, then assume someone + * has created a val specific area to place service specific certificates. + * + * If the service specific directory doesn't exist, 'assume' that the + * user has created and populated the "SYSCONFDIR" + "pki/libvirt-default". + */ +#define SET_TLS_X509_CERT_DEFAULT(val) \ + do { \ + if (virFileExists(SYSCONFDIR "/pki/libvirt-"#val)) { \ + if (VIR_STRDUP(cfg->val ## TLSx509certdir, \ + SYSCONFDIR "/pki/libvirt-"#val) < 0) \ + goto error; \ + } else { \ + if (VIR_STRDUP(cfg->val ## TLSx509certdir, \ + cfg->defaultTLSx509certdir) < 0) \ + goto error; \ + } \ + } while (false); + + SET_TLS_X509_CERT_DEFAULT(vnc); + SET_TLS_X509_CERT_DEFAULT(spice); + +#undef SET_TLS_X509_CERT_DEFAULT cfg->remotePortMin = QEMU_REMOTE_PORT_MIN; cfg->remotePortMax = QEMU_REMOTE_PORT_MAX; @@ -333,6 +358,8 @@ static void virQEMUDriverConfigDispose(void *obj) VIR_FREE(cfg->channelTargetDir); VIR_FREE(cfg->nvramDir); + VIR_FREE(cfg->defaultTLSx509certdir); + VIR_FREE(cfg->vncTLSx509certdir); VIR_FREE(cfg->vncListen); VIR_FREE(cfg->vncPassword); @@ -445,6 +472,8 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, goto cleanup; \ } + GET_VALUE_STR("default_tls_x509_cert_dir", cfg->defaultTLSx509certdir); + GET_VALUE_BOOL("vnc_auto_unix_socket", cfg->vncAutoUnixSocket); GET_VALUE_BOOL("vnc_tls", cfg->vncTLS); GET_VALUE_BOOL("vnc_tls_x509_verify", cfg->vncTLSx509verify); diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index a09c81d..db22433 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -109,6 +109,8 @@ struct _virQEMUDriverConfig { char *channelTargetDir; char *nvramDir; + char *defaultTLSx509certdir; + bool vncAutoUnixSocket; bool vncTLS; bool vncTLSx509verify; diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in index c4d4f19..a4c9737 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -2,6 +2,7 @@ module Test_libvirtd_qemu = ::CONFIG:: test Libvirtd_qemu.lns get conf = +{ "default_tls_x509_cert_dir" = "/etc/pki/libvirt-default" } { "vnc_listen" = "0.0.0.0" } { "vnc_auto_unix_socket" = "1" } { "vnc_tls" = "1" } -- 2.5.5

On Thu, Jun 16, 2016 at 06:42:22AM -0400, John Ferlan wrote:
Rather that specify perhaps multiple TLS X.509 certificate directories, let's create a "default" directory which can then be used if the service (e.g. for now vnc and spice) does not supply a default directory.
Since the default for vnc and spice may have existed before without being supplied, the default check will first check if the service specific path exists and if so, set the cfg entry to that; otherwise, the default will be set to the (now) new defaultTLSx509certdir.
Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/libvirtd_qemu.aug | 5 ++++- src/qemu/qemu.conf | 36 ++++++++++++++++----------------- src/qemu/qemu_conf.c | 41 ++++++++++++++++++++++++++++++++------ src/qemu/qemu_conf.h | 2 ++ src/qemu/test_libvirtd_qemu.aug.in | 1 + 5 files changed, 60 insertions(+), 25 deletions(-)
diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index 8bc23ba..39b3a34 100644 --- a/src/qemu/libvirtd_qemu.aug +++ b/src/qemu/libvirtd_qemu.aug @@ -24,6 +24,8 @@ module Libvirtd_qemu =
(* Config entry grouped by function - same order as example config *) + let default_tls_entry = str_entry "default_tls_x509_cert_dir" + let vnc_entry = str_entry "vnc_listen" | bool_entry "vnc_auto_unix_socket" | bool_entry "vnc_tls" @@ -93,7 +95,8 @@ module Libvirtd_qemu = let nvram_entry = str_array_entry "nvram"
(* Each entry in the config is one of the following ... *) - let entry = vnc_entry + let entry = default_tls_entry + | vnc_entry | spice_entry | nogfx_entry | remote_display_entry diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index 7964273..72acdfb 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -2,6 +2,16 @@ # All settings described here are optional - if omitted, sensible # defaults are used.
+# Use of TLS requires that x509 certificates be issued. The default is +# to keep them in /etc/pki/libvirt-default. This directory must contain +# +# ca-cert.pem - the CA master certificate +# server-cert.pem - the server certificate signed with ca-cert.pem +# server-key.pem - the server private key +#
Nit-pick, latest QEMU now also looks for an (optional) dh-params.pem file
+#default_tls_x509_cert_dir = "/etc/pki/libvirt-default"
I wonder if it would be better to say "/etc/pki/qemu" as our default location since this isn't really stuff used by libvirt.
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 6dfa738..118ca63 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -236,19 +236,44 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged) if (virAsprintf(&cfg->autostartDir, "%s/qemu/autostart", cfg->configBaseDir) < 0) goto error;
- - if (VIR_STRDUP(cfg->vncListen, "127.0.0.1") < 0) + /* Set the default directory to find TLS X.509 certificates. + * This will then be used as a fallback if the service specific + * directory doesn't exist (although we don't check if this exists). + */ + if (VIR_STRDUP(cfg->defaultTLSx509certdir, + SYSCONFDIR "/pki/libvirt-default") < 0)
s/libvirt-default/qemu/
goto error;
- if (VIR_STRDUP(cfg->vncTLSx509certdir, SYSCONFDIR "/pki/libvirt-vnc") < 0) + if (VIR_STRDUP(cfg->vncListen, "127.0.0.1") < 0) goto error;
if (VIR_STRDUP(cfg->spiceListen, "127.0.0.1") < 0) goto error;
- if (VIR_STRDUP(cfg->spiceTLSx509certdir, - SYSCONFDIR "/pki/libvirt-spice") < 0) - goto error; + /* + * If a "SYSCONFDIR" + "pki/libvirt-<val>" exists, then assume someone + * has created a val specific area to place service specific certificates. + * + * If the service specific directory doesn't exist, 'assume' that the + * user has created and populated the "SYSCONFDIR" + "pki/libvirt-default". + */ +#define SET_TLS_X509_CERT_DEFAULT(val) \ + do { \ + if (virFileExists(SYSCONFDIR "/pki/libvirt-"#val)) { \ + if (VIR_STRDUP(cfg->val ## TLSx509certdir, \ + SYSCONFDIR "/pki/libvirt-"#val) < 0) \ + goto error; \ + } else { \ + if (VIR_STRDUP(cfg->val ## TLSx509certdir, \ + cfg->defaultTLSx509certdir) < 0) \ + goto error; \ + } \ + } while (false); + + SET_TLS_X509_CERT_DEFAULT(vnc); + SET_TLS_X509_CERT_DEFAULT(spice); + +#undef SET_TLS_X509_CERT_DEFAULT
cfg->remotePortMin = QEMU_REMOTE_PORT_MIN; cfg->remotePortMax = QEMU_REMOTE_PORT_MAX; @@ -333,6 +358,8 @@ static void virQEMUDriverConfigDispose(void *obj) VIR_FREE(cfg->channelTargetDir); VIR_FREE(cfg->nvramDir);
+ VIR_FREE(cfg->defaultTLSx509certdir); + VIR_FREE(cfg->vncTLSx509certdir); VIR_FREE(cfg->vncListen); VIR_FREE(cfg->vncPassword); @@ -445,6 +472,8 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, goto cleanup; \ }
+ GET_VALUE_STR("default_tls_x509_cert_dir", cfg->defaultTLSx509certdir); + GET_VALUE_BOOL("vnc_auto_unix_socket", cfg->vncAutoUnixSocket); GET_VALUE_BOOL("vnc_tls", cfg->vncTLS); GET_VALUE_BOOL("vnc_tls_x509_verify", cfg->vncTLSx509verify); diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index a09c81d..db22433 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -109,6 +109,8 @@ struct _virQEMUDriverConfig { char *channelTargetDir; char *nvramDir;
+ char *defaultTLSx509certdir; + bool vncAutoUnixSocket; bool vncTLS; bool vncTLSx509verify; diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in index c4d4f19..a4c9737 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -2,6 +2,7 @@ module Test_libvirtd_qemu = ::CONFIG::
test Libvirtd_qemu.lns get conf = +{ "default_tls_x509_cert_dir" = "/etc/pki/libvirt-default" }
s/libvirt-default/qemu/
{ "vnc_listen" = "0.0.0.0" } { "vnc_auto_unix_socket" = "1" } { "vnc_tls" = "1" } -- 2.5.5
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
ACK with those minor tweaks. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Thu, Jun 16, 2016 at 06:42:22AM -0400, John Ferlan wrote:
Rather that specify perhaps multiple TLS X.509 certificate directories, let's create a "default" directory which can then be used if the service (e.g. for now vnc and spice) does not supply a default directory.
Since the default for vnc and spice may have existed before without being supplied, the default check will first check if the service specific path exists and if so, set the cfg entry to that; otherwise, the default will be set to the (now) new defaultTLSx509certdir.
Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/libvirtd_qemu.aug | 5 ++++- src/qemu/qemu.conf | 36 ++++++++++++++++----------------- src/qemu/qemu_conf.c | 41 ++++++++++++++++++++++++++++++++------ src/qemu/qemu_conf.h | 2 ++ src/qemu/test_libvirtd_qemu.aug.in | 1 + 5 files changed, 60 insertions(+), 25 deletions(-)
diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index 8bc23ba..39b3a34 100644 --- a/src/qemu/libvirtd_qemu.aug +++ b/src/qemu/libvirtd_qemu.aug @@ -24,6 +24,8 @@ module Libvirtd_qemu =
(* Config entry grouped by function - same order as example config *) + let default_tls_entry = str_entry "default_tls_x509_cert_dir" + let vnc_entry = str_entry "vnc_listen" | bool_entry "vnc_auto_unix_socket" | bool_entry "vnc_tls" @@ -93,7 +95,8 @@ module Libvirtd_qemu = let nvram_entry = str_array_entry "nvram"
(* Each entry in the config is one of the following ... *) - let entry = vnc_entry + let entry = default_tls_entry + | vnc_entry | spice_entry | nogfx_entry | remote_display_entry diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index 7964273..72acdfb 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -2,6 +2,16 @@ # All settings described here are optional - if omitted, sensible # defaults are used.
+# Use of TLS requires that x509 certificates be issued. The default is +# to keep them in /etc/pki/libvirt-default. This directory must contain +# +# ca-cert.pem - the CA master certificate +# server-cert.pem - the server certificate signed with ca-cert.pem +# server-key.pem - the server private key +# +#default_tls_x509_cert_dir = "/etc/pki/libvirt-default"
Oh, just remembered we should add a default_tls_x509_verify = 1|0 to control how we set the 'verify-peer' config option on the TLS certs (ie whether we mandate the client provide a x509 cert as a crude form of authorization, as opposed to letting any client conncect). Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Add a new TLS X.509 certificate type - "chartcp" (a/k/a charTCP). This will handle the creation of a TLS certificate capability (and possibly repository) for properly configured character device TCP backends. Unlike the vnc and spice there is no "listen" or "passwd" associated. The credentials will be handled via a libvirt secret provided to a specific backend. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/libvirtd_qemu.aug | 4 ++ src/qemu/qemu.conf | 16 +++++++ src/qemu/qemu_conf.c | 4 ++ src/qemu/qemu_conf.h | 3 ++ src/qemu/test_libvirtd_qemu.aug.in | 2 + .../qemuxml2argv-serial-tcp-tlsx509-chardev.xml | 41 ++++++++++++++++++ .../qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml | 50 ++++++++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 8 files changed, 121 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index 39b3a34..e70d38d 100644 --- a/src/qemu/libvirtd_qemu.aug +++ b/src/qemu/libvirtd_qemu.aug @@ -44,6 +44,9 @@ module Libvirtd_qemu = | bool_entry "spice_sasl" | str_entry "spice_sasl_dir" + let chartcp_entry = bool_entry "chartcp_tls" + | str_entry "chartcp_tls_x509_cert_dir" + let nogfx_entry = bool_entry "nographics_allow_host_audio" let remote_display_entry = int_entry "remote_display_port_min" @@ -98,6 +101,7 @@ module Libvirtd_qemu = let entry = default_tls_entry | vnc_entry | spice_entry + | chartcp_entry | nogfx_entry | remote_display_entry | security_entry diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index 72acdfb..fa00be4 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -166,6 +166,22 @@ # #spice_sasl_dir = "/some/directory/sasl2" +# Enable use of TLS encryption on the chardev TCP transports. +# +# It is necessary to setup CA and issue a server certificate +# before enabling this. +# +#chartcp_tls = 1 + + +# In order to override the default TLS certificate location for character +# device TCP certificates, supply a valid path to the certificate directory. +# If the provided path does not exist then the default_tls_x509_cert_dir +# path will be used. +# +#chartcp_tls_x509_cert_dir = "/etc/pki/libvirt-chartcp" + + # By default, if no graphical front end is configured, libvirt will disable # QEMU audio output since directly talking to alsa/pulseaudio may not work diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 118ca63..b4a9968 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -272,6 +272,7 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged) SET_TLS_X509_CERT_DEFAULT(vnc); SET_TLS_X509_CERT_DEFAULT(spice); + SET_TLS_X509_CERT_DEFAULT(charTCP); #undef SET_TLS_X509_CERT_DEFAULT @@ -370,6 +371,8 @@ static void virQEMUDriverConfigDispose(void *obj) VIR_FREE(cfg->spicePassword); VIR_FREE(cfg->spiceSASLdir); + VIR_FREE(cfg->charTCPTLSx509certdir); + while (cfg->nhugetlbfs) { cfg->nhugetlbfs--; VIR_FREE(cfg->hugetlbfs[cfg->nhugetlbfs].mnt_dir); @@ -537,6 +540,7 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_STR("spice_password", cfg->spicePassword); GET_VALUE_BOOL("spice_auto_unix_socket", cfg->spiceAutoUnixSocket); + GET_VALUE_STR("chartcp_tls_x509_cert_dir", cfg->charTCPTLSx509certdir); GET_VALUE_ULONG("remote_websocket_port_min", cfg->webSocketPortMin); if (cfg->webSocketPortMin < QEMU_WEBSOCKET_PORT_MIN) { diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index db22433..5054325 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -128,6 +128,9 @@ struct _virQEMUDriverConfig { char *spicePassword; bool spiceAutoUnixSocket; + bool charTCPTLS; + char *charTCPTLSx509certdir; + int remotePortMin; int remotePortMax; diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in index a4c9737..b04324e 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -19,6 +19,8 @@ module Test_libvirtd_qemu = { "spice_password" = "XYZ12345" } { "spice_sasl" = "1" } { "spice_sasl_dir" = "/some/directory/sasl2" } +{ "chartcp_tls" = "1" } +{ "chartcp_tls_x509_cert_dir" = "/etc/pki/libvirt-chartcp" } { "nographics_allow_host_audio" = "1" } { "remote_display_port_min" = "5900" } { "remote_display_port_max" = "65535" } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml new file mode 100644 index 0000000..1618b02 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml @@ -0,0 +1,41 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <serial type='udp'> + <source mode='bind' host='127.0.0.1' service='1111'/> + <source mode='connect' host='127.0.0.1' service='2222'/> + <target port='0'/> + </serial> + <serial type='tcp'> + <source mode='connect' host='127.0.0.1' service='5555'/> + <protocol type='raw'/> + <target port='0'/> + </serial> + <console type='udp'> + <source mode='bind' host='127.0.0.1' service='1111'/> + <source mode='connect' host='127.0.0.1' service='2222'/> + <target type='serial' port='0'/> + </console> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml new file mode 100644 index 0000000..832e2a2 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml @@ -0,0 +1,50 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <serial type='udp'> + <source mode='bind' host='127.0.0.1' service='1111'/> + <source mode='connect' host='127.0.0.1' service='2222'/> + <target port='0'/> + </serial> + <serial type='tcp'> + <source mode='connect' host='127.0.0.1' service='5555'/> + <protocol type='raw'/> + <target port='0'/> + </serial> + <console type='udp'> + <source mode='bind' host='127.0.0.1' service='1111'/> + <source mode='connect' host='127.0.0.1' service='2222'/> + <target type='serial' port='0'/> + </console> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 7db9cb7..3064458 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -483,6 +483,7 @@ mymain(void) DO_TEST("serial-tcp"); DO_TEST("serial-udp"); DO_TEST("serial-tcp-telnet"); + DO_TEST("serial-tcp-tlsx509-chardev"); DO_TEST("serial-many"); DO_TEST("serial-spiceport"); DO_TEST("serial-spiceport-nospice"); -- 2.5.5

On Thu, Jun 16, 2016 at 06:42:23AM -0400, John Ferlan wrote:
Add a new TLS X.509 certificate type - "chartcp" (a/k/a charTCP). This will handle the creation of a TLS certificate capability (and possibly repository) for properly configured character device TCP backends.
Unlike the vnc and spice there is no "listen" or "passwd" associated. The credentials will be handled via a libvirt secret provided to a specific backend.
Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/libvirtd_qemu.aug | 4 ++ src/qemu/qemu.conf | 16 +++++++ src/qemu/qemu_conf.c | 4 ++ src/qemu/qemu_conf.h | 3 ++ src/qemu/test_libvirtd_qemu.aug.in | 2 + .../qemuxml2argv-serial-tcp-tlsx509-chardev.xml | 41 ++++++++++++++++++ .../qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml | 50 ++++++++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 8 files changed, 121 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml
diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index 39b3a34..e70d38d 100644 --- a/src/qemu/libvirtd_qemu.aug +++ b/src/qemu/libvirtd_qemu.aug @@ -44,6 +44,9 @@ module Libvirtd_qemu = | bool_entry "spice_sasl" | str_entry "spice_sasl_dir"
+ let chartcp_entry = bool_entry "chartcp_tls" + | str_entry "chartcp_tls_x509_cert_dir" + let nogfx_entry = bool_entry "nographics_allow_host_audio"
let remote_display_entry = int_entry "remote_display_port_min" @@ -98,6 +101,7 @@ module Libvirtd_qemu = let entry = default_tls_entry | vnc_entry | spice_entry + | chartcp_entry | nogfx_entry | remote_display_entry | security_entry diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index 72acdfb..fa00be4 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -166,6 +166,22 @@ # #spice_sasl_dir = "/some/directory/sasl2"
+# Enable use of TLS encryption on the chardev TCP transports. +# +# It is necessary to setup CA and issue a server certificate +# before enabling this. +# +#chartcp_tls = 1 + + +# In order to override the default TLS certificate location for character +# device TCP certificates, supply a valid path to the certificate directory. +# If the provided path does not exist then the default_tls_x509_cert_dir +# path will be used. +# +#chartcp_tls_x509_cert_dir = "/etc/pki/libvirt-chartcp"
I'd suggest we just say 'chardev' instead of 'chartcp', as it is conceivable that we could use TLS with non-TCP chardevs in the future. I'm wondering if we should use /etc/pki/qemu-chardev as the default location too Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

It's not used externally anywhere else Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_command.c | 2 +- src/qemu/qemu_command.h | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index cbd40ea..4719881 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8273,7 +8273,7 @@ qemuBuildShmemDevStr(virDomainDefPtr def, return NULL; } -char * +static char * qemuBuildShmemBackendStr(virLogManagerPtr logManager, virCommandPtr cmd, virDomainDefPtr def, diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index f0ffe21..9ff4edb 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -142,12 +142,6 @@ int qemuBuildRNGBackendProps(virDomainRNGDefPtr rng, char *qemuBuildShmemDevStr(virDomainDefPtr def, virDomainShmemDefPtr shmem, virQEMUCapsPtr qemuCaps); -char *qemuBuildShmemBackendStr(virLogManagerPtr logManager, - virCommandPtr cmd, - virDomainDefPtr def, - virDomainShmemDefPtr shmem, - virQEMUCapsPtr qemuCaps); - int qemuOpenPCIConfig(virDomainHostdevDefPtr dev); -- 2.5.5

On Thu, Jun 16, 2016 at 06:42:24AM -0400, John Ferlan wrote:
It's not used externally anywhere else
Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_command.c | 2 +- src/qemu/qemu_command.h | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Soon at least one of them will need to grab something out of the qemu config structure Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_command.c | 56 ++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4719881..4a8def1 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4685,6 +4685,7 @@ qemuBuildChrChardevFileStr(virLogManagerPtr logManager, static char * qemuBuildChrChardevStr(virLogManagerPtr logManager, virCommandPtr cmd, + virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED, const virDomainDef *def, const virDomainChrSourceDef *dev, const char *alias, @@ -5081,6 +5082,7 @@ qemuBuildChrArgStr(const virDomainChrSourceDef *dev, static int qemuBuildMonitorCommandLine(virLogManagerPtr logManager, virCommandPtr cmd, + virQEMUDriverConfigPtr cfg, virDomainDefPtr def, virQEMUCapsPtr qemuCaps, const virDomainChrSourceDef *monitor_chr, @@ -5094,7 +5096,7 @@ qemuBuildMonitorCommandLine(virLogManagerPtr logManager, /* Use -chardev if it's available */ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV)) { - if (!(chrdev = qemuBuildChrChardevStr(logManager, cmd, def, + if (!(chrdev = qemuBuildChrChardevStr(logManager, cmd, cfg, def, monitor_chr, "monitor", qemuCaps))) return -1; @@ -5239,6 +5241,7 @@ qemuBuildSclpDevStr(virDomainChrDefPtr dev) static int qemuBuildRNGBackendChrdevStr(virLogManagerPtr logManager, virCommandPtr cmd, + virQEMUDriverConfigPtr cfg, const virDomainDef *def, virDomainRNGDefPtr rng, virQEMUCapsPtr qemuCaps, @@ -5253,7 +5256,7 @@ qemuBuildRNGBackendChrdevStr(virLogManagerPtr logManager, return 0; case VIR_DOMAIN_RNG_BACKEND_EGD: - if (!(*chr = qemuBuildChrChardevStr(logManager, cmd, def, + if (!(*chr = qemuBuildChrChardevStr(logManager, cmd, cfg, def, rng->source.chardev, rng->info.alias, qemuCaps))) return -1; @@ -5401,6 +5404,7 @@ qemuBuildRNGDevStr(const virDomainDef *def, static int qemuBuildRNGCommandLine(virLogManagerPtr logManager, virCommandPtr cmd, + virQEMUDriverConfigPtr cfg, const virDomainDef *def, virQEMUCapsPtr qemuCaps) { @@ -5417,7 +5421,7 @@ qemuBuildRNGCommandLine(virLogManagerPtr logManager, } /* possibly add character device for backend */ - if (qemuBuildRNGBackendChrdevStr(logManager, cmd, def, + if (qemuBuildRNGBackendChrdevStr(logManager, cmd, cfg, def, rng, qemuCaps, &tmp) < 0) return -1; @@ -8089,6 +8093,7 @@ qemuBuildNetCommandLine(virCommandPtr cmd, static int qemuBuildSmartcardCommandLine(virLogManagerPtr logManager, virCommandPtr cmd, + virQEMUDriverConfigPtr cfg, const virDomainDef *def, virQEMUCapsPtr qemuCaps) { @@ -8174,7 +8179,7 @@ qemuBuildSmartcardCommandLine(virLogManagerPtr logManager, return -1; } - if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, def, + if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, cfg, def, &smartcard->data.passthru, smartcard->info.alias, qemuCaps))) { @@ -8276,6 +8281,7 @@ qemuBuildShmemDevStr(virDomainDefPtr def, static char * qemuBuildShmemBackendStr(virLogManagerPtr logManager, virCommandPtr cmd, + virQEMUDriverConfigPtr cfg, virDomainDefPtr def, virDomainShmemDefPtr shmem, virQEMUCapsPtr qemuCaps) @@ -8288,7 +8294,7 @@ qemuBuildShmemBackendStr(virLogManagerPtr logManager, shmem->name) < 0) return NULL; - devstr = qemuBuildChrChardevStr(logManager, cmd, def, + devstr = qemuBuildChrChardevStr(logManager, cmd, cfg, def, &shmem->server.chr, shmem->info.alias, qemuCaps); @@ -8298,6 +8304,7 @@ qemuBuildShmemBackendStr(virLogManagerPtr logManager, static int qemuBuildShmemCommandLine(virLogManagerPtr logManager, virCommandPtr cmd, + virQEMUDriverConfigPtr cfg, virDomainDefPtr def, virDomainShmemDefPtr shmem, virQEMUCapsPtr qemuCaps) @@ -8310,7 +8317,7 @@ qemuBuildShmemCommandLine(virLogManagerPtr logManager, VIR_FREE(devstr); if (shmem->server.enabled) { - if (!(devstr = qemuBuildShmemBackendStr(logManager, cmd, def, + if (!(devstr = qemuBuildShmemBackendStr(logManager, cmd, cfg, def, shmem, qemuCaps))) return -1; @@ -8341,6 +8348,7 @@ qemuBuildChrDeviceCommandLine(virCommandPtr cmd, static int qemuBuildSerialCommandLine(virLogManagerPtr logManager, virCommandPtr cmd, + virQEMUDriverConfigPtr cfg, const virDomainDef *def, virQEMUCapsPtr qemuCaps) { @@ -8363,7 +8371,7 @@ qemuBuildSerialCommandLine(virLogManagerPtr logManager, /* Use -chardev with -device if they are available */ if (virQEMUCapsSupportsChardev(def, qemuCaps, serial)) { - if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, def, + if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, cfg, def, &serial->source, serial->info.alias, qemuCaps))) @@ -8390,6 +8398,7 @@ qemuBuildSerialCommandLine(virLogManagerPtr logManager, static int qemuBuildParallelsCommandLine(virLogManagerPtr logManager, virCommandPtr cmd, + virQEMUDriverConfigPtr cfg, const virDomainDef *def, virQEMUCapsPtr qemuCaps) { @@ -8401,7 +8410,7 @@ qemuBuildParallelsCommandLine(virLogManagerPtr logManager, /* Use -chardev with -device if they are available */ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV)) { - if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, def, + if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, cfg, def, ¶llel->source, parallel->info.alias, qemuCaps))) @@ -8429,6 +8438,7 @@ qemuBuildParallelsCommandLine(virLogManagerPtr logManager, static int qemuBuildChannelsCommandLine(virLogManagerPtr logManager, virCommandPtr cmd, + virQEMUDriverConfigPtr cfg, const virDomainDef *def, virQEMUCapsPtr qemuCaps) { @@ -8446,7 +8456,7 @@ qemuBuildChannelsCommandLine(virLogManagerPtr logManager, return -1; } - if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, def, + if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, cfg, def, &channel->source, channel->info.alias, qemuCaps))) @@ -8469,7 +8479,7 @@ qemuBuildChannelsCommandLine(virLogManagerPtr logManager, * the newer -chardev interface. */ ; } else { - if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, def, + if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, cfg, def, &channel->source, channel->info.alias, qemuCaps))) @@ -8492,6 +8502,7 @@ qemuBuildChannelsCommandLine(virLogManagerPtr logManager, static int qemuBuildConsoleCommandLine(virLogManagerPtr logManager, virCommandPtr cmd, + virQEMUDriverConfigPtr cfg, const virDomainDef *def, virQEMUCapsPtr qemuCaps) { @@ -8511,7 +8522,7 @@ qemuBuildConsoleCommandLine(virLogManagerPtr logManager, return -1; } - if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, def, + if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, cfg, def, &console->source, console->info.alias, qemuCaps))) @@ -8525,7 +8536,7 @@ qemuBuildConsoleCommandLine(virLogManagerPtr logManager, break; case VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO: - if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, def, + if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, cfg, def, &console->source, console->info.alias, qemuCaps))) @@ -8644,6 +8655,7 @@ qemuBuildRedirdevDevStr(const virDomainDef *def, static int qemuBuildRedirdevCommandLine(virLogManagerPtr logManager, virCommandPtr cmd, + virQEMUDriverConfigPtr cfg, const virDomainDef *def, virQEMUCapsPtr qemuCaps) { @@ -8653,7 +8665,7 @@ qemuBuildRedirdevCommandLine(virLogManagerPtr logManager, virDomainRedirdevDefPtr redirdev = def->redirdevs[i]; char *devstr; - if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, def, + if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, cfg, def, &redirdev->source.chr, redirdev->info.alias, qemuCaps))) { @@ -9227,7 +9239,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, if (qemuBuildSgaCommandLine(cmd, def, qemuCaps) < 0) goto error; - if (qemuBuildMonitorCommandLine(logManager, cmd, def, + if (qemuBuildMonitorCommandLine(logManager, cmd, cfg, def, qemuCaps, monitor_chr, monitor_json) < 0) goto error; @@ -9261,19 +9273,19 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, &bootHostdevNet) < 0) goto error; - if (qemuBuildSmartcardCommandLine(logManager, cmd, def, qemuCaps) < 0) + if (qemuBuildSmartcardCommandLine(logManager, cmd, cfg, def, qemuCaps) < 0) goto error; - if (qemuBuildSerialCommandLine(logManager, cmd, def, qemuCaps) < 0) + if (qemuBuildSerialCommandLine(logManager, cmd, cfg, def, qemuCaps) < 0) goto error; - if (qemuBuildParallelsCommandLine(logManager, cmd, def, qemuCaps) < 0) + if (qemuBuildParallelsCommandLine(logManager, cmd, cfg, def, qemuCaps) < 0) goto error; - if (qemuBuildChannelsCommandLine(logManager, cmd, def, qemuCaps) < 0) + if (qemuBuildChannelsCommandLine(logManager, cmd, cfg, def, qemuCaps) < 0) goto error; - if (qemuBuildConsoleCommandLine(logManager, cmd, def, qemuCaps) < 0) + if (qemuBuildConsoleCommandLine(logManager, cmd, cfg, def, qemuCaps) < 0) goto error; if (qemuBuildTPMCommandLine(cmd, def, qemuCaps) < 0) @@ -9297,7 +9309,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, if (qemuBuildWatchdogCommandLine(cmd, def, qemuCaps) < 0) goto error; - if (qemuBuildRedirdevCommandLine(logManager, cmd, def, qemuCaps) < 0) + if (qemuBuildRedirdevCommandLine(logManager, cmd, cfg, def, qemuCaps) < 0) goto error; if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps, &bootHostdevNet) < 0) @@ -9309,7 +9321,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, if (qemuBuildMemballoonCommandLine(cmd, def, qemuCaps) < 0) goto error; - if (qemuBuildRNGCommandLine(logManager, cmd, def, qemuCaps) < 0) + if (qemuBuildRNGCommandLine(logManager, cmd, cfg, def, qemuCaps) < 0) goto error; if (qemuBuildNVRAMCommandLine(cmd, def, qemuCaps) < 0) @@ -9345,7 +9357,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, goto error; for (i = 0; i < def->nshmems; i++) { - if (qemuBuildShmemCommandLine(logManager, cmd, + if (qemuBuildShmemCommandLine(logManager, cmd, cfg, def, def->shmems[i], qemuCaps)) goto error; } -- 2.5.5

On Thu, Jun 16, 2016 at 06:42:25AM -0400, John Ferlan wrote:
Soon at least one of them will need to grab something out of the qemu config structure
Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_command.c | 56 ++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 22 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

When building a chardev device string for tcp, add the necessary pieces to access provide the TLS X.509 path to qemu. This includes generating the 'tls-creds-x509' object and then adding the 'tls-creds' parameter to the VIR_DOMAIN_CHR_TYPE_TCP command line. Finally add the tests for the qemu command line. This test will make use of the "new(ish)" /etc/pki/libvirt-default setting for a TLS certificate environment by *not* "resetting" the charTCPTLSx509certdir prior to running the test. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_command.c | 102 ++++++++++++++++++++- .../qemuxml2argv-serial-tcp-tlsx509-chardev.args | 33 +++++++ tests/qemuxml2argvtest.c | 6 ++ 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4a8def1..815785c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -701,6 +701,97 @@ qemuBuildRBDSecinfoURI(virBufferPtr buf, } +/* qemuBuildTLSx509BackendProps: + * @tlspath: path to the TLS credentials + * @listen: boolen listen for client or server setting + * @qemuCaps: capabilities + * @propsret: json properties to return + * + * Create a backend string for the tls-creds-x509 object. + * + * Returns 0 on success, -1 on failure with error set. + */ +static int +qemuBuildTLSx509BackendProps(const char *tlspath, + bool listen, + virQEMUCapsPtr qemuCaps, + virJSONValuePtr *propsret) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *path = NULL; + int ret = -1; + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_TLS_CREDS_X509)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("tls-creds-x509 not supported in this QEMU binary")); + return -1; + } + + qemuBufferEscapeComma(&buf, tlspath); + if (virBufferCheckError(&buf) < 0) + goto cleanup; + path = virBufferContentAndReset(&buf); + + if (virJSONValueObjectCreate(propsret, + "s:dir", path, + "s:endpoint", (listen ? "server": "client"), + NULL) < 0) + goto cleanup; + + ret = 0; + + cleanup: + virBufferFreeAndReset(&buf); + VIR_FREE(path); + return ret; +} + + +/* qemuBuildTLSx509CommandLine: + * @cmd: Pointer to command + * @tlspath: path to the TLS credentials + * @listen: boolen listen for client or server setting + * @inalias: Alias for the parent (this code will add a "_tls0" to alias) + * @qemuCaps: capabilities + * + * Create the command line for a TLS object + * + * Returns 0 on success, -1 on failure with error set. + */ +static int +qemuBuildTLSx509CommandLine(virCommandPtr cmd, + const char *tlspath, + bool listen, + const char *inalias, + virQEMUCapsPtr qemuCaps) +{ + int ret = -1; + char *alias = NULL; + virJSONValuePtr props = NULL; + char *tmp = NULL; + + if (qemuBuildTLSx509BackendProps(tlspath, listen, qemuCaps, &props) < 0) + return -1; + + if (virAsprintf(&alias, "obj%s_tls0", inalias) < 0) + goto cleanup; + + if (!(tmp = virQEMUBuildObjectCommandlineFromJSON("tls-creds-x509", + alias, props))) + goto cleanup; + + virCommandAddArgList(cmd, "-object", tmp, NULL); + + ret = 0; + + cleanup: + virJSONValueFree(props); + VIR_FREE(alias); + VIR_FREE(tmp); + return ret; +} + + #define QEMU_DEFAULT_NBD_PORT "10809" static char * @@ -4685,7 +4776,7 @@ qemuBuildChrChardevFileStr(virLogManagerPtr logManager, static char * qemuBuildChrChardevStr(virLogManagerPtr logManager, virCommandPtr cmd, - virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED, + virQEMUDriverConfigPtr cfg, const virDomainDef *def, const virDomainChrSourceDef *dev, const char *alias, @@ -4768,6 +4859,15 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, dev->data.tcp.service, telnet ? ",telnet" : "", dev->data.tcp.listen ? ",server,nowait" : ""); + + if (cfg->charTCPTLS) { + if (qemuBuildTLSx509CommandLine(cmd, cfg->charTCPTLSx509certdir, + dev->data.tcp.listen, + alias, qemuCaps) < 0) + goto error; + + virBufferAsprintf(&buf, ",tls-creds=obj%s_tls0", alias); + } break; case VIR_DOMAIN_CHR_TYPE_UNIX: diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args new file mode 100644 index 0000000..183a0b3 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args @@ -0,0 +1,33 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu \ +-name QEMUGuest1 \ +-S \ +-M pc \ +-m 214 \ +-smp 1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-no-acpi \ +-boot c \ +-usb \ +-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \ +-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \ +-chardev udp,id=charserial0,host=127.0.0.1,port=2222,localaddr=127.0.0.1,\ +localport=1111 \ +-device isa-serial,chardev=charserial0,id=serial0 \ +-object tls-creds-x509,id=objserial1_tls0,dir=/etc/pki/libvirt-default,\ +endpoint=client \ +-chardev socket,id=charserial1,host=127.0.0.1,port=5555,\ +tls-creds=objserial1_tls0 \ +-device isa-serial,chardev=charserial1,id=serial1 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index c406b64..f1c3d1a 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1072,6 +1072,12 @@ mymain(void) QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); DO_TEST("serial-tcp-telnet-chardev", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); + driver.config->charTCPTLS = 1; + DO_TEST("serial-tcp-tlsx509-chardev", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_OBJECT_TLS_CREDS_X509); + driver.config->charTCPTLS = 0; + VIR_FREE(driver.config->charTCPTLSx509certdir); DO_TEST("serial-many-chardev", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); DO_TEST("parallel-tcp-chardev", -- 2.5.5

On Thu, Jun 16, 2016 at 06:42:26AM -0400, John Ferlan wrote:
When building a chardev device string for tcp, add the necessary pieces to access provide the TLS X.509 path to qemu. This includes generating the 'tls-creds-x509' object and then adding the 'tls-creds' parameter to the VIR_DOMAIN_CHR_TYPE_TCP command line.
Finally add the tests for the qemu command line. This test will make use of the "new(ish)" /etc/pki/libvirt-default setting for a TLS certificate environment by *not* "resetting" the charTCPTLSx509certdir prior to running the test.
Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_command.c | 102 ++++++++++++++++++++- .../qemuxml2argv-serial-tcp-tlsx509-chardev.args | 33 +++++++ tests/qemuxml2argvtest.c | 6 ++ 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4a8def1..815785c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -701,6 +701,97 @@ qemuBuildRBDSecinfoURI(virBufferPtr buf, }
+/* qemuBuildTLSx509BackendProps: + * @tlspath: path to the TLS credentials + * @listen: boolen listen for client or server setting + * @qemuCaps: capabilities + * @propsret: json properties to return + * + * Create a backend string for the tls-creds-x509 object. + * + * Returns 0 on success, -1 on failure with error set. + */ +static int +qemuBuildTLSx509BackendProps(const char *tlspath, + bool listen, + virQEMUCapsPtr qemuCaps, + virJSONValuePtr *propsret) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *path = NULL; + int ret = -1; + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_TLS_CREDS_X509)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("tls-creds-x509 not supported in this QEMU binary")); + return -1; + } + + qemuBufferEscapeComma(&buf, tlspath); + if (virBufferCheckError(&buf) < 0) + goto cleanup; + path = virBufferContentAndReset(&buf); + + if (virJSONValueObjectCreate(propsret, + "s:dir", path, + "s:endpoint", (listen ? "server": "client"),
We should also have ability to set 'verify-peer' to yes/no Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

If the incoming XML defined a path to a TLS X.509 certificate environment, add the necessary 'tls-creds-x509' object to the VIR_DOMAIN_CHR_TYPE_TCP character device. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/conf/domain_conf.h | 1 + src/qemu/qemu_command.c | 2 +- src/qemu/qemu_command.h | 6 ++++++ src/qemu/qemu_hotplug.c | 29 ++++++++++++++++++++++++++++- src/qemu/qemu_monitor_json.c | 9 +++++++++ 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 15f9c80..0e07504 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1097,6 +1097,7 @@ struct _virDomainChrSourceDef { char *service; bool listen; int protocol; + bool tlscreds; } tcp; struct { char *bindHost; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 815785c..effeee1 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -711,7 +711,7 @@ qemuBuildRBDSecinfoURI(virBufferPtr buf, * * Returns 0 on success, -1 on failure with error set. */ -static int +int qemuBuildTLSx509BackendProps(const char *tlspath, bool listen, virQEMUCapsPtr qemuCaps, diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 9ff4edb..0102c8f 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -61,6 +61,12 @@ virCommandPtr qemuBuildCommandLine(virQEMUDriverPtr driver, const char *domainLibDir) ATTRIBUTE_NONNULL(15); +/* Generate the object properties for a tls-creds-x509 */ +int qemuBuildTLSx509BackendProps(const char *tlspath, + bool listen, + virQEMUCapsPtr qemuCaps, + virJSONValuePtr *propsret); + /* Generate '-device' string for chardev device */ int qemuBuildChrDeviceStr(char **deviceStr, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 7d05073..7dea78f 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1496,10 +1496,14 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, virDomainChrDefPtr chr) { int ret = -1, rc; + virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); qemuDomainObjPrivatePtr priv = vm->privateData; virDomainDefPtr vmdef = vm->def; char *devstr = NULL; + virDomainChrSourceDefPtr dev = &chr->source; char *charAlias = NULL; + virJSONValuePtr props = NULL; + char *objAlias = NULL; bool need_release = false; if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL && @@ -1523,8 +1527,25 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, if (qemuDomainChrPreInsert(vmdef, chr) < 0) goto cleanup; + if (cfg->charTCPTLS) { + if (qemuBuildTLSx509BackendProps(cfg->charTCPTLSx509certdir, + dev->data.tcp.listen, + priv->qemuCaps, + &props) < 0) + goto cleanup; + + if (virAsprintf(&objAlias, "obj%s_tls0", chr->info.alias) < 0) + goto cleanup; + dev->data.tcp.tlscreds = true; + } + qemuDomainObjEnterMonitor(driver, vm); - if (qemuMonitorAttachCharDev(priv->mon, charAlias, &chr->source) < 0) + + if (objAlias && qemuMonitorAddObject(priv->mon, "tls-creds-x509", + objAlias, props) < 0) + goto failobject; + + if (qemuMonitorAttachCharDev(priv->mon, charAlias, dev) < 0) goto failchardev; if (qemuMonitorAddDevice(priv->mon, devstr) < 0) @@ -1542,14 +1563,20 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, qemuDomainChrInsertPreAllocCleanup(vm->def, chr); if (ret < 0 && need_release) qemuDomainReleaseDeviceAddress(vm, &chr->info, NULL); + VIR_FREE(objAlias); + virJSONValueFree(props); VIR_FREE(charAlias); VIR_FREE(devstr); + virObjectUnref(cfg); return ret; failadddev: /* detach associated chardev on error */ qemuMonitorDetachCharDev(priv->mon, charAlias); failchardev: + /* Remove the object */ + ignore_value(qemuMonitorDelObject(priv->mon, objAlias)); + failobject: ignore_value(qemuDomainObjExitMonitor(driver, vm)); goto audit; } diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 380ddab..703622a 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6137,6 +6137,7 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID, virJSONValuePtr data = NULL; virJSONValuePtr addr = NULL; const char *backend_type = NULL; + char *tlsalias = NULL; bool telnet; if (!(backend = virJSONValueNewObject()) || @@ -6182,6 +6183,13 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID, virJSONValueObjectAppendBoolean(data, "telnet", telnet) < 0 || virJSONValueObjectAppendBoolean(data, "server", chr->data.tcp.listen) < 0) goto error; + if (chr->data.tcp.tlscreds) { + if (virAsprintf(&tlsalias, "obj%s_tls0", chrID) < 0) + goto error; + + if (virJSONValueObjectAppendString(data, "tls-creds", tlsalias) < 0) + goto error; + } break; case VIR_DOMAIN_CHR_TYPE_UDP: @@ -6247,6 +6255,7 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID, return ret; error: + VIR_FREE(tlsalias); virJSONValueFree(addr); virJSONValueFree(data); virJSONValueFree(backend); -- 2.5.5

On Thu, Jun 16, 2016 at 06:42:27AM -0400, John Ferlan wrote:
If the incoming XML defined a path to a TLS X.509 certificate environment, add the necessary 'tls-creds-x509' object to the VIR_DOMAIN_CHR_TYPE_TCP character device.
Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/conf/domain_conf.h | 1 + src/qemu/qemu_command.c | 2 +- src/qemu/qemu_command.h | 6 ++++++ src/qemu/qemu_hotplug.c | 29 ++++++++++++++++++++++++++++- src/qemu/qemu_monitor_json.c | 9 +++++++++ 5 files changed, 45 insertions(+), 2 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (2)
-
Daniel P. Berrange
-
John Ferlan