? loginfailures.diff Index: pam_unix.c =================================================================== RCS file: /home/ncvs/src/lib/libpam/modules/pam_unix/pam_unix.c,v retrieving revision 1.11 diff -u -r1.11 pam_unix.c --- pam_unix.c 2001/10/25 15:51:50 1.11 +++ pam_unix.c 2001/11/18 04:55:57 @@ -1,4 +1,4 @@ -/*- +/* * Copyright 1998 Juniper Networks, Inc. * All rights reserved. * @@ -35,6 +35,8 @@ #include #include #endif +#include +#include #include #include #include @@ -67,6 +69,7 @@ #define PASSWORD_HASH "md5" #define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */ #define MAX_TRIES 3 +#define LOGIN_FAILURE_DB "/var/db/loginfailures" enum { PAM_OPT_AUTH_AS_SELF=PAM_OPT_STD_MAX, PAM_OPT_NULLOK, PAM_OPT_LOCAL_PASS, PAM_OPT_NIS_PASS }; @@ -101,6 +104,10 @@ int retval; const char *pass, *user; char *encrypted, *password_prompt; + DB *db; + DBT key, data; + char buf[5]; + int failures; pam_std_option(&options, other_options, argc, argv); @@ -152,6 +159,27 @@ retval = strcmp(encrypted, pwd->pw_passwd) == 0 ? PAM_SUCCESS : PAM_AUTH_ERR; + + /* if the login failed, record it in the login failure db */ + if (retval == PAM_AUTH_ERR) { + db = dbopen(LOGIN_FAILURE_DB, O_CREAT | O_RDWR, 0, \ + DB_HASH, 0); + if (db != NULL) { + key.data = pwd->pw_name; + key.size = strlen(pwd->pw_name) + 1; + if ((db->get)(db, &key, &data, 0) == 0) { + bcopy((char *)data.data, (char *)&buf, data.size); + failures = atoi(buf); + } else + failures = 0; + failures++; + sprintf(buf, "%d", failures); + data.data = buf; + data.size = strlen(buf); + (db->put)(db, &key, &data, 0); + (db->close)(db); + } + } } else { @@ -206,6 +234,9 @@ int retval; const char *user; char buf[128]; + DB *db; + DBT key, data; + int failures; pam_std_option(&options, other_options, argc, argv); @@ -260,6 +291,30 @@ } login_close(lc); + + /* show number of failed attempts since last successful login + * XXX: should we be doing this in login.c so it's after motd? + */ + db = dbopen(LOGIN_FAILURE_DB, O_CREAT | O_RDWR, 0, DB_HASH, 0); + if (db != NULL) { + key.data = pw->pw_name; + key.size = strlen(pw->pw_name) + 1; + if ((db->get)(db, &key, &data, 0) == 0) { + bcopy((char *)data.data, (char *)&buf, data.size); + failures = atoi(buf); + } else + failures = 0; + if (failures > 0) { + printf("\nThere %s been %d login failure%s since your last " \ + "login.\n\n", failures > 1 ? "have" : "has", failures, \ + failures > 1 ? "s" : ""); + /* reset login failures to 0 since we're logged in now... */ + data.data = "0"; + data.size = 2; + (db->put)(db, &key, &data, 0); + } + (db->close)(db); + } PAM_RETURN(retval); }