Re: [libvirt] adding smartcard support to libvirt

[adding the public list for feedback on new XML. Background: Alon is working on adding some new command line arguments to qemu to make it possible to share smartcard access between a host and its virtual guests; while this is not upstream yet, libvirt should be prepared to handle the new command line options] [lengthy email; skip to the tail end for a high-level summary of proposed XML changes] On 12/22/2010 03:00 AM, Alon Levy wrote:
On Mon, Dec 20, 2010 at 12:19:42PM -0700, Eric Blake wrote:
I also found the following which also served as a good overview for what you are proposing to add to qemu:
http://cgit.freedesktop.org/~alon/qemu/commit/?h=usb_ccid.v9&id=d5484a05
Of course, sorry, should have pointed you to that initially. I wrote the ccid.txt one, the other is Robert Relyea's (the author of the libcacard library).
Right now, I'm thinking of adding a new <smartcard> element under <devices>. Let me know if this makes sense or needs tweaking; once the XML is in place, I can then figure out how to map to qemu command lines pretty easily.
Ok, so to make a little order: There are three devices being added to qemu, they are: * usb-ccid - this is both a usb device and a ccid bus. The rest of the devices attach to this bus (so they don't care that the bus is actually a usb device itself, same as a PCI device exposing an IDE bus). * ccid-card-emulated - this device uses NSS directly, so it can work in two modes: * no arguments at all - in this case it will look for whatever hardware NSS can access by default. This will depend on the specific host setup, and on the user credentials qemu is running under. * cert1, cert2, cert3 arguments - in this case NSS will look for three certs with the names supplied, and use them instead of any physical hardware. In this case qemu just needs to have those certificates available, and no physical hardware is required. * ccid-card-passthru - this device doesn't rely on NSS at all. Instead it uses a chardevice, and implements the VSCard protocol over it, which is just a simple protocol for remoting the CCID requests (actually it works in the APDU level, so it doesn't care for CCID specifically, but then again if you read the CCID you'll notice the main messages are XferBlock which just passes an APDU along too). Here there are also two basic options, depending on which char device we want to use. Of course you are not limited to these two, you can use any chardevice, but I've been using only these two and I can't think of a use for any other right now: * tcp socket char device - in this case you can use the accompanying libcacard/vscclient program running on another (or the same) machine, it uses NSS in exactly the same ways (certs/hw) as described above for the emulated card (which is of course natural since it is using the same library to do that, libcacard). * spice chardevice - this is a chardevice that uses libspice, which is linked with qemu. spice in turn will use a channel to the client which links with libcacard. This device is available here: http://lists.gnu.org/archive/html/qemu-devel/2010-12/msg01442.html as you can see from that thread, it isn't accepted yet, but anthony told me he wants to schedule vdagent (and by extension, spice chardevice, i.e. spicevmc chardev) talk to qemu community meeting after new years.
So I hope you understand that you do in fact need some device, in this
case
the usb-ccid device, it's only the card emulated that uses the certificates, not the bus device. The bus device remains the same for all of the various configurations.
Just to restate (to make sure I'm understanding you correctly), smartcard support in qemu requires that you enable two things: the usb-ccid device, and your choice of the ccid-card-emulated device or the ccid-card-passthru device. The ccid-card-emulated device operates in two modes, and the ccid-card-passthru device uses a protocol to talk through a required associated chardev (where the other end of the chardev can operate in two modes, but that's outside of what the guest can see; and where two particular chardevs make the most sense).
So after this lengthy summary, you see that actually the mode tag is good, I guess also the names you set are good.
* passthrough from a host attached smartcard reader. (despite
Picking the right mode names is probably the hardest part of writing new XML in a way that can be reused across other hypervisor technologies if similar approaches are adopted there, as well as allowing reasonable XML additions in the future, which is why I'm opening the feedback to make sure it all looks good. passthrough in the use
case name, this is actually done using the ccid-card-emulated device)
<domain...> <devices> <smartcard mode='host'> <source path='usb-ccid'/> </smartcard> </devices> </domain>
maps to qemu -usb -device usb-ccid -device ccid-card-emulated
I don't really grok the "source path='usb-ccid'", unless you just want to ensure that this can be replaced with other devices in the future, which in this case sounds good to me.
Then <source> isn't quite the right terminology for this. If we ever do come up with a future qemu device that can replace usb-ccid while still providing everything needed for the ccid-card-emulated device to work, then we can augment the XML at that point for choosing how to replace the usb-ccid device, but I don't think we need to tie it to <source> for the current proposal. So, this mode can be simplified. In other words, requesting mode='host' implies turning on anything in the hypervisor necessary to let the hypervisor use NSS access to the host's smartcard support (in qemu's case, turning on both the usb-ccid device and the ccid-card-emulated device with no arguments). Therefore, mode='host' wouldn't need any sub-elements for now. <domain...> <devices> <smartcard mode='host'/> </devices> </domain>
* passthrough from a client via vscclient program (this is done using ccid-card-passthrough but with a standard tcp chardevice)
<domain...> <devices> <smartcard mode='certificates'> <source path='usb-ccid'/> <certificate id='1' path='cert1'/> <certificate id='2' path='cert2'/> <certificate id='3' path='cert3'/> </smartcard> </devices> </domain>
maps to qemu -usb -device usb-ccid -device
ccid-card-emulated,backend=certificates,cert1=cert1,cert2=cert2,cert3=cert3
Libvirt will have to ensure that the qemu user has access rights to read the three certificate files on the host. My idea here is that mode='certificates' requires an element for the host source, as well as paths to the three host certificates.
Also, maybe call certificates mode host-certificates, just to make it obvious?
So, here's the updated proposal (again, dropping a <source> element, and picking a better mode name): <domain...> <devices> <smartcard mode='host-certificates'> <certificate id='1' path='cert1'/> <certificate id='2' path='cert2'/> <certificate id='3' path='cert3'/> </smartcard> </devices> </domain>
* passthrough with spice ('my' use case, -chardev spicevmc,id=smartcard,name=smartcard -device ccid-card-passthru,chardev=smartcard)
<domain...> <devices> <smartcard mode='passthrough' name='smartcard'> <serial type='smartcard'> <source path='spicevmc'/> </serial> </smartcard> </devices> </domain
maps to qemu -chardev spicevmc,id=smartcard,name=smartcard -device ccid-card-passthru,chardev=smartcard
My idea here is that mode='passthrough' requires a name, which then gets used to create both the smartcard passthrough device and the backing chardev device. Then, as a child element, <smartcard> contains any other valid element that could serve as a top-level device, such as <serial type='tcp'>.
Ok, so this is wrong - there are actually two source paths, if I understand the idea - you would still want to explicitly specify usb-ccid (again, assuming this is a future proofing for changing the underlying device), and the other would be the spicevmc, and it would translate to the following command line:
qemu -chardev spicevmc,id=smartcard,name=smartcard -usb -device usb-ccid -device ccud-card-passthru,chardev=smartcard
I guess something like:
<smartcard mode='passthrough' name='smartcard'> <source path='usb-ccid'/> <serial type='smartcard'> <source path='spicevmc'/> </serial> </smartcard>
So the key point here is that use of the ccid-card-passthru device requires a chardev=xyz argument that maps to another existing -chardev device. And given that the chardev device in use is essential to the smartcard support, I'm proposing that the <smartcard> element require the paired chardev device as a sub-element, rather than as a sibling element. Right now, the XML for <devices> allows the following <serial> types: dev, file, pipe, unix, tcp, udp, null, stdio, vc, pty so there's no notion of a type='smartcard'. It looks more like the new serial type is 'spicevmc'. And back to my idea of omitting mention of usb-ccid in the XML, and refactoring things to avoid dupicate use of strings (to make it a bit more obvious which XML aspects impact which command-line aspects), that leaves us with: <domain...> <devices> <smartcard mode='passthrough' name='xyz'> <serial type='spicevmc'/> </smartcard> </devices> </domain> maps to qemu -chardev spicevmc,id=smartcard,name=xyz -usb -device usb-ccid -device ccid-card-passthru,chardev=xyz Am I correct that a spicevmc -chardev has to use a fixed id=smartcard but an arbitrary name, and that ccid-card-passthru has to have a chardev=name that maps to the same name= used for a -chardev? Or is it that ccid-card-passthru has to have a chardev=name that maps to the same name as a -chardev id=name? And, given the goal that <smartcard mode='passthrough'> then has a child element that describes the passthrough device, it also means that I would be adding support for a top-level spicevmc chardev device, unrelated to smartcards; would this need any additional XML parameters? <domain...> <devices> <serial type='spicevmc'> <!-- anything else needed for a top-level spicevmc chardev? --> </serial> </devices> </domain>
<domain...> <devices> <smartcard mode='passthrough' name='ccid'> <serial type='tcp'> <source host='0.0.0.0' port='2001'/> <protocol type='tcp'/> </serial> </smartcard> </devices> </domain>
maps to qemu -chardev socket,server,host=0.0.0.0,port=2001,id=ccid,nowait -usb -device usb-ccid -device ccid-card-passthru,chardev=ccid
So actually here you got the command line correctly (again, no difference between both ccid-card-passthru uses except for the -chardev created), and I guess I would just add the same usb-ccid specification to your element:
<smartcard mode='passthrough' name='ccid'> <source path='usb-ccid'/> <serial type='tcp'> <source host='0.0.0.0' port='2001'/> <protocol type='tcp'/> </serial> </smartcard>
btw, I'm guessing the name attribute on the top level (smartcard) element is just a descriptor, like id? or is it something else? does libvirt have id and name, or just name?
My thoughts were that the name attribute of the <smartcard> element becomes the string that get reused twice in the qemu command line (once in the -chardev name, once I figure out whether that is by the id= or the name= field, and once in the -ccid-card-passthru chardev= field). This one is a bit easier, since top-level <serial type='tcp'> already exists, so I think this one remains: <domain...> <devices> <smartcard mode='passthrough' name='ccid'> <serial type='tcp'> <source host='0.0.0.0' port='2001'/> <protocol type='tcp'/> </serial> </smartcard> </devices> </domain>
Ok, so I don't understand exactly what you wanted the name to mean. Unless you meant for it to do exactly what I thought adding a source element side by side with the serial element would do, namely specifying the device (devices) to use, what I called future proofing.
* emulated with certificates (ccid-card-emulated with proper parameters to use user provided file certificates)
Since the certificates live in the guest and do not pass through the qemu command line, my understanding is that libvirt does not see this as any different from mode='passthrough' above.
Yes, I just specified this for completness sake.
In summary, this is my proposal for the new XML; feedback welcome to correct anything: <devices> modifies one existing sub-element (<serial> learns a new type='spicevmc' to match qemu's new spicevmc chardev), and adds a new sub-element <smartcard>. The new <smartcard> element has a required mode attribute, that takes on one of three strings: <smartcard mode='host'/> no other attributes, no sub-elements. Implies that the hypervisor exposes whatever devices necessary to the guest to see a smartcard, and feeds the smartcard implementation by communicating natively with the host smartcard for all needed information (maps to qemu -usb -device usb-ccid -device ccid-card-emulated) <smartcard mode='host-certificates'> <certificate id='1' path='cert1'/> <certificate id='2' path='cert2'/> <certificate id='3' path='cert3'/> </smartcard> no other attributes, but requires three <certificate> sub-elements. Implies that the hypervisor exposes whatever devices necessary to the guest to see a smartcard, and that it feeds the smartcard implementation with three certificate files living in the host rather than trying to talk to a host smartcard (maps to qemu -usb -device usb-ccid -device ccid-card-emulated,backend=certificates,cert1=cert1,cert2=cert2,cert3=cert3) <smartcard mode='passthrough' name='xyz'> <serial .../> </smartcard> name attribute is optional but recommended (assuming libvirt can create a unique name if none is provided). <serial> sub-element is required, with the same form as a normal <serial> sub-element of <devices>, but the common uses will be <serial type='tcp'> (existing) or <serial type='spicevmc'> (new). Implies that the hypervisor exposes whatever devices necessary to the guest to see a smartcard, and that it feeds the smartcard implementation via the associated char device (maps to qemu -chardev ...,name=xyz -usb -device usb-ccid -device ccid-card-passthru,chardev-xyz) -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Mon, Jan 03, 2011 at 11:50:18AM -0700, Eric Blake wrote:
[adding the public list for feedback on new XML. Background: Alon is working on adding some new command line arguments to qemu to make it possible to share smartcard access between a host and its virtual guests; while this is not upstream yet, libvirt should be prepared to handle the new command line options]
[lengthy email; skip to the tail end for a high-level summary of proposed XML changes]
So my own summary: it's all good, you just mixed the name and id for the spicevmc. More about the spicevmc below.
On 12/22/2010 03:00 AM, Alon Levy wrote:
On Mon, Dec 20, 2010 at 12:19:42PM -0700, Eric Blake wrote:
I also found the following which also served as a good overview for what you are proposing to add to qemu:
http://cgit.freedesktop.org/~alon/qemu/commit/?h=usb_ccid.v9&id=d5484a05
Of course, sorry, should have pointed you to that initially. I wrote the ccid.txt one, the other is Robert Relyea's (the author of the libcacard library).
Right now, I'm thinking of adding a new <smartcard> element under <devices>. Let me know if this makes sense or needs tweaking; once the XML is in place, I can then figure out how to map to qemu command lines pretty easily.
Ok, so to make a little order: There are three devices being added to qemu, they are: * usb-ccid - this is both a usb device and a ccid bus. The rest of the devices attach to this bus (so they don't care that the bus is actually a usb device itself, same as a PCI device exposing an IDE bus). * ccid-card-emulated - this device uses NSS directly, so it can work in two modes: * no arguments at all - in this case it will look for whatever hardware NSS can access by default. This will depend on the specific host setup, and on the user credentials qemu is running under. * cert1, cert2, cert3 arguments - in this case NSS will look for three certs with the names supplied, and use them instead of any physical hardware. In this case qemu just needs to have those certificates available, and no physical hardware is required. * ccid-card-passthru - this device doesn't rely on NSS at all. Instead it uses a chardevice, and implements the VSCard protocol over it, which is just a simple protocol for remoting the CCID requests (actually it works in the APDU level, so it doesn't care for CCID specifically, but then again if you read the CCID you'll notice the main messages are XferBlock which just passes an APDU along too). Here there are also two basic options, depending on which char device we want to use. Of course you are not limited to these two, you can use any chardevice, but I've been using only these two and I can't think of a use for any other right now: * tcp socket char device - in this case you can use the accompanying libcacard/vscclient program running on another (or the same) machine, it uses NSS in exactly the same ways (certs/hw) as described above for the emulated card (which is of course natural since it is using the same library to do that, libcacard). * spice chardevice - this is a chardevice that uses libspice, which is linked with qemu. spice in turn will use a channel to the client which links with libcacard. This device is available here: http://lists.gnu.org/archive/html/qemu-devel/2010-12/msg01442.html as you can see from that thread, it isn't accepted yet, but anthony told me he wants to schedule vdagent (and by extension, spice chardevice, i.e. spicevmc chardev) talk to qemu community meeting after new years.
So I hope you understand that you do in fact need some device, in this
case
the usb-ccid device, it's only the card emulated that uses the certificates, not the bus device. The bus device remains the same for all of the various configurations.
Just to restate (to make sure I'm understanding you correctly), smartcard support in qemu requires that you enable two things: the usb-ccid device, and your choice of the ccid-card-emulated device or the ccid-card-passthru device. The ccid-card-emulated device operates in two modes, and the ccid-card-passthru device uses a protocol to talk through a required associated chardev (where the other end of the chardev can operate in two modes, but that's outside of what the guest can see; and where two particular chardevs make the most sense).
Exactly.
So after this lengthy summary, you see that actually the mode tag is good, I guess also the names you set are good.
Picking the right mode names is probably the hardest part of writing new XML in a way that can be reused across other hypervisor technologies if similar approaches are adopted there, as well as allowing reasonable XML additions in the future, which is why I'm opening the feedback to make sure it all looks good.
* passthrough from a host attached smartcard reader. (despite passthrough in the use case name, this is actually done using the ccid-card-emulated device)
<domain...> <devices> <smartcard mode='host'> <source path='usb-ccid'/> </smartcard> </devices> </domain>
maps to qemu -usb -device usb-ccid -device ccid-card-emulated
I don't really grok the "source path='usb-ccid'", unless you just want to ensure that this can be replaced with other devices in the future, which in this case sounds good to me.
Then <source> isn't quite the right terminology for this. If we ever do come up with a future qemu device that can replace usb-ccid while still providing everything needed for the ccid-card-emulated device to work, then we can augment the XML at that point for choosing how to replace the usb-ccid device, but I don't think we need to tie it to <source> for the current proposal.
So, this mode can be simplified. In other words, requesting mode='host' implies turning on anything in the hypervisor necessary to let the hypervisor use NSS access to the host's smartcard support (in qemu's case, turning on both the usb-ccid device and the ccid-card-emulated device with no arguments). Therefore, mode='host' wouldn't need any sub-elements for now.
<domain...> <devices> <smartcard mode='host'/> </devices> </domain>
Looks good.
* passthrough from a client via vscclient program (this is done using ccid-card-passthrough but with a standard tcp chardevice)
<domain...> <devices> <smartcard mode='certificates'> <source path='usb-ccid'/> <certificate id='1' path='cert1'/> <certificate id='2' path='cert2'/> <certificate id='3' path='cert3'/> </smartcard> </devices> </domain>
maps to qemu -usb -device usb-ccid -device
ccid-card-emulated,backend=certificates,cert1=cert1,cert2=cert2,cert3=cert3
Libvirt will have to ensure that the qemu user has access rights to read the three certificate files on the host. My idea here is that mode='certificates' requires an element for the host source, as well as paths to the three host certificates.
Also, maybe call certificates mode host-certificates, just to make it obvious?
So, here's the updated proposal (again, dropping a <source> element, and picking a better mode name):
<domain...> <devices> <smartcard mode='host-certificates'> <certificate id='1' path='cert1'/> <certificate id='2' path='cert2'/> <certificate id='3' path='cert3'/> </smartcard> </devices> </domain>
Looks good.
* passthrough with spice ('my' use case, -chardev spicevmc,id=smartcard,name=smartcard -device ccid-card-passthru,chardev=smartcard)
<domain...> <devices> <smartcard mode='passthrough' name='smartcard'> <serial type='smartcard'> <source path='spicevmc'/> </serial> </smartcard> </devices> </domain
maps to qemu -chardev spicevmc,id=smartcard,name=smartcard -device ccid-card-passthru,chardev=smartcard
My idea here is that mode='passthrough' requires a name, which then gets used to create both the smartcard passthrough device and the backing chardev device. Then, as a child element, <smartcard> contains any other valid element that could serve as a top-level device, such as <serial type='tcp'>.
Ok, so this is wrong - there are actually two source paths, if I understand the idea - you would still want to explicitly specify usb-ccid (again, assuming this is a future proofing for changing the underlying device), and the other would be the spicevmc, and it would translate to the following command line:
qemu -chardev spicevmc,id=smartcard,name=smartcard -usb -device usb-ccid -device ccud-card-passthru,chardev=smartcard
I guess something like:
<smartcard mode='passthrough' name='smartcard'> <source path='usb-ccid'/> <serial type='smartcard'> <source path='spicevmc'/> </serial> </smartcard>
So the key point here is that use of the ccid-card-passthru device requires a chardev=xyz argument that maps to another existing -chardev device. And given that the chardev device in use is essential to the smartcard support, I'm proposing that the <smartcard> element require the paired chardev device as a sub-element, rather than as a sibling element.
Right now, the XML for <devices> allows the following <serial> types: dev, file, pipe, unix, tcp, udp, null, stdio, vc, pty
so there's no notion of a type='smartcard'. It looks more like the new serial type is 'spicevmc'. And back to my idea of omitting mention of usb-ccid in the XML, and refactoring things to avoid dupicate use of strings (to make it a bit more obvious which XML aspects impact which command-line aspects), that leaves us with:
<domain...> <devices> <smartcard mode='passthrough' name='xyz'> <serial type='spicevmc'/> </smartcard> </devices> </domain>
maps to qemu -chardev spicevmc,id=smartcard,name=xyz -usb -device usb-ccid -device ccid-card-passthru,chardev=xyz
ok, here you just mixed the id and name. I admit name is a bad, well, name, but it was already available as a parameter to chardev's (used as the filename for a file chardev). In the context of a spicevmc chardev the name is actually what I internally call a subtype. There are two subtypes/names that are valid currently: vdagent and smartcard. The id attribute is a global qemu tag that identifies a particular instance, so what needs to match is the chardev id and the chardev value given to the ccid-card-passthru device: qemu -chardev spicevmc,name=smartcard,id=xyz -usb -device usb-ccid -device ccid-card-passthru,chardev=xyz Which is just what you have above, just name and id interchanged.
Am I correct that a spicevmc -chardev has to use a fixed id=smartcard Fixed name, yes.
but an arbitrary name, and that ccid-card-passthru has to have a arbitrary id.
chardev=name that maps to the same name= used for a -chardev? Or is it To the same id.
that ccid-card-passthru has to have a chardev=name that maps to the same name as a -chardev id=name?
Same id. With these corrections - yes.
And, given the goal that <smartcard mode='passthrough'> then has a child element that describes the passthrough device, it also means that I would be adding support for a top-level spicevmc chardev device, unrelated to smartcards; would this need any additional XML parameters?
Right, again sorry for introducing it this way - exactly correct, the spicevmc is a separate entity. It is a new chardev, this is the chardev suggested last time I talked to libvirt when I tried to introduce a similarly named device called spicevmc. So instead of a superficial wrapper around virtio-serial I am introducing a chardev that can be used to connect to the spice server that is linked to the qemu process. The parameters for spicevmc are: id - this is the normal identifier that all chardev's must have. name - this distinguishes between the use of this chardev internal to spice, it can be of two values right now as I mentioned, 'vdagent' for use as the vdagent connection, and 'smartcard' for use by the smartcard channel.
<domain...> <devices> <serial type='spicevmc'> <!-- anything else needed for a top-level spicevmc chardev? --> </serial> </devices> </domain>
<serial type='spicevmc' id='xyz' name='vdagent'/> <serial type='spicevmc' id='xyz' name='smartcard'/> ?
<domain...> <devices> <smartcard mode='passthrough' name='ccid'> <serial type='tcp'> <source host='0.0.0.0' port='2001'/> <protocol type='tcp'/> </serial> </smartcard> </devices> </domain>
maps to qemu -chardev socket,server,host=0.0.0.0,port=2001,id=ccid,nowait -usb -device usb-ccid -device ccid-card-passthru,chardev=ccid
So actually here you got the command line correctly (again, no difference between both ccid-card-passthru uses except for the -chardev created), and I guess I would just add the same usb-ccid specification to your element:
<smartcard mode='passthrough' name='ccid'> <source path='usb-ccid'/> <serial type='tcp'> <source host='0.0.0.0' port='2001'/> <protocol type='tcp'/> </serial> </smartcard>
btw, I'm guessing the name attribute on the top level (smartcard) element is just a descriptor, like id? or is it something else? does libvirt have id and name, or just name?
My thoughts were that the name attribute of the <smartcard> element becomes the string that get reused twice in the qemu command line (once in the -chardev name, once I figure out whether that is by the id= or the name= field, and once in the -ccid-card-passthru chardev= field). This one is a bit easier, since top-level <serial type='tcp'> already exists, so I think this one remains:
<domain...> <devices> <smartcard mode='passthrough' name='ccid'> <serial type='tcp'> <source host='0.0.0.0' port='2001'/> <protocol type='tcp'/> </serial> </smartcard> </devices> </domain>
So just s/name/id/ there (i.e. id='ccid') and it's good.
Ok, so I don't understand exactly what you wanted the name to mean. Unless you meant for it to do exactly what I thought adding a source element side by side with the serial element would do, namely specifying the device (devices) to use, what I called future proofing.
* emulated with certificates (ccid-card-emulated with proper parameters to use user provided file certificates)
Since the certificates live in the guest and do not pass through the qemu command line, my understanding is that libvirt does not see this as any different from mode='passthrough' above.
Yes, I just specified this for completness sake.
In summary, this is my proposal for the new XML; feedback welcome to correct anything:
<devices> modifies one existing sub-element (<serial> learns a new type='spicevmc' to match qemu's new spicevmc chardev), and adds a new sub-element <smartcard>. The new <smartcard> element has a required mode attribute, that takes on one of three strings:
<smartcard mode='host'/> no other attributes, no sub-elements. Implies that the hypervisor exposes whatever devices necessary to the guest to see a smartcard, and feeds the smartcard implementation by communicating natively with the host smartcard for all needed information (maps to qemu -usb -device usb-ccid -device ccid-card-emulated)
<smartcard mode='host-certificates'> <certificate id='1' path='cert1'/> <certificate id='2' path='cert2'/> <certificate id='3' path='cert3'/> </smartcard> no other attributes, but requires three <certificate> sub-elements. Implies that the hypervisor exposes whatever devices necessary to the guest to see a smartcard, and that it feeds the smartcard implementation with three certificate files living in the host rather than trying to talk to a host smartcard (maps to qemu -usb -device usb-ccid -device ccid-card-emulated,backend=certificates,cert1=cert1,cert2=cert2,cert3=cert3)
<smartcard mode='passthrough' name='xyz'> <serial .../> </smartcard> name attribute is optional but recommended (assuming libvirt can create a unique name if none is provided). <serial> sub-element is required, with the same form as a normal <serial> sub-element of <devices>, but the common uses will be <serial type='tcp'> (existing) or <serial type='spicevmc'> (new). Implies that the hypervisor exposes whatever devices necessary to the guest to see a smartcard, and that it feeds the smartcard implementation via the associated char device (maps to qemu -chardev ...,name=xyz -usb -device usb-ccid -device ccid-card-passthru,chardev-xyz)
just s/name/id/.
-- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 01/04/2011 02:17 AM, Alon Levy wrote: [focusing on the spicevmc chardev aspect]
<domain...> <devices> <smartcard mode='passthrough' name='xyz'> <serial type='spicevmc'/> </smartcard> </devices> </domain>
maps to qemu -chardev spicevmc,id=smartcard,name=xyz -usb -device usb-ccid -device ccid-card-passthru,chardev=xyz
ok, here you just mixed the id and name. I admit name is a bad, well, name, but it was already available as a parameter to chardev's (used as the filename for a file chardev). In the context of a spicevmc chardev the name is actually what I internally call a subtype. There are two subtypes/names that are valid currently: vdagent and smartcard. The id attribute is a global qemu tag that identifies a particular instance, so what needs to match is the chardev id and the chardev value given to the ccid-card-passthru device:
And, given the goal that <smartcard mode='passthrough'> then has a child element that describes the passthrough device, it also means that I would be adding support for a top-level spicevmc chardev device, unrelated to smartcards; would this need any additional XML parameters?
Right, again sorry for introducing it this way - exactly correct, the spicevmc is a separate entity. It is a new chardev, this is the chardev suggested last time I talked to libvirt when I tried to introduce a similarly named device called spicevmc. So instead of a superficial wrapper around virtio-serial I am introducing a chardev that can be used to connect to the spice server that is linked to the qemu process. The parameters for spicevmc are: id - this is the normal identifier that all chardev's must have. name - this distinguishes between the use of this chardev internal to spice, it can be of two values right now as I mentioned, 'vdagent' for use as the vdagent connection, and 'smartcard' for use by the smartcard channel.
<domain...> <devices> <serial type='spicevmc'> <!-- anything else needed for a top-level spicevmc chardev? --> </serial> </devices> </domain>
<serial type='spicevmc' id='xyz' name='vdagent'/> <serial type='spicevmc' id='xyz' name='smartcard'/>
According to our existing XML: http://libvirt.org/formatdomain.html#elementsConsole there are four categories of chardevs: <serial>, <parallel>, <console>, and <channel>. Within each chardev, there are two optional sub-elements: <source> describing the host's view of the chardev, and a <target> describing the guest's view (the chardev type dictates whether <source> must exist, and the chardev category dictates what <target> must look like). It sounds to me like spicevmc is best described as a <channel>, since it is exposing a spice channel for host communications rather than an actual character device on the host. The chardev type of spicevmc (the type attribute under <serial|parallel|console|channel>) does not fit in with any of the existing channel types of 'stdio', 'file', 'vc', 'null', 'pty', 'dev', 'pipe', 'tcp', 'udp', or 'unix', so it would be a new type 'spicevmc'. It probably only makes sense to use type='spicevmc' with <channel>, so the other three chardev types should probably reject it. When the chardev type is 'spicevmc', the <source> sub-element seems like it is optional (since the spice connection has sane defaults), but if provided, will provide the extra information that can also be provided through the existing <graphics type='spice'> element, such as port='5903'. Meanwhile, since spicevmc is a <channel>, the <target> element must specify a type (right now, the only types expected for <channel> are 'guestfwd' and 'virtio'), so we're effectively adding two new types ('vdagent' and 'smartcard'). So, I'm thinking that this XML representation matches the spicevmc chardev: <devices> <channel type='spicevmc'/> <source port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'/> <target type='smartcard'/> </channel> </devices> In looking more at libvirt XML, I don't see any fields that match id assignments; rather, libvirt auto-assigns unique ids in the form %s%d, category, count, where category matches <channel> and count matches how many <channel> devices are present. That is, the above xml would map to: qemu -chardev spicevmc,id=smartcard,name=channel1 Hmm; getting spicevmc to work seems independent enough of getting <smartcard> implemented by using existing <channel type='tcp'/>, so I'll try to split my libvirt XML improvements into two batches. Should I focus on <channel type='spicevmc'> or on <smartcard> first? -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Wed, Jan 05, 2011 at 12:25:58PM -0700, Eric Blake wrote:
On 01/04/2011 02:17 AM, Alon Levy wrote:
[focusing on the spicevmc chardev aspect]
<domain...> <devices> <smartcard mode='passthrough' name='xyz'> <serial type='spicevmc'/> </smartcard> </devices> </domain>
maps to qemu -chardev spicevmc,id=smartcard,name=xyz -usb -device usb-ccid -device ccid-card-passthru,chardev=xyz
ok, here you just mixed the id and name. I admit name is a bad, well, name, but it was already available as a parameter to chardev's (used as the filename for a file chardev). In the context of a spicevmc chardev the name is actually what I internally call a subtype. There are two subtypes/names that are valid currently: vdagent and smartcard. The id attribute is a global qemu tag that identifies a particular instance, so what needs to match is the chardev id and the chardev value given to the ccid-card-passthru device:
And, given the goal that <smartcard mode='passthrough'> then has a child element that describes the passthrough device, it also means that I would be adding support for a top-level spicevmc chardev device, unrelated to smartcards; would this need any additional XML parameters?
Right, again sorry for introducing it this way - exactly correct, the spicevmc is a separate entity. It is a new chardev, this is the chardev suggested last time I talked to libvirt when I tried to introduce a similarly named device called spicevmc. So instead of a superficial wrapper around virtio-serial I am introducing a chardev that can be used to connect to the spice server that is linked to the qemu process. The parameters for spicevmc are: id - this is the normal identifier that all chardev's must have. name - this distinguishes between the use of this chardev internal to spice, it can be of two values right now as I mentioned, 'vdagent' for use as the vdagent connection, and 'smartcard' for use by the smartcard channel.
<domain...> <devices> <serial type='spicevmc'> <!-- anything else needed for a top-level spicevmc chardev? --> </serial> </devices> </domain>
<serial type='spicevmc' id='xyz' name='vdagent'/> <serial type='spicevmc' id='xyz' name='smartcard'/>
According to our existing XML: http://libvirt.org/formatdomain.html#elementsConsole
there are four categories of chardevs: <serial>, <parallel>, <console>, and <channel>. Within each chardev, there are two optional sub-elements: <source> describing the host's view of the chardev, and a <target> describing the guest's view (the chardev type dictates whether <source> must exist, and the chardev category dictates what <target> must look like).
It sounds to me like spicevmc is best described as a <channel>, since it is exposing a spice channel for host communications rather than an actual character device on the host.
The chardev type of spicevmc (the type attribute under <serial|parallel|console|channel>) does not fit in with any of the existing channel types of 'stdio', 'file', 'vc', 'null', 'pty', 'dev', 'pipe', 'tcp', 'udp', or 'unix', so it would be a new type 'spicevmc'. It probably only makes sense to use type='spicevmc' with <channel>, so the other three chardev types should probably reject it.
When the chardev type is 'spicevmc', the <source> sub-element seems like it is optional (since the spice connection has sane defaults), but if provided, will provide the extra information that can also be provided through the existing <graphics type='spice'> element, such as port='5903'.
Meanwhile, since spicevmc is a <channel>, the <target> element must specify a type (right now, the only types expected for <channel> are 'guestfwd' and 'virtio'), so we're effectively adding two new types ('vdagent' and 'smartcard').
So, I'm thinking that this XML representation matches the spicevmc chardev:
<devices> <channel type='spicevmc'/> <source port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'/>
I got you until now - but what's with the port/tlsPort - all of that stuff belongs to the spice flag, and I'm pretty sure is already taken care of by some other tag (I guess <spice> probably?). This chardev is totally separate (sure, you need to be using spice for it to make sense, but there is not overlap in parameters, for instance you don't give a port nor a tlsPort to the spicevmc chardev).
<target type='smartcard'/>
This looks right.
</channel> </devices>
In looking more at libvirt XML, I don't see any fields that match id assignments; rather, libvirt auto-assigns unique ids in the form %s%d, category, count, where category matches <channel> and count matches how many <channel> devices are present. That is, the above xml would map to:
qemu -chardev spicevmc,id=smartcard,name=channel1
I hope you meant id=channel1,name=smartcard ? the id needs to be the same as the ccid-passthru uses. But I guess we determined that it's easiest to let the <smartcard mode="passthru"/> already add the spicevmc chardev itself? the usage of "-chardev spicevmc,id=xyz,type=smartcard" is only for a "-device ccid-card-passthru,chardev=xyz", so one won't appear without the other. The usage of "-chardev spicevmc,id=xyz,type=vdagent" is also just with the usage of spice, I'm guessing the existing <spice> tag (sorry, not familiar with it - I use qemu from shell scripts.. :/ ) should just always create this chardev, and libvirt will make sure it's id doesn't conflict with any other, i.e. for spice usage a spicevmc chardev used by a virtioserialport device: -chardev spicevmc,id=chardev1,name=vdagent -device virtserialport,chardev=chardev1,name=com.redhat.spice.0 This creates the virtioserialport device with the name the in-guest agent looks for, and ties it to the correct spice server interface via the spicevmc chardev.
Hmm; getting spicevmc to work seems independent enough of getting <smartcard> implemented by using existing <channel type='tcp'/>, so I'll try to split my libvirt XML improvements into two batches. Should I focus on <channel type='spicevmc'> or on <smartcard> first?
I guess start with the smartcard first? Implement it without dealing with the spicevmc side - i.e. don't implement the passthru type first, or propose it but don't implement it. Then do the spicevmc part. I'm not particular on the order - both are required for RHEL 6.1 anyhow, and each is testable without the other (spicevmc with vdagent usage outlined above, and smartcard without spice by using it locally through libvirt).
-- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 01/05/2011 02:09 PM, Alon Levy wrote:
So, I'm thinking that this XML representation matches the spicevmc chardev:
<devices> <channel type='spicevmc'/> <source port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'/>
I got you until now - but what's with the port/tlsPort - all of that stuff belongs to the spice flag, and I'm pretty sure is already taken care of by some other tag (I guess <spice> probably?).
Hmm, right now, the only use of spice in XML is under <graphics type='spice'>, and it is the <graphics> element that contains port, tlsPort, autoport, and listen arguments. So we may need to revisit that, and have some way to use a single location for spice parameters shared among all spice-related devices, and a way for both <graphics type='spice'> and <smartcard type='passthrough'> to reference that rather than repeating it. Meaning that spicevmc support just got more difficult, if it involves tweaking <graphics> rather than just adding a new <channel type='spicevmc'> element.
This chardev is totally separate (sure, you need to be using spice for it to make sense, but there is not overlap in parameters, for instance you don't give a port nor a tlsPort to the spicevmc chardev).
Okay, looking more at existing devices, I agree that <channel type='spicevmc'> should only need additional attributes/sub-elements corresponding to parameters appearing directly in the -chardev/-device argument pair handed to qemu. So I'm not sure if <source> makes sense any more, or if <source> would be what ends up pointing to common details about the spice server as shared with the <graphics> element.
<target type='smartcard'/>
This looks right.
</channel> </devices>
In looking more at libvirt XML, I don't see any fields that match id assignments; rather, libvirt auto-assigns unique ids in the form %s%d, category, count, where category matches <channel> and count matches how many <channel> devices are present. That is, the above xml would map to:
qemu -chardev spicevmc,id=smartcard,name=channel1
I hope you meant id=channel1,name=smartcard ? the id needs to be the same as the ccid-passthru uses.
Arrgh - yes, more fallout from me swapping id= and name=, and copying and pasting from the wrong email. You already made it clear that id= is the unique name referenced in some other -device chardev=id location, and that for spicevmc, name= is one of two fixed values (vdagent or smartcard).
But I guess we determined that it's easiest to let the <smartcard mode="passthru"/> already add the spicevmc chardev itself? the usage of "-chardev spicevmc,id=xyz,type=smartcard" is only for a "-device ccid-card-passthru,chardev=xyz", so one won't appear without the other.
Looking even more at existing examples (can you tell that I'm trying to learn more about existing <devices> at the same time as implementing a new one?), I see this good example from qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev: <serial type='tcp'> <source mode='connect' host='127.0.0.1' service='9999'/> <protocol type='raw'/> <target port='0'/> </serial> maps to: -chardev socket,id=serial0,host=127.0.0.1,port=9999 -device isa-serial,chardev=serial0 It looks like -chardev was added in qemu 0.12, and that earlier versions used just -device without having to map things back to a chardev; but since smartcard is post-0.12, I only need to worry about the -chardev side of things.
Hmm; getting spicevmc to work seems independent enough of getting <smartcard> implemented by using existing <channel type='tcp'/>, so I'll try to split my libvirt XML improvements into two batches. Should I focus on <channel type='spicevmc'> or on <smartcard> first?
I guess start with the smartcard first? Implement it without dealing with the spicevmc side - i.e. don't implement the passthru type first, or propose it but don't implement it. Then do the spicevmc part.
Yep, that's pretty much what I'm settling on right now - figure out how to map <smartcard> to existing 'tcp' mapping first, then figure out about adding spicevmc support including expanding <smartcard> to handle spicevmc.
I'm not particular on the order - both are required for RHEL 6.1 anyhow, and each is testable without the other (spicevmc with vdagent usage outlined above, and smartcard without spice by using it locally through libvirt).
So, back to thinking about the new <smartcard> element. The <smartcard mode='host'> and <smartcard mode='host-certificates'> modes are simple, since -device ccid-card-emulated has no associated -chardev argument. But if we go with the ideas that <smartcard mode='passthrough'> implies -device ccid-card-passthru and an associated -chardev, and that the only -chardev's worth pairing with a <smartcard> are tcp and spicevmc, then it's simpler to just add a type attribute, and make <smartcard mode='passthrough' type='tcp'> look a lot like <serial type='tcp'> (no <serial> sub-element, but instead have a <source> sub-element directly resembling the <source> sub-element of serial). Meanwhile, <serial> allows a <target> sub-element (which virtual serial port the guest will access as the chardev), whereas <smartcard> would not (the guest sees the smartcard via the emulated card from the usb-ccid bus, and not as a raw serial port). Thus, <devices> <smartcard mode='passthrough' type='tcp'> <source host='0.0.0.0' port='2001'/> <protocol type='raw'/> </smartcard> </devices> maps to: -usb -device usb-ccid -chardev socket,server,host=0.0.0.0,port=2001,id=smartcard1,nowait -device ccid-card-passthru,chardev=smartcard1 and I think it leaves the door open for: <devices> <channel type='spicevmc'> <target type='vdagent'/> </channel> <smartcard mode='passthrough' type='spicevmc'> <target type='smartcard'/> </smartcard> </devices> to map to: -chardev spicevmc,id=channel1,name=vdagent -device vdagent,... -usb -device usb-ccid -chardev spicevmc,id=smartcard1,name=smartcard -device ccid-card-passthru,chardev=smartcard1 Hopefully this will make more sense once I actually finish coding up the RelaxNG schema validation, and propose a first round patch that documents the proposed XML with examples. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Wed, Jan 05, 2011 at 02:55:55PM -0700, Eric Blake wrote:
On 01/05/2011 02:09 PM, Alon Levy wrote:
So, I'm thinking that this XML representation matches the spicevmc chardev:
<devices> <channel type='spicevmc'/> <source port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'/>
I got you until now - but what's with the port/tlsPort - all of that stuff belongs to the spice flag, and I'm pretty sure is already taken care of by some other tag (I guess <spice> probably?).
Hmm, right now, the only use of spice in XML is under <graphics type='spice'>, and it is the <graphics> element that contains port, tlsPort, autoport, and listen arguments. So we may need to revisit that, and have some way to use a single location for spice parameters shared among all spice-related devices, and a way for both <graphics type='spice'> and <smartcard type='passthrough'> to reference that rather than repeating it. Meaning that spicevmc support just got more difficult, if it involves tweaking <graphics> rather than just adding a new <channel type='spicevmc'> element.
Are you saying that for correctness you want to tie the two elements together? I mean, that's the only possible reason I see. If you want to tie them together to prevent an instance of spicevmc without an instance of graphics of type spice, I understand. I guess (after seeing the patch you sent) there is a verifier to the xml inputs to libvirt that would be able to deduce invalidity in that case? Of course the alternative is to have logic elsewhere, but I see the point in trying to verify the xml input only at one place.
This chardev is totally separate (sure, you need to be using spice for it to make sense, but there is not overlap in parameters, for instance you don't give a port nor a tlsPort to the spicevmc chardev).
Okay, looking more at existing devices, I agree that <channel type='spicevmc'> should only need additional attributes/sub-elements corresponding to parameters appearing directly in the -chardev/-device argument pair handed to qemu. So I'm not sure if <source> makes sense any more, or if <source> would be what ends up pointing to common details about the spice server as shared with the <graphics> element.
<target type='smartcard'/>
This looks right.
</channel> </devices>
In looking more at libvirt XML, I don't see any fields that match id assignments; rather, libvirt auto-assigns unique ids in the form %s%d, category, count, where category matches <channel> and count matches how many <channel> devices are present. That is, the above xml would map to:
qemu -chardev spicevmc,id=smartcard,name=channel1
I hope you meant id=channel1,name=smartcard ? the id needs to be the same as the ccid-passthru uses.
Arrgh - yes, more fallout from me swapping id= and name=, and copying and pasting from the wrong email. You already made it clear that id= is the unique name referenced in some other -device chardev=id location, and that for spicevmc, name= is one of two fixed values (vdagent or smartcard).
But I guess we determined that it's easiest to let the <smartcard mode="passthru"/> already add the spicevmc chardev itself? the usage of "-chardev spicevmc,id=xyz,type=smartcard" is only for a "-device ccid-card-passthru,chardev=xyz", so one won't appear without the other.
Looking even more at existing examples (can you tell that I'm trying to learn more about existing <devices> at the same time as implementing a new one?), I see this good example from qemuxml2argvdata/qemuxml2argv-serial-tcp-chardev:
<serial type='tcp'> <source mode='connect' host='127.0.0.1' service='9999'/> <protocol type='raw'/> <target port='0'/> </serial>
maps to: -chardev socket,id=serial0,host=127.0.0.1,port=9999 -device isa-serial,chardev=serial0
It looks like -chardev was added in qemu 0.12, and that earlier versions used just -device without having to map things back to a chardev; but since smartcard is post-0.12, I only need to worry about the -chardev side of things.
Hmm; getting spicevmc to work seems independent enough of getting <smartcard> implemented by using existing <channel type='tcp'/>, so I'll try to split my libvirt XML improvements into two batches. Should I focus on <channel type='spicevmc'> or on <smartcard> first?
I guess start with the smartcard first? Implement it without dealing with the spicevmc side - i.e. don't implement the passthru type first, or propose it but don't implement it. Then do the spicevmc part.
Yep, that's pretty much what I'm settling on right now - figure out how to map <smartcard> to existing 'tcp' mapping first, then figure out about adding spicevmc support including expanding <smartcard> to handle spicevmc.
I'm not particular on the order - both are required for RHEL 6.1 anyhow, and each is testable without the other (spicevmc with vdagent usage outlined above, and smartcard without spice by using it locally through libvirt).
So, back to thinking about the new <smartcard> element. The <smartcard mode='host'> and <smartcard mode='host-certificates'> modes are simple, since -device ccid-card-emulated has no associated -chardev argument. But if we go with the ideas that <smartcard mode='passthrough'> implies -device ccid-card-passthru and an associated -chardev, and that the only -chardev's worth pairing with a <smartcard> are tcp and spicevmc, then it's simpler to just add a type attribute, and make <smartcard mode='passthrough' type='tcp'> look a lot like <serial type='tcp'> (no <serial> sub-element, but instead have a <source> sub-element directly resembling the <source> sub-element of serial). Meanwhile, <serial> allows a <target> sub-element (which virtual serial port the guest will access as the chardev), whereas <smartcard> would not (the guest sees the smartcard via the emulated card from the usb-ccid bus, and not as a raw serial port). Thus,
<devices> <smartcard mode='passthrough' type='tcp'> <source host='0.0.0.0' port='2001'/> <protocol type='raw'/> </smartcard> </devices>
maps to: -usb -device usb-ccid -chardev socket,server,host=0.0.0.0,port=2001,id=smartcard1,nowait -device ccid-card-passthru,chardev=smartcard1
and I think it leaves the door open for:
<devices> <channel type='spicevmc'> <target type='vdagent'/> </channel> <smartcard mode='passthrough' type='spicevmc'> <target type='smartcard'/> </smartcard> </devices>
to map to: -chardev spicevmc,id=channel1,name=vdagent -device vdagent,... -usb -device usb-ccid -chardev spicevmc,id=smartcard1,name=smartcard -device ccid-card-passthru,chardev=smartcard1
Hopefully this will make more sense once I actually finish coding up the RelaxNG schema validation, and propose a first round patch that documents the proposed XML with examples.
-- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 01/06/2011 04:33 AM, Alon Levy wrote:
Hmm, right now, the only use of spice in XML is under <graphics type='spice'>, and it is the <graphics> element that contains port, tlsPort, autoport, and listen arguments. So we may need to revisit that, and have some way to use a single location for spice parameters shared among all spice-related devices, and a way for both <graphics type='spice'> and <smartcard type='passthrough'> to reference that rather than repeating it. Meaning that spicevmc support just got more difficult, if it involves tweaking <graphics> rather than just adding a new <channel type='spicevmc'> element.
Are you saying that for correctness you want to tie the two elements together? I mean, that's the only possible reason I see. If you want to tie them together to prevent an instance of spicevmc without an instance of graphics of type spice, I understand. I guess (after seeing the patch you sent) there is a verifier to the xml inputs to libvirt that would be able to deduce invalidity in that case? Of course the alternative is to have logic elsewhere, but I see the point in trying to verify the xml input only at one place.
I'm thinking more along the lines that the spice parameters (port, tlsport, autoPort, listen, passwd, and child <channel> elements main, display, inputs, cursor, playback, and record) _might_ need to be specified independently from their current position under <graphics>, since we are likely adding new channels. That is, I think it should be possible to use a spicevmc agent for _just_ a smartcard channel, while still using older vnc or other graphics, in which case specifying spice parameters living under <graphics> doesn't make sense, but neither should the spice parameters live under <smartcard>. For that reason, it does seem to argue that creating a top-level <spice> element would make sense. However, it's a tricky proposition, because we have to maintain backwards compatibility; so _if_ we decide that making a higher-level <spice> element for fine-tuning spice parameters (rather than the current approach of sticking spice parameters under <graphics>), then yes, the XML parser will have to do consistency checks that either spice parameters are only provided in one location, or that the multiple locations are consistent. At any rate, I'm not going to give spicevmc much further thought until I first get <smartcard> with tcp passthru working, so it may be a few more days before I reply any further on this portion of the thread. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Thu, Jan 06, 2011 at 08:05:55AM -0700, Eric Blake wrote:
On 01/06/2011 04:33 AM, Alon Levy wrote:
Hmm, right now, the only use of spice in XML is under <graphics type='spice'>, and it is the <graphics> element that contains port, tlsPort, autoport, and listen arguments. So we may need to revisit that, and have some way to use a single location for spice parameters shared among all spice-related devices, and a way for both <graphics type='spice'> and <smartcard type='passthrough'> to reference that rather than repeating it. Meaning that spicevmc support just got more difficult, if it involves tweaking <graphics> rather than just adding a new <channel type='spicevmc'> element.
Are you saying that for correctness you want to tie the two elements together? I mean, that's the only possible reason I see. If you want to tie them together to prevent an instance of spicevmc without an instance of graphics of type spice, I understand. I guess (after seeing the patch you sent) there is a verifier to the xml inputs to libvirt that would be able to deduce invalidity in that case? Of course the alternative is to have logic elsewhere, but I see the point in trying to verify the xml input only at one place.
I'm thinking more along the lines that the spice parameters (port, tlsport, autoPort, listen, passwd, and child <channel> elements main, display, inputs, cursor, playback, and record) _might_ need to be specified independently from their current position under <graphics>, since we are likely adding new channels. That is, I think it should be possible to use a spicevmc agent for _just_ a smartcard channel, while still using older vnc or other graphics, in which case specifying spice parameters living under <graphics> doesn't make sense, but neither should the spice parameters live under <smartcard>. For that reason, it does seem to argue that creating a top-level <spice> element would make sense.
The primary reason for the tunnelling, is that it directly associates the smartcard with your current remote desktop client. If you're not using SPICE for the remote desktop, then there's no value in using it for the smartcard. NB, it is possible to configured multiple display protocols at the same time (eg multiple <graphics> elements) but we've not supported that in the QEMU driver yet. This would let you configure both VNC and SPICE at the same time.
However, it's a tricky proposition, because we have to maintain backwards compatibility; so _if_ we decide that making a higher-level <spice> element for fine-tuning spice parameters (rather than the current approach of sticking spice parameters under <graphics>), then yes, the XML parser will have to do consistency checks that either spice parameters are only provided in one location, or that the multiple locations are consistent.
As above, I don't think a <spice> element makes sense. The use of a <graphics type=spice> element is the primary enabler. Only once you have that, does it make sense to want to associate further devices with that mechanism Regards, Daniel

On 01/03/2011 11:50 AM, Eric Blake wrote:
<domain...> <devices> <smartcard mode='host-certificates'> <certificate id='1' path='cert1'/> <certificate id='2' path='cert2'/> <certificate id='3' path='cert3'/> </smartcard> </devices> </domain>
Slight tweak - filenames can be arbitrary, so they have to be nested text rather than attributes. Also, we know there are exactly three, and can use them in listed order, without having to require an extra id attribute. And absolute paths may make more sense (since a libvirt user can't be sure what a relative path is relative to). Leading to: <domain...> <devices> <smartcard mode='host-certificates'> <certificate>path='/path/to/cert1'</certificate> <certificate>path='/path/to/cert2'</certificate> <certificate>path='/path/to/cert3'</certificate> </smartcard> </devices> </domain> -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 01/05/2011 04:59 PM, Eric Blake wrote:
On 01/03/2011 11:50 AM, Eric Blake wrote:
<domain...> <devices> <smartcard mode='host-certificates'> <certificate id='1' path='cert1'/> <certificate id='2' path='cert2'/> <certificate id='3' path='cert3'/> </smartcard> </devices> </domain>
Slight tweak - filenames can be arbitrary, so they have to be nested text rather than attributes. Also, we know there are exactly three, and can use them in listed order, without having to require an extra id attribute. And absolute paths may make more sense (since a libvirt user can't be sure what a relative path is relative to). Leading to:
<certificate>path='/path/to/cert1'</certificate>
Hit send too soon; I meant to strip the path=' and ' portions. <domain...> <devices> <smartcard mode='host-certificates'> <certificate>/path/to/cert1</certificate> <certificate>/path/to/cert2</certificate> <certificate>/path/to/cert3</certificate> </smartcard> </devices> </domain> -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

Assuming a hypervisor that supports multiple smartcard devices in the guest, this would be a valid XML description: <devices> <smartcard mode='host'/> <smartcard mode='host-certificates'> <certificate>/path/to/cert1</certificate> <certificate>/path/to/cert2</certificate> <certificate>/path/to/cert3</certificate> </smartcard> <smartcard mode='passthrough' type='tcp'> <source mode='connect' host='127.0.0.1' service='2001'/> <protocol type='raw'/> </smartcard> </devices> * docs/formatdomain.html.in (Smartcard devices): New section. * docs/schemas/domain.rng (smartcard): New define, used in devices. * tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.xml: New file to test schema. * tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.xml: Likewise. * tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.xml: Likewise. --- Figuring it's easier to discuss alternatives with a documentation patch in hand, here's what I've got so far. My next task is to update conf/domain_conf.c to parse the new XML, then to teach qemu/qemu_command.c how to represent it on the command line. After that, I'll revisit figuring out how to support spicevmc chardevs, for both vdagent and smartcard. It looks like 'virsh domxml-from-native qemu-argv file' has suffered some bit-rot, as it doesn't know how to parse existing -chardev/-device pairings from valid qemu 0.12+ command lines; so for now I will focus on the XML->native direction, and leave improvements to the native->XML direction for another day. docs/formatdomain.html.in | 72 ++++++++++++++++++++ docs/schemas/domain.rng | 35 ++++++++++ .../qemuxml2argv-smartcard-host-certificates.xml | 20 ++++++ .../qemuxml2argv-smartcard-host.xml | 16 +++++ .../qemuxml2argv-smartcard-passthrough-tcp.xml | 19 +++++ 5 files changed, 162 insertions(+), 0 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index e9fcea1..bf46106 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -799,6 +799,78 @@ not used by qemu.</dd> </dl> + <h4><a name="elementsSmartcard">Smartcard devices</a></h4> + + <p> + A virtual smartcard device can be supplied to the guest via the + <code>smartcard</code> element. A USB smartcard reader device on + the host cannot be used on a guest with simple device + passthrough, since it will then not be available on the host, + possibly locking the host computer when it is "removed". + Therefore, some hypervisors provide a specialized virtual device + that can present a smartcard interface to the guest, with + several modes for describing how credentials are obtained from + the host or even a from a channel created to a third-party + smartcard provider. <span class="since">Since 0.8.8</span> + </p> + +<pre> + ... + <devices> + <smartcard mode='host'/> + <smartcard mode='host-certificates'> + <certificate>/path/to/cert1</certificate> + <certificate>/path/to/cert2</certificate> + <certificate>/path/to/cert3</certificate> + </smartcard> + <smartcard mode='passthrough' type='tcp'> + <source mode='connect' host='127.0.0.1' service='2001'/> + <protocol type='raw'/> + </smartcard> + </devices> + ... +</pre> + + <p> + The <code><smartcard></code> element has a mandatory + attribute <code>mode</code>. The following modes are supported; + in each mode, the guest sees a device on its USB bus that + behaves like a physical USB CCID (Chip/Smart Card Interface + Device) card. + </p> + + <ul> + <li><code>mode='host'</code> — the simplest operation, + where the hypervisor relays all requests from the guest into + direct access to the host's smartcard via NSS. No other + attributes or sub-elements are required.</li> + + <li><code>mode='host-certificates'</code> — rather than + requiring a smartcard to be plugged into the host, it is + possible to provide three files residing on the host and + containing NSS certificates. These certificates can be + generated via the command <code>certutil -d /etc/pki/nssdb -x -t + CT,CT,CT -S -s CN=cert1 -n cert1</code>, and the resulting three + files must be supplied as the content of each of + three <code><certificate></code> sub-elements.</li> + + <li><code>mode='passthrough'</code> — rather than having + the hypervisor directly communicate with the host, it is + possible to tunnel all requests through a secondary character + device to a third-party provider (which may in turn be talking + to a smartcard or using three certificate files). In this mode + of operation, an additional attribute <code>type</code> is + required, which matches the types of one of the + supported <a href="#elementsConsole">serial devices</a>. + Further sub-elements, such as <code><source></code> are + required according to the given type, although + a <code><target></code> sub-element is not required (since + the consumer of the character device is the hypervisor itself, + rather than a device visible in the guest). Use + of <code>type='tcp'</code> is most common.</li> + </ul> + + <h4><a name="elementsNICS">Network interfaces</a></h4> <pre> diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index a524e4b..385d1b6 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -1579,6 +1579,40 @@ </interleave> </element> </define> + <define name="smartcard"> + <element name="smartcard"> + <choice> + <attribute name="mode"> + <value>host</value> + </attribute> + <group> + <attribute name="mode"> + <value>host-certificates</value> + </attribute> + <ref name='certificate'/> + <ref name='certificate'/> + <ref name='certificate'/> + </group> + <group> + <attribute name="mode"> + <value>passthrough</value> + </attribute> + <ref name="qemucdevSrcType"/> + <interleave> + <ref name="qemucdevSrcDef"/> + <optional> + <ref name="qemucdevTgtDef"/> + </optional> + </interleave> + </group> + </choice> + </element> + </define> + <define name="certificate"> + <element name="certificate"> + <ref name="absFilePath"/> + </element> + </define> <define name="input"> <element name="input"> <attribute name="type"> @@ -1736,6 +1770,7 @@ <ref name="parallel"/> <ref name="serial"/> <ref name="channel"/> + <ref name="smartcard"/> </choice> </zeroOrMore> <optional> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.xml b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.xml new file mode 100644 index 0000000..f70395d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.xml @@ -0,0 +1,20 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <devices> + <emulator>/usr/bin/qemu</emulator> + <smartcard mode='host-certificates'> + <certificate>/etc/pki/cert1</certificate> + <certificate>/etc/pki/cert2</certificate> + <certificate>/etc/pki/cert3</certificate> + </smartcard> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.xml b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.xml new file mode 100644 index 0000000..faa2231 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.xml @@ -0,0 +1,16 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <devices> + <emulator>/usr/bin/qemu</emulator> + <smartcard mode='host'/> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.xml b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.xml new file mode 100644 index 0000000..8e2fa52 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.xml @@ -0,0 +1,19 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <devices> + <emulator>/usr/bin/qemu</emulator> + <smartcard mode='passthrough' type='tcp'> + <source mode='connect' host='127.0.0.1' service='2001'/> + <protocol type='raw'/> + </smartcard> + <memballoon model='virtio'/> + </devices> +</domain> -- 1.7.3.4
participants (3)
-
Alon Levy
-
Daniel P. Berrange
-
Eric Blake