As mentioned on SmartcardAuthenticationStep1 the primary focus of the development was the authentication to an IPA client. Nevertheless, the general authentication code path is the same and when the needed requirements are met it can be used to authenticate on a AD domain client as well. But please note that as with an IPA client this will only be a local authentication, so far no Kerberos tickets will be available after authentication. pkinit will be added in one of the next steps.
As with IPA the current requirement is that the full certificate is stored in the user’s LDAP entry in AD. Since the AD CA uses the userCertificate attribute for this as well we will further assume that this attribute is used to store the certificate.
By default the SSSD AD provider does not read certificates, so this must be set in sssd.conf with the option :
ldap_user_certificate = userCertificate;binary
(I guess it would make sense to set this by default)
Additionally, the AD provider will not create the indication file for the pam_sss client that pre-authentication is available and it has to be created manually :
(I guess it would make sense that the PAM responder creates the file is certificate authentication is enabled.)
Next, certificate authentication must be enabled in the pam section of sssd.conf by setting :
pam_cert_auth = True
Finally, CA certificates should be imported in the systems NSS database to be able to verify the certificate. :
certutil -d /etc/pki/nssdb -A -n 'My Issuer' -t CT,CT,CT -a -i /path/to/cert/in/PEM/format
These steps are needed on the client and now we will discuss how a certificate can be added to the AD user entry and together with the keys to a Smartcard.
If you do not have a Certificate Server in your AD domain you have to install one by enabling the ‘Active Directory Certificate Service’ on one of the servers in the domain.
To allow users to request certificates follow the steps in <https://msdn.microsoft.com/en-us/library/cc770857.aspx.
Now AD user should be able to request a user certificate from the AD CA. For this the user should open the Management Console, e.g. via Start->Run->mmc. In the Management Console the Certificates snap-in can be activated via File->Add/Remove-Snap-ins. In the Certificates snap-in the ‘All Tasks’ context menu should offer ‘Automatically Enroll and Retrieve Certificates’ where you can choose new user certificate template which was created in the instructions from MSDN. If no templates are available you should check the steps from the MSDN instructions again or check if there is already a certificate generated for the user by looking at the ‘Personal’ folder of the Certificates snap-in. Here you will find the freshly created certificate as well.
Now you have to write the certificate and the keys to a Smartcard. You can use a suitable Windows tool for this. Or you can export the data and write it to a Smartcard from a GNU/Linux client which will be explained in the following.
To export the certificate select it in the Certificates Snap-in and call ‘Export’ from the ‘All Tasks’ context menu. In the export wizard the private key must be exported as well. The generated file can now be copied to a GNU/Linux host.
The file created on the AD side is PKCS#12 formatted and can be inspected on the GNU/Linux side with the openssl pkcs12 utility. NSS, which is currently used by SSSD to access the Smartcard, expected that the Smartcard will contain the certificate together with the public and private key in separate objects, connected by the same label and id. We will use pkcs11-tool from the opensc package to write the data to the card. In general p11tool from the gnutls project can be used as well but support for writing public keys was added quite recently (gnutls-3.4.6) so it might no be available on your platform. There might be an issue with pkcs11-tool as well, if after writing to the card the certificate and the public key are only visible after you logged into the card, i.e. entered the PIN, you need a newer version of pkcs11-tool as well.
Extracting the certificate and storing it in DER encoding :
openssl pkcs12 -in ./ad_user.pfx -nokeys -out ./cert.pem openssl x509 -in ./cert.pem -outform der -out ./cert.der
Extracting the private key and storing it in DER format. Please note that the private key in priv.pem and priv.der is not encrypted, please remove the files as soon as possible :
openssl pkcs12 -in ./ad_user.pfx -nocerts -nodes -out ./priv.pem openssl rsa -in ./priv.pem -outform der -out ./priv.der
Extracting the public key from the certificate and storing it in DER encoding :
openssl x509 -in ./cert.pem -pubkey -noout | openssl rsa -pubin -outform der -out ./pubkey.der
First write the certificate data to the Smartcard by calling :
pkcs11-tool --module my_pkcs11_module.so --slot 0 -w ./cert.der -y cert -a 'My Label' --id 0123456789abcdef0123456789abcdef01234567
where my_pkcs11_module.so and My Label should be replaced by suitable values. The id value is typically the Subject Key Identifier which is typically the sha1 hash value of the public key bit string from the certificate. The value can either obtained from the output of :
openssl x509 -in ./cert.pem -text | grep -A 1 'Subject Key Identifier:'
or by inspecting the public key with :
openssl asn1parse -inform der -in ./pubkey.der 0:d=0 hl=4 l= 290 cons: SEQUENCE 4:d=1 hl=2 l= 13 cons: SEQUENCE 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption 17:d=2 hl=2 l= 0 prim: NULL 19:d=1 hl=4 l= 271 prim: BIT STRING openssl asn1parse -inform der -in ./pubkey.der -strparse 19 -noout -out /dev/stdout |sha1sum
where the 19 in the second call has to match the offset value shown for the BIT STRING component in the output of the first call.
The label and the id should be the same when writing the public and the private key object to indicated to applications that the 3 objects belong to each other.
As a second step the public key is written to the Smartcard by calling :
pkcs11-tool --module my_pkcs11_module.so --slot 0 -w ./pubkey.der -y pubkey -a 'My Label' --id 0123456789abcdef0123456789abcdef01234567
And finally the private key can be written by calling :
pkcs11-tool --module my_pkcs11_module.so --slot 0 -w ./priv.der -y privkey -a 'My Label' --id 0123456789abcdef0123456789abcdef01234567 -l
Since the private key must be protected by the PIN you have to login to the Smartcard first, this is done with the help of the -l option which instructs pkcs11-tool to ask for the PIN and login before writing the certificate.
Now the Smartcard content should look like :
pkcs11-tool --module my_pkcs11_module.so --slot 0 --list-objects -l Logging in to "My Token". Please enter User PIN: Private Key Object; RSA label: My Label ID: 0123456789abcdef0123456789abcdef01234567 Usage: decrypt, sign, unwrap Public Key Object; RSA 2048 bits label: My Label ID: 0123456789abcdef0123456789abcdef01234567 Usage: encrypt, verify, wrap Certificate Object, type = X.509 cert label: My Label ID: 0123456789abcdef0123456789abcdef01234567
If the PKCS#11 module is properly added to the system’s NSS database (see <smartcard_authentication_step1#configuring-ipa-client-for-local-authentication-with-a-smartcard> for details) p11_child should be able to return the certificate :
/usr/libexec/sssd/p11_child --pre --nssdb=/etc/pki/nssdb
If this works well SSSD should now be able to authenticate the AD user with the help of the Smartcard.
There are various ways how to get a certificate from an external CA, see e.g. <https://blog-nkinder.rhcloud.com/?p=179how to generate the keys on a Smartcard, request a certificate from a CA and store it on the Smartcard. As a result the certificate and all the needed keys are already on the Smartcard. In the following we will explain how to make AD aware of it and enable local Smartcard login for an AD user.
In other situations the certificate and the keys might be available as files. The previous section should help to convert the file content into DER encoded objects and write them to a Smartcard.
The certificate can be read with various tools like certutil, pkcs11-tool or p11tool. But using SSSD’S p11_child has the advantage that it is verified that SSSD can access the certificate as well. :
/usr/libexec/sssd/p11_child --pre --nssdb=/etc/pki/nssdb | tail -1 | base64 -d ./cert.der
should write the DER encode certificate data into the file cert.der. If there are any issue you can call :
/usr/libexec/sssd/p11_child --pre -d 10 --debug-fd=2 --nssdb=/etc/pki/nssdb
to see the full debug output which might help to identify what is going wrong.
For the following operations the permissions of the AD user which should get the certificate are sufficient. So either login as the user or call kinit aduser@AD.DOMAIN.
First the distinguished name (DN) of the user object in AD has to be identified with :
ldapsearch -Y GSSAPI -H ldap://ad-dc.ad.domain -b 'dc=ad,dc=domain' samAccountName=aduser dn
In the most easy case the DN will look like CN=aduser,CN=Users,DC=ad,DC=domain.
With this DN a simple LDIF file can be created :
dn: CN=aduser,CN=Users,DC=ad,DC=domain changetype: modify add: userCertificate userCertificate:< file:cert.der
With this LDIF file the certificate can be loaded into the aduser entry :
ldapmodify -Y GSSAPI -H ldap://ad-dc.ad.domain -f file.ldif
Now SSSD can check if the certificate belongs to the aduser and can authenticate the aduser locally with the Smartcard. Please note that SSSD might have a valid user entry in the cache and will not read the freshly added certificate immediately. To force a refresh just call sss_cache -u firstname.lastname@example.org.