# Ubuntu Smartcard (UI) login support While we're focusing here only on login for a graphical session, once this is setup is done, it can be easily adapted to SSH logins, but this is out of scope for this document. ## Prerequisites This assumes having a smartcard reader supported by OpenSC, but setup for other libraries supported by `p11-kit` should not differ substancially ```bash # The SSSD PAM module, needed for authentication sudo apt install libpam-sss # Replace this with the pkcs11 driver supporting your device sudo apt install opensc-pkcs11 # This is needed to expose the SmartCard reader sudo apt install pcscd ``` ## Smartcard module There are various smartcard modules out there, most of the cards should be supported by the OpenSC module (`opensc-pkcs11` package), and this can be verified by: ``` p11-kit list-modules p11-kit-trust: p11-kit-trust.so library-description: PKCS#11 Kit Trust Module library-manufacturer: PKCS#11 Kit library-version: 0.23 token: System Trust manufacturer: PKCS#11 Kit model: p11-kit-trust serial-number: 1 hardware-version: 0.23 flags: write-protected token-initialized opensc-pkcs11: opensc-pkcs11.so library-description: OpenSC smartcard framework library-manufacturer: OpenSC Project library-version: 0.20 token: MARCO TREVISAN (PIN CNS0) manufacturer: IC: STMicroelectronics; mask:... model: PKCS#15 emulated serial-number: 6090010669298009 flags: login-required user-pin-initialized token-initialized user-pin-locked ``` ### NSS Database (to be deprecated post 20.04) Up to 20.04, SSSD and gnome-settings-daemon versions provided in ubuntu, need to have an NSS database (by default in `/etc/pki/nssdb`) that contains: - A reference of the smartcard p11 module to use (for g-s-d up to 20.10) - The trusted CA certificates (for SSSD) In particular, `gnome-settings-daemon` uses is configured by default to use some Fedora specific feature, by getting all the allowed device drivers from an NSS database. While SSSD is configured to use NSS (now deprecated even uptream) over openssl (to be the default and that is already [since 20.10](https://salsa.debian.org/sssd-team/sssd/-/commit/f4f7bfee91e9aa929585b95e5c579597d0ab156b)) Given that we don't provide one in ubuntu, we need an hack to enable the smartcard modules to work right now, creating a database and falling-back to `p11-kit` device proxy: ```bash sudo apt install libnss3-tools # Create a db, with an empty password sudo mkdir /etc/pki/nssdb sudo certutil -N -d /etc/pki/nssdb -f /dev/zero # Sad but true... As g-s-d can need to read this when ran as user sudo chmod 644 /etc/pki/nssdb/* sudo modutil -dbdir /etc/pki/nssdb -add "PKCS#11 Kit modules proxy" -libfile /usr/lib/x86_64-linux-gnu/p11-kit-proxy.so # Now you should get the Smart card info showing up modutil -dbdir /etc/pki/nssdb -list .... 2. PKCS#11 Kit modules proxy library name: p11-kit-proxy.so uri: pkcs11:library-manufacturer=PKCS%2311%20Kit;library-description=PKCS%2311%20Kit%20Proxy%20Module;library-version=1.1 slots: 1 slot attached status: loaded slot: VMware Virtual USB CCID 00 00 token: MARCO TREVISAN (PIN CNS0) uri: pkcs11:token=MARCO%20TREVISAN%20(PIN%20CNS0);manufacturer=IC:%20STMicroelectronics%3B%20mask:...;serial=6090010669298009;model=PKCS%2315%20emulated # While g-s-d should list the token as well gdbus call --session --dest org.gnome.SettingsDaemon.Smartcard --object-path /org/gnome/SettingsDaemon/Smartcard/Manager --method org.gnome.SettingsDaemon.Smartcard.Manager.GetInsertedTokens ([objectpath '/org/gnome/SettingsDaemon/Smartcard/Manager/Tokens/token_from_p11_2d_kit_2d_proxy_2e_so_slot_17'],) ``` ## SmartCard certificate To be validated, a smart card certificate should be verified by a Certificate Authority ### Certificate Authority verification The card certificate must be allowed by a CA, these should be part of `/etc/sssd/pki/sssd_auth_ca_db.pem` in recent SSSD versions or in `/etc/pki/nssdb` for older ones (or any other location configured in `[pam]` config section of `sssd.conf` as `pam_cert_db_path`) You can check this by using something like: ```bash # List certificates pkcs15-tool --list-certificates Using reader with a card: Alcor Micro AU9560 00 00 X.509 Certificate [CNS0] Object Flags : [0x00] Authority : no Path : 3f0011001101 ID : 01 Encoded serial : 02 03 3435CC pkcs15-tool --read-certificate 1 > card-CERT.pem # See the certificate contents with openssl x509 -text -noout -in card-CERT.pem # Verify it is valid for the given CA openssl verify -verbose -CAfile CA-Auth-CERT.pem card-CERT.pem ``` ### Include the CA certificates in the SSSD CA database #### Ubuntu 20.04 In this case we need to use the NSS database, and so any certificate (one by one, as it doesn't support a certificate chain) should be added to it: ``` sudo certutil -A -d /etc/pki/nssdb -n Ca-Auth-Cert -t CT,C,C -a -i CA-Auth-CERT.pem sudo certutil -A -d /etc/pki/nssdb -n Ca-Auth-Cert -t CT,C,C -a -i CA-Auth-CERT2.pem ``` This can be quite slow if you've a card inserted during this operation, so better if you remove it as nss will always open it on load ##### Debugging This can be simulated using SSSD login tool using: ```bash sudo /usr/libexec/sssd/p11_child --pre -d 10 --debug-fd=2 --nssdb=/etc/pki/nssdb ``` If everything is correct, the certificate should be printed #### Ubuntu 20.10 (and next versions) As per SSSD using openssl, we need to add the certificate to the SSD well known certificate path (if not changed via `sssd.certificate_verification`), so copying the certificates (can be a chain of certificates) ```bash sudo cat Ca-Auth-CERT*.pem >> /etc/sssd/pki/sssd_auth_ca_db.pem ``` ##### Debugging This can be simulated using SSSD login tool using: ```bash sudo /usr/libexec/sssd/p11_child --pre -d 10 --debug-fd=2 --nssdb=/etc/sssd/pki/sssd_auth_ca_db.pem ``` If everything is correct, the certificate should be printed ##### Use Ubuntu default CA file It's possible to use the default ubuntu ca-certificates, so that it can be easily managed using `ca-certificates` by using this: ```ini [pam] pam_cert_db_path = /etc/ssl/certs/ca-certificates.crt ``` To add specific CA cert files there, you only have to add your `*.crt` (extension matters, no `*.pem`!) to `/usr/local/share/ca-certificates/` (or a subfolder of it) and run `sudo update-ca-certificates` ### Ignore CA This is not suggested, but can be done for testing, disabling the CA check in `sssd.conf`: ```ini [sssd] certificate_verification = no_ocsp ``` This can be simulated using SSSD login tool using: ```bash sudo /usr/libexec/sssd/p11_child --pre -d 10 --debug-fd=2 --nssdb=/etc/ssl/certs/ca-certificates.crt --verify=no_ocsp ``` ## Certificate mapping ### For local users When using only local users, sssd can be easily configured to define an `implicit_domain` that maps all the local users. Certificate mapping for local users it can be easily done using the certificate Subject check, in my case: ```bash openssl x509 -noout -subject -in card-CERT.pem | sed "s/, /,/g;s/ = /=/g" subject=C=IT,O=Actalis S.p.A.,OU=REGIONE TOSCANA,CN=TRVMRC[...data-removed...]/6090010669298009.YOrY0zOk5CdMby2Z2O/HnVRA8Ao=,GN=MARCO,SN=TREVISAN ``` So I can use ```ini [sssd] enable_files_domain = True services = pam [certmap/implicit_files/marco] matchrule = <SUBJECT>.*CN=TRVMRC[A-Z0-9]+/6090010669298009\.YOrY0zOk5CdMby2Z2O/HnVRA8Ao.* [pam] pam_cert_auth = True ``` That can be tested working in versions newer than Ubuntu 20.04 with: ```bash sudo dbus-send --system --print-reply \ --dest=org.freedesktop.sssd.infopipe \ /org/freedesktop/sssd/infopipe/Users # returns... org.freedesktop.sssd.infopipe.Users.ListByCertificate string:"$(cat card-CERT.pem)" uint32:10 method return time=1605127192.698667 sender=:1.1628 -> destination=:1.1629 serial=6 reply_serial=2 array [ object path "/org/freedesktop/sssd/infopipe/Users/implicit_5ffiles/1000" ] ``` ### Other mappings Mapping for more complicated configurations can be done following the official [SSSD documentation](https://sssd.io/docs/design_pages/certmaps_for_LDAP_AD_file.html). ## Basic SSSD configuration The SSSD configuration for accessing to the system is out of the scope of this document, however for smartcard access it should contain at least such values: ```ini [sssd] # Comma separated list of domains ;domains = your-domain1, your-domain2 # comma-separated list of SSSD services # pam might be implicitly loaded already, so the line is optional services = pam # You can enable debug of the SSSD daemon # Logs will be in /var/log/sssd/sssd.log ;debug_level = 10 # A mapping between the SC certificate and users ;[certmap/your-domain1/<username>] ;matchrule = <SUBJECT>.*CN=TRVMRC[A-Z0-9]+/6090010669298009\.YOrY0zOk5CdMby2Z2O/HnVRA8Ao.* [pam] pam_cert_auth = True # The Certificate DB to be used: # - Needs to be an openSSL certs file starting Ubuntu 20.10 # - Needs to be an NSS database for Ubuntu 20.4 ;pam_cert_db_path = /etc/ssl/certs/ca-certificates.crt # You can enable debug infos for the PAM module # Logs will be in /var/log/sssd/sssd_pam.log # p11 child logs are in /var/log/sssd/p11_child.log # standard auth logs are in /var/log/auth.log ;pam_verbosity = 10 ;debug_level = 10 ``` In general what's in the configuration file will affect the way SSSD will call the `p11_child` tool (that is the one in charge for the actual authentication). Check `man sssd.conf` for details. Remember that this file should be owned by `root` and have permission set to `600`, otherwise won't be loaded and SSSD will not complain gracefully. On errors you can test running SSSD temporary with `sudo sssd -d9 -i`. Every time the configuration is changed sssd should be restarted (`systemctl restart sssd`). You can see a working example for the [local users case here](#For-local-users). ## GDM / GSD configuration GDM needs pam configuration files, those are not shipped by default until Ubuntu 21.04, so they need to be manually created. Other than that, GDM and gnome-settings-daemon can be configured to enforce further checks ### For smartcard access with password fallback ```bash cat << EOF | sudo tee -a /etc/pam.d/gdm-smartcard-optional #%PAM-1.0 auth requisite pam_nologin.so auth required pam_succeed_if.so user != root quiet_success auth sufficient pam_sss.so allow_missing_name try_cert_auth auth optional pam_gnome_keyring.so @include common-auth @include common-account #account [default=bad success=ok user_unknown=ignore] pam_sss.so # SELinux needs to be the first session rule. This ensures that any # lingering context has been cleared. Without this it is possible # that a module could execute code in the wrong domain. session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close session required pam_loginuid.so # SELinux needs to intervene at login time to ensure that the process # starts in the proper default security context. Only sessions which are # intended to run in the user's context should be run after this. # pam_selinux.so changes the SELinux context of the used TTY and configures # SELinux in order to transition to the user context with the next execve() # call. session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open session optional pam_keyinit.so force revoke session required pam_limits.so session required pam_env.so readenv=1 session required pam_env.so readenv=1 user_readenv=1 envfile=/etc/default/locale password required pam_sss.so @include common-session session optional pam_gnome_keyring.so auto_start EOF ``` Then set it as default with: ```bash sudo ln -sfv /etc/pam.d/gdm-smartcard-optional /etc/pam.d/gdm-smartcard ``` ### For smartcard-only access ```cat << EOF | sudo tee -a /etc/pam.d/gdm-smartcard-required #%PAM-1.0 auth requisite pam_nologin.so auth required pam_succeed_if.so user != root quiet_success auth required pam_sss.so allow_missing_name auth optional pam_gnome_keyring.so @include common-account #account [default=bad success=ok user_unknown=ignore] pam_sss.so # SELinux needs to be the first session rule. This ensures that any # lingering context has been cleared. Without this it is possible # that a module could execute code in the wrong domain. session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close session required pam_loginuid.so # SELinux needs to intervene at login time to ensure that the process # starts in the proper default security context. Only sessions which are # intended to run in the user's context should be run after this. # pam_selinux.so changes the SELinux context of the used TTY and configures # SELinux in order to transition to the user context with the next execve() # call. session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open session optional pam_keyinit.so force revoke session required pam_limits.so session required pam_env.so readenv=1 session required pam_env.so readenv=1 user_readenv=1 envfile=/etc/default/locale @include common-session session optional pam_gnome_keyring.so auto_start EOF ``` Then set it as default with: ```bash sudo ln -sfv /etc/pam.d/gdm-smartcard-required /etc/pam.d/gdm-smartcard ``` ### Choose the GDM method Once the two PAM configuration are installed, the preferred can be configured globally making the `/etc/pam.d/gdm-smartcard` symlink to point to the choosen one ### Disable password access ```bash sudo -u gdm env DCONF_PROFILE=gdm gsettings set org.gnome.login-screen enable-password-authentication false ``` ### Set action on card removal #### User setting This can be configured at user level for each user by just changing this gsettings key: ```bash # Valid values can be 'none', 'lock-screen' or 'force-logout' gsettings set org.gnome.settings-daemon.peripherals.smartcard removal-action 'lock-screen' ``` #### Global settings This value can be locked down at user level by creating these files: ```bash cat << EOF | sudo tee -a /etc/dconf/profile/user user-db:user system-db:local EOF sudo mkdir -p /etc/dconf/db/local.d/locks cat << EOF | sudo tee -a /etc/dconf/db/local.d/00_gdm-smartcard-action [org/gnome/settings-daemon/peripherals/smartcard] # 'lock-screen' or 'force-logout' or 'none' removal-action='lock-screen' EOF cat << EOF | sudo tee -a /etc/dconf/db/local.d/locks/00_gdm-smartcard-action # Make action non-user configurable /org/gnome/settings-daemon/peripherals/smartcard/removal-action EOF # Update system db sudo dconf update ``` Read more in the [GNOME documentation](https://help.gnome.org/admin/system-admin-guide/stable/dconf-lockdown.html.en) or in `man dconf.7`. These files can be safely removed to disable the lockdown (including the `profile/user` one, if no other override/lock is set). ## Work Items ### Add PAM profiles to debian's GDM There are currently two methdos that gdm would support - [pam_pkcs11](https://github.com/OpenSC/pam_pkcs11) - [pam_sss](https://sssd.io/) (SSSD PAM module) So in debian we could provide two more packages - `gdm3-smartcard-sssd` (depends on `libpam_sss`) - installing `/etc/pam.d/gdm-smartcard-sssd` - `gdm3-smartcard-pkcs11` (depends on `libpam-pkcs11`) - installing `/etc/pam.d/gdm-smartcard-pkcs11` ### Rewrite g-s-d smartcard module to use p11-kit This another legacy from RH usage, SSSD is not using anymore NSS for device listing, so g-s-d should not. There's a long standing [upstream issue](https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/issues/260), and I'm working on it. - [Merge Request](https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/merge_requests/208) ### Add `gdm-auth-config` tool upstream Write a tool that will handle all the configurations parameters so that there's less manual intervention when it comes to GDM configuration, with an interface such as: ```bash gdm-auth-config smartcard --{enable, disable, required} [--removal-action=lock-screen|log-out|none|user-defined ] gdm-auth-config fingerprint --{enable, disable} gdm-auth-config password --{enable, disable} gdm-auth-config show ``` - [Merge Request](https://gitlab.gnome.org/GNOME/gdm/-/merge_requests/125) ### Make SSSD to use OpenSSL in 20.04 Also according his debian maintainer, there's no drawback, as it right now points to an NSS database that simply never existed in Ubuntu and that's a Fedora/RH-ism, so nothing should depend on it right now. Not to mention that [**NSS support has been dropped** completely from current SSSD](https://github.com/SSSD/sssd/commit/266ecc083d5fe9f576b7932a80ecb014d2d25311#diff-0462e381b2fb3286568215681c8983490a37ac9ae0f0c5ee304df7fa6426d4afL4756). So [dropping NSS in favour of OpenSSL](https://salsa.debian.org/sssd-team/sssd/-/commit/f4f7bfee91e9aa929585b95e5c579597d0ab156b) in 20.04 would make possible to have just one way to configure SSSD that will persist across LTSes, and avoid [*hacks*](#NSS-Database-to-be-deprecated-post-2004). In the worst case, it would technically possible also to just ship the `p11_child` component (the only one used for the SC auth) to be compiled using openssl instead. - [Example of `p11_child`-only OpenSSL based](https://salsa.debian.org/3v1n0-guest/sssd/-/commits/p11-kit-p11_child) - [Merge request](https://code.launchpad.net/~3v1n0/ubuntu/+source/sssd/+git/sssd/+merge/395411) to get SSSD to use OpenSSL and convert old nss-database to PEM-chain. ### Bugs - Looks like gnome-shell doesn't select automatically the user associated with the card, so one needs to type it. Something I still have to debug. - In 20.04 CA-verification of the card may not work as expected, even though the manual `p11_child` check works