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

Reply via email to