The main goal top
The goal was to use OTP generator ( tested mOTP ) to authenticate from unsafe/mobile computers, and keep a strong passphrase in secure password stores on my computers.
A simple way to achieve it : pam_oath
libpam_oath allows PAM authentication using HOTP or TOPT OTP. It should be possible to write rules testing OTP passphrase or, in cas of failure, fallback on unix passwd file tests.
Doing it
First problems top
Understanding PAM basics
- PAM applies conf files depending on a service name
- Dovecot defines its PAM's service name in /etc/dovecot/conf.d/auth-system.conf (on Debian Buster)
# /etc/dovcot/auth-system.conf passdb { driver = pam args = dovecot } # Implies we will modify /etc/pam/pam.d/dovecot file on Debian Buster
Understanding libpam_oath internals
PAM applies rules/check to validate an authentication. Following all the documentation found on the web ( on the project's wiki or archlinux wiki ) leads in strange errors.
To see libpam_oath errors you have to monitor /var/log/syslog and give pam_oath.so a debug argument
# In /etc/pam.d/dovecot #... auth [success=2 default=ignore] pam_oath.so debug usersfile=/etc/users.oath window=30 digits=6 #... # Producing : Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:parse_cfg(118)] called. Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:parse_cfg(119)] flags 0 argc 4 Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:parse_cfg(121)] argv[0]=debug Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:parse_cfg(121)] argv[1]=usersfile=/etc/users.oath Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:parse_cfg(121)] argv[2]=window=30 Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:parse_cfg(121)] argv[3]=digits=6 Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:parse_cfg(122)] debug=1 Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:parse_cfg(123)] alwaysok=0 Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:parse_cfg(124)] try_first_pass=0 Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:parse_cfg(125)] use_first_pass=0 Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:parse_cfg(126)] usersfile=/etc/users.oath Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:parse_cfg(127)] digits=6 Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:parse_cfg(128)] window=30 Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:pam_sm_authenticate(163)] get user returned: zered Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:pam_sm_authenticate(238)] conv returned: 142132 Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:pam_sm_authenticate(302)] OTP: 142132 Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:pam_sm_authenticate(312)] authenticate rc -14 (OATH_FILE_CREATE_ERROR: System error when creating file) last otp Thu Jan 1 01:00:00 1970 Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:pam_sm_authenticate(317)] One-time password not authorized to login as user 'zered' Jan 20 17:15:57 mails dovecot[13678]: [pam_oath.c:pam_sm_authenticate(333)] done. [Authentication failure]
Unfortunately the error message don't ring a bell...
authenticate rc -14 (OATH_FILE_CREATE_ERROR: System error when creating file) last otp Thu Jan 1 01:00:00 1970
All permission modification on /etc/users.oath on a /etc/oath directory containing the users.oath file change nothing...
Patching libpam_oath to have more informations
Getting source using apt-get source libpam-oath, adding a strerror on errno set by failling fopen, recompiling debian packages with debuild -us -uc
# Dirty & quick patch adding a custom debug # errno should be set by failing fopen in oath_authenticate_usersfile() --- oath-toolkit-2.6.1.orig/pam_oath/pam_oath.c +++ oath-toolkit-2.6.1/pam_oath/pam_oath.c @@ -26,6 +26,7 @@ #include <stdlib.h> #include <stdarg.h> #include <ctype.h> +#include <errno.h> /* Libtool defines PIC for shared objects */ #ifndef PIC @@ -307,6 +307,7 @@ pam_sm_authenticate (pam_handle_t * pamh rc = oath_authenticate_usersfile (cfg.usersfile, user, otp, cfg.window, onlypasswd, &last_otp); + DBG (("CUSTOM DEBUG : %s", strerror(errno))); DBG (("authenticate rc %d (%s: %s) last otp %s", rc, oath_strerror_name (rc) ? oath_strerror_name (rc) : "UNKNOWN", oath_strerror (rc), ctime (&last_otp)));
A usefull message and a solution
CUSTOM DEBUG : Read-only file system authenticate rc -14 (OATH_FILE_CREATE_ERROR: System error when creating file) last otp Thu Jan 1 01:00:00 1970
Postfix run chrooted on a read only FS ! The solution found was to put the users.oath file in /home/users.oath : Postfix delivers mails in /home, it should be possible to write lock files in this directory even if chrooted :-)
Tests and saaaaaaad conclusion top
A lots of tests implying thunderbird leads to this /etc/pam.d/dovecot
#%PAM-1.0 auth [success=2 default=ignore] pam_oath.so usersfile=/home/users.oath window=30 digits=6 auth [success=1 default=ignore] pam_unix.so use_first_pass auth requisite pam_deny.so auth required pam_permit.so @include common-account @include common-session
The success=N is a kind of goto argument :
- If the check fails the evaluation continue normally
- if the check passes the evaluation jumps N instructions further
If the oath OTP check fails, the pam_unix.so check is use as fallback. The use_first_pass argument seems to tell PAM to use the password given to previous check.
It kind of works for imap, sometimes it worked for smtp.... But thunderbird seems to keep trying to send the same password (that is obviously expired since we are speaking of OTP)....
Sad conclusion
After all those debugging tests using a huge/glitchy mail client, I decided to test using a mobile phone App. All tested Apps ask for a password on account creation. Then you have to go in a sub-sub-sub-sub-menu (clicking (with your finger)) to change the Imap password (and another sub-...-menu for SMTP)), perfect for one time passwords.....
Next steps top
Trying the Dovecot SQL Auth database to handle custom account name & password for mobile devices (referencing the same single account).
The main goal will not be reachable. But it should be possible to have a solution with revocable account/password and less risk to leak a strong, kept in head, password using it on unsafe/mobile platforms.
Another solution would be to setup a webmail to use OTP authentication and then use this interface to read/send emails on unsafe/mobile platforms. But no desire to install/setup a webmail right now...