diff --git a/lib/getdef.c b/lib/getdef.c index d57b12de..ece33a78 100644 --- a/lib/getdef.c +++ b/lib/getdef.c @@ -92,6 +92,7 @@ static struct itemdef def_table[] = { {"GID_MIN", NULL}, {"HUSHLOGIN_FILE", NULL}, {"KILLCHAR", NULL}, + {"LASTLOG_UID_MAX", NULL}, {"LOGIN_RETRIES", NULL}, {"LOGIN_TIMEOUT", NULL}, {"LOG_OK_LOGINS", NULL}, diff --git a/man/Makefile.am b/man/Makefile.am index 4c340229..3f040e05 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -137,6 +137,7 @@ login_defs_v = \ ISSUE_FILE.xml \ KILLCHAR.xml \ LASTLOG_ENAB.xml \ + LASTLOG_UID_MAX.xml \ LOGIN_RETRIES.xml \ LOGIN_STRING.xml \ LOGIN_TIMEOUT.xml \ diff --git a/man/lastlog.8.xml b/man/lastlog.8.xml index 3ee1b3a8..fc096c8f 100644 --- a/man/lastlog.8.xml +++ b/man/lastlog.8.xml @@ -31,6 +31,7 @@ --> ]> @@ -200,6 +201,18 @@ + + CONFIGURATION + + The following configuration variables in + /etc/login.defs change the behavior of this + tool: + + + &LASTLOG_UID_MAX; + + + FILES diff --git a/man/login.defs.5.xml b/man/login.defs.5.xml index 98d37fdc..ebf60ba3 100644 --- a/man/login.defs.5.xml +++ b/man/login.defs.5.xml @@ -54,6 +54,7 @@ + @@ -188,6 +189,7 @@ &ISSUE_FILE; &KILLCHAR; &LASTLOG_ENAB; + &LASTLOG_UID_MAX; &LOG_OK_LOGINS; &LOG_UNKFAIL_ENAB; &LOGIN_RETRIES; @@ -349,7 +351,12 @@ - + + lastlog + + LASTLOG_UID_MAX + + login @@ -365,7 +372,7 @@ HUSHLOGIN_FILE ISSUE_FILE KILLCHAR - LASTLOG_ENAB + LASTLOG_ENAB LASTLOG_UID_MAX LOGIN_RETRIES LOGIN_STRING LOGIN_TIMEOUT LOG_OK_LOGINS LOG_UNKFAIL_ENAB @@ -474,6 +481,7 @@ CREATE_HOME GID_MAX GID_MIN + LASTLOG_UID_MAX MAIL_DIR MAX_MEMBERS_PER_GROUP PASS_MAX_DAYS PASS_MIN_DAYS PASS_WARN_AGE SUB_GID_COUNT SUB_GID_MAX SUB_GID_MIN @@ -498,6 +506,7 @@ usermod + LASTLOG_UID_MAX MAIL_DIR MAIL_FILE MAX_MEMBERS_PER_GROUP TCB_SYMLINKS USE_TCB diff --git a/man/login.defs.d/LASTLOG_UID_MAX.xml b/man/login.defs.d/LASTLOG_UID_MAX.xml new file mode 100644 index 00000000..ba3025a6 --- /dev/null +++ b/man/login.defs.d/LASTLOG_UID_MAX.xml @@ -0,0 +1,46 @@ + + + (number) + + + Highest user ID number for which the lastlog entries should be + updated. As higher user IDs are usually tracked by remote user + identity and authentication services there is no need to create + a huge sparse lastlog file for them. + + + No option present in the configuration + means that there is no user ID limit for writing lastlog entries. + + + diff --git a/man/useradd.8.xml b/man/useradd.8.xml index 582b39c7..59e53c1f 100644 --- a/man/useradd.8.xml +++ b/man/useradd.8.xml @@ -32,6 +32,7 @@ "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ + @@ -670,6 +671,7 @@ &CREATE_HOME; &GID_MAX; + &LASTLOG_UID_MAX; &MAIL_DIR; &MAX_MEMBERS_PER_GROUP; &PASS_MAX_DAYS; diff --git a/man/usermod.8.xml b/man/usermod.8.xml index 7fea2981..bb8312db 100644 --- a/man/usermod.8.xml +++ b/man/usermod.8.xml @@ -30,6 +30,7 @@ --> @@ -517,6 +518,7 @@ tool: + &LASTLOG_UID_MAX; &MAIL_DIR; &MAX_MEMBERS_PER_GROUP; &SUB_GID_COUNT; diff --git a/src/lastlog.c b/src/lastlog.c index 965691db..c1caedb0 100644 --- a/src/lastlog.c +++ b/src/lastlog.c @@ -44,6 +44,7 @@ #include #include "defines.h" #include "prototypes.h" +#include "getdef.h" /*@-exitarg@*/ #include "exitcodes.h" @@ -182,6 +183,15 @@ static void print_one (/*@null@*/const struct passwd *pw) static void print (void) { const struct passwd *pwent; + unsigned long lastlog_uid_max; + + lastlog_uid_max = getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL); + if ( (has_umin && umin > lastlog_uid_max) + || (has_umax && umax > lastlog_uid_max)) { + fprintf (stderr, _("%s: Selected uid(s) are higher than LASTLOG_UID_MAX (%lu),\n" + "\tthe output might be incorrect.\n"), Prog, lastlog_uid_max); + } + if (uflg && has_umin && has_umax && (umin == umax)) { print_one (getpwuid ((uid_t)umin)); } else { @@ -191,6 +201,8 @@ static void print (void) && ( (has_umin && (pwent->pw_uid < (uid_t)umin)) || (has_umax && (pwent->pw_uid > (uid_t)umax)))) { continue; + } else if ( !uflg && pwent->pw_uid > (uid_t) lastlog_uid_max) { + continue; } print_one (pwent); } @@ -246,10 +258,19 @@ static void update_one (/*@null@*/const struct passwd *pw) static void update (void) { const struct passwd *pwent; + unsigned long lastlog_uid_max; if (!uflg) /* safety measure */ return; + lastlog_uid_max = getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL); + if ( (has_umin && umin > lastlog_uid_max) + || (has_umax && umax > lastlog_uid_max)) { + fprintf (stderr, _("%s: Selected uid(s) are higher than LASTLOG_UID_MAX (%lu),\n" + "\tthey will not be updated.\n"), Prog, lastlog_uid_max); + return; + } + if (has_umin && has_umax && (umin == umax)) { update_one (getpwuid ((uid_t)umin)); } else { diff --git a/src/login.c b/src/login.c index 7677adf1..492021a1 100644 --- a/src/login.c +++ b/src/login.c @@ -1162,7 +1162,9 @@ int main (int argc, char **argv) #endif /* WITH_AUDIT */ #ifndef USE_PAM /* pam_lastlog handles this */ - if (getdef_bool ("LASTLOG_ENAB")) { /* give last login and log this one */ + if ( getdef_bool ("LASTLOG_ENAB") + && pwd->pw_uid <= (uid_t) getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL)) { + /* give last login and log this one */ dolastlog (&ll, pwd, tty, hostname); } #endif @@ -1298,6 +1300,7 @@ int main (int argc, char **argv) } } if ( getdef_bool ("LASTLOG_ENAB") + && pwd->pw_uid <= (uid_t) getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL) && (ll.ll_time != 0)) { time_t ll_time = ll.ll_time; diff --git a/src/useradd.c b/src/useradd.c index e074844d..41e2ace4 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -1863,11 +1863,18 @@ static void lastlog_reset (uid_t uid) struct lastlog ll; int fd; off_t offset_uid = (off_t) (sizeof ll) * uid; + uid_t max_uid; if (access (LASTLOG_FILE, F_OK) != 0) { return; } + max_uid = (uid_t) getdef_ulong ("LASTLOG_UID_MAX", 0xFFFFFFFFUL); + if (uid > max_uid) { + /* do not touch lastlog for large uids */ + return; + } + memzero (&ll, sizeof (ll)); fd = open (LASTLOG_FILE, O_RDWR); diff --git a/src/usermod.c b/src/usermod.c index fd9a98a6..72eeb8b2 100644 --- a/src/usermod.c +++ b/src/usermod.c @@ -1864,11 +1864,18 @@ static void update_lastlog (void) int fd; off_t off_uid = (off_t) user_id * sizeof ll; off_t off_newuid = (off_t) user_newid * sizeof ll; + uid_t max_uid; if (access (LASTLOG_FILE, F_OK) != 0) { return; } + max_uid = (uid_t) getdef_ulong ("LASTLOG_MAX_UID", 0xFFFFFFFFUL); + if (user_newid > max_uid) { + /* do not touch lastlog for large uids */ + return; + } + fd = open (LASTLOG_FILE, O_RDWR); if (-1 == fd) {