QubesOS / qubes-issues

The Qubes OS Project issue tracker
https://www.qubes-os.org/doc/issue-tracking/
534 stars 47 forks source link

RPC service ctap.ClientPin is called 4 times for a single use of the PIN #8847

Open ben-grande opened 9 months ago

ben-grande commented 9 months ago

How to file a helpful issue

Qubes OS release

R4.2

Brief summary

Try to register or authenticate with Qubes CTAP, notice that when the policy for ctap.ClientPin is set to ask, it will ask 2 (two) times before being able to enter the device PIN and 2 (two) times after the PIN has been entered.

Steps to reproduce

  1. Have a FIDO2 device with a PIN configured
  2. Go to https://webauthn.io/
  3. Insert username and click on Register
  4. Accept ctap.GetInfo, accept ctap.ClientPin and accept again ctap.ClientPin
  5. Enter the PIN for the device
  6. Accept ctap.ClientPin and accept again ctap.ClientPin
  7. Accept u2f.Authenticate (optional) as it is unrelated to the problem

If I can provide the proxy logs, please let me know how to find them. It may be an error with the testing site... but that is a reference site.

qrexec: ctap.GetInfo+: disp6066 -> sys-usb-left: allowed to sys-usb-left
qrexec: ctap.ClientPin+: disp6066 -> sys-usb-left: allowed to sys-usb-left
qrexec: ctap.ClientPin+: disp6066 -> sys-usb-left: allowed to sys-usb-left
qrexec: ctap.ClientPin+: disp6066 -> sys-usb-left: allowed to sys-usb-left
qrexec: ctap.ClientPin+: disp6066 -> sys-usb-left: allowed to sys-usb-left
qrexec: u2f.Authenticate+somestring: disp6066 -> sys-usb-left: allowed to sys-usb-left

Expected behavior

Accept ctap.ClientPin prompt only once.

Actual behavior

Accept ctap.ClientPin 4 times.

UndeadDevel commented 9 months ago

Possibly related: #8808

marmarek commented 9 months ago

@piotrbartman any ideas? @ben-grande try enabling debug log, maybe it will explain things

ben-grande commented 9 months ago

I managed to enable debug logs on sys-usb.

I don't understand how private these information really are to share, the client pin, the codes sent and received... I understand they are local to my device, but I don't know how to share relevant data without sharing everything... for example, policy.RegisterArgument +u2f.Authenticate leaks all configured policies to sys-usb.

Bellow you will find the duplicated ctap.ClientPin.

ctap.GetInfo

sys-usb qrexec-agent[5669]: qrexec-agent[5669]: qrexec-agent-data.c:293:handle_new_process_common: executed: root:QUBESRPC ctap.GetInfo+ disp6066 (pid 5671)
sys-usb qrexec-agent[5671]: pam_unix(qrexec:session): session opened for user root(uid=0) by (uid=0)
sys-usb systemd[1]: Started session-c147.scope - Session c147 of User root.
sys-usb qctap-get-info[5672]: asyncio Using selector: EpollSelector
sys-usb qctap-get-info[5672]: fido2.hid SEND:  [REDACTED]
sys-usb qctap-get-info[5672]: fido2.hid RECV:  [REDACTED]
sys-usb qctap-get-info[5672]: mux pending={<Future pending cb=[_chain_future.<locals>._call_check_cancel() at /usr/lib/python3.11/asyncio/futures.py:387]>}
sys-usb qctap-get-info[5672]: ctap.request Use CTAP 2 protocol.
sys-usb qctap-get-info[5672]: ctap.request return CborRequestWrapper
sys-usb qctap-get-info[5672]: mux.device request: b'[REDACTED]'
sys-usb qctap-get-info[5672]: fido2.hid SEND:  [REDACTED]
sys-usb qctap-get-info[5672]: fido2.hid RECV: [REDACTED]
sys-usb qctap-get-info[5672]: fido2.hid RECV: [REDACTED]
sys-usb qctap-get-info[5672]: fido2.hid RECV: [REDACTED]
sys-usb qctap-get-info[5672]: ctap Execute CTAP2 request
sys-usb qctap-get-info[5672]: fido2.hid SEND:  [REDACTED]
sys-usb qctap-get-info[5672]: fido2.hid SEND: [REDACTED]
sys-usb qctap-get-info[5672]: fido2.hid RECV: [REDACTED]
sys-usb qctap-get-info[5672]: fido2.hid RECV: [REDACTED]
sys-usb qctap-get-info[5672]: fido2.hid RECV: [REDACTED]
sys-usb qctap-get-info[5672]: mux.device response b'[REDACTED]'
sys-usb qctap-get-info[5672]: root pending=set() done={<Future finished result=<qubesctap.pr...x78e110f8f010>>}
sys-usb qrexec-agent[5671]: pam_unix(qrexec:session): session closed for user root
sys-usb qrexec-agent[5669]: qrexec-agent[5669]: qrexec-agent-data.c:324:handle_new_process_common: pid 5671 exited with 0
sys-usb systemd[1]: session-c147.scope: Deactivated successfully.

ctap.GetPin

sys-usb qrexec-agent[5684]: qrexec-agent[5684]: qrexec-agent-data.c:293:handle_new_process_common: executed: root:QUBESRPC ctap.ClientPin+ disp6066 (pid 5687)
sys-usb qrexec-agent[5687]: pam_unix(qrexec:session): session opened for user root(uid=0) by (uid=0)
sys-usb systemd[1]: Started session-c148.scope - Session c148 of User root.
sys-usb qctap-client-pi[5688]: asyncio Using selector: EpollSelector
sys-usb qctap-client-pi[5688]: fido2.hid SEND: [REDACTED]
sys-usb qctap-client-pi[5688]: fido2.hid RECV: [REDACTED]
sys-usb qctap-client-pi[5688]: mux pending={<Future pending cb=[_chain_future.<locals>._call_check_cancel() at /usr/lib/python3.11/asyncio/futures.py:387]>}
sys-usb qctap-client-pi[5688]: ctap.request Use CTAP 2 protocol.
sys-usb qctap-client-pi[5688]: ctap.request return CborRequestWrapper
sys-usb qctap-client-pi[5688]: mux.device request: b'[REDACTED]'
sys-usb qctap-client-pi[5688]: fido2.hid SEND: [REDACTED]
sys-usb qctap-client-pi[5688]: fido2.hid RECV: [REDACTED]
sys-usb qctap-client-pi[5688]: fido2.hid RECV: [REDACTED]
sys-usb qctap-client-pi[5688]: fido2.hid RECV: [REDACTED]
sys-usb qctap-client-pi[5688]: ctap Execute CTAP2 request
sys-usb qctap-client-pi[5688]: fido2.hid SEND: [REDACTED]
sys-usb qctap-client-pi[5688]: fido2.hid RECV: [REDACTED]
sys-usb qctap-client-pi[5688]: fido2.hid RECV: [REDACTED]
sys-usb qctap-client-pi[5688]: fido2.hid RECV: [REDACTED]
sys-usb qctap-client-pi[5688]: mux.device response b'[REDACTED]'
sys-usb qctap-client-pi[5688]: root pending=set() done={<Future finished result=<qubesctap.pr...x70e96441ec10>>}
sys-usb qrexec-agent[5687]: pam_unix(qrexec:session): session closed for user root
sys-usb qrexec-agent[5684]: qrexec-agent[5684]: qrexec-agent-data.c:324:handle_new_process_common: pid 5687 exited with 0
sys-usb systemd[1]: session-c148.scope: Deactivated successfully.

ctap.ClientPin (second)

sys-usb qrexec-agent[5699]: qrexec-agent[5699]: qrexec-agent-data.c:293:handle_new_process_common: executed: root:QUBESRPC ctap.ClientPin+ disp6066 (pid 5701)
sys-usb qrexec-agent[5701]: pam_unix(qrexec:session): session opened for user root(uid=0) by (uid=0)
sys-usb systemd[1]: Started session-c149.scope - Session c149 of User root.
sys-usb qctap-client-pi[5702]: asyncio Using selector: EpollSelector
sys-usb qctap-client-pi[5702]: fido2.hid SEND: [REDACTED]
sys-usb qctap-client-pi[5702]: fido2.hid RECV: [REDACTED]
sys-usb qctap-client-pi[5702]: mux pending={<Future pending cb=[_chain_future.<locals>._call_check_cancel() at /usr/lib/python3.11/asyncio/futures.py:387]>}
sys-usb qctap-client-pi[5702]: ctap.request Use CTAP 2 protocol.
sys-usb qctap-client-pi[5702]: ctap.request return CborRequestWrapper
sys-usb qctap-client-pi[5702]: mux.device request: b'[REDACTED]'
sys-usb qctap-client-pi[5702]: fido2.hid SEND: [REDACTED]
sys-usb qctap-client-pi[5702]: fido2.hid RECV: [REDACTED]
sys-usb qctap-client-pi[5702]: fido2.hid RECV: [REDACTED]
sys-usb qctap-client-pi[5702]: fido2.hid RECV: [REDACTED]
sys-usb qctap-client-pi[5702]: ctap Execute CTAP2 request
sys-usb qctap-client-pi[5702]: fido2.hid SEND: [REDACTED]
sys-usb qctap-client-pi[5702]: fido2.hid RECV: [REDACTED]
sys-usb qctap-client-pi[5702]: mux.device response b'[REDACTED]'
sys-usb qctap-client-pi[5702]: root pending=set() done={<Future finished result=<qubesctap.pr...x71c430b667d0>>}
sys-usb qrexec-agent[5701]: pam_unix(qrexec:session): session closed for user root
sys-usb qrexec-agent[5699]: qrexec-agent[5699]: qrexec-agent-data.c:324:handle_new_process_common: pid 5701 exited with 0
sys-usb systemd[1]: session-c149.scope: Deactivated successfully.
ben-grande commented 9 months ago

I forgot to mention, everything above was with Chromium 120.0.6099.199.

With Firefox 115.6.0esr, ctap.ClientPin is asked only once, no password prompt in webauthn.io, but u2f.Register and u2f.Authenticate are hard, there is not limit of how many times it may take to work besides possibly timing out. The response time is too short t to press the key, something like less than a second, pressing the key before accepting the prompt does not help much, it can still fail to authenticate. It varied for me of accept the u2f.* prompts from 4 to 8 times.... because it does not give enough time to press it.

With this, I'd say that Chromium has the best integration with Qubes CTAP Proxy as of now.

ben-grande commented 9 months ago

@andrewdavidwong I believe you removed the tag C: U2F proxy by mistake.

ben-grande commented 5 months ago

Update: if site requires a pin, the call ctap.ClientPin is run 4 times. If the site does not require a pin from the FIDO key, the call happens only once.