pcsc: guide by PolicyKit actions, not a pcscd group

A headless/SSH box can show a world-writable /run/pcscd/pcscd.comm
(srw-rw-rw- root root) and still be denied: pcscd enforces its PolicyKit
policy, whose defaults allow only active local sessions.  The startup
report, the start.sh pre-flight and the README troubleshooting now name
the exact rule (99-pcscd-allow.rules, org.debian.pcsc-lite.access_pcsc
and access_card) and explain why the socket mode does not matter.  The
pcscd-group instruction is gone: there may be no such group, and it is
not the gate.  The group route stays only as a note for a pcscd built
without PolicyKit.

Tests: tests/test_pcsc_startup.py asserts the polkit action IDs, the
rule filename and the 0666-socket explanation.
1088 Python + 1075 frontend.
This commit is contained in:
2026-10-25 00:50:24 +03:00
parent 2ecf7bb45c
commit 295f5553fc
6 changed files with 60 additions and 14 deletions
+11 -2
View File
@@ -102,7 +102,12 @@ class ReportTests(unittest.TestCase):
low = text.lower()
self.assertIn('access denied', low)
self.assertIn('pcscd', low)
self.assertIn('usermod -aG pcscd'.lower(), low)
# polkit, not the socket group, is the gate (the socket can be 0666)
self.assertIn('polkit', low)
self.assertIn('org.debian.pcsc-lite.access_pcsc', low)
self.assertIn('org.debian.pcsc-lite.access_card', low)
self.assertIn('99-pcscd-allow.rules', low)
self.assertIn('0666', low)
self.assertIn('pcsc_scan', low)
self.assertIn('0x80100027', text)
@@ -136,8 +141,12 @@ class SourcePins(unittest.TestCase):
def test_the_start_script_probes_access_and_guides(self):
src = (Path(m.__file__).parent.parent / 'start.sh').read_text()
self.assertIn('from smartcard.System import readers', src)
self.assertIn('usermod -aG pcscd', src)
self.assertIn('polkit', src)
self.assertIn('org.debian.pcsc-lite.access_pcsc', src)
self.assertIn('99-pcscd-allow.rules', src)
self.assertIn('pcsc_scan', src)
# the group route is not the gate (the socket may be 0666)
self.assertNotIn('usermod -aG pcscd', src)
# the old "is pcscd running" heuristic is gone
self.assertNotIn('pgrep -x pcscd', src)