* src/qemu/qemu_command.c (qemuBuildCommandLine): Emit smartcard
options.
(qemuAssignDeviceAliases): Assign an alias for smartcards.
(qemuBuildControllerDevStr): Manage the usb-ccid controller.
* tests/qemuxml2argvtest.c (mymain): Add new tests.
* tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args: New
file.
* tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args:
Likewise.
* tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough.args:
Likewise.
* tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args:
Likewise.
Notes:
v2: new patch
v3: reject ',' in cert name, alias for host smartcard use, output
usb-ccid controller separate from rest of command line, enforce at
most one smartcard for now
---
src/qemu/qemu_command.c | 90 +++++++++++++++++++-
.../qemuxml2argv-smartcard-controller.args | 1 +
.../qemuxml2argv-smartcard-host-certificates.args | 1 +
.../qemuxml2argv-smartcard-host.args | 1 +
.../qemuxml2argv-smartcard-passthrough-tcp.args | 1 +
tests/qemuxml2argvtest.c | 13 +++
6 files changed, 106 insertions(+), 1 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.args
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 5b65f26..5197ab6 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -638,6 +638,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, unsigned long long
qemuCmdFlags)
if (virAsprintf(&def->channels[i]->info.alias, "channel%d",
i) < 0)
goto no_memory;
}
+ for (i = 0; i < def->nsmartcards ; i++) {
+ if (virAsprintf(&def->smartcards[i]->info.alias,
"smartcard%d", i) < 0)
+ goto no_memory;
+ }
if (def->console) {
if (virAsprintf(&def->console->info.alias, "console%d", i)
< 0)
goto no_memory;
@@ -1003,7 +1007,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
qemuDomainPCIAddressSetPtr addrs)
/* Disk controllers (SCSI only for now) */
for (i = 0; i < def->ncontrollers ; i++) {
/* FDC lives behind the ISA bridge */
- if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC)
+ if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC ||
+ def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_CCID)
continue;
/* First IDE controller lives on the PIIX3 at slot=1, function=1,
@@ -1505,6 +1510,10 @@ qemuBuildControllerDevStr(virDomainControllerDefPtr def)
}
break;
+ case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
+ virBufferVSprintf(&buf, "usb-ccid,id=ccid%d", def->idx);
+ break;
+
/* We always get an IDE controller, whether we want it or not. */
case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
default:
@@ -3412,6 +3421,85 @@ qemuBuildCommandLine(virConnectPtr conn,
}
}
+ if (def->nsmartcards) {
+ /* -device usb-ccid was already emitted along with other
+ * controllers. For now, qemu handles only one smartcard. */
+ virDomainSmartcardDefPtr smartcard = def->smartcards[0];
+ char *devstr;
+ virBuffer opt = VIR_BUFFER_INITIALIZER;
+ int j;
+
+ if (!(qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) ||
+ !(qemuCmdFlags & QEMUD_CMD_FLAG_USB_CCID)) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("this QEMU binary lacks smartcard support"));
+ goto error;
+ }
+ if (def->nsmartcards > 1 ||
+ smartcard->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID ||
+ smartcard->info.addr.ccid.controller != 0 ||
+ smartcard->info.addr.ccid.slot != 0) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("this QEMU binary lacks multiple smartcard "
+ "support"));
+ virBufferFreeAndReset(&opt);
+ goto error;
+ }
+
+ switch (smartcard->type) {
+ case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
+ virBufferAddLit(&opt,
"ccid-card-emulated,backend=nss-emulated");
+ break;
+ case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES:
+ virBufferAddLit(&opt,
"ccid-card-emulated,backend=certificates");
+ for (j = 0; j < VIR_DOMAIN_SMARTCARD_NUM_CERTIFICATES; j++) {
+ if (strchr(smartcard->data.cert.file[j], ',')) {
+ virBufferFreeAndReset(&opt);
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("invalid certificate name: %s"),
+ smartcard->data.cert.file[j]);
+ goto error;
+ }
+ virBufferVSprintf(&opt, ",cert%d=%s", j + 1,
+ smartcard->data.cert.file[j]);
+ }
+ if (smartcard->data.cert.database) {
+ if (strchr(smartcard->data.cert.database, ',')) {
+ virBufferFreeAndReset(&opt);
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("invalid database name: %s"),
+ smartcard->data.cert.database);
+ goto error;
+ }
+ virBufferVSprintf(&opt, ",database=%s",
+ smartcard->data.cert.database);
+ }
+ break;
+ case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
+ virCommandAddArg(cmd, "-chardev");
+ if (!(devstr = qemuBuildChrChardevStr(&smartcard->data.passthru,
+ smartcard->info.alias))) {
+ virBufferFreeAndReset(&opt);
+ goto error;
+ }
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
+
+ virBufferVSprintf(&opt, "ccid-card-passthru,chardev=char%s",
+ smartcard->info.alias);
+ break;
+ default:
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected smartcard type %d"),
+ smartcard->type);
+ virBufferFreeAndReset(&opt);
+ goto error;
+ }
+ virCommandAddArg(cmd, "-device");
+ virBufferVSprintf(&opt, ",id=%s,bus=ccid0.0",
smartcard->info.alias);
+ virCommandAddArgBuffer(cmd, &opt);
+ }
+
if (!def->nserials) {
/* If we have -device, then we set -nodefault already */
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args
b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args
new file mode 100644
index 0000000..89fa54d
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args
@@ -0,0 +1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214
-smp 1 -nographic -nodefconfig -nodefaults -chardev
socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon
chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device usb-ccid,id=ccid0
-device ccid-card-emulated,backend=nss-emulated,id=smartcard0,bus=ccid0.0 -usb -device
virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args
b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args
new file mode 100644
index 0000000..2647b13
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args
@@ -0,0 +1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214
-smp 1 -nographic -nodefconfig -nodefaults -chardev
socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon
chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device usb-ccid,id=ccid0
-device
ccid-card-emulated,backend=certificates,cert1=/etc/pki/cert1,cert2=/etc/pki/cert2,cert3=/etc/pki/cert3,id=smartcard0,bus=ccid0.0
-usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args
b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args
new file mode 100644
index 0000000..89fa54d
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args
@@ -0,0 +1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214
-smp 1 -nographic -nodefconfig -nodefaults -chardev
socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon
chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device usb-ccid,id=ccid0
-device ccid-card-emulated,backend=nss-emulated,id=smartcard0,bus=ccid0.0 -usb -device
virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.args
b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.args
new file mode 100644
index 0000000..a44d3cb
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.args
@@ -0,0 +1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214
-smp 1 -nographic -nodefconfig -nodefaults -chardev
socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon
chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device usb-ccid,id=ccid0
-chardev socket,id=charsmartcard0,host=127.0.0.1,port=2001 -device
ccid-card-passthru,chardev=charsmartcard0,id=smartcard0,bus=ccid0.0 -usb -device
virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 0a39791..483916c 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -408,6 +408,19 @@ mymain(int argc, char **argv)
DO_TEST("console-virtio", QEMUD_CMD_FLAG_DEVICE |
QEMUD_CMD_FLAG_NODEFCONFIG, false);
+ DO_TEST("smartcard-host",
+ QEMUD_CMD_FLAG_CHARDEV | QEMUD_CMD_FLAG_DEVICE |
+ QEMUD_CMD_FLAG_NODEFCONFIG | QEMUD_CMD_FLAG_USB_CCID, false);
+ DO_TEST("smartcard-host-certificates",
+ QEMUD_CMD_FLAG_CHARDEV | QEMUD_CMD_FLAG_DEVICE |
+ QEMUD_CMD_FLAG_NODEFCONFIG | QEMUD_CMD_FLAG_USB_CCID, false);
+ DO_TEST("smartcard-passthrough-tcp",
+ QEMUD_CMD_FLAG_CHARDEV | QEMUD_CMD_FLAG_DEVICE |
+ QEMUD_CMD_FLAG_NODEFCONFIG | QEMUD_CMD_FLAG_USB_CCID, false);
+ DO_TEST("smartcard-controller",
+ QEMUD_CMD_FLAG_CHARDEV | QEMUD_CMD_FLAG_DEVICE |
+ QEMUD_CMD_FLAG_NODEFCONFIG | QEMUD_CMD_FLAG_USB_CCID, false);
+
DO_TEST("smbios", QEMUD_CMD_FLAG_SMBIOS_TYPE, false);
DO_TEST("watchdog", 0, false);
--
1.7.3.5