gnome-shell debdiff for noble (LP: #2170508).
** Description changed:
+ [ Impact ]
+
+ With smartcard authentication configured through SSSD (pam_cert_auth, a
+ certmap rule and the gdm-smartcard-sssd-* PAM service), GDM is meant to start
+ the gdm-smartcard conversation without a username when a smartcard is
+ inserted, so that pam_sss can identify the user from the certificate and the
+ user only types the PIN.
+
+ This doesn't work, because of two independent bugs, and both must be
+ fixed:
+
+ 1. gnome-shell (Ubuntu authd patch set, Login Options button): if the card is
+ already inserted when the login screen starts, the greeter cancels the
+ username-less gdm-smartcard conversation about 10 ms after starting it
+ ("GdmManager: Session was cancelled", then "Object
+ Gdm.UserVerifierProxy ... has been already disposed" and an unhandled
+ promise rejection). The login screen is left with a PIN entry that no PAM
+ conversation is behind.
+
+ Cause: the smartcard makes gdm-smartcard the foreground service by
+ preempting the default service (gdm-password).
+ ShellUserVerifier._getForegroundMechanism() only builds a mechanism for
+ the default service, so it returns null. Populating the Login Options menu
+ then makes the Smartcard mechanism active, setForegroundMechanism() sees a
+ change from null, emits foreground-mechanism-changed, and the auth prompt
+ resets, cancelling the conversation. Re-inserting the card works because
+ by then the foreground mechanism is already set.
+
+ 2. gdm3 (Debian packaging, debian/gdm3.gdm-smartcard-*.pam): the stacks start
+ with "pam_succeed_if.so user != root". pam_succeed_if calls
+ pam_get_user(), which prompts for a username when none is set, so GDM
+ shows a "Username" entry and pam_sss never gets to identify the user. The
+ same reasoning moved pam_nologin after the smartcard module in 2021
+ (LP: #1917362); pam_succeed_if was assumed to return PAM_USER_UNKNOWN
+ instead, but it prompts.
+
+ Users have to type their username (or pick it from the list, or re-insert
+ the card) before smartcard login proceeds.
+
+ [ Test Plan ]
+
+ On a machine (or VM) with GDM, SSSD smartcard login configured for a local
+ user (pam_cert_auth = True, a certmap rule matching the card's certificate,
+ the CA in /etc/sssd/pki/sssd_auth_ca_db.pem), and a PIV card or token:
+
+ 1. Insert the card and reboot (or restart gdm) so the card is present when
+ the greeter starts.
+ 2. Expected: the login screen asks "PIN for <user>:" straight away; entering
+ the PIN logs the user in. `journalctl -b | grep gdm-smartcard` shows the
+ conversation started with username=(null) and then "username is
+ '<user>'", and no "Session was cancelled".
+ Before the fix: a PIN entry with no prompt (gnome-shell bug), or a
+ "Username" prompt (gdm3 bug).
+ 3. Remove and re-insert the card at the login screen: same result.
+ 4. Without a card: password login still works, and the Login Options menu
+ still switches between Password and Smartcard when a card is inserted.
+ 5. root cannot log in through gdm-smartcard, with a card mapped to root or
+ through the password fallback (sssd-exclusive with SSSD not installed).
+
+ Verified in VMs with a simulated PIV card (PivApplet in jCardSim behind
+ vsmartcard-vpcd, opensc), with the attached changes built on noble
+ (gnome-shell 46.0-0ubuntu6~24.04.16, gdm3 46.2-1ubuntu1~24.04.9) and
+ resolute (gnome-shell 50.1-0ubuntu1.4, gdm3 50.1-0ubuntu0.1).
+
+ [ Where problems could occur ]
+
+ gnome-shell: _getForegroundMechanism() now also returns a mechanism when a
+ discrete service other than the default one is in the foreground. Only
+ gdm-smartcard can be such a service (credential managers and the unified
+ authd service have no discrete definition and still return null). A mistake
+ here would show up as the login or unlock screen not switching mechanism
+ when a smartcard is inserted or removed, or the Login Options menu selecting
+ the wrong mechanism.
+
+ gdm3: the root check moves after the smartcard module in all three
+ gdm-smartcard stacks, and gdm-smartcard-sssd-or-password's pam_sss success
+ jump changes from 2 to 1, so that it no longer skips pam_nologin (which
+ e8a5b196 meant to always run). A mistake would show up as smartcard login
+ failing, root being allowed in through gdm-smartcard, or /run/nologin not
+ being honoured. Only the gdm-smartcard service is affected; gdm-password and
+ the other services are unchanged.
+
+ [ Other Info ]
+
+ Debian merge request for gdm3:
+ https://salsa.debian.org/gnome-team/gdm/-/merge_requests/49
+
+ GNOME 51 (stonking, tenacious): the gnome-shell code involved was replaced
+ upstream (authServices.js, gdm-switchable-auth), so the gnome-shell patch
+ is for noble and resolute only. Whether 51 has an equivalent greeter problem
+ is untested: the stonking greeter would not stay up in the test VM (likely
+ LP: #2170614). The gdm3 PAM change applies to 51 unchanged, and a debdiff
+ for tenacious is attached.
+
+ Debdiffs attached: gnome-shell for noble and resolute; gdm3 for noble,
+ resolute and tenacious.
+
+ [ Original description ]
+
[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
** Patch added: "gnome-shell_46.0-0ubuntu6~24.04.17.debdiff"
https://bugs.launchpad.net/bugs/2170508/+attachment/6011056/+files/gnome-shell_46.0-0ubuntu6~24.04.17.debdiff
--
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/gdm3/+bug/2170508/+subscriptions
--
desktop-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/desktop-bugs