Public bug reported:

[Impact]

If you enable smartcard authentication on Ubuntu Desktop on Jammy, and
set it up so the smartcard must be present for all authentication
attempts, enforced by PAM's require_cert_auth, if you remove the
smartcard, it will fall back to password authentication.

What is worse is that the password authentication will work, skipping
the point of having a smartcard in the first place.

require_cert_auth should enforce the smartcard be present, and should
not fallback to password authentication.

[Testcase]

This testcase is courtesy of Fabio Miranda Martins, who diligently
researched and explained it in excellent detail.

In order to reproduce the issue following the same steps as I'm using,
you will need at least one Windows Active Directory enabled with Active
Directory Certificate Services [1] and one Yubikey to be used as a
smartcard [2], but it should be possible to reproduce the same problem
with any smartcard and most likely any sort of smartcard based
authentication using SSSD [3] [4].

[1] 
https://learn.microsoft.com/en-us/windows-server/identity/ad-cs/active-directory-certificate-services-overview
[2] https://www.yubico.com/
[3] https://ubuntu.com/server/docs/smart-card-authentication
[4] 
https://ubuntu.com/tutorials/how-to-use-smart-card-authentication-in-ubuntu-desktop#1-overview

Launch one Jammy desktop and one Noble desktop VMs, so you can compare
the behavior on both, and then:

0. Prereqs and Joining the Domain:

    sudo add-apt-repository ppa:yubico/stable
    sudo apt-get update
    sudo apt upgrade -y
    sudo apt install libpam-sss opensc-pkcs11 pcscd libpam-pkcs11 sssd opensc 
sssd-dbus sssd-tools yubico-piv-tool sssd-ad realmd adcli vim krb5-user 
krb5-pkinit -y
     
    sudo realm -v discover <domain controller>
    sudo realm -v join <domain controller>
    
1. Generate a private key:

    yubico-piv-tool -a generate -s 9a -A RSA2048 -o fabiopub.key

2. Generate a CSR:

    yubico-piv-tool -a verify-pin -a request-certificate -s 9a -S
'/CN=Fabio Martins/OU=Users/O=fabiomirmar.net/' -i fabiopub.key -o
fabiocsr.pem

3. cat the content of fabiocsr.pem and paste into the Active Directory
Certificate Services website to issue the certificate
(https://<active_directory_ip_address>/certsrv/). Make sure to login as
the Domain user for which you want to issue the certificate. Click
Request a certificate, advanced certificate request, and paste the
content of the csr file.

4. Download the certificate and the CA from the tool and save back into
the Ubuntu VM

5. Convert the certificate to pem format:

    openssl x509 -in ./fabioissued.cer -out fabioissued.pem -outform pem

6. Make sure it looks OK:

    cat fabioissued.pem | openssl x509 -text -noout

7. If you need the certificate in der format for some reason you can
use:

    openssl x509 -in ./fabioissued.pem -out fabioissued.der -outform der

8. Import the certificate to yubikey:

    yubico-piv-tool -a import-certificate -s 9a -k -i fabioissued.pem

9. You don't need to use ldapmodify to add the certificate to the user.
You can query the user with ldapsearch and will notice that the
certificate is already added by AD when it issued the certificate:

    ldapsearch -x -H ldap://<domain controller> -D
"[email protected]" -W  -b "CN=Fabio
Martins,CN=Users,DC=fabiomirmar,DC=net"

10. If you would like to confirm that the certificate in the ldapsearch
output matches the one you downloaded from ADCS, you can save the
content from the userCertificate field into a tempfile. That's a base64
encoded DER formatted certificate. Then you can convert from DER to PEM
and compare (they should match):

    cat ldapcertoutput.base64 | tr -d '\n' | base64 -d  > ldapcertoutput.der
    openssl x509 -in ./ldapcertoutput.der -out ldapcertoutput.pem -outform pem
    diff ldapcertoutput.pem fabioissued.pem

11. Make sure the certificate from yubikey looks correct:

    pkcs15-tool --read-certificate 1 > card-cert.pem
    openssl x509 -text -noout -in card-cert.pem

12. When you downloaded the CA certificate, it was provided in a DER
format. Convert it to PEM:

    openssl x509 -in ./cacert.cer -out cacert.crt -outform pem

13. Add the CA to the Ubuntu VM:

    sudo cp cacert.crt /usr/local/share/ca-certificates/
    sudo update-ca-certificates

14. This is duplicate effort, but you can also add to the CA file being
used by SSSD and kerberos. In our Lab:

    sudo mkdir /etc/sssd/pki/
    cat cacert.crt | sudo tee -a /etc/sssd/pki/sssd_auth_ca_db.pem

15. Check that openssl is able to validate the certificate against the
CA:

    openssl verify -verbose card-cert.pem
    openssl verify -verbose -CAfile /etc/sssd/pki/sssd_auth_ca_db.pem 
card-cert.pem

Both should say "OK"

16. Make sure you configure sssd.conf with the appropriate certmap. This
is how my file look like:

    [pam]
    pam_cert_auth = True
    pam_cert_db_path = /etc/sssd/pki/sssd_auth_ca_db.pem
     
    [certmap/fabiomirmar.net/fabio]
    matchrule = <SUBJECT>CN=Fabio.*
    maprule = (userCertificate;binary={cert!bin})
     
    [sssd]
    certificate_verification = partial_chain
    domains = fabiomirmar.net
    config_file_version = 2
    services = nss, pam
    default_domain_suffix = fabiomirmar.net
     
    [domain/fabiomirmar.net]
    default_shell = /bin/bash
    ad_server = <domain controller>
    krb5_store_password_if_offline = True
    cache_credentials = True
    krb5_realm = FABIOMIRMAR.NET
    realmd_tags = manages-system joined-with-adcli 
    id_provider = ad
    fallback_homedir = /home/%u
    ad_domain = fabiomirmar.net
    use_fully_qualified_names = True
    ldap_id_mapping = True
    access_provider = ad

17. Make sure to configure krb5.conf correctly:

NOTE: Setting pkinit_kdc_hostname and pkinit_eku_checking were required
for this to work. Depending on the ADCS / Certificate configuration, you
might not need this:

    # cat /etc/krb5.conf 
     
    [libdefaults]
    udp_preference_limit = 0
    default_realm = FABIOMIRMAR.NET
    pkinit_anchors = FILE:/etc/sssd/pki/sssd_auth_ca_db.pem
    pkinit_kdc_hostname = <domain controller>
    pkinit_eku_checking = none
    #rdns = false
    #dns_lookup_realm = false
     
    [domain_realm]
     
    [plugins]
     localauth = {
      module = 
sssd:/usr/lib/x86_64-linux-gnu/sssd/modules/sssd_krb5_localauth_plugin.so
     }

18. Configure PAM:

- For noble:

    $ sudo pam-auth-update --disable sss-smart-card-optional --enable
sss-smart-card-required

- For jammy:

Edit /etc/pam.d/common-auth and add:

    auth    [success=3 ignore=ignore default=die]   pam_sss.so
allow_missing_name require_cert_auth

The order matters, and I've been using the exact same order as we get in
noble. Example:

    ubuntu@jammy-desktop:~$ sudo cat /etc/pam.d/common-auth     
    # here are the per-package modules (the "Primary" block)
    auth    [success=3 ignore=ignore default=die]   pam_sss.so 
allow_missing_name require_cert_auth
    auth        [success=2 default=ignore]      pam_unix.so nullok
    auth        [success=1 default=ignore]      pam_sss.so use_first_pass
    # here's the fallback if no module succeeds
    auth        requisite                       pam_deny.so
    # prime the stack with a positive return value if there isn't one already;
    # this avoids us returning an error just because nothing sets a success code
    # since the modules above will each just jump around
    auth        required                        pam_permit.so
    # and here are more per-package modules (the "Additional" block)
    auth        optional                        pam_cap.so 
    # end of pam-auth-update config

Also on both jammy and noble, configure pam to automatically create the
home directory:

    sudo pam-auth-update --enable mkhomedir

19. Restart SSSD

    systemctl restart sssd

20. Check that the certmap is working:

    pkcs15-tool --read-certificate 1 > card-cert.pem
     
    sudo dbus-send --system --print-reply --dest=org.freedesktop.sssd.infopipe 
/org/freedesktop/sssd/infopipe/Users 
org.freedesktop.sssd.infopipe.Users.ListByCertificate string:"$(cat 
card-cert.pem)" uint32:10

Now you should be able to login both on console and GDM using the
smartcard.

After loging in using GDM, open a terminal and try to run a sudo
command:

- Noble:

    [email protected]@noble-desktop2:~$ sudo -i
    PIN for Users: 
    [email protected] is not in the sudoers file.

- Jammy:

    [email protected]@jammy-desktop:~$ sudo -i
    PIN for Users: 
    [email protected] is not in the sudoers file.  This incident will be 
reported.

So far so good. Now, remove the smartcard and try again:

- Noble:

    [email protected]@noble-desktop2:~$ sudo -i
    Please insert smart card
    Please (re)insert (different) Smartcard
    Please (re)insert (different) Smartcard

- Jammy:

    [email protected]@jammy-desktop:~$ sudo -i
    Please insert smart card
    [sudo] password for [email protected]: 
    [email protected] is not in the sudoers file.  This incident will be 
reported.

As you can see from above, on Jammy it fallsback to password based
authentication, and that works if you type the correct password.

If you enable the following ppa, the issue is fixed and jammy now
behaves like Kinetic or later.

https://launchpad.net/~mruffell/+archive/ubuntu/sf395104-test

    ubuntu@jammy-desktop:~$ apt-cache policy sssd | grep Installed
      Installed: 2.6.3-1ubuntu3.3+sf395104v20240916b1
     
    [email protected]@jammy-desktop:~$ sudo -i
    Please insert smart card
    Please (re)insert (different) Smartcard
    Please (re)insert (different) Smartcard

[Where problems could occur]

We are changing the behaviour of require_cert_auth to actually do what
it says on the tin, which is to enforce that the smartcard is present,
and has the correct certificate in order for authentication to succeed.

require_cert_auth works in some cases, namely at the GDM login screen,
but doesn't in other places, like sudo.

The changes to require_cert_auth could potentially lock users out of
their systems, if they were relying on the broken behaviour of password
fallbacks. Users of these systems should hopefully have their smartcard
present and working in order to log in. If they don't, they will be
locked out of their systems.

It is very difficult to estimate if there is anyone relying on faulty
behaviour.

Since this changes how smartcards authenticate, if a regression were to
occur, it could affect anyone that uses smartcards with sssd / libpam-
sss.

[Other info]

Upstream bug:
https://github.com/SSSD/sssd/issues/6022
https://github.com/SSSD/sssd/issues/6023

Commits that fix the issue, landed in 2.7.0 present in Kinetic or later.

commit 731b3e668c6a659922466aee7fa8093412707325
Author: Sumit Bose <[email protected]>
Date:  Tue Apr 13 17:12:24 2021 +0200
Subject: pam: add more checks for require_cert_auth
Link: 
https://github.com/SSSD/sssd/commit/731b3e668c6a659922466aee7fa8093412707325

commit 4d2277f8c3065771a8c3bbc7938309a4905640f0
Author: Sumit Bose <[email protected]>
Date:  Mon Feb 21 18:02:47 2022 +0100
Subject: pam: better SC fallback message
Link: 
https://github.com/SSSD/sssd/commit/4d2277f8c3065771a8c3bbc7938309a4905640f0

** Affects: sssd (Ubuntu)
     Importance: Undecided
         Status: Fix Released

** Affects: sssd (Ubuntu Jammy)
     Importance: Medium
     Assignee: Matthew Ruffell (mruffell)
         Status: In Progress


** Tags: jammy sts

** Tags added: jammy sts

** Also affects: sssd (Ubuntu Jammy)
   Importance: Undecided
       Status: New

** Changed in: sssd (Ubuntu)
       Status: New => Fix Released

** Changed in: sssd (Ubuntu Jammy)
       Status: New => In Progress

** Changed in: sssd (Ubuntu Jammy)
   Importance: Undecided => Medium

** Changed in: sssd (Ubuntu Jammy)
     Assignee: (unassigned) => Matthew Ruffell (mruffell)

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

Title:
  libpam-sss: require_cert_auth is not absolute, will fall back to
  password auth on smartcard removal

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/sssd/+bug/2081129/+subscriptions


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

Reply via email to