** Description changed:

  [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>
-     
+     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
+     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
+     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
+     openssl x509 -in ./fabioissued.cer -out fabioissued.pem -outform pem
  
  6. Make sure it looks OK:
  
-     cat fabioissued.pem | openssl x509 -text -noout
+     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
+     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
+     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
+     ldapsearch -x -H ldap://<domain controller> -D
  "administra...@fabiomirmar.net" -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
+     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
+     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
+     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
+     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
+     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
+     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
+     [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
-      }
+     # 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
+     $ 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:
+ 
+     fa...@fabiomirmar.net@noble-desktop2:~$ sudo -i
+     PIN for Users:
+     fa...@fabiomirmar.net is not in the sudoers file.
+ 
+ - Jammy:
+ 
+     fa...@fabiomirmar.net@jammy-desktop:~$ sudo -i
+     PIN for Users:
+     fa...@fabiomirmar.net is not in the sudoers file.  This incident will be 
reported.
+ 
+ So far so good. Now, remove the smartcard and try again:
+ 
+ - Noble:
+ 
+     fa...@fabiomirmar.net@noble-desktop2:~$ sudo -i
+     Please insert smart card
+     Please (re)insert (different) Smartcard
+     Please (re)insert (different) Smartcard
+ 
+ - Jammy:
+ 
+     fa...@fabiomirmar.net@jammy-desktop:~$ sudo -i
+     Please insert smart card
+     [sudo] password for fa...@fabiomirmar.net:
+     fa...@fabiomirmar.net 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
+ 
+     fa...@fabiomirmar.net@jammy-desktop:~$ sudo -i
+     Please insert smart card
+     Please (re)insert (different) Smartcard
+     Please (re)insert (different) Smartcard
+ 
+ Additional testcase, covering (f) of comment #2:
+ 
+ Remove smartcard requirement, and go back to password authentication:
+ 
+ Run:
+ 
+     sudo update-alternatives --set gdm-smartcard 
/etc/pam.d/gdm-smartcard-sssd-or-password
+     
+ And then also comment out the following line in /etc/pam.d/common-auth:
  
      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:
- 
-     fa...@fabiomirmar.net@noble-desktop2:~$ sudo -i
-     PIN for Users: 
-     fa...@fabiomirmar.net is not in the sudoers file.
- 
- - Jammy:
- 
-     fa...@fabiomirmar.net@jammy-desktop:~$ sudo -i
-     PIN for Users: 
-     fa...@fabiomirmar.net is not in the sudoers file.  This incident will be 
reported.
- 
- So far so good. Now, remove the smartcard and try again:
- 
- - Noble:
- 
-     fa...@fabiomirmar.net@noble-desktop2:~$ sudo -i
-     Please insert smart card
-     Please (re)insert (different) Smartcard
-     Please (re)insert (different) Smartcard
- 
- - Jammy:
- 
-     fa...@fabiomirmar.net@jammy-desktop:~$ sudo -i
-     Please insert smart card
-     [sudo] password for fa...@fabiomirmar.net: 
-     fa...@fabiomirmar.net 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
-      
-     fa...@fabiomirmar.net@jammy-desktop:~$ sudo -i
-     Please insert smart card
-     Please (re)insert (different) Smartcard
-     Please (re)insert (different) Smartcard
+ Attempt a login through SSH, sudo, and GDM. All authentication attempts
+ should be presented with a password prompt, and domain password should
+ succeed.
  
  [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 <sb...@redhat.com>
  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 <sb...@redhat.com>
  Date:  Mon Feb 21 18:02:47 2022 +0100
  Subject: pam: better SC fallback message
  Link: 
https://github.com/SSSD/sssd/commit/4d2277f8c3065771a8c3bbc7938309a4905640f0

-- 
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
ubuntu-bugs@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to