diff options
author | Thorsten Kukuk <kukuk@suse.com> | 2023-02-21 17:00:25 +0100 |
---|---|---|
committer | Thorsten Kukuk <5908016+thkukuk@users.noreply.github.com> | 2023-02-28 07:03:30 +0100 |
commit | 8a3f0810397c992a1155d815b1dd40b0b8fed59d (patch) | |
tree | b886faa6c66a2f1f8a8afecbfa220882bf4580f3 | |
parent | 53b5e0d9e4b993cd9b0c3757adc02fae1505e99d (diff) | |
download | pam-8a3f0810397c992a1155d815b1dd40b0b8fed59d.tar.gz pam-8a3f0810397c992a1155d815b1dd40b0b8fed59d.tar.bz2 pam-8a3f0810397c992a1155d815b1dd40b0b8fed59d.zip |
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.ac | 11 | ||||
-rw-r--r-- | modules/pam_issue/Makefile.am | 4 | ||||
-rw-r--r-- | modules/pam_issue/pam_issue.c | 20 | ||||
-rw-r--r-- | modules/pam_timestamp/Makefile.am | 6 | ||||
-rw-r--r-- | modules/pam_timestamp/pam_timestamp.c | 46 |
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) { |