Public bug reported:

[What happened]

With SSSD smartcard authentication configured (YubiKey PIV, certmap rule mapping
the certificate to a local user), the GDM login screen does not automatically
fill in my username when the machine boots with the YubiKey already inserted.
I have to pick my user from the user list manually, after which smartcard PIN
auth proceeds normally.

[What I expected]

The greeter should begin smartcard verification with no username, let pam_sss
resolve the certificate to a user, and prefill it. This is the documented and
intended behaviour, and gnome-shell explicitly aims for it — gdm/util.js
`_initSmartcardManager()` carries the comment:

    // We check for smartcards right away, since an inserted smartcard
    // at startup should result in immediately initiating authentication.

[Steps to reproduce]

1. Configure SSSD smartcard auth for a local user (pam_cert_auth = true, a
   [certmap/...] rule matching the PIV cert, trust anchor in
   /etc/sssd/pki/sssd_auth_ca_db.pem).
2. Insert the smartcard and boot / restart gdm so the card is present *before*
   the greeter starts.
3. Observe: the username is not prefilled.
4. Now unplug and re-insert the card at the greeter. The username IS prefilled.

Step 4 is the key signal: it only fails when the card is present during the
greeter's initial setup.

[This is not an SSSD misconfiguration]

I verified the whole SSSD path works:

- p11_child, run against the configured CA DB, returns the token and
  certificate successfully:
  `/usr/libexec/sssd/p11_child --pre --ca_db=/etc/sssd/pki/sssd_auth_ca_db.pem`
  -> emits token name, module, key id, label and cert.
- The certmap rule loads (sssd_pam.log):
  `p11_refresh_certmap_ctx: Trying to add rule 
[user][-1][<SUBJECT>^CN=user$][(user)].`
- The cert -> user lookup succeeds:
  `pam_forwarder_lookup_by_cert_done: Found [1] certificates and [1] related 
users.`
- /etc/pam.d/gdm-smartcard has the correct
  `pam_sss.so allow_missing_name try_cert_auth`.

Crucially, SSSD's PAM responder records *no* request at the time of the failed
attempt. gdm3 (with debug enabled) logs `starting conversation gdm-smartcard` at
22:55:46, but the first gdm-smartcard transaction to reach sssd_pam.log is 26
seconds later, and it already arrives with `user:` and `logon name:` set — i.e.
after I selected my name by hand. The username-less BeginVerification never
lands, so SSSD is never asked to map the certificate.

[Root cause]

gnome-shell aborts the username-less verification with an unhandled promise
rejection. Line numbers below are from the JS shipped in
gnome-shell 46.0-0ubuntu6~24.04.15 (extracted from
/usr/lib/gnome-shell/libshell-14.so). Full stack trace attached.

1. Card already inserted -> `_initSmartcardManager()` -> `_checkForSmartcard()`
   -> emits `smartcard-status-changed`.
2. `_onSmartcardStatusChanged` (authPrompt.js:542) -> `reset()` -> `_onReset`
   -> `_hideUserListAndBeginVerification` -> `begin()` -> `_getUserVerifier()`
   -> `_beginVerification()`.
3. `_beginVerification()` (util.js:1044):
     this._startService(foregroundService);            // line 1053
     this._startBackgroundServices();
     this._generateMechanismsFromDiscreteServices();   // line 1055
   `_startService` is `async` and is NOT awaited. It acquires the hold and then
   suspends on `await this._userVerifier.call_begin_verification(...)` — the 
very
   call that would let pam_sss supply the username
   (`foregroundServiceDeterminesUsername()` returns true for smartcard).
4. Line 1055 then runs synchronously and emits `mechanisms-list-changed` ->
   `_onAuthMechanismsListChanged` (authPrompt.js:404) -> `_onMechanismsChanged`
   (loginDialog.js:1047) -> `AuthMenuButton.setActiveItem` 
(authMenuButton.js:202)
   -> `active-item-changed` -> the handler at loginDialog.js:632 ->
   `setForegroundMechanism` -> emits `foreground-mechanism-changed`.
5. `_onForegroundMechanismChanged` (authPrompt.js:545) calls `reset()`
   **unconditionally**, which re-enters `_getUserVerifier()` ->
   `_clearUserVerifier()` -> `this._userVerifier.run_dispose()`.
6. The suspended `_startService` from step 3 resumes against the freed proxy:
   "Object Gdm.UserVerifierProxy (0x...), has been already disposed". The
   promise rejects and nothing catches it, because line 1053 neither awaits nor
   attaches a .catch().

Note the asymmetry: `_onSmartcardStatusChanged` (authPrompt.js:535-539) already
has a re-entrancy guard for exactly this hazard:

    if (this._userVerifier.serviceIsDefault(GdmUtil.SMARTCARD_SERVICE_NAME) &&
        (this.verificationStatus === AuthPromptStatus.VERIFYING ||
         this.verificationStatus === AuthPromptStatus.VERIFICATION_IN_PROGRESS) 
&&
        this.smartcardDetected)
        return;

`_onForegroundMechanismChanged` has no equivalent guard.

This only triggers on the first population of the mechanism list, because both
`AuthMenuButton.setActiveItem` and `ShellUserVerifier.setForegroundMechanism`
early-return when the mechanism is unchanged. That is exactly why it fails at
boot (card present during initial setup) but works on re-insertion.

[Suggested fix]

Either of:

- Guard `_onForegroundMechanismChanged` against re-entering reset while a
  verification is already in flight, mirroring `_onSmartcardStatusChanged`; or
- Await (or at minimum `.catch()`) `_startService()` at util.js:1053, and don't
  emit a mechanism-list change that can re-enter `reset()` from inside
  `_beginVerification()`.

[Scope]

authMenuButton.js, `_generateMechanismsFromDiscreteServices` and
`setForegroundMechanism` are not in upstream GNOME 46; they arrive via the
Ubuntu authd patch set (d/changelog: "debian/patches/authd: Cleanup code and fix
mechanism switch handling"). So this looks Ubuntu-specific rather than upstream.

Note `com.ubuntu.login-screen enable-authd-authentication=false` does NOT avoid
it: `_generateMechanismsFromDiscreteServices` is not gated on that key (it
synthesizes mechanisms from the discrete gdm-smartcard/gdm-password services;
the key only gates the gdm-authd unified service at util.js:899).

[Workaround]

Unplug and re-insert the smartcard at the login screen.

[Possibly related]

LP#2161662 "smartcard auth breaks lockscreen" — different symptom and a much
newer gnome-shell (50.1 on 26.04), but same area of code.

[Versions]

Ubuntu 24.04.5 LTS, x11 session
gnome-shell   46.0-0ubuntu6~24.04.15
gdm3          46.2-1ubuntu1~24.04.9
sssd          2.9.4-1.1ubuntu6.8
libpam-sss    2.9.4-1.1ubuntu6.8
opensc        0.25.0~rc1-1ubuntu0.2
pcscd         2.0.3-1build1
kernel        7.0.0-38-generic
Hardware token: YubiKey (PIV), self-signed PIV certs, trust anchor installed in
/etc/sssd/pki/sssd_auth_ca_db.pem

** Affects: gnome-shell (Ubuntu)
     Importance: Undecided
         Status: New

** Attachment added: "Trace of the smartcard logic"
   
https://bugs.launchpad.net/bugs/2170508/+attachment/6008319/+files/gnome-shell-smartcard-trace.txt

-- 
You received this bug notification because you are a member of Ubuntu
Desktop Bugs, which is subscribed to gnome-shell in Ubuntu.
https://bugs.launchpad.net/bugs/2170508

Title:
  GDM does not prefill the username from a smartcard when the card is
  already inserted at greeter startup (re-entrant reset disposes the
  UserVerifierProxy)

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/2170508/+subscriptions


-- 
desktop-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/desktop-bugs

Reply via email to