[...] >> >> @@ -8546,6 +8561,18 @@ qemuBuildSerialCommandLine(virLogManagerPtr logManager, >> >> /* Use -chardev with -device if they are available */ >> if (virQEMUCapsSupportsChardev(def, qemuCaps, serial)) { >> + qemuDomainChardevPrivatePtr chardevPriv = >> + QEMU_DOMAIN_CHARDEV_PRIVATE(serial); >> + >> + /* Add the secret object first if necessary. The >> + * secinfo is added only to a TCP serial device during >> + * qemuDomainSecretChardevPrepare. Subsequently called >> + * functions can just check the config fields */ >> + if (serial->source.type == VIR_DOMAIN_CHR_TYPE_TCP && >> + chardevPriv && chardevPriv->secinfo && >> + qemuBuildObjectSecretCommandLine(cmd, chardevPriv->secinfo) < 0) >> + return -1; >> + > > This should be used also for other chardev devices. > Easily done for parallels, consoles, and channel... IOW: Others that call virDomainChrDefParseXML which calls virDomainChrDefNew(xmlopt) in order to set up privateData. Less easy for smartcard, rng, and redirdev's. Unfortunately the PRIVATE stuff is based off a virDomainChrDefPtr while the smartcard, rng, and redirdev's each use their own virDomain*DefPtr that includes a virDomainChrSourceDefPtr (for RNG) or virDomainChrSourceDef (for smartcard and redirdev). BTW: The hotplug code for smartcard, rng, and redirdev isn't implemented... Follow qemuDomainAttachChrDevice callers and you'll see separate calls for redirdev, rng, and smartcard. Clearly I misread all the various permutations... Looks like I'll need to either implement privateData for virDomainCharSourceDefPtr or duplicate what's done for ChrDef for redevdir, rng, and smartcard. Neither is appealing... John >> if (!(devstr = qemuBuildChrChardevStr(logManager, cmd, cfg, def, >> &serial->source, >> serial->info.alias, >> diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h >> index 2f2a6ff..a793fb6 100644 >> --- a/src/qemu/qemu_command.h >> +++ b/src/qemu/qemu_command.h >> @@ -69,6 +69,7 @@ int qemuBuildSecretInfoProps(qemuDomainSecretInfoPtr secinfo, >> int qemuBuildTLSx509BackendProps(const char *tlspath, >> bool isListen, >> bool verifypeer, >> + const char *secalias, >> virQEMUCapsPtr qemuCaps, >> virJSONValuePtr *propsret); >> >> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c >> index 7b518c6..adc078b 100644 >> --- a/src/qemu/qemu_domain.c >> +++ b/src/qemu/qemu_domain.c >> @@ -1042,7 +1042,8 @@ qemuDomainSecretSetup(virConnectPtr conn, >> if (virCryptoHaveCipher(VIR_CRYPTO_CIPHER_AES256CBC) && >> virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_SECRET) && >> (secretUsageType == VIR_SECRET_USAGE_TYPE_CEPH || >> - secretUsageType == VIR_SECRET_USAGE_TYPE_VOLUME)) { >> + secretUsageType == VIR_SECRET_USAGE_TYPE_VOLUME || >> + secretUsageType == VIR_SECRET_USAGE_TYPE_TLS)) { >> if (qemuDomainSecretAESSetup(conn, priv, secinfo, srcalias, >> secretUsageType, username, >> seclookupdef, isLuks) < 0) >> @@ -1220,6 +1221,95 @@ qemuDomainSecretHostdevPrepare(virConnectPtr conn, >> } >> >> >> +/* qemuDomainSecretChardevDestroy: >> + * @disk: Pointer to a chardev definition >> + * >> + * Clear and destroy memory associated with the secret >> + */ >> +void >> +qemuDomainSecretChardevDestroy(virDomainChrDefPtr chardev) >> +{ >> + qemuDomainChardevPrivatePtr chardevPriv = >> + QEMU_DOMAIN_CHARDEV_PRIVATE(chardev); >> + >> + if (!chardevPriv || !chardevPriv->secinfo) >> + return; >> + >> + qemuDomainSecretInfoFree(&chardevPriv->secinfo); >> +} >> + >> + >> +/* qemuDomainSecretChardevPrepare: >> + * @conn: Pointer to connection >> + * @driver: Pointer to driver object >> + * @priv: pointer to domain private object >> + * @chardev: Pointer to a chardev definition >> + * >> + * For a TCP character device, generate a qemuDomainSecretInfo to be used >> + * by the command line code to generate the secret for the tls-creds to use. >> + * >> + * Returns 0 on success, -1 on failure >> + */ >> +int >> +qemuDomainSecretChardevPrepare(virConnectPtr conn, >> + virQEMUDriverPtr driver, >> + qemuDomainObjPrivatePtr priv, >> + virDomainChrDefPtr chardev) >> +{ >> + virQEMUDriverConfigPtr cfg; >> + virSecretLookupTypeDef seclookupdef = {0}; >> + qemuDomainSecretInfoPtr secinfo = NULL; >> + char *charAlias = NULL; >> + >> + if (chardev->source.type != VIR_DOMAIN_CHR_TYPE_TCP) >> + return 0; >> + >> + cfg = virQEMUDriverGetConfig(driver); >> + if (qemuDomainSupportTLSChardevTCP(cfg, &chardev->source) && >> + cfg->chardevTLSx509secretUUID) { >> + qemuDomainChardevPrivatePtr chardevPriv = >> + QEMU_DOMAIN_CHARDEV_PRIVATE(chardev); >> + >> + if (virUUIDParse(cfg->chardevTLSx509secretUUID, >> + seclookupdef.u.uuid) < 0) { >> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", >> + _("malformed chardev TLS secret uuid in qemu.conf")); >> + goto error; >> + } >> + seclookupdef.type = VIR_SECRET_LOOKUP_TYPE_UUID; >> + >> + if (VIR_ALLOC(secinfo) < 0) >> + goto error; >> + >> + if (!(charAlias = qemuAliasChardevFromDevAlias(chardev->info.alias))) >> + goto error; >> + >> + if (qemuDomainSecretSetup(conn, priv, secinfo, charAlias, >> + VIR_SECRET_USAGE_TYPE_TLS, NULL, >> + &seclookupdef, false) < 0) >> + goto error; >> + >> + if (secinfo->type == VIR_DOMAIN_SECRET_INFO_TYPE_PLAIN) { >> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", >> + _("TLS X.509 requires encrypted secrets " >> + "to be supported")); >> + goto error; >> + } >> + >> + chardevPriv->secinfo = secinfo; >> + } >> + >> + VIR_FREE(charAlias); >> + virObjectUnref(cfg); >> + return 0; >> + >> + error: >> + virObjectUnref(cfg); >> + qemuDomainSecretInfoFree(&secinfo); >> + return -1; >> +} >> + >> + >> /* qemuDomainSecretDestroy: >> * @vm: Domain object >> * >> @@ -1236,11 +1326,15 @@ qemuDomainSecretDestroy(virDomainObjPtr vm) >> >> for (i = 0; i < vm->def->nhostdevs; i++) >> qemuDomainSecretHostdevDestroy(vm->def->hostdevs[i]); >> + >> + for (i = 0; i < vm->def->nserials; i++) >> + qemuDomainSecretChardevDestroy(vm->def->serials[i]); > > This should iterate over all chardevs, not only over serial ... > >> } >> >> >> /* qemuDomainSecretPrepare: >> * @conn: Pointer to connection >> + * @driver: Pointer to driver object >> * @vm: Domain object >> * >> * For any objects that may require an auth/secret setup, create a >> @@ -1253,6 +1347,7 @@ qemuDomainSecretDestroy(virDomainObjPtr vm) >> */ >> int >> qemuDomainSecretPrepare(virConnectPtr conn, >> + virQEMUDriverPtr driver, >> virDomainObjPtr vm) >> { >> qemuDomainObjPrivatePtr priv = vm->privateData; >> @@ -1269,6 +1364,12 @@ qemuDomainSecretPrepare(virConnectPtr conn, >> return -1; >> } >> >> + for (i = 0; i < vm->def->nserials; i++) { >> + if (qemuDomainSecretChardevPrepare(conn, driver, priv, >> + vm->def->serials[i]) < 0) >> + return -1; >> + } > > ... and same here. > > Pavel > >> + >> return 0; >> } >> >> diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h >> index 156e0fc..1bb2f2d 100644 >> --- a/src/qemu/qemu_domain.h >> +++ b/src/qemu/qemu_domain.h >> @@ -726,11 +726,23 @@ int qemuDomainSecretHostdevPrepare(virConnectPtr conn, >> virDomainHostdevDefPtr hostdev) >> ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); >> >> +void qemuDomainSecretChardevDestroy(virDomainChrDefPtr chardev) >> + ATTRIBUTE_NONNULL(1); >> + >> +int qemuDomainSecretChardevPrepare(virConnectPtr conn, >> + virQEMUDriverPtr driver, >> + qemuDomainObjPrivatePtr priv, >> + virDomainChrDefPtr chardev) >> + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) >> + ATTRIBUTE_NONNULL(4); >> + >> void qemuDomainSecretDestroy(virDomainObjPtr vm) >> ATTRIBUTE_NONNULL(1); >> >> -int qemuDomainSecretPrepare(virConnectPtr conn, virDomainObjPtr vm) >> - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); >> +int qemuDomainSecretPrepare(virConnectPtr conn, >> + virQEMUDriverPtr driver, >> + virDomainObjPtr vm) >> + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); >> >> int qemuDomainDefValidateDiskLunSource(const virStorageSource *src) >> ATTRIBUTE_NONNULL(1); >> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c >> index 9643a68..59c3b25 100644 >> --- a/src/qemu/qemu_hotplug.c >> +++ b/src/qemu/qemu_hotplug.c >> @@ -1734,6 +1734,7 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, >> if (qemuBuildTLSx509BackendProps(cfg->chardevTLSx509certdir, >> dev->data.tcp.listen, >> cfg->chardevTLSx509verify, >> + NULL, >> priv->qemuCaps, >> &tlsProps) < 0) >> goto cleanup; >> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c >> index d641f33..643741d 100644 >> --- a/src/qemu/qemu_process.c >> +++ b/src/qemu/qemu_process.c >> @@ -5157,8 +5157,8 @@ qemuProcessPrepareDomain(virConnectPtr conn, >> if (qemuDomainMasterKeyCreate(vm) < 0) >> goto cleanup; >> >> - VIR_DEBUG("Add secrets to disks and hostdevs"); >> - if (qemuDomainSecretPrepare(conn, vm) < 0) >> + VIR_DEBUG("Add secrets to disks, hostdevs, and chardevs"); >> + if (qemuDomainSecretPrepare(conn, driver, vm) < 0) >> goto cleanup; >> >> for (i = 0; i < vm->def->nchannels; i++) { >> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.args >> new file mode 100644 >> index 0000000..7f9fedb >> --- /dev/null >> +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.args >> @@ -0,0 +1,38 @@ >> +LC_ALL=C \ >> +PATH=/bin \ >> +HOME=/home/test \ >> +USER=test \ >> +LOGNAME=test \ >> +QEMU_AUDIO_DRV=none \ >> +/usr/bin/qemu \ >> +-name QEMUGuest1 \ >> +-S \ >> +-object secret,id=masterKey0,format=raw,\ >> +file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ >> +-M pc \ >> +-m 214 \ >> +-smp 1,sockets=1,cores=1,threads=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 secret,id=charserial1-secret0,\ >> +data=9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1,\ >> +keyid=masterKey0,iv=AAECAwQFBgcICQoLDA0ODw==,format=base64 \ >> +-object tls-creds-x509,id=objcharserial1_tls0,dir=/etc/pki/libvirt-chardev,\ >> +endpoint=client,verify-peer=no,passwordid=charserial1-secret0 \ >> +-chardev socket,id=charserial1,host=127.0.0.1,port=5555,\ >> +tls-creds=objcharserial1_tls0 \ >> +-device isa-serial,chardev=charserial1,id=serial1 \ >> +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 >> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.xml >> new file mode 100644 >> index 0000000..23c244b >> --- /dev/null >> +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-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' tls='yes'/> >> + <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/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c >> index 52d85fa..541a498 100644 >> --- a/tests/qemuxml2argvtest.c >> +++ b/tests/qemuxml2argvtest.c >> @@ -1170,6 +1170,23 @@ mymain(void) >> DO_TEST("serial-tcp-tlsx509-chardev-notls", >> QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, >> QEMU_CAPS_OBJECT_TLS_CREDS_X509); >> + VIR_FREE(driver.config->chardevTLSx509certdir); >> + if (VIR_STRDUP_QUIET(driver.config->chardevTLSx509certdir, "/etc/pki/libvirt-chardev") < 0) >> + return EXIT_FAILURE; >> + if (VIR_STRDUP_QUIET(driver.config->chardevTLSx509secretUUID, >> + "6fd3f62d-9fe7-4a4e-a869-7acd6376d8ea") < 0) >> + return EXIT_FAILURE; >> +# ifdef HAVE_GNUTLS_CIPHER_ENCRYPT >> + DO_TEST("serial-tcp-tlsx509-secret-chardev", >> + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, >> + QEMU_CAPS_OBJECT_SECRET, >> + QEMU_CAPS_OBJECT_TLS_CREDS_X509); >> +# else >> + DO_TEST_FAILURE("serial-tcp-tlsx509-secret-chardev", >> + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, >> + QEMU_CAPS_OBJECT_SECRET, >> + QEMU_CAPS_OBJECT_TLS_CREDS_X509); >> +# endif >> driver.config->chardevTLS = 0; >> VIR_FREE(driver.config->chardevTLSx509certdir); >> DO_TEST("serial-many-chardev", >> -- >> 2.7.4 >> >> -- >> libvir-list mailing list >> libvir-list@xxxxxxxxxx >> https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list