Configuring Smart Card authentication on SUSE Linux Enterprise
This guide describes the configuration of Smart Card authentication on SUSE Linux Enterprise Server 12.
Smart Cards are used for user authentication and related cryptography applications. The configuration described here includes the Common Access Card (commonly referred to CAC card) , as used by the United States Department of Defense (DoD) for civil and military application.
The main software elements include pcsc-lite, PAM, pam_pkcs11 and coolkey. When this guide is followed, the system will be able to validate the certificates on the smart cards, authenticate users using their smart card and PIN for login, and lock the session upon smart card removal.
What was tested
This procedure has been tested on SUSE Linux Enterprise Server 12 SP2 and using the specified packages.
Required Operating System Version
- SUSE Enterprise Linux Server 12 SP1 for x86_64
- SUSE Enterprise Linux Server 12 SP2 for x86_64
- SUSE Enterprise Linux Server 12 SP3 for x86_64
Package versions used during testing
- pam_pkcs11 0.6.8-5.81
- mozilla-nss 3.29.5-57.1
- mozilla-nss-tools 3.29.5-57.1
- pcsc-lite 1.8.10-6.1-x86_64
- pcsc-ccid 1.4.25-4.1-x86_64
- opensc 0.13.0-1.122-x86_64
- coolkey 1.1.0-148.3.1-x86_64
- pcsc-tools 1.5.2-2.1-x86_64 (from SUSE Package Hub)
Activation of SUSE Package Hub
As of writing, pcsc-tools
is available in the SUSE Package Hub.
- To get an overview on the available modules and extensions:
SUSEConnect --list-extensions
- To enable the SUSE Package Hub (example shown for SP2):
SUSEConnect -p PackageHub/12.2/x86_64
- The package can now be installed as usual:
zypper in pcsc-tools
Prerequisite Configuration
Removing pam_config tool symbolic links
The pam-config
tool helps configure the global PAM configurations files, such as /etc/pam.d/common-*
, and some applications configurations. See the pam-config documentation for more details.
To successfully be able to configure smart card authentication in SLES 12 SP2 you will need to disable the pam_config
tool. You will have manually create and maintain the required files. See the section in the documentation on disabling the PAM configuration symbolic links.
To disable the pam-config
tool proceed with the following directions:
- Disable
pam-config
by removing the symlinks:
find /etc/pam.d/ -type l -iname "common-*" -delete
- Copy the past
pam-config
generated configuration to the actual files:
for X in /etc/pam.d/common-*-pc; do cp -ivp $X ${X:0:-3}; done
'/etc/pam.d/common-account-pc' -> '/etc/pam.d/common-account'
'/etc/pam.d/common-auth-pc' -> '/etc/pam.d/common-auth'
'/etc/pam.d/common-password-pc' -> '/etc/pam.d/common-password'
'/etc/pam.d/common-session-pc' -> '/etc/pam.d/common-session'
Configuring necessary services to be enabled and started
Configure the PC/SC Smart Card Daemon to be enabled and started.
- As root, issue the following command to enable the service to start at boot:
systemctl enable pcscd.service
- As root, issue the following command to start the pcscd.service:
systemctl start pcscd.services
- As root, issue the following command to check the pcscd.service:
systemctl start pcscd.service
Installing Trust Anchors and Hashes
Creating the PKCS11 Hash file
It is necessary to obtain the public root certificate from your Certificate Authority (CA) and sub CAs in .pem
format for this step.
- To create a PKCS11 hash file copy the public certificate from your Certificate Authority to
/etc/pam_pkcs11/cacerts
as root:
cp /location_of_ca_root_cert/rootcert.pem /etc/pam_pkcs11/cacerts
- Change the permissions on the file to allow for the creation of the hash
chmod a+r /etc/pam_pkcs11/cacert/rootcert.pem
- To create the hash use the following command as root:
pkcs11_make_hash_link
Installing the NSSdb trust anchors
Creating an nssdb
- Create the directory for the NSSdb to exist in as root:
mkdir /etc/pam_pkcs11/nssdb
- Create the NSSdb using the certutil commands as root:
certutil -N -d /etc/pam_pkcs11/nssdb
- Verify the database was created by listing certificates. (If the NSSdb was created from scratch at this step it should be blank. If not, then you will see the previously loaded certificates.)
certutil -L -d /etc/pam_pkcs11/nssdb
Optional step for FIPS mode compliance
If FIPS mode for NSSdb is required in your environment follow these steps for turning on FIPS mode.
- Check to see if FIPS mode is already enabled as root in the run:
modutil -chkfips true -dbdir /etc/pam_pkcs11/nssdb
If it returns that FIPS mode is enabled then proceed to loading in the certificates. - If FIPS mode is returned as disabled, to enable it run this as root:
modutil -fips true -dbdir /etc/pam_pkcs11/nssdb
Load the public root certificate from the CA and all sub CAs into the NSSdb
For this step you will need the .pem file from early that was used to create the hash.
- As root, load the root CA certificate into the NSSdb
certutil -A -n rootca -i /location_of_ca_root_cert/rootcert.pem -t "CT,CT,CT" -d /etc/pam_pkcs11/nssdb
- If needed as root load each sub CA’s public certificate into the NSSdb
certutil -A -n subca -i /location_of_subca_root_cert/rootcert.pem -t "CT,CT,CT" -d /etc/pam_pkcs11/nssdb
- Verify expected certificates have loaded, as root:
certutil -L -d /etc/pam_pkcs11/nssdb
Logging in using a Smart Card
Configuring pam_pkcs11.conf
Configuring pam_pkcs11 to use Coolkey Libraries
- Find the line that looks like this:
use_pkcs11_module = nss
and change it to:
use_pkcs11_module = coolkey
- Add a module description for coolkey, which will handle OCSP and CRL checking.
pkcs11_module coolkey { module = libcoolkeypk11.so; description = "Cool Key" # Slot-number to use. One for the first, two for the second and so # on. The default value is zero which means to use the first slot # with an available token. slot_num = 0; # Path to the directory where the NSS CA certificate database is stored. # you can mange the certs in this database with the certutil command in # the package nss-tools nss_dir = /etc/pam_pkcs11/nssdb; # Sets the Certificate verification policy. # "none" Performs no verification # "ca" Does CA check # "crl_online" Downloads the CRL form the location given by the # CRL distribution point extension of the certificate # "crl_offline" Uses the locally stored CRLs # "crl_auto" Is a combination of online and offline; it first # tries to download the CRL from a possibly given CRL # distribution point and if this fails, uses the local # CRLs # "ocsp_on" Turn on OCSP. # "signature" Does also a signature check to ensure that private # and public key matches # You can use a combination of ca,crl, and signature flags, or just # use "none". cert_policy = ca, ocsp_on, signature, crl_auto; }
- Find the line that looks like this:
nss_dir = /etc/pki/nssdb
and change it to:
nss_dir = /etc/pam_pkcs11/nssdb
- Configuring the mappers in
/etc/pam_pkcs11/pam_pkcs11.conf
:
You can map to Common Name (CN), subject, kpn, email, upn, uid or serial.
For example, to change the mapping to look at CN and email address:
Find the line that looks like this:
user_mappers = ms;
and change it to look for CN and email:
user_mappers = cn, mail, null;
Verifying the Smart Card Reader Setup
- Verify the card hardware using pcsc_scan (if installed). As root issue the following command:
pcsc_scan
If this command is successful it verifies that the card and hardware and the kernel are passing information. - Inspect the certificates on the smart card. As root issue the following command:
pkcs11_listcerts
If this command is successful it will show you the certificate on the card after entering the pin. - Inspect the certificates on the smart card using the mappers. As root issue the following command:
pkcs11_inspect
If this command is successful it will show you the certificate on the card using the mappers after entering the pin.
Mapping Smart Card certificates to user names
A mapping configures the logic that lets the system associate a certificate on the smart card with username in the local system.
Common Name mapping
In the file /etc/pam_pkcs11/cn_map
use the following format:
Common_Name_from_Certificate -> linux_username
For example, in the file for user Jane Doe with CN Jane.Doe.5555555555
and Linux username jdoe
:
Jane.Doe.5555555555 -> jdoe
This file can be appended with all the Common Names and usernames that are being mapped to each other.
Email mapping
In the file /etc/pam_pkcs11/mail_mapping
use the following format:
Email_from_certificate@example.com -> linux_username
For example, in the file for user Jane Doe with email jane.doe@example.com
and Linux username jdoe
:
jane.doe@example.com -> jdoe
This file can be appended with all the usernames and emails that are being mapped to each other.
Checking the mappings
As root run the command with a smart card inserted:
pklogin_finder debug
It will show the mapping of the login id to the certificate and then will attempt to validate the certificates on the card.
Configuring PAM to use the pam_pkcs11.so authentication module
Edit /etc/pam.d/common-auth
and add pam_pkcs11.so
to the authentication stack:
auth required pam_env.so
auth sufficient pam_pkcs11.so
auth optional pam_gnome_keyring.so
auth required pam_unix.so try_first_pass
The system should now be able to validate the certificates on the smart card and authenticate users using their smart card and PIN.
Locking session upon smart card removal
One organisational requirement is that the session is locked when the user is no longer present. For smart cards this is triggered when the card is removed form the reader.
Configuring pkcs11_event_mgr
The pkcs11_event_mgr
daemon can be used to trigger actions upon smart card related event. This section will configure that the session is locked upon smart card removal. Edit /etc/pam_pkcs11/pkcs11_event_mgr.conf
as root as follows:
- Find the line that looks like this:
pkcs11_module = /usr/lib64/opensc-pkcs11.so;
and change it to use the coolkey library:
pkcs11_module = /usr/lib64/libcoolkeypk11.so;
- Find the lines that looks like this:
# Card has been removed
event card_remove {
on_error = ignore;
action = "play /usr/share/sounds/error.wav",
"xscreensaver-command -lock";
}
and change it to:
# Card has been removed
event card_remove {
on_error = ignore;
action = "loginctl lock-sessions";
}
This configuration can be tested by running the following command as root:
pkcs11_eventmgr nodaemon debug
If the card is removed during a GUI login session this should print a message indicating so and lock the screen.
Configuring pkcs11_event_mgr to start on boot
If the above is working, enforce screen locking upon smart card removal system wide.
Configure one of the following:
- Using
/etc/init.d/boot.local
:
In a text editor as root add the following line to /etc/init.d/boot.local:
/usr/bin/pkcs11_eventmgr
- Create a systemd unit file /usr/lib/systemd/system/pkcs11_eventmgr.service:
[Unit] Description=pkcs11 event manager [Service] Type=forking ExecStart=/usr/bin/pkcs11_eventmgr StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
Make the system recognize the new unit, enable and start it:
systemctl daemon-reload
systemctl enable pkcs11_eventmgr
systemctl start pkcs11_eventmgr
Conclusion
We have shown how SUSE Linux Enterprise Server 12 can be configured to validate the smart card certificate and authenticate users using their smart card and PIN, and locking the session when it is removed.
Please refer to your organization IT security policy for specifics on CA, CRL, Mapping and Smart Card requirements, and thorougly testall configuration elements in your environment.
Acknowledgments
This guide was developed to implement requirements for an upcoming STIG for SLES 12 governed by the Defense Information Systems Agency (DISA).
This guide was developed with Jamie Martin and Craig Liddle of the SUSE US Federal Sales Engineering team. See how SUSE Linux Enterprise can help you achieve your mission.
Appendix: Full /etc/pam_pkcs11.conf file
Below is the full /etc/pam_pkcs11.conf
file as tested
# # Configuration file for pam_pkcs11 module # # Version 0.4 # Author: Juan Antonio Martinez # pam_pkcs11 { # Allow empty passwords nullok = true; # Enable debugging support. debug = false; # If the smart card is inserted, only use it # card_only = true; # Do not prompt the user for the passwords but take them from the # PAM_ items instead. use_first_pass = false; # Do not prompt the user for the passwords unless PAM_(OLD)AUTHTOK # is unset. try_first_pass = false; # Like try_first_pass, but fail if the new PAM_AUTHTOK has not been # previously set (intended for stacking password modules only). use_authtok = false; # Filename of the PKCS #11 module. The default value is "default" # use_pkcs11_module = nss; - commented out # Changed from pam_pkcs11.conf for coolkey use_pkcs11_module = coolkey; # Added from CentOS pam_pkcs11.conf by JLM 07/14/2017 screen_savers = gnome-screensaver,xscreensaver,kscreensaver # Added to pam_pkcs11.conf for libcoolkeypk11.so pkcs11_module coolkey { module = libcoolkeypk11.so; description = "Cool Key" # Slot-number to use. One for the first, two for the second and so # on. The default value is zero which means to use the first slot # with an available token. slot_num = 0; # Path to the directory where the NSS CA certificate database is stored. # you can mange the certs in this database with the certutil command in # the package nss-tools nss_dir = /etc/pam_pkcs11/nssdb; # Sets the Certificate verification policy. # "none" Performs no verification # "ca" Does CA check # "crl_online" Downloads the CRL form the location given by the # CRL distribution point extension of the certificate # "crl_offline" Uses the locally stored CRLs # "crl_auto" Is a combination of online and offline; it first # tries to download the CRL from a possibly given CRL # distribution point and if this fails, uses the local # CRLs # "ocsp_on" Turn on OCSP. # "signature" Does also a signature check to ensure that private # and public key matches # You can use a combination of ca,crl, and signature flags, or just # use "none". cert_policy = ca, ocsp_on, signature, crl_auto; } pkcs11_module nss { # changed for directory location # nss_dir = /etc/pki/nssdb; nss_dir = /etc/pam_pkcs11/nssdb; crl_policy = none; } pkcs11_module opensc { module = /usr/lib64/opensc-pkcs11.so; description = "OpenSC PKCS#11 module"; # Which slot to use? # You can use "slot_num" or "slot_description", but not both, to specify # the slot to use. Using "slot_description" is preferred because the # PKCS#11 specification does not guarantee slot ordering. "slot_num" should # only be used with those PKCS#11 implementations that guarantee # constant slot numbering. # # slot_description = "xxxx" # The slot is specified by the slot description, for example, # slot_description = "Sun Crypto Softtoken". The default value is # "none" which means to use the first slot with an available token. # # slot_num = a_number # The slot is specified by the slot number, for example, slot_num = 1. # The default value is zero which means to use the first slot with an # available token. # slot_description = "none"; # Where are CA certificates stored? # You can setup this value to: # 1- A directory with openssl hash-links to all certificates # 2- A CA file in PEM (.pem) or ASN1 (.cer) format, # containing all allowed CA certs # The default value is /etc/pam_pkcs11/cacerts. ca_dir = /etc/pam_pkcs11/cacerts; # Path to the directory where the local (offline) CRLs are stored. # Same convention as above is applied: you can choose either # hash-link directory or CRL file # The default value is /etc/pam_pkcs11/crls. crl_dir = /etc/pam_pkcs11/crls; # Some pcks#11 libraries can handle multithreading. So # set it to true to properly call C_Initialize() support_threads = false; # Sets the Certificate verification policy. # "none" Performs no verification # "ca" Does CA check # "crl_online" Downloads the CRL form the location given by the # CRL distribution point extension of the certificate # "crl_offline" Uses the locally stored CRLs # "crl_auto" Is a combination of online and offline; it first # tries to download the CRL from a possibly given CRL # distribution point and if this fails, uses the local # CRLs # "signature" Does also a signature check to ensure that private # and public key matches # You can use a combination of ca,crl, and signature flags, or just # use "none". cert_policy = ca,signature; # What kind of token? # The value of the token_type parameter will be used in the user prompt # messages. The default value is "Smart card". token_type = "Smart card"; } # Aladdin eTokenPRO 32 pkcs11_module etoken { module = /usr/local/lib64/libetpkcs11.so description = "Aladdin eTokenPRO-32"; slot_num = 0; support_threads = true; ca_dir = /etc/pam_pkcs11/cacerts; crl_dir = /etc/pam_pkcs11/crls; cert_policy = ca,signature; } # NSS (Network Security Service) config pkcs11_module nss { nss_dir = /etc/ssl/nssdb; crl_policy = none; } # Default pkcs11 module pkcs11_module default { module = /usr/lib64/pam_pkcs11/pkcs11_module.so; description = "Default pkcs#11 module"; slot_num = 0; support_threads = false; ca_dir = /etc/pam_pkcs11/cacerts; crl_dir = /etc/pam_pkcs11/crls; cert_policy = none; } # Which mappers ( Cert to login ) to use? # you can use several mappers: # # subject - Cert Subject to login file based mapper # pwent - CN to getpwent() login or gecos fields mapper # ldap - LDAP mapper # opensc - Search certificate in ${HOME}/.eid/authorized_certificates # openssh - Search certificate public key in ${HOME}/.ssh/authorized_keys # mail - Compare email fields from certificate # ms - Use Microsoft Universal Principal Name extension # krb - Compare againts Kerberos Principal Name # cn - Compare Common Name (CN) # uid - Compare Unique Identifier # digest - Certificate digest to login (mapfile based) mapper # generic - User defined certificate contents mapped # null - blind access/deny mapper # # You can select a comma-separated mapper list. # If used null mapper should be the last in the list :-) # Also you should select at least one mapper, otherwise # certificate will not match :-) use_mappers = cn, mail, null; # When no absolute path or module info is provided, use this # value as module search path # TODO: # This is not still functional: use absolute pathnames or LD_LIBRARY_PATH mapper_search_path = /usr/lib64/pam_pkcs11; # # Generic certificate contents mapper mapper generic { debug = true; #module = /usr/lib64/pam_pkcs11/generic_mapper.so; module = internal; # ignore letter case on match/compare ignorecase = false; # Use one of "cn" , "subject" , "kpn" , "email" , "upn" , "uid" or "serial" cert_item = cn; # Define mapfile if needed, else select "none" mapfile = file:///etc/pam_pkcs11/generic_mapping; # Decide if use getpwent() to map login use_getpwent = false; } # Certificate Subject to login based mapper # provided file stores one or more "Subject -> login" lines mapper subject { debug = false; # module = /usr/lib64/pam_pkcs11/subject_mapper.so; module = internal; ignorecase = false; mapfile = file:///etc/pam_pkcs11/subject_mapping; } # Search public keys from $HOME/.ssh/authorized_keys to match users mapper openssh { debug = false; module = /usr/lib64/pam_pkcs11/openssh_mapper.so; } # Search certificates from $HOME/.eid/authorized_certificates to match users mapper opensc { debug = false; module = /usr/lib64/pam_pkcs11/opensc_mapper.so; } # Certificate Common Name ( CN ) to getpwent() mapper mapper pwent { debug = false; ignorecase = false; module = internal; # module = /usr/lib64/pam_pkcs11/pwent_mapper.so; } # Null ( no map ) mapper. when user as finder matchs to NULL or "nobody" mapper null { debug = false; # module = /usr/lib64/pam_pkcs11/null_mapper.so; module = internal ; # select behavior: always match, or always fail default_match = false; # on match, select returned user default_user = nobody ; } # Directory ( ldap style ) mapper mapper ldap { debug = false; module = /usr/lib64/pam_pkcs11/ldap_mapper.so; # hostname of ldap server (use LDAP-URI for more then one) ldaphost = ""; # Port on ldap server to connect, this is also the default # if no port is given in URI below # if empty, then 389 for TLS and 636 for SSL is used ldapport = ; # space separted list of LDAP URIs (URIs are used by given order) URI = ""; # Scope of search: 0-2 # Default is 1 = "one", meaning the set of records one # level below the basedn. # 0 = "base" means search only the basedn, and # 2 = "sub" means the union of entries at the "base" level # and ? all or "one" level below ??? FIXME scope = 2; # DN to bind with. Must have read-access for user entries # under "base" binddn = "cn=pam,o=example,c=com"; # Password for above DN passwd = ""; # Searchbase for user entries base = "ou=People,o=example,c=com"; # Attribute of user entry which contains the certificate attribute = "userCertificate"; # Searchfilter for user entry. Must only let pass user entry # for the login user. filter = "(&(objectClass=posixAccount)(uid=%s))" # SSL/TLS-Switch # This is a global switch, you can't switch between # SSL or TLS and non secured connections per URI! # values: off (standard), tls or on (ssl) or ssl ssl = tls # SSL specific settings # tls_randfile = ... tls_cacertfile = /etc/ssl/cacert.pem # tls_cacertdir = ... tls_checkpeer = 0 #tls_ciphers = ... #tls_cert = ... #tls_key = ... } # Assume common name (CN) to be the login mapper cn { debug = false; module = internal; # module = /usr/lib64/pam_pkcs11/cn_mapper.so; ignorecase = true; # mapfile = file:///etc/pam_pkcs11/cn_map; mapfile = "none"; } # mail - Compare email field from certificate mapper mail { debug = false; module = internal; # module = /usr/lib64/pam_pkcs11/mail_mapper.so; # Declare mapfile or # leave empty "" or "none" to use no map mapfile = file:///etc/pam_pkcs11/mail_mapping; # Some certs store email in uppercase. take care on this ignorecase = true; # Also check that host matches mx domain # when using mapfile this feature is ignored ignoredomain = false; } # ms - Use Microsoft Universal Principal Name extension # UPN is in format login@ADS_Domain. No map is needed, just # check domain name. mapper ms { debug = false; module = internal; # module = /usr/lib64/pam_pkcs11/ms_mapper.so; ignorecase = false; ignoredomain = false; domainname = "domain.com"; } # krb - Compare againts Kerberos Principal Name mapper krb { debug = false; module = internal; # module = /usr/lib64/pam_pkcs11/krb_mapper.so; ignorecase = false; mapfile = "none"; } # uid - Maps Subject Unique Identifier field (if exist) to login mapper uid { debug = false; module = internal; # module = /usr/lib64/pam_pkcs11/uid_mapper.so; ignorecase = false; mapfile = "none"; } # digest - elaborate certificate digest and map it into a file mapper digest { debug = false; module = internal; # module = /usr/lib64/pam_pkcs11/digest_mapper.so; # algorithm used to evaluate certificate digest # Select one of: # "null","md2","md4","md5","sha","sha1","dss","dss1","ripemd160" algorithm = "sha1"; mapfile = file:///etc/pam_pkcs11/digest_mapping; # mapfile = "none"; } }
Related Articles
Apr 03rd, 2023
Comments
Hello,
Thank you for this post.
Does Smart Card authentication available also through RDP session?
Best Regards
Shavit
Smart Card authentication through an RDP session was not considered in this scenario. We are not aware of support in the protocol remotely authenticating via RDP (client has the smartcard). We realize that smartcard authentication may work if it is connected to the server, but this would defeat it’s intended purpose.
Hello,
Thanks for this post.
Is it possible to configure Smartcard authentication + ldap authentication (without yast) ?
Do you know any good ressource to guide this ?
Thanks!
haingone
I believe this might be possible by stacking multiple PAM modules.