The PAM
modules can provide a level of flexibility that will achieve almost exactly what you want. Based on your response in a comment, you would be happy to allow su
to offer three attempts before failing. That is what I offer here.
I strongly recommend that you backup every PAM
configuration file that you change, and that you have a root shell already open somewhere ready to revert broken changes. After any change to PAM
it is very important to test that you can still log in and gain root access. If you get it wrong you can completely hose your system.
The PAM
files live in /etc/pam.d
, and you will need root access to change them.
The su
file on Debian 8 contains one authentication line and a reference to the include file common-auth
. Putting them together we get this:
auth sufficient pam_rootok.so
auth [success=1 default=ignore] pam_unix.so nullok_secure
auth requisite pam_deny.so
auth required pam_permit.so
auth optional pam_cap.so
The exciting part is the call to pam_unix.so
, which authenticates against the password database (/etc/passwd
and /etc/shadow
). The [success=N]
component tells PAM
that if the module returns a success status it is to skip the next N modules. So if you get a successful return from pam_unix.so
the configuration will skip the failure module pam_deny.so
.
We can use this approach to build a further two authentication attempts, like this:
auth sufficient pam_rootok.so
auth [success=3 default=ignore] pam_unix.so nullok_secure
auth [success=2 default=ignore] pam_unix.so nullok_secure
auth [success=1 default=ignore] pam_unix.so nullok_secure
auth requisite pam_deny.so
auth required pam_permit.so
auth optional pam_cap.so
There, job done.
Note, if you're running SAMBA or some other external authentication scheme you will need to adjust the changes slightly. On one of my systems there is such an additional check through pam_winbind.so
. This would also need to be replicated, so you'd go from this:
auth [success=2 default=ignore] pam_unix.so nullok_secure
auth [success=1 default=ignore] pam_winbind.so krb5_auth krb5_ccache_type=FILE cached_login try_first_pass
auth requisite pam_deny.so
to this:
auth [success=6 default=ignore] pam_unix.so nullok_secure
auth [success=5 default=ignore] pam_winbind.so krb5_auth krb5_ccache_type=FILE cached_login try_first_pass
auth [success=4 default=ignore] pam_unix.so nullok_secure
auth [success=3 default=ignore] pam_winbind.so krb5_auth krb5_ccache_type=FILE cached_login try_first_pass
auth [success=2 default=ignore] pam_unix.so nullok_secure
auth [success=1 default=ignore] pam_winbind.so krb5_auth krb5_ccache_type=FILE cached_login try_first_pass
auth requisite pam_deny.so
pam
-based solution. – Chris Davies Mar 25 '17 at 16:31