Adding a little bit of historical perspective, the idea of sleeping after a bad password is not just found in PAM-based systems. It's very old. For eaxmple in the 4.4BSD login source you'll find this tasty fragment:
/* we allow 10 tries, but after 3 we start backing off */
if (++cnt > 3) {
if (cnt >= 10) {
badlogin(username);
sleepexit(1);
}
sleep((u_int)((cnt - 3) * 5));
}
so the first 3 failures are free, the next 7 have increasing delays (5 seconds, 10 seconds, 15 seconds...) and after 10 it does a sleepexit(1)
which is a 5 second delay followed by an exit(1)
.
The sleeps are just an annoyance when you're typing a password on the console, but they're important when the input is coming from a remote user who might be automating the process.
The sleepexit
after 10 failures deserves special explanation. After login
exits, getty
just prints another login prompt and starts the cycle again. So why sleep and exit instead of just sleeping? Because when this feature was introduced, login over dialup was common. (Note for people who never used a modem before 1995: I said login over dialup, not PPP or other packet-based protocol over dialup. You'd dial a number in a terminal emulator and get a login prompt.)
In the dialup world, anybody could just dial your number and start throwing passwords at it, so the login
process exited after a few bad passwords, causing the modem connection to terminate, forcing them to redial before they could try more passwords. The same principle applies to ssh
today (configuration option MaxAuthTries
) but it was more effective in the old days, because dialing a modem was quite a bit slower than a TCP handshake.