pcscd runs as pcscd user
With pcsc-lite 2.4.0 (New version of pcsc-lite: 2.4.0) the pcscd
daemon process now runs (if systemd is used) as user pcscd in group
pcscd.
Possible problem
For example if I use libccid version 1.6.2 (so before the update to set the access rights, implemented in version 1.7.0, New version of libccid: 1.7.0) I get the error:
$ journalctl -u pcscd -f oct. 21 21:41:26 MacBookPro pcscd[25848]: 00000000 ccid_usb.c:564:OpenUSBByName() Can't libusb_open(4/6): LIBUSB_ERROR_ACCESS
If I start pcscd in foreground and debug mode I get more details:
$ sudo -u pcscd -g pcscd LIBCCID_ifdLogLevel=0x000F pcscd --foreground --debug 00000000 [140406854371648] ../src/debuglog.c:395:DebugLogSetLevel() debug level=debug 00000369 [140406854371648] ../src/configfile.l:293:DBGetReaderListDir() Parsing conf directory: /etc/reader.conf.d 00000055 [140406854371648] ../src/configfile.l:326:DBGetReaderListDir() Skipping non regular file: .. 00000010 [140406854371648] ../src/configfile.l:365:DBGetReaderList() Parsing conf file: /etc/reader.conf.d/libccidtwin 00000096 [140406854371648] ../src/configfile.l:326:DBGetReaderListDir() Skipping non regular file: . 00000037 [140406854371648] ../src/pcscdaemon.c:669:main() pcsc-lite 2.4.0 daemon ready. 00000111 [140406854371648] ../src/pcscdaemon.c:752:main() Using drivers directory: /usr/lib/pcsc/drivers 00008375 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/003/001 00000275 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/003/001 00000240 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8242, path: /dev/bus/usb/003/002 00000311 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/003/001 00000325 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x0237, path: /dev/bus/usb/003/003 00000237 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x0237, path: /dev/bus/usb/003/003 00000237 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x0237, path: /dev/bus/usb/003/003 00000408 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/002/001 00000239 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/002/001 00000271 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8507, path: /dev/bus/usb/002/002 00000417 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/004/001 00000246 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/004/001 00000254 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x0A5C, PID: 0x4500, path: /dev/bus/usb/004/002 00000266 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8213, path: /dev/bus/usb/004/003 00000254 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8213, path: /dev/bus/usb/004/003 00000266 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8213, path: /dev/bus/usb/004/003 00000258 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8213, path: /dev/bus/usb/004/003 00000298 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x0A5C, PID: 0x4500, path: /dev/bus/usb/004/002 00000242 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/004/001 00000260 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x08E6, PID: 0x3438, path: /dev/bus/usb/004/006 00000186 [140406854371648] ../src/hotplug_libudev.c:430:HPAddDevice() Adding USB device: Gemalto USB Shell Token V2 00000089 [140406854371648] ../src/readerfactory.c:1103:RFInitializeReader() Attempting startup of Gemalto USB Shell Token V2 00 00 using /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux/libccid.so 00000597 [140406854371648] ../src/readerfactory.c:977:RFBindFunctions() Loading IFD Handler 3.0 00000083 [140406854371648] ../src/ifdhandler.c:2130:init_driver() Driver version: 1.6.2 00001019 [140406854371648] ../src/ifdhandler.c:2152:init_driver() LogLevel: 0x0003 00000012 [140406854371648] ../src/ifdhandler.c:2163:init_driver() DriverOptions: 0x0000 00000370 [140406854371648] ../src/ifdhandler.c:2176:init_driver() LogLevel from LIBCCID_ifdLogLevel: 0x000F 00000040 [140406854371648] ../src/ifdhandler.c:93:CreateChannelByNameOrChannel() Lun: 0, device: usb:08e6/3438:libudev:0:/dev/bus/usb/004/006 00000011 [140406854371648] ../src/ccid_usb.c:261:OpenUSBByName() Reader index: 0, Device: usb:08e6/3438:libudev:0:/dev/bus/usb/004/006 00000069 [140406854371648] ../src/ccid_usb.c:293:OpenUSBByName() interface_number: 0 00000008 [140406854371648] ../src/ccid_usb.c:294:OpenUSBByName() usb bus/device: 4/6 00000006 [140406854371648] ../src/ccid_usb.c:331:OpenUSBByName() Using: /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist 00001026 [140406854371648] ../src/ccid_usb.c:349:OpenUSBByName() ifdManufacturerString: Ludovic Rousseau (ludovic.rousseau@free.fr) 00000008 [140406854371648] ../src/ccid_usb.c:350:OpenUSBByName() ifdProductString: Generic CCID driver 00000007 [140406854371648] ../src/ccid_usb.c:351:OpenUSBByName() Copyright: This driver is protected by terms of the GNU Lesser General Public License version 2.1, or (at your option) any later version. 00011059 [140406854371648] ../src/ccid_usb.c:435:OpenUSBByName() Try device: 4/6 00000062 [140406854371648] ../src/ccid_usb.c:445:OpenUSBByName() vid/pid : 08E6/3438 00000007 [140406854371648] ../src/ccid_usb.c:561:OpenUSBByName() Checking device: 4/6 00000005 [140406854371648] ../src/ccid_usb.c:632:OpenUSBByName() Trying to open USB bus/device: 4/6 00000136 [140406854371648] ../src/ccid_usb.c:638:OpenUSBByName() Can't libusb_open(4/6): LIBUSB_ERROR_ACCESS 00000706 [140406854371648] ../src/ccid_usb.c:208:close_libusb_if_needed() libusb_exit 00000239 [140406854371648] ../src/ccid_usb.c:892:OpenUSBByName() Device not found? 00000103 [140406854371648] ../src/ifdhandler.c:134:CreateChannelByNameOrChannel() failed 00000042 [140406854371648] ../src/readerfactory.c:1144:RFInitializeReader() Open Port 0x200000 Failed (usb:08e6/3438:libudev:0:/dev/bus/usb/004/006) 00000007 [140406854371648] ../src/readerfactory.c:371:RFAddReader() Gemalto USB Shell Token V2 init failed. 00000008 [140406854371648] ../src/readerfactory.c:627:RFRemoveReader() UnrefReader() count was: 1 00000005 [140406854371648] ../src/readerfactory.c:1157:RFUnInitializeReader() Attempting shutdown of Gemalto USB Shell Token V2 00 00. 00000006 [140406854371648] ../src/readerfactory.c:1014:RFUnloadReader() Unloading reader driver. 00000830 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/001/001 00000225 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/001/001 00000223 [140406854371648] ../src/hotplug_libudev.c:299:get_driver() Looking for a driver for VID: 0x05AC, PID: 0x8403, path: /dev/bus/usb/001/003
And the reader is not available for PC/SC applications:
Solution
The reader driver must set the access rights of the device file, such as
/dev/bus/usb/004/006 in the example above, so that the pcscd group
has read and write access rights.
Please note that the file belongs to the pcscd group and not the root group.
Implementation
Create a udev rule file that contains something like:
# If not adding the device, go away ACTION!="add", GOTO="foobar_rules_end" SUBSYSTEM!="usb", GOTO="foobar_rules_end" ENV{DEVTYPE}!="usb_device", GOTO="foobar_rules_end" # CherrySmartTerminalST2XXX.txt ATTRS{idVendor}=="046A", ATTRS{idProduct}=="003E", GROUP="pcscd" # All done LABEL="foobar_rules_end"
For example the libccid udev rule file is available at https://salsa.debian.org/rousseau/CCID/-/blob/master/src/92_pcscd_ccid.rules?ref_type=heads#L12. The important part for the generic CCID driver is:
For earch USB device with an interface equal to 0x0b, i.e. CCID class, then set the group to pcscd.
The pcscd group should be created by the installation of pcsc-lite package. If it is not the case for your distribution, you should report it as a bug to your distribution pcsc-lite package.
Build requirements
To build the CCID driver with this new feature, you need to have udev pkg-config file installed.
You need to be able to get the udevdir variable from the udev.pc
file:
For Debian/Ubuntu and derivatives distributions just install the package systemd-dev.
Conclusion
This change significantly improves your system security. A bug in pcsc-lite, or in a smart card reader driver used by pcsc-lite, will not allow an attacker to gain access to the root account. The attacker would only have access to a normal/unprivileged account.
This mechanism cannot be used everywhere, for example on systems without systemd or udev. However, most GNU/Linux systems should be covered.