summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/pam_lastlog/pam_lastlog.8.xml10
-rw-r--r--modules/pam_lastlog/pam_lastlog.c42
2 files changed, 50 insertions, 2 deletions
diff --git a/modules/pam_lastlog/pam_lastlog.8.xml b/modules/pam_lastlog/pam_lastlog.8.xml
index 77da9dbc..c8f247e9 100644
--- a/modules/pam_lastlog/pam_lastlog.8.xml
+++ b/modules/pam_lastlog/pam_lastlog.8.xml
@@ -65,10 +65,18 @@
cases, this module is not necessary.
</para>
<para>
+ The module checks <option>LASTLOG_UID_MAX</option> option in
+ <filename>/etc/login.defs</filename> and does not update or display
+ last login records for users with UID higher than its value.
+ If the option is not present or its value is invalid, no user ID
+ limit is applied.
+ </para>
+ <para>
If the module is called in the auth or account phase, the accounts that
were not used recently enough will be disallowed to log in. The
check is not performed for the root account so the root is never
- locked out.
+ locked out. It is also not performed for users with UID higher
+ than the <option>LASTLOG_UID_MAX</option> value.
</para>
</refsect1>
diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c
index 1a796b99..18bf7bec 100644
--- a/modules/pam_lastlog/pam_lastlog.c
+++ b/modules/pam_lastlog/pam_lastlog.c
@@ -20,6 +20,7 @@
#endif
#include <pwd.h>
#include <stdlib.h>
+#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
@@ -50,6 +51,10 @@ struct lastlog {
# define _PATH_BTMP "/var/log/btmp"
#endif
+#ifndef PATH_LOGIN_DEFS
+# define PATH_LOGIN_DEFS "/etc/login.defs"
+#endif
+
/* XXX - time before ignoring lock. Is 1 sec enough? */
#define LASTLOG_IGNORE_LOCK_TIME 1
@@ -187,6 +192,37 @@ get_tty(pam_handle_t *pamh)
return terminal_line;
}
+#define MAX_UID_VALUE 0xFFFFFFFFUL
+
+static uid_t
+get_lastlog_uid_max(pam_handle_t *pamh)
+{
+ uid_t uid_max = MAX_UID_VALUE;
+ unsigned long ul;
+ char *s, *ep;
+
+ s = pam_modutil_search_key(pamh, PATH_LOGIN_DEFS, "LASTLOG_UID_MAX");
+ if (s == NULL)
+ return uid_max;
+
+ ep = s + strlen(s);
+ while (ep > s && isspace(*(--ep))) {
+ *ep = '\0';
+ }
+ errno = 0;
+ ul = strtoul(s, &ep, 10);
+ if (!(ul >= MAX_UID_VALUE
+ || (uid_t)ul >= MAX_UID_VALUE
+ || (errno != 0 && ul == 0)
+ || s == ep
+ || *ep != '\0')) {
+ uid_max = (uid_t)ul;
+ }
+ free(s);
+
+ return uid_max;
+}
+
static int
last_login_open(pam_handle_t *pamh, int announce, uid_t uid)
{
@@ -418,6 +454,10 @@ last_login_date(pam_handle_t *pamh, int announce, uid_t uid, const char *user, t
int retval;
int last_fd;
+ if (uid > get_lastlog_uid_max(pamh)) {
+ return PAM_SUCCESS;
+ }
+
/* obtain the last login date and all the relevant info */
last_fd = last_login_open(pamh, announce, uid);
if (last_fd < 0) {
@@ -602,7 +642,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags,
uid = pwd->pw_uid;
pwd = NULL; /* tidy up */
- if (uid == 0)
+ if (uid == 0 || uid > get_lastlog_uid_max(pamh))
return PAM_SUCCESS;
/* obtain the last login date and all the relevant info */