Overview
On Unix-like systems, processes such as the OpenSSH daemon need to authenticate the user and gather some information about them (e.g., user ID, home directory, shell...). Authentication is done through a mechanism called Pluggable Authentication Modules (PAM), while retrieving information about users (or groups, hostnames, etc.) is done through another mechanism called the Name Service Switch (NSS).
In this tutorial, we will allow user accounts stored as posixAccount objects in an LDAP server to be considered valid in a system, in addition to the locally-defined ones, by configuring NSS. We will then configure PAM to delegate authentication to OpenOTP accounts stored on the LDAP server.
When authenticating a user through PAM, a process will read /etc/pam.d/<service>
, where <service>
is the name of the service that the process implements. Each line in that file mentions a module to load, how to use it, and what decision to make based on the result. We will install the pam_openotp plugin and add a line mandating its use to contact your OpenOTP server.
Processes that need to determine, for example, which users or groups exist, use a set of functions implemented by the C standard library. These functions will read the file /etc/nsswitch.conf
and, according to the information it contains, load modules in the form of libraries and retrieve the needed information through these modules in a specific order. We will install the NSS-based Spankey module to collect user account information from our LDAP server. If the pam_ldap module returns the account information, you don’t need to install Spankey; this particular case is not explained in this documentation.
The modules pam_ldap.so
, nss_ldap.so
, and nscd
are not maintained by RCDevs.
There are two kinds of integration with PAM. In both integrations, accounts that need to authenticate with PAM OpenOTP must be available on the WebADM server.
-
Using local accounts on the OS: This method is not preferred because it involves creating users on each client systems and the WebADM server, and each user will need to be created on every machine they need to access. This setup is not demonstrated in this how-to.
-
Using remote/LDAP accounts with the Spankey client/server: In this integration, Spankey is free and is used solely for NSS requests to retrieve LDAP users and groups from the Spankey server on the Linux machine. Any LDAP account can natively become a Linux account by adding the Posix ObjectClass to the user account and filling in the mandatory attributes. This process is explained later in this documentation.
Prerequisites
Firstly, you need to have a configured OpenOTP and SpanKey server available via WebADM.
Next, install the spankey_client
, pam_openotp
, and nscd
packages on your server where you want to enable Two-Factor Authentication (2FA). All these packages are available on the RCDevs Repository.
On RedHat, CentOS, or Fedora systems, you can simplify the installation and updates using our repository:
dnf install pam_openotp nscd spankey_client
For Debian and Ubuntu systems, use the following command:
apt install pam-openotp nscd spankey-client
Once you have downloaded and installed these packages, you can proceed with configuring these products accordingly.
WebADM Accounts Configuration
To use your LDAP account on UNIX servers, you need to extend your account to UNIX through the WebADM GUI. Follow these steps:
- Log in to WebADM and navigate to your account in the left tree.
- In the user details section, locate the option labeled
Add Extension
. - Select
UNIX Account
from the available extensions. - Click on the
Add
button to confirm and apply the extension.
This process will enable your LDAP account for UNIX authentication and access on the designated servers.
After clicking Add, you will be directed to a screen where you can confirm the addition or configuration of the extension.
At this step, be careful to not use a UID already assigned to an existing user. We advise starting from uid=500...
Click on Proceed
and Extend Object
to finish the UNIX extension for your account.
If you want to use a Hardware Token for this account, remember to change the OTP method and Token Type to LDAPOTP/TOKEN. Failure to do so may result in an error message such as Account Require Missing Data
when you attempt to log in.
WebADM Group Configuration
To create a Sudoers group in WebADM and add users to this group, follow these steps.
Click on create
, select UNIX Group
, and click on Proceed
button.
Give a name to the Group
, and click on Proceed
button.
Now you can add the User
to the Group
by clicking on Add members
After clicking on Proceed
, clear the cache of WebADM :
Now we are going to add our Group
to sudoers
file :
root@Ubuntu-machine:~# visudo
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
Defaults use_pty
# This preserves proxy settings from user environments of root
# equivalent users (group sudo)
#Defaults:%sudo env_keep += "http_proxy https_proxy ftp_proxy all_proxy no_proxy"
# This allows running arbitrary commands, but so does ALL, and it means
# different sudoers have their choice of editor respected.
#Defaults:%sudo env_keep += "EDITOR"
# Completely harmless preservation of a user preference.
#Defaults:%sudo env_keep += "GREP_COLOR"
# While you shouldn't normally run git as root, you need to with etckeeper
#Defaults:%sudo env_keep += "GIT_AUTHOR_* GIT_COMMITTER_*"
# Per-user preferences; root won't have sensible values for them.
#Defaults:%sudo env_keep += "EMAIL DEBEMAIL DEBFULLNAME"
# "sudo scp" or "sudo rsync" should be able to use your SSH agent.
#Defaults:%sudo env_keep += "SSH_AGENT_PID SSH_AUTH_SOCK"
# Ditto for GPG agent
#Defaults:%sudo env_keep += "GPG_AGENT_INFO"
# Host alias specification
# User alias specification
# Cmnd alias specification
# User privilege specification
root ALL=(ALL:ALL) ALL
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
%sudoers ALL=(ALL:ALL) ALL
# See sudoers(5) for more information on "@include" directives:
@includedir /etc/sudoers.d
root@Ubuntu-machine:~# getent group | grep sudoers
sudoers:x:234:test
root@Ubuntu-machine:~# getent passwd | grep test
test:x:5009:100::/home/test:/bin/bash
Switch to test
user :
root@Ubuntu-machine:~# sudo -iu test
test@Ubuntu-machine:/root$ whoami
test
test@Ubuntu-machine:/root$ sudo -i
[sudo] password for test: password
Enter your TOKEN password: 388229
root@Ubuntu-machine:~# whoami
root
To use sudo -i with MFA, you must edit the file /etc/pam.d/sudo-i
SpanKey Client Setup (Client Machine)
When the spankey_client
package is installed, you can configure it using the setup script located at /opt/spankey/bin/setup
. To execute this script, simply run the following command in a shell prompt:
/opt/spankey/bin/setup
This script initiates the configuration process for the spankey client.
root@ubuntu18client:/home/ubuntu18-client# /opt/spankey/bin/setup
Enter one of your running WebADM server IP or hostname: 192.168.3.131
Detected hostname is 'ubuntu18client'. Would you like to use it as client id (y/n)? [N]
Do you want to enable SpanKey Client for OpenSSH server (y/n)? [N]
Do you want to enable SpanKey Client NSS plugin (y/n)? [Y]
Do you want to register SpanKey Client logrotate script (y/n)? [Y]
Do you want SpanKey Client to be automatically started at boot (y/n)? [Y]
Primary OpenOTP service URL is: 'https://192.168.3.131:8443/spankey/'
Secondary OpenOTP service URL is: 'NONE'.
Use 'ubuntu18client' as client id: No
Enable SpanKey Client for OpenSSH server: No
Enable SpanKey Client NSS plugin: Yes
Register SpanKey Client logrotate script: Yes
SpanKey Client must be automatically started at boot: Yes
Do you confirm (y/n)?: y
Applying SpanKey Client setting from default configuration files... Ok
Retrieving WebADM CA certificate from host '192.168.3.131'... Ok
The setup needs now to request a signed 'SpanKey' client certificate.
This request should show up as pending in your WebADM interface and an administrator must accept it.
Waiting for approbation... Ok
At this step, you have to log in on the WebADM Admin GUI to approve the SSL Certificate Request in pending...
Updating file '/etc/nsswitch.conf'... Ok
Updating file '/etc/pam.d/common-account'... Ok
Registering SpanKey Client service... Ok
Adding logrotate script... Ok
SpanKey Client has successfully been setup.
IMPORTANT: Do not forget to perform the following action before you exit this session:
- Start SpanKey (/opt/spankey/bin/spankey start)
- Restart 'nscd'
That’s all for configuring the SpanKey client. We are using it specifically for the NSS part, so the configuration process is straightforward.
Note: In the example above, we selected "No" to enable SpanKey for the OpenSSH server because in our setup, SpanKey is utilized only for the NSS functionality. SpanKey for OpenSSH is a separate product that functions as an SSH Key Management Service, requiring an enterprise license (for more than 5 managed servers). For more information about SpanKey, please visit the RCDevs | SpanKey website.
PAM OpenOTP Setup (Client Machine)
Configuring the OpenOTP client is straightforward. Simply execute the following command in a shell and provide the required information:
root@ubuntu18client:/home/ubuntu18-client# /usr/bin/openotp_setup
This is the configuration tool for RCDevs PAM module.
It will configure WebADM Server URL(s), SSH helper and NSS.
Enter WebADM server IP or hostname [localhost]: 192.168.3.131
Found one server URL: https://192.168.3.131:8443/openotp/
Retrieving WebADM CA certificate... Ok
Do you want PAM module to auto-create home directories ([y]/n)?:
y
Do you want to keep local password authentication as a fallback to OpenOTP? ([y]/n)?:
y
Do you want to activate PAM OpenOTP for ssh ([y]/n)?:
y
Do you want to activate PAM OpenOTP for graphical login with lightdm ([y]/n)?:
y
Auto-create home directories: Yes
Keep local password authentication as a fallback: Yes
Activate PAM OpenOTP for ssh: Yes
Do you confirm ([y]/n)?: y
Updating /etc/openotp/openotp.conf... Ok
Updating /etc/ssh/sshd_config... Ok
Updating /etc/pam.d/sshd... OK
Synchronizing state of ssh.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable ssh
Synchronizing state of nscd.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable nscd
PAM OpenOTP has been succesfully configured.
The setup for PAM OpenOTP is now complete. During the setup, we can automatically configure PAM OpenOTP for OpenSSH. However, in the next section, we will outline the specific configuration steps required for OpenSSH.
OpenSSH Server Configuration (Client Machine)
These settings are already configured with the PAM_OpenOTP setup.
For SSHd, you can keep the default configuration on each UNIX distribution. Simply edit the file /etc/ssh/sshd_config
and adjust the following settings:
ChallengeResponseAuthentication yes
UsePAM yes
Since OpenSSH 1:8.7, the references to ChallengeResponseAuthentication are removed in favor of KbdInteractiveAuthentication. For this end, you need to enable the line in /etc/ssh/sshd_config :
KbdInteractiveAuthentication yes
#ChallengeResponseAuthentication yes
If your OpenSSH server supports it or is configured to load different configuration files, you can create a file similar to the one below:
/etc/ssh/sshd_config.d/49-rcdevs.conf
which include the following lines:
PasswordAuthentication yes
KbdInteractiveAuthentication yes
The prefix number in the name of the configuration file matters as it determines the priority of the OpenSSH settings loaded. For example, on RHEL9, there is typically a file named 50-redhat.conf
in the configuration folder by default. To ensure that your SSHD configuration file takes priority, use a number lower than 50 in the filename. Otherwise, your settings may be overridden by 50-redhat.conf
and not applied.
Restart OpenSSH server to apply the new configuration.
root@ubuntu18client:/home/ubuntu18-client# systemctl restart sshd
PAM Integrations with OpenOTP
To configure UNIX services with OpenOTP authentication, you need to edit the files that correspond to the service you want to enable two-factor authentication (2FA) for, located in /etc/pam.d/<service>
.
After running the PAM OpenOTP setup script, an openotp-auth
PAM file is created which typically looks like the example below on every Linux distribution:
bash-4.1# cat /etc/pam.d/openotp-auth
auth required pam_env.so
auth sufficient pam_unix.so
auth sufficient pam_openotp.so
auth required pam_deny.so
The fallback to local accounts is maintained with the line calling pam_unix.so
library. If authentication fails at the local level, it proceeds to pam_openotp.so
, which involves the OpenOTP server.
To modify the PAM configuration file for a service, you only need to include the openotp-auth
configuration file in the PAM configuration file of the service.
Optionally, you can edit the openotp-auth
file to prioritize the first OpenOTP authentication stack before the UNIX stack by switching the order of the lines like this:
bash-4.1# cat /etc/pam.d/openotp-auth
auth required pam_env.so
auth sufficient pam_openotp.so
auth sufficient pam_unix.so
auth required pam_deny.so
RHEL / CentOS
Found below, few configuration examples for different services.
SSH
These files should be already configured with the PAM_OpenOTP setup because we answered yes to configure OpenSSH server during PAM_OpenOPT setup.
bash-4.1# vi /etc/pam.d/sshd
#%PAM-1.0
auth substack openotp-auth
auth include postlogin
account required pam_sepermit.so
account required pam_nologin.so
account include password-auth
password include password-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open env_params
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session optional pam_motd.so
session include password-auth
session include postlogin
Configuration for OpenSSH is complete. You can now log in to your OpenSSH server using your LDAP credentials and OTP password.
Test:
[yoann@iMac ~]$ ssh Administrator@192.168.3.69
Password: xxxxxxx
Enter your TOKEN password: 043792
-bash-4.1$ whoami
Administrator
-bash-4.1$
XRDP
Found below, the configuration for XRDP.
bash-4.1# vi /etc/pam.d/xrdp-sesman
#%PAM-1.0
# Generic Fedora config
#auth include password-auth
auth include openotp-auth
account include password-auth
password include password-auth
session include password-auth
# Gnome specific Fedora config
#auth include gdm-password
#account include gdm-password
#password include gdm-password
#session include gdm-password
Restart the server to ensure XRDP integration works correctly after configuring PAM. Simply restarting the XRDP service may not be sufficient when editing the PAM configuration for the XRDP service.
CONSOLE
To configure console login with OpenOTP, you need to edit the file /etc/pam.d/login
.
bash-4.1# vi /etc/pam.d/login
#%PAM-1.0
auth include openotp-auth
auth substack system-auth
auth include postlogin
account required pam_nologin.so
account include system-auth
password include system-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include system-auth
session include postlogin
-session optional pam_ck_connector.so
GDM
These files should already be configured with the PAM_OpenOTP setup because we selected "yes" to configure GDM during the PAM_OpenOTP setup process.
bash-4.1# vi /etc/pam.d/gdm-password
auth [success=done ignore=ignore default=bad] pam_selinux_permit.so
auth substack openotp-auth
auth optional pam_gnome_keyring.so
auth include postlogin
account required pam_nologin.so
account include password-auth
password substack password-auth
-password optional pam_gnome_keyring.so use_authtok
session required pam_selinux.so close
session required pam_loginuid.so
session optional pam_console.so
session required pam_selinux.so open
session optional pam_keyinit.so force revoke
session required pam_namespace.so
session include password-auth
session optional pam_gnome_keyring.so auto_start
session include postlogin
SUDO
In this section, we will configure sudo to use OpenOTP for authentication. Switching users using sudo requires appropriate authorizations, which are configured by the root user in /etc/sudoers
. Refer to UNIX documentation for instructions on editing this file.
Here, we will edit /etc/pam.d/sudo
to enforce One-Time Password authentication when users execute a sudo command.
This integration does not grant SUDO privileges as Spankey server does under its licensing. Instead, this integration prompts end-users for Multi-Factor Authentication (MFA) when requesting SUDO privileges.
bash-4.1# vi /etc/pam.d/sudo
#%PAM-1.0
#auth include system-auth
auth include openotp-auth
account include system-auth
password include system-auth
session include system-auth
As mentioned earlier, the user Administrateur
must have permissions to execute sudo commands. You will be prompted to enter your OTP when entering SUDO mode.
Test:
Debian / Ubuntu
SSH
To configure UNIX services with OpenOTP authentication, you need to edit the respective files located in /etc/pam.d/<service>
.
Here’s an example for SSH. Disable @include common-auth
and add @include openotp-auth
:
bash-4.1# vi /etc/pam.d/sshd
# PAM configuration for the Secure Shell service
# OpenOTP authentication.
@include openotp-auth
# Disallow non-root logins when /etc/nologin exists.
account required pam_nologin.so
# Uncomment and edit /etc/security/access.conf if you need to set complex
# access limits that are hard to express in sshd_config.
# account required pam_access.so
# Standard Un*x authorization.
@include common-account
# 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
# Set the loginuid process attribute.
session required pam_loginuid.so
# Create a new session keyring.
session optional pam_keyinit.so force revoke
# Standard Un*x session setup and teardown.
@include common-session
# Print the message of the day upon successful login.
# This includes a dynamically generated part from /run/motd.dynamic
# and a static (admin-editable) part from /etc/motd.
session optional pam_motd.so motd=/run/motd.dynamic
session optional pam_motd.so noupdate
# Print the status of the user's mailbox upon successful login.
session optional pam_mail.so standard noenv # [1]
# Set up user limits from /etc/security/limits.conf.
session required pam_limits.so
# Read environment variables from /etc/environment and
# /etc/security/pam_env.conf.
session required pam_env.so # [1]
# In Debian 4.0 (etch), locale-related environment variables were moved to
# /etc/default/locale, so read that as well.
session required pam_env.so user_readenv=1 envfile=/etc/default/locale
# 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.
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
# Standard Un*x password updating.
@include common-password
XRDP
bash-4.1# vi /etc/pam.d/xrdp-sesman
#%PAM-1.0
#@include common-auth
@include openotp-auth
@include common-account
@include common-session
@include common-password
Restart the server in order to have XRDP integration working after the PAM configuration. Restart the XRDP services may not be enough when editing PAM configuration of XRDP service.
CONSOLE
# The PAM configuration file for the Shadow `login' service
#
# Enforce a minimal delay in case of failure (in microseconds).
# (Replaces the `FAIL_DELAY' setting from login.defs)
# Note that other modules may require another minimal delay. (for example,
# to disable any delay, you should add the nodelay option to pam_unix)
auth optional pam_faildelay.so delay=3000000
# Outputs an issue file prior to each login prompt (Replaces the
# ISSUE_FILE option from login.defs). Uncomment for use
# auth required pam_issue.so issue=/etc/issue
# Disallows other than root logins when /etc/nologin exists
# (Replaces the `NOLOGINS_FILE' option from login.defs)
auth requisite pam_nologin.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.
# When the module is present, "required" would be sufficient (When SELinux
# is disabled, this returns success.)
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
# Sets the loginuid process attribute
session required pam_loginuid.so
# Prints the message of the day upon successful login.
# (Replaces the `MOTD_FILE' option in login.defs)
# This includes a dynamically generated part from /run/motd.dynamic
# and a static (admin-editable) part from /etc/motd.
session optional pam_motd.so motd=/run/motd.dynamic
session optional pam_motd.so noupdate
# 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
# When the module is present, "required" would be sufficient (When SELinux
# is disabled, this returns success.)
# This module parses environment configuration file(s)
# and also allows you to use an extended config
# file /etc/security/pam_env.conf.
#
# parsing /etc/environment needs "readenv=1"
session required pam_env.so readenv=1
# locale variables are also kept into /etc/default/locale in etch
# reading this file *in addition to /etc/environment* does not hurt
session required pam_env.so readenv=1 envfile=/etc/default/locale
# Standard Un*x authentication.
#@include common-auth
@include openotp-auth
# This allows certain extra groups to be granted to a user
# based on things like time of day, tty, service, and user.
# Please edit /etc/security/group.conf to fit your needs
# (Replaces the `CONSOLE_GROUPS' option in login.defs)
auth optional pam_group.so
# Uncomment and edit /etc/security/time.conf if you need to set
# time restraint on logins.
# (Replaces the `PORTTIME_CHECKS_ENAB' option from login.defs
# as well as /etc/porttime)
# account requisite pam_time.so
# Uncomment and edit /etc/security/access.conf if you need to
# set access limits.
# (Replaces /etc/login.access file)
# account required pam_access.so
# Sets up user limits according to /etc/security/limits.conf
# (Replaces the use of /etc/limits in old login)
session required pam_limits.so
# Prints the last login info upon successful login
# (Replaces the `LASTLOG_ENAB' option from login.defs)
session optional pam_lastlog.so
# Prints the status of the user's mailbox upon successful login
# (Replaces the `MAIL_CHECK_ENAB' option from login.defs).
#
# This also defines the MAIL environment variable
# However, userdel also needs MAIL_DIR and MAIL_FILE variables
# in /etc/login.defs to make sure that removing a user
# also removes the user's mail spool file.
# See comments in /etc/login.defs
session optional pam_mail.so standard
# Create a new session keyring.
session optional pam_keyinit.so force revoke
# Standard Un*x account and session
@include common-account
@include common-session
@include common-password
{{< figure src="../15.webp" class="img80 center" width="640" height="538" >}}
GDM
For GDM, the only file you need to edit is /etc/pam.d/gdm-password
. Here is an example of how it should be configured:
#%PAM-1.0
auth requisite pam_nologin.so
auth required pam_succeed_if.so user != root quiet_success
@include openotp-auth
auth optional pam_gnome_keyring.so
@include common-account
# 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.
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 envfile=/etc/default/locale
@include common-session
session optional pam_gnome_keyring.so auto_start
@include common-password
This is the default file, we only change @include common-auth
by @include openotp-auth
on line 4.
Configuration is done, you are now able to log in on the Gnome desktop with an OTP:
Lightdm
When the default graphical interface is LightDM and you want to allow the user to enter their own username, you need to edit the following file:
vi /usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf
And add the following line:
greeter-show-manual-login=true
You can now reboot your machine, and on the next login, you will be able to enter your username manually.
After running the openotp_setup script, if you chose yes to enable PAM OpenOTP for LightDM, the line including OpenOTP authentication should already be configured.
Edit the file /etc/pam.d/lightdm
and it should resemble something like this:
#%PAM-1.0
auth requisite pam_nologin.so
auth sufficient pam_succeed_if.so user ingroup nopasswdlogin
@include openotp-auth
auth optional pam_gnome_keyring.so
auth optional pam_kwallet.so
auth optional pam_kwallet5.so
@include common-account
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
session required pam_loginuid.so
session required pam_limits.so
@include common-session
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
session optional pam_gnome_keyring.so auto_start
session optional pam_kwallet.so auto_start
session optional pam_kwallet5.so auto_start
session required pam_env.so readenv=1
session required pam_env.so readenv=1 user_readenv=1 envfile=/etc/default/locale
@include common-password
This is the default file; the only change required is to replace @include common-auth
with @include openotp-auth
.
Configuration is complete. You can now log in to your desktop using OTP.
SUDO
In this section, we will configure sudo to use OpenOTP for authentication. Switching users using sudo requires appropriate authorizations, which are configured by the root user in /etc/sudoers
. Refer to UNIX documentation for instructions on editing this file.
user_spankey@ubuntu18client:~$ whoami
user_spankey
user_spankey@ubuntu18client:~$ sudo su
[sudo] password for user_spankey:
Enter your TOKEN password: 745487
root@ubuntu18client:/home/user_spankey# whoami
root
This integration is not to give SUDO privileges as Spankey server is able to do under the Spankey licensing. This integration is to prompt the end-user for MFA when asking SUDO privileges.
First, we'll add the user (user_spankey) to /etc/sudoers
with the following command:
root@ubuntu18client:/home/ubuntu18-client# addgroup user_spankey sudo
Adding user `user_spankey' to group `sudo' ...
Adding user user_spankey to group sudo
Done.
Here, we will edit /etc/pam.d/sudo
to prompt a One-Time Password when users execute a sudo command.
root@ubuntu18client:/home/ubuntu18-client# vi /etc/pam.d/sudo
#%PAM-1.0
session required pam_env.so readenv=1 user_readenv=0
session required pam_env.so readenv=1 envfile=/etc/default/locale user_readenv=0
@include openotp-auth
#@include common-auth
@include common-account
@include common-session-noninteractive
Client policy
A policy can be configured per service (e.g., xrdp, ssh, console). Configuring a client policy for your different accesses will allow you to control which group(s) can access the system, from which network...
Troubleshooting
There are many files that you can check to troubleshoot the Linux client and WebADM/OpenOTP/SpanKey servers.
WebADM/OpenOTP/SpanKey Servers
WebADM/OpenOTP has a transaction log that records all requests/responses in the following file:
bash-4.1# cat /opt/webadm/logs/webadm.log
Typical logs of an authentication success using SSH and PAM_OpenOTP:
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] New openotpSimpleLogin SOAP request
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] > Username: Administrateur
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] > Password: xxxxxxxx
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] > Client ID: SSH
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] > Source IP: 10.0.3.22
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] > Options: -U2F
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Enforcing client policy: SSH
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Registered openotpSimpleLogin request
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Resolved LDAP user: CN=Administrateur,CN=Users,DC=yorcdevs,DC=com
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Resolved LDAP groups: propri\xc3\xa9taires cr\xc3\xa9ateurs de la strat\xc3\xa9gie de groupe,admins du domaine,administrateurs de l\xe2\x80\x99entreprise,administrateurs du sch\xc3\xa9ma,administrateurs,utilisateurs du bureau \xc3\xa0 distance,groupe de r\xc3\xa9plication dont le mot de passe rodc est refus\xc3\xa9
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Started transaction lock for user
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Found user language: EN
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Found 3 user certificate
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Found 37 user settings: LoginMode=LDAPMFA,OTPType=TOKEN,OTPLength=6,ChallengeMode=Yes,ChallengeTimeout=90,ChallengeLock=No,PushLogin=No,EnableLogin=Yes,AppKeyLength=20,HOTPLookAheadWindow=25,TOTPTimeStep=30,TOTPTimeOffsetWindow=120,MOTPTimeOffsetWindow=120,OCRASuite=OCRA-1:HOTP-SHA1-6:QN06-T1M,SMSType=Normal,SMSMode=Ondemand,MailMode=Ondemand,LastOTPTime=300,ListChallengeMode=ShowID
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Found 12 user data: LoginCount,RejectCount,LastOTP,ListInit,ListState,TokenType,TokenKey,TokenState,TokenID,Device1Name,Device1Data,Device1State
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Found 1 registered OTP token (TOTP)
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Requested login factors: LDAP & OTP
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] LDAP password Ok
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Challenge required
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Started OTP challenge session of ID PaS3WXe2HDJFz0st valid for 90 seconds
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Sent challenge response
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] New openotpChallenge SOAP request
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] > Username: Administrateur
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] > Session: PaS3WXe2HDJFz0st
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] > OTP Password: xxxxxx
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Enforcing client policy: SSH
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Registered openotpChallenge request
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Found challenge session started 2017-02-03 15:54:30
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Started transaction lock for user
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] TOTP password Ok (token #1)
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Updated user data
[2017-02-03 15:54:30] [192.168.3.134] [OpenOTP:3MJAB3KR] Sent success response
Typical logs of an authentication failure caused by WebADM configuration. Challenge Mode Supported
should be configured to Yes
either in OpenOTP Application settings or in the sudo Client Policy settings.
[2017-02-03 13:26:41] [192.168.3.60] [OpenOTP:7UERIOQE] New openotpSimpleLogin SOAP request
[2017-02-03 13:26:41] [192.168.3.60] [OpenOTP:7UERIOQE] > Username: Administrateur
[2017-02-03 13:26:41] [192.168.3.60] [OpenOTP:7UERIOQE] > Password: xxxxxxxx
[2017-02-03 13:26:41] [192.168.3.60] [OpenOTP:7UERIOQE] > Client ID: sudo
[2017-02-03 13:26:41] [192.168.3.60] [OpenOTP:7UERIOQE] > Source IP: 10.0.3.21
[2017-02-03 13:26:41] [192.168.3.60] [OpenOTP:7UERIOQE] Options: -U2F
[2017-02-03 13:26:41] [192.168.3.60] [OpenOTP:7UERIOQE] Enforcing client policy: sudo
[2017-02-03 13:26:41] [192.168.3.60] [OpenOTP:7UERIOQE] Registered openotpSimpleLogin request
[2017-02-03 13:26:41] [192.168.3.60] [OpenOTP:7UERIOQE] Resolved LDAP user: CN=Administrateur,CN=Users,DC=yorcdevs,DC=com
[2017-02-03 13:26:41] [192.168.3.60] [OpenOTP:7UERIOQE] Resolved LDAP groups: propri\xc3\xa9taires cr\xc3\xa9ateurs de la strat\xc3\xa9gie de groupe,admins du domaine,administrateurs de l\xe2\x80\x99entreprise,administrateurs du sch\xc3\xa9ma,administrateurs,utilisateurs du bureau \xc3\xa0 distance,groupe de r\xc3\xa9plication dont le mot de passe rodc est refus\xc3\xa9
[2017-02-03 13:26:41] [192.168.3.60] [OpenOTP:7UERIOQE] Started transaction lock for user
[2017-02-03 13:26:44] [192.168.3.60] [OpenOTP:7UERIOQE] Found user language: EN
[2017-02-03 13:26:44] [192.168.3.60] [OpenOTP:7UERIOQE] Found 3 user certificate
[2017-02-03 13:26:44] [192.168.3.60] [OpenOTP:7UERIOQE] Found 37 user settings: LoginMode=LDAPMFA,OTPType=TOKEN,OTPLength=6,ChallengeMode=Yes,ChallengeTimeout=90,ChallengeLock=No,PushLogin=No,EnableLogin=Yes,AppKeyLength=20,HOTPLookAheadWindow=25,TOTPTimeStep=30,TOTPTimeOffsetWindow=120,MOTPTimeOffsetWindow=120,OCRASuite=OCRA-1:HOTP-SHA1-6:QN06-T1M,SMSType=Normal,SMSMode=Ondemand,MailMode=Ondemand,LastOTPTime=300,ListChallengeMode=ShowID
[2017-02-03 13:26:44] [192.168.3.60] [OpenOTP:7UERIOQE] Found 12 user data: LoginCount,RejectCount,LastOTP,ListInit,ListState,TokenType,TokenKey,TokenState,TokenID,Device1Name,Device1Data,Device1State
[2017-02-03 13:26:44] [192.168.3.60] [OpenOTP:7UERIOQE] Challenge mode disabled (assuming concatened passwords)
[2017-02-03 13:26:44] [192.168.3.60] [OpenOTP:7UERIOQE] Found 1 registered OTP token (TOTP)
[2017-02-03 13:26:44] [192.168.3.60] [OpenOTP:7UERIOQE] Requested login factors: LDAP & OTP
[2017-02-03 13:26:44] [192.168.3.60] [OpenOTP:7UERIOQE] LDAP password Ok
[2017-02-03 13:26:44] [192.168.3.60] [OpenOTP:7UERIOQE] Updated user data
[2017-02-03 13:26:44] [192.168.3.60] [OpenOTP:7UERIOQE] Sent failure response
SpanKey Client
To know if SpanKey client works properly, you can run the following command on your client:
bash-4.1# getent passwd
This command must return Local and LDAP account (Extended to UNIX in WebADM).
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:103:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:104:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:105:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:106:systemd Bus Proxy,,,:/run/systemd:/bin/false
Debian-exim:x:104:109::/var/spool/exim4:/bin/false
messagebus:x:105:110::/var/run/dbus:/bin/false
statd:x:106:65534::/var/lib/nfs:/bin/false
sshd:x:107:65534::/var/run/sshd:/usr/sbin/nologin
test:x:1000:1000::/home/test:/bin/bash
Administrator:x:1100:100::/home/administrator:/bin/bash
yo:x:1101:100::/home/yo:/bin/sh
You should see a UNIX extended LDAP account in the result of the getent passwd
command:
test:x:1000:1000:test::/home/test:/bin/bash
Administrator:x:1100:100::/home/administrator:/bin/bash
yo:x:1101:100::/home/yo:/bin/sh
If this command doesn’t return your LDAP Accounts, please check the firewall configuration and SpanKey’s configuration URLs in /etc/spankey/spankey.conf. You can also try to restart the nscd service and check the SELinux configuration.
On Unix client, you can see the logs of the getent command in /var/log/messages
:
Feb 3 15:33:40 debian8 spankey[2043]: RCDevs SpanKey NSS Plugin version 1.0.2-3 loaded
If this log doesn’t appear when you call the getent command, SpanKey is not installed correctly. Try to reinstall it.
In WebADM logs, you can see the logs for the getent command too, getent call SpanKey module:
[2017-02-03 16:48:15] [192.168.3.134] [SpanKey:VOK85UQY] New spankeyNSSList SOAP request
[2017-02-03 16:48:15] [192.168.3.134] [SpanKey:VOK85UQY] > Database: user
[2017-02-03 16:48:15] [192.168.3.134] [SpanKey:VOK85UQY] > Client ID: SSH
[2017-02-03 16:48:15] [192.168.3.134] [SpanKey:VOK85UQY] Enforcing client policy: SSH
[2017-02-03 16:48:15] [192.168.3.134] [SpanKey:VOK85UQY] Registered spankeyNSSList request
[2017-02-03 16:48:15] [192.168.3.134] [SpanKey:VOK85UQY] Found 2 posix users
[2017-02-03 16:48:15] [192.168.3.134] [SpanKey:VOK85UQY] Sent success response
CentOS & Debian
Typical logs of an authentication success:
For CentOS:
bash-4.1# cat /var/log/secure
Feb 3 16:24:30 centos7 openotp[2132]: PAM Module for OpenOTP version 1.0.12 starting
Feb 3 16:24:30 centos7 openotp[2132]: Server URLs: https://192.168.3.55:8443/openotp/
Feb 3 16:24:30 centos7 openotp[2132]: Server Policy: Ordered
Feb 3 16:24:30 centos7 openotp[2132]: Domain name: [None]
Feb 3 16:24:30 centos7 openotp[2132]: Client id: SSH
Feb 3 16:24:30 centos7 openotp[2132]: Challenge suffix: :
Feb 3 16:24:30 centos7 openotp[2132]: User settings: [None]
Feb 3 16:24:30 centos7 openotp[2132]: Cert file: [None]
Feb 3 16:24:30 centos7 openotp[2132]: Cert password: [None]
Feb 3 16:24:30 centos7 openotp[2132]: CA file: [None]
Feb 3 16:24:30 centos7 openotp[2132]: SOAP timeout: [Default]
Feb 3 16:24:30 centos7 openotp[2132]: Create homedirs: No
Feb 3 16:24:30 centos7 openotp[2132]: Password mode: [Default]
Feb 3 16:24:30 centos7 openotp[2132]: Password separator: [None]
Feb 3 16:24:30 centos7 openotp[2132]: OTP length: [Default]
Feb 3 16:24:30 centos7 openotp[2132]: Got user name Administrateur
Feb 3 16:24:30 centos7 openotp[2132]: Got host name 10.0.3.28
Feb 3 16:24:30 centos7 openotp[2132]: Got anyPassword ******** for user Administrateur
Feb 3 16:24:30 centos7 openotp[2132]: Sending OpenOTP SimpleLogin request for user Administrateur
Feb 3 16:24:31 centos7 openotp[2132]: Authentication challenge for user Administrateur
Feb 3 16:24:53 centos7 openotp[2132]: Got OTP password ****** for user Administrateur
Feb 3 16:24:53 centos7 openotp[2132]: Sending OpenOTP Challenge request for user Administrateur
Feb 3 16:24:56 centos7 openotp[2132]: Authentication succeeded for user Administrateur
For Debian:
bash-4.1# cat /var/log/auth.log
Feb 3 15:54:30 debian8 openotp[2048]: PAM Module for OpenOTP version 1.0.12 starting
Feb 3 15:54:30 debian8 openotp[2048]: Server URLs: https://192.168.3.55:8443/openotp/
Feb 3 15:54:30 debian8 openotp[2048]: Server Policy: Ordered
Feb 3 15:54:30 debian8 openotp[2048]: Domain name: [None]
Feb 3 15:54:30 debian8 openotp[2048]: Client id: SSH
Feb 3 15:54:30 debian8 openotp[2048]: Challenge suffix:
Feb 3 15:54:30 debian8 openotp[2048]: User settings: [None]
Feb 3 15:54:30 debian8 openotp[2048]: Cert file: [None]
Feb 3 15:54:30 debian8 openotp[2048]: Cert password: [None]
Feb 3 15:54:30 debian8 openotp[2048]: CA file: [None]
Feb 3 15:54:30 debian8 openotp[2048]: SOAP timeout: [Default]
Feb 3 15:54:30 debian8 openotp[2048]: Create homedirs: No
Feb 3 15:54:30 debian8 openotp[2048]: Password mode: [Default]
Feb 3 15:54:30 debian8 openotp[2048]: Password separator: [None]
Feb 3 15:54:30 debian8 openotp[2048]: OTP length: [Default]
Feb 3 15:54:30 debian8 openotp[2048]: Got user name Administrateur
Feb 3 15:54:30 debian8 openotp[2048]: Got host name 10.0.3.22
Feb 3 15:54:30 debian8 openotp[2048]: Got anyPassword ******** for user Administrateur
Feb 3 15:54:30 debian8 openotp[2048]: Sending OpenOTP SimpleLogin request for user Administrateur
Feb 3 15:54:31 debian8 openotp[2048]: Authentication challenge for user Administrateur
Feb 3 15:54:53 debian8 openotp[2048]: Got OTP password ****** for user Administrateur
Feb 3 15:54:53 debian8 openotp[2048]: Sending OpenOTP Challenge request for user Administrateur
Feb 3 15:54:56 debian8 openotp[2048]: Authentication succeeded for user Administrateur
Name Service Cache Daemon (NSCD)
In Linux, user and group information is often cached by NSCD (Name Service Cache Daemon), this can result in failed PAM-OpenOTP login right after the installation or after creating a new user since the user is not available in the cache yet.
To resolve this issue, you can wait for the cache to be refreshed on its own, or start and stop the nscd process and to flush the NSCD cache on your server.
The exact command and configuration depend on the Linux distribution in question. These commands are a sample for CentOS 7.
To stop and start NSCD:
systemctl stop nscd
systemctl start nscd
To clear NSCD cache files, invalidate the passwd and group cache:
[root@centos8-client ~]# nscd --invalidate=passwd
[root@centos8-client ~]# nscd --invalidate=group
Enable debug logs
To enable the debug logs of PAM OpenOTP plugin, you have to edit the OpenOTP PAM configuration file and add debug value on the openotp.so library line.
vi /etc/pam.d/openotp-auth
auth required pam_env.so
auth sufficient pam_unix.so
auth sufficient pam_openotp.so debug
auth required pam_deny.so
Then in /var/log/message
you will have the following output when performing an authentication :
Dec 9 11:40:56 webadm2 openotp[70367]: Got user name yoann
Dec 9 11:40:56 webadm2 openotp[70367]: Got host name 192.168.3.205
Dec 9 11:40:56 webadm2 openotp[70367]: Got anyPassword ******** for user yoann
Dec 9 11:40:56 webadm2 openotp[70367]: Sending OpenOTP SimpleLogin request for user yoann
Dec 9 11:40:57 webadm2 openotp[70367]: Authentication challenge for user yoann
Dec 9 11:40:57 webadm2 openotp[70367]: Could not get user password for user yoann