Yubico PAM module

The Yubico PAM module provides an easy way to integrate the YubiKey into your existing user authentication infrastructure. PAM is used by GNU/Linux, Solaris and Mac OS X for user authentication, and by other specialized applications such as NCSA MyProxy.

Status and Roadmap

The module is working for multi-user systems. The primary mode of operation is by doing online validation using a YubiKey validation service (such as the YubiCloud, or a private one configured using the urllist parameter).

In version 2.6, offline validation was also made possible through the use of HMAC-SHA1 Challenge-Response found in YubiKey 2.2 and later. This has introduced a dependency of libykpers-1 from the ykpersonalize package. Pass --without-cr to configure to avoid this dependency.

The development community is co-ordinated via the GitHub project page.

The project is licensed under a BSD license. See the file COPYING for exact wording. For any copyright year range specified as YYYY-ZZZZ in this package note that the range specifies every single year in that closed interval.

Building from Git

Skip to the next section if you are using an official packaged version.

You may check out the sources using Git with the following command:

git clone https://github.com/Yubico/yubico-pam.git

This will create the directory yubico-pam.

Autoconf, automake, libtool, asciidoc, xsltproc and docbook-xsl must be installed to create a compilable source tree.

Generate the build system using:

cd yubico-pam
autoreconf --install

Building

You will need to have libykclient (ykclient.h, libykclient.so) and libpam-dev (security/pam_appl.h, libpam.so) installed. It in turn requires cURL, which you need to have installed, and libyubikey.

The Challenge-Response offline authentication requires libykpers-1 from the yubikey-personalization project:

The selftests require perl with the module Net::LDAP::Server installed.

The build system uses Autoconf, to set up the build system run:

./configure

Use --without-ldap to disable ldap support.

Then build the code, run the self-test and install the binaries:

make check install

Installation

Fedora/EPEL

There is already a package in Fedora/EPEL of yubico-pam that can be installed by using yum:

sudo yum install pam_yubico

Ubuntu PPA

There is an Ubuntu PPA (Personal Package Archive) for yubico-pam that can be installed using the following commands on reasonably modern Ubuntu platforms :

sudo add-apt-repository ppa:yubico/stable
sudo apt-get update
sudo apt-get install libpam-yubico

See the file /usr/share/doc/libpam-yubico/README.Debian after installing.

FreeBSD ports

yubico-pam and the supporting Yubico packages have corresponding FreeBSD ports. To install:

cd /usr/ports/security/pam_yubico
make install clean

Advanced configuration notes are available here.

Configuration

Install it in your PAM setup by adding a line to an appropriate file in /etc/pam.d/:

auth sufficient pam_yubico.so id=[Your API Client ID] debug

and move pam_yubico.so into /lib/security/ (or wherever PAM modules live in your system) :

mv /usr/local/lib/security/pam_yubico.so /lib/security/

For more information, see the project documentation.

Supported PAM module parameters are:

authfile

To indicate the location of the file that holds the mappings of YubiKey token IDs to user names.

id

Your API Client ID in the Yubico validation server. If you want to use the default YubiCloud service, go here.

key

To indicate your client key in base64 format. The client key is also known as API key, and provides integrity in the communication between the client (you) and the validation server. If you want to get one for use with the default YubiCloud service, go here.

debug

to enable debug output.

debug_file

filename to write debug to, file must exist and be a regular file. stdout is default.

alwaysok

to enable all authentication attempts to succeed (aka presentation mode).

try_first_pass

Before prompting the user for their password, the module first tries the previous stacked module´s password in case that satisfies this module as well.

use_first_pass

The argument use_first_pass forces the module to use a previous stacked modules password and will never prompt the user - if no password is available or the password is not appropriate, the user will be denied access.

always_prompt

If set, don’t attempt to do a lookup to determine if the user has a YubiKey configured but instead prompt for one no matter what. This is useful in the case where ldap_bind_as_user is enabled but this module is being used to read the user’s password (in a YubiKey+OTP auth scenario).

nullok

If set, don’t fail when there are no tokens declared for the user in the authorization mapping files or in LDAP. This can be used to make YubiKey authentication optional unless the user has associated tokens.

ldap_starttls

If set, issue a STARTTLS command to the LDAP connection before attempting to bind to it. This is a common setup for servers that only listen on port 389 but still require TLS.

ldap_bind_as_user

If set, use the user logging in to bind to LDAP. This will use the password provided by the user via PAM. If this is set, ldapdn and uid_attr must also be set. Enabling this will cause ldap_bind_user and ldap_bind_password to be ignored

urllist

List of URL templates to be used. This is set by calling ykclient_set_url_bases. The list should be in the format : https://server/wsapi/2.0/verify;https://server/wsapi/2.0/verify

url

This option should not be used, please use the urllist option instead. Specify the URL template to use, this is set by calling yubikey_client_set_url_template, which defaults to: https://api.yubico.com/wsapi/verify?id=%d&otp=%s or https://api.yubico.com/wsapi/2.0/verify?id=%d&otp=%s depending on your version of yubico-c-client.

capath

specify the path where X509 certificates are stored. This is required if https or ldaps are used in url and ldap_uri respectively.

cainfo

Option to allow usage of a CA bundle instead of path.

proxy

specify a proxy to connect to the validation server. Valid schemes are http://, https://, socks4://, socks4a://, socks5:// or socks5h://. Socks5h asks the proxy to do the dns resolving. If no scheme or port is specified HTTP proxy port 1080 will be used.

verbose_otp

This argument is used to show the OTP (One-Time Password) when it is entered, i.e. to enable terminal echo of entered characters. You are advised to not use this, if you are using two factor authentication because that will display your password on the screen. This requires the service using the PAM module to display custom fields. This option can not be used with OpenSSH.

ldap_uri

specify the LDAP server URI (e.g. ldap://localhost).

ldapserver

specify the LDAP server host (default LDAP port is used). Deprecated. Use "ldap_uri" instead.

ldapdn

specify the dn where the users are stored (eg: ou=users,dc=domain,dc=com).

ldap_clientcertfile

The path to a client cert file to use when talking to the LDAP server. Note this requires ldap_clientkeyfile to be set as well.

ldap_clientkeyfile

The path to a key to be used with the client cert when talking to the LDAP server. Note this requires ldap_clientcertfile to be set as well.

ldap_bind_user

The user to attempt a LDAP bind as.

ldap_bind_password

The password to use on LDAP bind.

ldap_filter

An LDAP filter to use for attempting to find the correct object in LDAP. In this string %u will be replaced with the username.

ldap_cacertfile

CA certifcate file for the LDAP connection.

user_attr

specify the LDAP attribute used to store user names (eg:cn).

yubi_attr

specify the LDAP attribute used to store the YubiKey ID.

yubi_attr_prefix

specify the prefix of the LDAP attribute’s value, in case of a generic attribute, used to store several types of IDs.

token_id_length

Length of ID prefixing the OTP (this is 12 if using the YubiCloud).

mode

Mode of operation. Use "client" for online validation with a YubiKey validation service such as the YubiCloud, or use "challenge-response" for offline validation using YubiKeys with HMAC-SHA-1 Challenge-Response configurations. See the man-page ykpamcfg(1) for further details on how to configure offline Challenge-Response validation.

chalresp_path

Directory that is used to store the challenge files in case of a system-wide configuration (in contrast to challenge files being stored in a user’s home directory). This location should be only readable and writable by root. Refer to Authentication_Using_Challenge-Response.adoc for more information about such a setup.

mysql_server

Hostname/Adress of mysql server to use for mapping.

mysql_port

Network port of mysql server.

mysql_user

User for accessing the mysql database.

mysql_password

Password for the mysql user.

mysql_database

The mysql database to use.

If you are using "debug" you may find it useful to create a world-writable log file:

touch /var/run/pam-debug.log
chmod go+w /var/run/pam-debug.log
Note
Please remember, physical access to systems often allows the circumvention of security controls. If an attacker has physical access to your system (such as a laptop left in a hotel room) and can boot into single user mode, they can disable yubico-pam in your system configuration.

Authorization Mapping Files

A mapping must be made between the YubiKey token ID and the user ID it is attached to. There are two ways to do this, either centrally in one file, or individually, where users can create the mapping in their home directories. If the central authorization mapping file is being used, user home directory mappings will not be used and the opposite applies if user home directory mappings are being used, the central authorization mappings file will not be used.

Central authorization mapping

Create a /etc/yubikey_mappings, the file must contain a user name and the YubiKey token ID separated by colons (same format as the passwd file) for each user you want to allow onto the system using a YubiKey.

The mappings should look like this, one per line:

<first user name>:<YubiKey token ID1>:<YubiKey token ID2>:….
<second user name>:<YubiKey token ID3>:<YubiKey token ID4>:….

Now add authfile=/etc/yubikey_mappings to your PAM configuration line, so it looks like:

auth sufficient pam_yubico.so id=[Your API Client ID] authfile=/etc/yubikey_mappings

Individual authorization mapping by user

Each user creates a ~/.yubico/authorized_yubikeys file inside of their home directory and places the mapping in that file, the file must have only one line:

<user name>:<YubiKey token ID1>:<YubiKey token ID2>

This is much the same concept as the SSH authorized_keys file.

Obtaining the YubiKey token ID (a.k.a. public ID)

You can obtain the YubiKey token ID in several ways. One is by removing the last 32 characters of any OTP (One Time Password) generated with your YubiKey. Another is by using the modhex calculator.

Enter your YubiKey OTP and convert it, your YubiKey token ID is 12 characters and listed as:

Modhex encoded: XXXXXXX

Not sure what that last bit meant? Here is how to get a copy of your OTP.

Fast way

  1. Open a terminal

  2. Press the YubiKey’s button It will output an OTP into the shell:

    $ cccccccgklgcvnkcvnnegrnhgrjkhlkfhdkclfncvlgj
    bash: cccccccgklgcvnkcvnnegrnhgrjkhlkfhdkclfncvlgj: command not found
    

    This can be pasted into the Modhex_Calculator page.

Harder way

This requires you to have the pam module enabled with debug turned on. When prompted for the YubiKey press the button. The pam module will print out debug information including the OTP and ID of your token to the shell — copy the ID into your config file and you should be up and going.

YubiKey for `youruser':
[pam_yubico.c:pam_sm_authenticate(867)] conv returned 44 bytes
[pam_yubico.c:pam_sm_authenticate(885)] Skipping first 0 bytes. Length is 44, token_id set to 12 and token OTP always 32.
[pam_yubico.c:pam_sm_authenticate(892)] OTP: ccccccclabcabkhbdncicglfltnukadfoifadfhhhhfe ID: cccccclabcab

Yubico PAM module and SELinux.

Users with SELinux in enforcing mode (the default on Fedora 17+) may experience login problems with services including those validated via polkit-agent-helper-1, sshd and login.

This is documented in Red Hat bugzilla including a work around for ssh (Equivalent files could be created for other services). Systems in permissive mode will generate AVC warnings but authentication will succeed.

To determine if you have SELinux enforcing or not run the sestatus command.

Examples

If you want to use the YubiKey to authenticate you on Linux console logins, add the following to the top of /etc/pam.d/login:

auth sufficient pam_yubico.so id=[Your API Client ID] debug

OpenVPN and ActiveDirectory

See Michael Ludvig’s sample Active Directory schema extensions for YubiKey public ID attribute storage / association with a particular user account: https://github.com/mludvig/yubikey-ldap/tree/master/microsoft-schema

create file /etc/pam.d/openvpn:

auth  required  pam_yubico.so ldap_uri=ldap://contoso.com debug id=[Your API ID] yubi_attr=YubiKeyID
   ldapdn=DC=contoso,DC=com
   ldap_filter=(&(sAMAccountName=%u)(objectClass=user)(memberOf=CN=somegroup,DC=contoso,DC=com))
   [ldap_bind_user=CN=binduser,OU=Service Accounts,DC=contoso,DC=com] ldap_bind_password=bind_password try_first_pass
account required  pam_yubico.so

create file openvpn.conf

plugin openvpn-plugin-auth-pam.so openvpn