diff --git a/baselibs.conf b/baselibs.conf index aae13c0..af91018 100644 --- a/baselibs.conf +++ b/baselibs.conf @@ -4,3 +4,4 @@ pam obsoletes "pam_unix-nis-" pam-extra pam-devel +pam-userdb diff --git a/common-session-nonlogin.pamd b/common-session-nonlogin.pamd index 665a150..827283b 100644 --- a/common-session-nonlogin.pamd +++ b/common-session-nonlogin.pamd @@ -8,7 +8,6 @@ # non-interactive), but not if they don't create a new login session # (e.g. like cron, chfn, chsh, ...) # -session required pam_limits.so session required pam_unix.so try_first_pass session optional pam_umask.so session optional pam_env.so diff --git a/common-session.pamd b/common-session.pamd index f20e8c2..c57304c 100644 --- a/common-session.pamd +++ b/common-session.pamd @@ -7,7 +7,6 @@ # non-interactive). # session optional pam_systemd.so -session required pam_limits.so session required pam_unix.so try_first_pass session optional pam_umask.so session optional pam_env.so diff --git a/pam.changes b/pam.changes index 2ed849d..c0863c9 100644 --- a/pam.changes +++ b/pam.changes @@ -1,3 +1,22 @@ +------------------------------------------------------------------- +Thu Sep 12 07:50:55 UTC 2024 - Thorsten Kukuk + +- baselibs.conf: add pam-userdb + +------------------------------------------------------------------- +Tue Sep 10 08:22:02 UTC 2024 - Thorsten Kukuk + +- pam_limits-systemd.patch: update to final PR + +------------------------------------------------------------------- +Fri Sep 6 08:13:22 UTC 2024 - Thorsten Kukuk + +- Add systemd-logind support to pam_limits (pam_limits-systemd.patch) +- Remove /usr/etc/pam.d, everything should be migrated +- Remove pam_limits from default common-sessions* files. pam_limits + is now part of pam-extra and not in our default generated config. +- pam_issue-systemd.patch: only count class user sessions + ------------------------------------------------------------------- Wed Aug 7 14:44:56 UTC 2024 - Stanislav Brabec diff --git a/pam.spec b/pam.spec index 8c9a480..ea90976 100644 --- a/pam.spec +++ b/pam.spec @@ -98,6 +98,10 @@ Source24: postlogin-session.pamd Patch1: pam-limit-nproc.patch # https://github.com/linux-pam/linux-pam/pull/816 Patch2: pam-bsc1194818-cursor-escape.patch +# https://github.com/linux-pam/linux-pam/pull/826 +Patch3: pam_limits-systemd.patch +# https://github.com/linux-pam/linux-pam/pull/825 +Patch4: pam_issue-systemd.patch BuildRequires: audit-devel BuildRequires: bison BuildRequires: flex @@ -150,6 +154,7 @@ Group: System/Libraries BuildRequires: systemd-devel >= 254 BuildRequires: pam-devel Provides: pam:%{_sbindir}/pam_timestamp_check +Provides: pam:%{_pam_moduledir}/pam_limits.so %description -n pam-extra PAM (Pluggable Authentication Modules) is a system security tool that @@ -335,12 +340,13 @@ echo '.so man8/pam_motd.8' > %{buildroot}%{_mandir}/man5/motd.5 %endif %if !%{build_main} -rm -rf %{buildroot}{%{_sysconfdir},%{_distconfdir},%{_sbindir}/{f*,m*,pam_n*,pw*,u*},%{_pam_secconfdir},%{_pam_confdir},%{_datadir}/locale} +rm -rf %{buildroot}{%{_distconfdir}/environment,%{_pam_secdistconfdir}/{a,f,g,n,p,s,t}*} +rm -rf %{buildroot}{%{_sysconfdir},%{_sbindir}/{f*,m*,pam_n*,pw*,u*},%{_pam_secconfdir},%{_pam_confdir},%{_datadir}/locale} rm -rf %{buildroot}{%{_includedir},%{_libdir}/{libpam*,pkgconfig},%{_pam_vendordir},%{_rpmmacrodir},%{_tmpfilesdir},%{_unitdir}/pam_namespace.service} -rm -rf %{buildroot}%{_pam_moduledir}/pam_{a,b,c,d,e,f,g,h,j,k,l,m,n,o,p,q,r,s,v,w,x,y,z,time.,tt,um,un,usertype}* +rm -rf %{buildroot}%{_pam_moduledir}/pam_{a,b,c,d,e,f,g,h,j,k,la,lis,lo,m,n,o,p,q,r,s,v,w,x,y,z,time.,tt,um,un,usertype}* %else # Delete files for extra package -rm -rf %{buildroot}{%{_pam_moduledir}/pam_issue.so,%{_pam_moduledir}/pam_timestamp.so,%{_sbindir}/pam_timestamp_check} +rm -rf %{buildroot}{%{_pam_moduledir}/pam_limits.so,%{_pam_secdistconfdir}/limits.conf,%{_pam_moduledir}/pam_issue.so,%{_pam_moduledir}/pam_timestamp.so,%{_sbindir}/pam_timestamp_check} # Create filelist with translations %find_lang Linux-PAM @@ -382,9 +388,6 @@ done %dir %{_pam_vendordir} %dir %{_pam_secconfdir} %dir %{_pam_secdistconfdir} -%dir %{_pam_secdistconfdir}/limits.d -# /usr/etc/pam.d is for compat reasons -%dir %{_distconfdir}/pam.d %dir %{_prefix}/lib/motd.d %if %{defined config_noreplace} %config(noreplace) %{_pam_confdir}/other @@ -398,7 +401,6 @@ done %{_pam_secdistconfdir}/access.conf %{_pam_secdistconfdir}/group.conf %{_pam_secdistconfdir}/faillock.conf -%{_pam_secdistconfdir}/limits.conf %{_pam_secdistconfdir}/pam_env.conf %if %{with selinux} %{_pam_secdistconfdir}/sepermit.conf @@ -430,7 +432,6 @@ done %{_pam_moduledir}/pam_ftp.so %{_pam_moduledir}/pam_group.so %{_pam_moduledir}/pam_keyinit.so -%{_pam_moduledir}/pam_limits.so %{_pam_moduledir}/pam_listfile.so %{_pam_moduledir}/pam_localuser.so %{_pam_moduledir}/pam_loginuid.so @@ -491,6 +492,10 @@ done %if %{build_extra} %files -n pam-extra %defattr(-,root,root,755) +%dir %{_pam_secdistconfdir} +%dir %{_pam_secdistconfdir}/limits.d +%{_pam_secdistconfdir}/limits.conf +%{_pam_moduledir}/pam_limits.so %{_pam_moduledir}/pam_issue.so %{_pam_moduledir}/pam_timestamp.so %{_sbindir}/pam_timestamp_check diff --git a/pam_issue-systemd.patch b/pam_issue-systemd.patch new file mode 100644 index 0000000..40e3bfb --- /dev/null +++ b/pam_issue-systemd.patch @@ -0,0 +1,51 @@ +From 8401cef10cd5f62849c5fcfef4c82db92712296c Mon Sep 17 00:00:00 2001 +From: Thorsten Kukuk +Date: Wed, 4 Sep 2024 16:07:56 +0200 +Subject: [PATCH] pam_issue: only count class user + +Since systemd added new types of classes (e.g. manager*), we cannot +use the count of all sessions anymore, but have to check which class +this is. + +This is backward compatible, systemd v209 or newer is required. +--- + modules/pam_issue/pam_issue.c | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +diff --git a/modules/pam_issue/pam_issue.c b/modules/pam_issue/pam_issue.c +index aade642ec5..e2c555c405 100644 +--- a/modules/pam_issue/pam_issue.c ++++ b/modules/pam_issue/pam_issue.c +@@ -165,13 +165,31 @@ read_issue_quoted(pam_handle_t *pamh, FILE *fp, char **prompt) + { + unsigned int users = 0; + #ifdef USE_LOGIND +- int sessions = sd_get_sessions(NULL); ++ char **sessions_list; ++ int sessions = sd_get_sessions(&sessions_list); + + if (sessions < 0) { + pam_syslog(pamh, LOG_ERR, "logind error: %s", + strerror(-sessions)); + _pam_drop(issue); + return PAM_SERVICE_ERR; ++ } else if (sessions > 0 && sessions_list != NULL) { ++ int i; ++ ++ for (i = 0; i < sessions; i++) { ++ char *class; ++ ++ if (sd_session_get_class(sessions_list[i], &class) < 0 || class == NULL) ++ continue; ++ ++ if (strncmp(class, "user", 4) == 0) // user, user-early, user-incomplete ++ users++; ++ free(class); ++ } ++ ++ for (i = 0; i < sessions; i++) ++ free(sessions_list[i]); ++ free(sessions_list); + } else { + users = sessions; + } diff --git a/pam_limits-systemd.patch b/pam_limits-systemd.patch new file mode 100644 index 0000000..3934ba9 --- /dev/null +++ b/pam_limits-systemd.patch @@ -0,0 +1,157 @@ +From 12bb33b56dee6d6b05200d4b776c7e6de3d0df91 Mon Sep 17 00:00:00 2001 +From: Thorsten Kukuk +Date: Fri, 6 Sep 2024 11:55:46 +0200 +Subject: [PATCH] pam_limits: use systemd-logind instead of utmp (#822) + +The utmp database is unreliable for counting logged in users, since +there is no standard which defines who should create an entry at which +time for which reason. And it has a Y2038 problem with glibc/x86-64. +Query systemd-logind for the number of user sessions instead. +--- + modules/pam_limits/Makefile.am | 4 +- + modules/pam_limits/pam_limits.c | 81 +++++++++++++++++++++++++++++++-- + 2 files changed, 80 insertions(+), 5 deletions(-) + +diff --git a/modules/pam_limits/Makefile.am b/modules/pam_limits/Makefile.am +index ab3cf33ed..3f64d79bb 100644 +--- a/modules/pam_limits/Makefile.am ++++ b/modules/pam_limits/Makefile.am +@@ -24,7 +24,7 @@ limits_conf_dir = $(SCONFIGDIR)/limits.d + + AM_CFLAGS = -I$(top_srcdir)/libpam/include \ + -DLIMITS_FILE_DIR=\"$(limits_conf_dir)\" \ +- $(WARN_CFLAGS) ++ $(LOGIND_CFLAGS) $(WARN_CFLAGS) + AM_LDFLAGS = -no-undefined -avoid-version -module + if HAVE_VERSIONING + AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map +@@ -32,7 +32,7 @@ endif + + securelib_LTLIBRARIES = pam_limits.la + pam_limits_la_LIBADD = $(top_builddir)/libpam_internal/libpam_internal.la \ +- $(top_builddir)/libpam/libpam.la ++ $(top_builddir)/libpam/libpam.la $(SYSTEMD_LIBS) + + dist_secureconf_DATA = limits.conf + +diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c +index 75c584fca..1e4dfa3d0 100644 +--- a/modules/pam_limits/pam_limits.c ++++ b/modules/pam_limits/pam_limits.c +@@ -36,7 +36,12 @@ + #include + #include + #include ++#ifdef USE_LOGIND ++#include ++#else + #include ++#endif ++ + #ifndef UT_USER /* some systems have ut_name instead of ut_user */ + #define UT_USER ut_user + #endif +@@ -240,7 +245,6 @@ static int + check_logins (pam_handle_t *pamh, const char *name, int limit, int ctrl, + struct pam_limit_s *pl) + { +- struct utmp *ut; + int count; + + if (ctrl & PAM_DEBUG_ARG) { +@@ -255,8 +259,6 @@ check_logins (pam_handle_t *pamh, const char *name, int limit, int ctrl, + return LOGIN_ERR; + } + +- setutent(); +- + /* Because there is no definition about when an application + actually adds a utmp entry, some applications bizarrely do the + utmp call before the have PAM authenticate them to the system: +@@ -273,6 +275,78 @@ check_logins (pam_handle_t *pamh, const char *name, int limit, int ctrl, + count = 1; + } + ++#ifdef USE_LOGIND ++ char **sessions_list; ++ int sessions = sd_get_sessions(&sessions_list); ++ ++ /* maxlogins needs to be 2 with systemd-logind because ++ of the systemd --user process started with first login by ++ pam_systemd. ++ Which is also calling pam_limits, but in this very first special ++ case the session does already exist and is counted twice. ++ With start of the second session, session manager is already running ++ and no longer counted. */ ++ if (limit == 1) { ++ pam_syslog(pamh, LOG_WARNING, "Maxlogin limit needs to be 2 or higher with systemd-logind"); ++ return LIMIT_ERR; ++ } ++ ++ if (sessions < 0) { ++ pam_syslog(pamh, LOG_ERR, "logind error getting session list: %s", ++ strerror(-sessions)); ++ return LIMIT_ERR; ++ } else if (sessions > 0 && sessions_list != NULL && !pl->flag_numsyslogins) { ++ int i; ++ ++ for (i = 0; i < sessions; i++) { ++ char *user = NULL; ++ char *class = NULL; ++ ++ if (sd_session_get_class(sessions_list[i], &class) < 0 || class == NULL) ++ continue; ++ ++ if (strncmp(class, "user", 4) != 0) { /* user, user-early, user-incomplete */ ++ free (class); ++ continue; ++ } ++ free (class); ++ ++ if (sd_session_get_username(sessions_list[i], &user) < 0 || user == NULL) { ++ pam_syslog(pamh, LOG_ERR, "logind error getting username: %s", ++ strerror(-sessions)); ++ return LIMIT_ERR; ++ } ++ ++ if (((pl->login_limit_def == LIMITS_DEF_USER) ++ || (pl->login_limit_def == LIMITS_DEF_GROUP) ++ || (pl->login_limit_def == LIMITS_DEF_DEFAULT)) ++ && strcmp(name, user) != 0) { ++ free(user); ++ continue; ++ } ++ if ((pl->login_limit_def == LIMITS_DEF_ALLGROUP) ++ && pl->login_group != NULL ++ && !pam_modutil_user_in_group_nam_nam(pamh, user, pl->login_group)) { ++ free(user); ++ continue; ++ } ++ free(user); ++ ++ if (++count > limit) { ++ break; ++ } ++ } ++ for (i = 0; i < sessions; i++) ++ free(sessions_list[i]); ++ free(sessions_list); ++ } else { ++ count = sessions; ++ } ++#else ++ struct utmp *ut; ++ ++ setutent(); ++ + while((ut = getutent())) { + #ifdef USER_PROCESS + if (ut->ut_type != USER_PROCESS) { +@@ -311,6 +385,7 @@ check_logins (pam_handle_t *pamh, const char *name, int limit, int ctrl, + } + } + endutent(); ++#endif + if (count > limit) { + if (name) { + pam_syslog(pamh, LOG_NOTICE,