pcsc-lite and polkit
Red Hat and derivatives (Fedora, etc.) use polkit to restrict access to the smart cards.
You can find documentation at Chapter 7. Controlling access to smart cards using polkit. polkit Authorization Manager is documented at polkit — Authorization Manager.
Test on Fedora 39
Local execution
I login on the console and run pcsc_scan
or scriptor
(both from
pcsc-tools): no problem.
Remote execution
I login using ssh and I get:
Logs
The message from pcscd logs is more explicit than the numerical value
SCARD_W_SECURITY_VIOLATION
(0x8010006A) returned by
SCardEstablishContext()
.
$ journalctl --unit=pcscd --follow [...] nov. 13 18:41:38 fedora39 pcscd[1353]: 40822797 auth.c:143:IsClientAuthorized() Process 6512 (user: 1000) is NOT authorized for action: access_pcsc nov. 13 18:41:38 fedora39 pcscd[1353]: 00000189 winscard_svc.c:336:ContextThread() Rejected unauthorized PC/SC client
New rule
To get access, when connecting from remote, I need to create a file
/usr/share/polkit-1/rules.d/03-polkit-pcscd.rules
containing:
polkit.addRule(function(action, subject) { if (action.id == "org.debian.pcsc-lite.access_pcsc" && subject.user == "rousseau") { return polkit.Result.YES; } });
The programming language in the rules file is JavaScript. You can change the code to be whatever you want.
Of course change the test subject.user == ...
to use your own login
name.
And now I can access PC/SC even when connected from remote.
There is another control, this time at the smart card reader level. Even
if I can access PC/SC to list readers I may not be allowed to access the
readers. For example if I use scriptor
to use the smart card
inserted in the reader I get:
$ scriptor No reader given: using Alcor Micro AU9540 00 00 Can't allocate Chipcard::PCSC::Card object: Access denied.
To access a specific reader I need to add a new rule in
/usr/share/polkit-1/rules.d/03-polkit-pcscd.rules
.
polkit.addRule(function(action, subject) { if (action.id == "org.debian.pcsc-lite.access_card" && action.lookup("reader").startsWith('Alcor Micro AU9540') && subject.user == "rousseau") { return polkit.Result.YES; } });
Note the test action.lookup("reader").startsWith('Alcor Micro AU9540')
.
You could use the test for string equality ==
but the reader name is
"Alcor Micro AU9540 00 00" and I don't care about the numbers at the end
of the reader name. The numbers indicate the index and slot. See
What is in a PC/SC reader name?. I want to be able to access this
specific reader even if it is the second reader connected with index=01
insead of 00.
With this second polkit rule I can access the reader and I get:
$ scriptor No reader given: using Alcor Micro AU9540 00 00 Using T=0 protocol Reading commands from STDIN
See Controlling access to smart cards for more examples.
Disabling polkit
You can disable polkit at build time using ./configure --disable-polkit
.
But you may not want to rebuild a package provided by your GNU/Linux
distribution.
It is also possible to disable polkit at runtime using pcscd --disable-polkit
.
In general pcscd
(the PC/SC daemon) is started by systemd so the solution is to create a file
/etc/default/pcscd
with the content:
Issues
This default configuration is causing some problems when you access a remote system (RDP, ssh, etc.). For example see Bug 1478345 - Repeated authentication requests in remote session.
It is the job of the system administrator to define who has access to what in the system. The default is to refuse the smart card accesses from a non local user. I think this is a good choice, but we can discuss it and change the default behaviour.
Non Red Hat systems
Debian now provides a recent enough version of polkit library polkit-gobject-1. I have enabled polkit support by default in pcsc-lite. So Debian, Ubuntu and derivatives systems and other GNU/Linux distribution will also benefit from polkit security feature.
Conclusion
polkit is a nice security feature.
I have other possible security improvements for pcsc-lite in my list like Use systemd to restrict pcscd rights. If you want to have them implemented please contact me.