summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorsten Kukuk <kukuk@suse.com>2023-02-21 17:00:25 +0100
committerThorsten Kukuk <5908016+thkukuk@users.noreply.github.com>2023-02-28 07:03:30 +0100
commit8a3f0810397c992a1155d815b1dd40b0b8fed59d (patch)
treeb886faa6c66a2f1f8a8afecbfa220882bf4580f3
parent53b5e0d9e4b993cd9b0c3757adc02fae1505e99d (diff)
downloadlinux-pam-git-8a3f0810397c992a1155d815b1dd40b0b8fed59d.tar.gz
Y2038: use logind instead of utmp
The struct utmp from glibc uses on many 64bit architectures a 32bit time_t for compatibility with a 32bit userland, which means utmp will not survive the year 2038 (32bit time_t overflow). Use the data from logind instead of utmp. * configure.ac: Add option --enable-logind * modules/pam_issue/Makefile.am: Add CFLAGS/LIBS for logind support * modules/pam_issue/pam_issue.c: Use sd_get_sessions instead of utmp * modules/pam_timestamp/Makefile.am: Add CFLAGS/LIBS for logind support * modules/pam_timestamp/pam_timestamp.c: query logind for login time
-rw-r--r--configure.ac11
-rw-r--r--modules/pam_issue/Makefile.am4
-rw-r--r--modules/pam_issue/pam_issue.c20
-rw-r--r--modules/pam_timestamp/Makefile.am6
-rw-r--r--modules/pam_timestamp/pam_timestamp.c46
5 files changed, 78 insertions, 9 deletions
diff --git a/configure.ac b/configure.ac
index ad534b39..8b89124e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -526,6 +526,17 @@ if test -n "$LIBSELINUX" ; then
LIBS=$BACKUP_LIBS
fi
+LOGIND_CFLAGS=
+SYSTEMD_LIBS=
+AC_ARG_ENABLE([logind],
+ AS_HELP_STRING([--disable-logind], [Disable logind support]),
+ [WITH_LOGIND=$enableval], [WITH_LOGIND=yes])
+if test "$WITH_LOGIND" = "yes"; then
+ PKG_CHECK_MODULES([SYSTEMD], [libsystemd >= 254], [LOGIND_CFLAGS="-DUSE_LOGIND=1 $SYSTEMD_CFLAGS"], [:])
+fi
+AC_SUBST([LOGIND_CFLAGS])
+AC_SUBST([SYSTEMD_LIBS])
+
ECONF_CFLAGS=
ECONF_LIBS=
AC_ARG_ENABLE([econf],
diff --git a/modules/pam_issue/Makefile.am b/modules/pam_issue/Makefile.am
index f8678063..1ab2b2ce 100644
--- a/modules/pam_issue/Makefile.am
+++ b/modules/pam_issue/Makefile.am
@@ -22,14 +22,14 @@ secureconfdir = $(SCONFIGDIR)
endif
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
- $(WARN_CFLAGS)
+ $(LOGIND_CFLAGS) $(WARN_CFLAGS)
AM_LDFLAGS = -no-undefined -avoid-version -module
if HAVE_VERSIONING
AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
endif
securelib_LTLIBRARIES = pam_issue.la
-pam_issue_la_LIBADD = $(top_builddir)/libpam/libpam.la
+pam_issue_la_LIBADD = $(top_builddir)/libpam/libpam.la $(SYSTEMD_LIBS)
if ENABLE_REGENERATE_MAN
dist_noinst_DATA = README
diff --git a/modules/pam_issue/pam_issue.c b/modules/pam_issue/pam_issue.c
index 2f53440f..c08f90c3 100644
--- a/modules/pam_issue/pam_issue.c
+++ b/modules/pam_issue/pam_issue.c
@@ -25,10 +25,15 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/utsname.h>
-#include <utmp.h>
#include <time.h>
#include <syslog.h>
+#ifdef USE_LOGIND
+#include <systemd/sd-login.h>
+#else
+#include <utmp.h>
+#endif
+
#include <security/_pam_macros.h>
#include <security/pam_modules.h>
#include <security/pam_ext.h>
@@ -159,6 +164,18 @@ read_issue_quoted(pam_handle_t *pamh, FILE *fp, char **prompt)
case 'U':
{
unsigned int users = 0;
+#ifdef USE_LOGIND
+ int sessions = sd_get_sessions(NULL);
+
+ if (sessions < 0) {
+ pam_syslog(pamh, LOG_ERR, "logind error: %s",
+ strerror(-sessions));
+ _pam_drop(issue);
+ return PAM_SERVICE_ERR;
+ } else {
+ users = sessions;
+ }
+#else
struct utmp *ut;
setutent();
while ((ut = getutent())) {
@@ -166,6 +183,7 @@ read_issue_quoted(pam_handle_t *pamh, FILE *fp, char **prompt)
++users;
}
endutent();
+#endif
if (c == 'U')
snprintf (buf, sizeof buf, "%u %s", users,
(users == 1) ? "user" : "users");
diff --git a/modules/pam_timestamp/Makefile.am b/modules/pam_timestamp/Makefile.am
index 37a70b2b..bc2f3617 100644
--- a/modules/pam_timestamp/Makefile.am
+++ b/modules/pam_timestamp/Makefile.am
@@ -25,10 +25,10 @@ endif
noinst_HEADERS = hmacsha1.h sha1.h hmac_openssl_wrapper.h
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
- $(WARN_CFLAGS)
+ $(LOGIND_CFLAGS) $(WARN_CFLAGS)
pam_timestamp_la_LDFLAGS = -no-undefined -avoid-version -module $(AM_LDFLAGS) $(CRYPTO_LIBS)
-pam_timestamp_la_LIBADD = $(top_builddir)/libpam/libpam.la
+pam_timestamp_la_LIBADD = $(top_builddir)/libpam/libpam.la $(SYSTEMD_LIBS)
if HAVE_VERSIONING
pam_timestamp_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
endif
@@ -46,7 +46,7 @@ pam_timestamp_la_CFLAGS = $(AM_CFLAGS)
pam_timestamp_check_SOURCES = pam_timestamp_check.c
pam_timestamp_check_CFLAGS = $(AM_CFLAGS) @EXE_CFLAGS@
-pam_timestamp_check_LDADD = $(top_builddir)/libpam/libpam.la
+pam_timestamp_check_LDADD = $(top_builddir)/libpam/libpam.la $(SYSTEMD_LIBS)
pam_timestamp_check_LDFLAGS = @EXE_LDFLAGS@
if COND_USE_OPENSSL
diff --git a/modules/pam_timestamp/pam_timestamp.c b/modules/pam_timestamp/pam_timestamp.c
index 01dd1385..572d9ff2 100644
--- a/modules/pam_timestamp/pam_timestamp.c
+++ b/modules/pam_timestamp/pam_timestamp.c
@@ -53,7 +53,6 @@
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
-#include <utmp.h>
#include <syslog.h>
#include <paths.h>
#ifdef WITH_OPENSSL
@@ -62,6 +61,12 @@
#include "hmacsha1.h"
#endif /* WITH_OPENSSL */
+#ifdef USE_LOGIND
+#include <systemd/sd-login.h>
+#else
+#include <utmp.h>
+#endif
+
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
#include <security/pam_ext.h>
@@ -200,10 +205,26 @@ timestamp_good(time_t then, time_t now, time_t interval)
}
static int
-check_login_time(const char *ruser, time_t timestamp)
+check_login_time(
+#ifdef USE_LOGIND
+ uid_t uid,
+#else
+ const char *ruser,
+#endif
+ time_t timestamp)
{
- struct utmp utbuf, *ut;
time_t oldest_login = 0;
+#ifdef USE_LOGIND
+#define USEC_PER_SEC ((uint64_t) 1000000ULL)
+ uint64_t usec = 0;
+
+ if (sd_uid_get_login_time(uid, &usec) < 0) {
+ return PAM_SERVICE_ERR;
+ }
+
+ oldest_login = usec/USEC_PER_SEC;
+#else
+ struct utmp utbuf, *ut;
setutent();
while(
@@ -224,6 +245,7 @@ check_login_time(const char *ruser, time_t timestamp)
}
}
endutent();
+#endif
if(oldest_login == 0 || timestamp < oldest_login) {
return PAM_AUTH_ERR;
}
@@ -532,7 +554,15 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
close(fd);
return PAM_AUTH_ERR;
}
+#ifdef USE_LOGIND
+ struct passwd *pwd = pam_modutil_getpwnam(pamh, ruser);
+ if (pwd != NULL) {
+ return PAM_SERVICE_ERR;
+ }
+ if (check_login_time(pwd->pw_uid, then) != PAM_SUCCESS)
+#else
if (check_login_time(ruser, then) != PAM_SUCCESS)
+#endif
{
pam_syslog(pamh, LOG_NOTICE, "timestamp file `%s' is "
"older than oldest login, disallowing "
@@ -728,6 +758,9 @@ main(int argc, char **argv)
fd_set write_fds;
char path[BUFLEN];
struct stat st;
+#ifdef USE_LOGIND
+ uid_t uid;
+#endif
/* Check that there's nothing funny going on with stdio. */
if ((fstat(STDIN_FILENO, &st) == -1) ||
@@ -783,6 +816,9 @@ main(int argc, char **argv)
if (pwd == NULL) {
retval = 4;
}
+#ifdef USE_LOGIND
+ uid = pwd->pw_uid;
+#endif
/* Get the name of the target user. */
user = strdup(pwd->pw_name);
@@ -833,7 +869,11 @@ main(int argc, char **argv)
/* Check the timestamp. */
if (lstat(path, &st) != -1) {
/* Check oldest login against timestamp */
+#ifdef USE_LOGIND
+ if (check_login_time(uid, st.st_mtime) != PAM_SUCCESS) {
+#else
if (check_login_time(user, st.st_mtime) != PAM_SUCCESS) {
+#endif
retval = 7;
} else if (timestamp_good(st.st_mtime, time(NULL),
DEFAULT_TIMESTAMP_TIMEOUT) != PAM_SUCCESS) {