diff options
Diffstat (limited to 'source/a/pam/fedora-patches')
18 files changed, 2973 insertions, 0 deletions
diff --git a/source/a/pam/fedora-patches/pam-1.1.3-nouserenv.patch b/source/a/pam/fedora-patches/pam-1.1.3-nouserenv.patch new file mode 100644 index 00000000..f3a742c8 --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.1.3-nouserenv.patch @@ -0,0 +1,27 @@ +diff -up pam/modules/pam_env/pam_env.c.nouserenv pam/modules/pam_env/pam_env.c +--- pam/modules/pam_env/pam_env.c.nouserenv 2010-10-20 09:59:30.000000000 +0200 ++++ pam/modules/pam_env/pam_env.c 2010-11-01 14:42:01.000000000 +0100 +@@ -10,7 +10,7 @@ + #define DEFAULT_READ_ENVFILE 1 + + #define DEFAULT_USER_ENVFILE ".pam_environment" +-#define DEFAULT_USER_READ_ENVFILE 1 ++#define DEFAULT_USER_READ_ENVFILE 0 + + #include "config.h" + +diff -up pam/modules/pam_env/pam_env.8.xml.nouserenv pam/modules/pam_env/pam_env.8.xml +--- pam/modules/pam_env/pam_env.8.xml.nouserenv 2010-10-20 09:59:30.000000000 +0200 ++++ pam/modules/pam_env/pam_env.8.xml 2010-11-01 14:42:01.000000000 +0100 +@@ -147,7 +147,10 @@ + <listitem> + <para> + Turns on or off the reading of the user specific environment +- file. 0 is off, 1 is on. By default this option is on. ++ file. 0 is off, 1 is on. By default this option is off as user ++ supplied environment variables in the PAM environment could affect ++ behavior of subsequent modules in the stack without the consent ++ of the system administrator. + </para> + </listitem> + </varlistentry> diff --git a/source/a/pam/fedora-patches/pam-1.1.6-limits-user.patch b/source/a/pam/fedora-patches/pam-1.1.6-limits-user.patch new file mode 100644 index 00000000..3c17b781 --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.1.6-limits-user.patch @@ -0,0 +1,20 @@ +diff -up Linux-PAM-1.1.6/modules/pam_limits/limits.conf.limits Linux-PAM-1.1.6/modules/pam_limits/limits.conf +--- Linux-PAM-1.1.6/modules/pam_limits/limits.conf.limits 2012-08-15 13:08:43.000000000 +0200 ++++ Linux-PAM-1.1.6/modules/pam_limits/limits.conf 2013-03-14 16:43:37.615087671 +0100 +@@ -1,5 +1,16 @@ + # /etc/security/limits.conf + # ++#This file sets the resource limits for the users logged in via PAM. ++#It does not affect resource limits of the system services. ++# ++#Also note that configuration files in /etc/security/limits.d directory, ++#which are read in alphabetical order, override the settings in this ++#file in case the domain is the same or more specific. ++#That means for example that setting a limit for wildcard domain here ++#can be overriden with a wildcard setting in a config file in the ++#subdirectory, but a user specific setting here can be overriden only ++#with a user specific setting in the subdirectory. ++# + #Each line describes a limit for a user in the form: + # + #<domain> <type> <item> <value> diff --git a/source/a/pam/fedora-patches/pam-1.1.8-audit-user-mgmt.patch b/source/a/pam/fedora-patches/pam-1.1.8-audit-user-mgmt.patch new file mode 100644 index 00000000..277a5699 --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.1.8-audit-user-mgmt.patch @@ -0,0 +1,31 @@ +diff -up Linux-PAM-1.1.8/modules/pam_tally2/pam_tally2.c.audit-user-mgmt Linux-PAM-1.1.8/modules/pam_tally2/pam_tally2.c +--- Linux-PAM-1.1.8/modules/pam_tally2/pam_tally2.c.audit-user-mgmt 2013-06-18 16:11:21.000000000 +0200 ++++ Linux-PAM-1.1.8/modules/pam_tally2/pam_tally2.c 2014-10-17 12:09:12.965490940 +0200 +@@ -997,9 +997,9 @@ main( int argc UNUSED, char **argv ) + #ifdef HAVE_LIBAUDIT + char buf[64]; + int audit_fd = audit_open(); +- snprintf(buf, sizeof(buf), "pam_tally2 uid=%u reset=%hu", uid, cline_reset); +- audit_log_user_message(audit_fd, AUDIT_USER_ACCT, +- buf, NULL, NULL, ttyname(STDIN_FILENO), 1); ++ snprintf(buf, sizeof(buf), "pam_tally2 reset=%hu", cline_reset); ++ audit_log_acct_message(audit_fd, AUDIT_USER_MGMT, NULL, ++ buf, NULL, uid, NULL, NULL, ttyname(STDIN_FILENO), 1); + if (audit_fd >=0) + close(audit_fd); + #endif +@@ -1040,11 +1040,10 @@ main( int argc UNUSED, char **argv ) + } + else if ( !cline_reset ) { + #ifdef HAVE_LIBAUDIT +- char buf[64]; + int audit_fd = audit_open(); +- snprintf(buf, sizeof(buf), "pam_tally2 uid=all reset=0"); +- audit_log_user_message(audit_fd, AUDIT_USER_ACCT, +- buf, NULL, NULL, ttyname(STDIN_FILENO), 1); ++ audit_log_acct_message(audit_fd, AUDIT_USER_MGMT, NULL, ++ "pam_tally2-reset-all-accts reset=0", "*", -1, ++ NULL, NULL, ttyname(STDIN_FILENO), 1); + if (audit_fd >=0) + close(audit_fd); + #endif diff --git a/source/a/pam/fedora-patches/pam-1.1.8-full-relro.patch b/source/a/pam/fedora-patches/pam-1.1.8-full-relro.patch new file mode 100644 index 00000000..b2d8526f --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.1.8-full-relro.patch @@ -0,0 +1,67 @@ +diff -up Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am +--- Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am.relro 2014-09-10 17:17:20.273401344 +0200 ++++ Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am 2014-09-10 17:17:07.857115369 +0200 +@@ -9,7 +9,7 @@ securelibfilterdir = $(SECUREDIR)/pam_fi + + AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ + -I$(srcdir)/.. @PIE_CFLAGS@ +-AM_LDFLAGS = @PIE_LDFLAGS@ ++AM_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@ + LDADD = $(top_builddir)/libpam/libpam.la + + securelibfilter_PROGRAMS = upperLOWER +diff -up Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am +--- Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200 ++++ Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am 2014-09-10 17:18:42.922304935 +0200 +@@ -30,6 +30,8 @@ endif + + sbin_PROGRAMS = mkhomedir_helper + mkhomedir_helper_SOURCES = mkhomedir_helper.c ++mkhomedir_helper_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ ++mkhomedir_helper_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@ + mkhomedir_helper_LDADD = $(top_builddir)/libpam/libpam.la + + if ENABLE_REGENERATE_MAN +diff -up Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am +--- Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200 ++++ Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am 2014-09-10 17:22:04.339944040 +0200 +@@ -26,6 +26,8 @@ if HAVE_VERSIONING + pam_tally2_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map + endif + ++pam_tally2_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ ++pam_tally2_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@ + pam_tally2_LDADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT) + + securelib_LTLIBRARIES = pam_tally2.la +diff -up Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am +--- Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200 ++++ Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am 2014-08-13 16:02:49.906688139 +0200 +@@ -36,7 +36,7 @@ pam_timestamp_la_CFLAGS = $(AM_CFLAGS) + pam_timestamp_check_SOURCES = pam_timestamp_check.c + pam_timestamp_check_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ + pam_timestamp_check_LDADD = $(top_builddir)/libpam/libpam.la +-pam_timestamp_check_LDFLAGS = @PIE_LDFLAGS@ ++pam_timestamp_check_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@ + + hmacfile_SOURCES = hmacfile.c hmacsha1.c sha1.c + hmacfile_LDADD = $(top_builddir)/libpam/libpam.la +diff -up Linux-PAM-1.1.8/modules/pam_unix/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_unix/Makefile.am +--- Linux-PAM-1.1.8/modules/pam_unix/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200 ++++ Linux-PAM-1.1.8/modules/pam_unix/Makefile.am 2014-08-13 16:02:49.906688139 +0200 +@@ -55,13 +55,13 @@ bigcrypt_LDADD = @LIBCRYPT@ + unix_chkpwd_SOURCES = unix_chkpwd.c md5_good.c md5_broken.c bigcrypt.c \ + passverify.c + unix_chkpwd_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_chkpwd\" +-unix_chkpwd_LDFLAGS = @PIE_LDFLAGS@ ++unix_chkpwd_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@ + unix_chkpwd_LDADD = @LIBCRYPT@ @LIBSELINUX@ @LIBAUDIT@ + + unix_update_SOURCES = unix_update.c md5_good.c md5_broken.c bigcrypt.c \ + passverify.c + unix_update_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_update\" +-unix_update_LDFLAGS = @PIE_LDFLAGS@ ++unix_update_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@ + unix_update_LDADD = @LIBCRYPT@ @LIBSELINUX@ + + if ENABLE_REGENERATE_MAN diff --git a/source/a/pam/fedora-patches/pam-1.3.0-pwhistory-helper.patch b/source/a/pam/fedora-patches/pam-1.3.0-pwhistory-helper.patch new file mode 100644 index 00000000..554e5c8f --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.0-pwhistory-helper.patch @@ -0,0 +1,806 @@ +diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/Makefile.am.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/Makefile.am +--- Linux-PAM-1.3.0/modules/pam_pwhistory/Makefile.am.pwhhelper 2016-03-24 12:45:42.000000000 +0100 ++++ Linux-PAM-1.3.0/modules/pam_pwhistory/Makefile.am 2016-05-06 15:18:42.307637933 +0200 +@@ -1,5 +1,6 @@ + # + # Copyright (c) 2008, 2009 Thorsten Kukuk <kukuk@suse.de> ++# Copyright (c) 2013 Red Hat, Inc. + # + + CLEANFILES = *~ +@@ -9,25 +10,34 @@ EXTRA_DIST = README $(MANS) $(XMLS) tst- + + TESTS = tst-pam_pwhistory + +-man_MANS = pam_pwhistory.8 ++man_MANS = pam_pwhistory.8 pwhistory_helper.8 + +-XMLS = README.xml pam_pwhistory.8.xml ++XMLS = README.xml pam_pwhistory.8.xml pwhistory_helper.8.xml + + securelibdir = $(SECUREDIR) + secureconfdir = $(SCONFIGDIR) + +-AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include +-AM_LDFLAGS = -no-undefined -avoid-version -module ++AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ ++ -DPWHISTORY_HELPER=\"$(sbindir)/pwhistory_helper\" ++ ++pam_pwhistory_la_LDFLAGS = -no-undefined -avoid-version -module + if HAVE_VERSIONING +- AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map ++ pam_pwhistory_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map + endif + + noinst_HEADERS = opasswd.h + + securelib_LTLIBRARIES = pam_pwhistory.la +-pam_pwhistory_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@ ++pam_pwhistory_la_CFLAGS = $(AM_CFLAGS) ++pam_pwhistory_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@ @LIBSELINUX@ + pam_pwhistory_la_SOURCES = pam_pwhistory.c opasswd.c + ++sbin_PROGRAMS = pwhistory_helper ++pwhistory_helper_CFLAGS = $(AM_CFLAGS) -DHELPER_COMPILE=\"pwhistory_helper\" @PIE_CFLAGS@ ++pwhistory_helper_SOURCES = pwhistory_helper.c opasswd.c ++pwhistory_helper_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@ ++pwhistory_helper_LDADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@ ++ + if ENABLE_REGENERATE_MAN + noinst_DATA = README + README: pam_pwhistory.8.xml +diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.c.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.c +--- Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.c.pwhhelper 2016-03-24 12:45:42.000000000 +0100 ++++ Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.c 2016-05-06 15:18:42.307637933 +0200 +@@ -1,5 +1,6 @@ + /* + * Copyright (c) 2008 Thorsten Kukuk <kukuk@suse.de> ++ * Copyright (c) 2013 Red Hat, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -38,6 +39,7 @@ + #endif + + #include <pwd.h> ++#include <shadow.h> + #include <time.h> + #include <ctype.h> + #include <errno.h> +@@ -47,6 +49,7 @@ + #include <string.h> + #include <stdlib.h> + #include <syslog.h> ++#include <stdarg.h> + #include <sys/stat.h> + + #if defined (HAVE_XCRYPT_H) +@@ -55,7 +58,14 @@ + #include <crypt.h> + #endif + ++#ifdef HELPER_COMPILE ++#define pam_modutil_getpwnam(h,n) getpwnam(n) ++#define pam_modutil_getspnam(h,n) getspnam(n) ++#define pam_syslog(h,a,...) helper_log_err(a,__VA_ARGS__) ++#else ++#include <security/pam_modutil.h> + #include <security/pam_ext.h> ++#endif + #include <security/pam_modules.h> + + #include "opasswd.h" +@@ -76,6 +86,19 @@ typedef struct { + char *old_passwords; + } opwd; + ++#ifdef HELPER_COMPILE ++void ++helper_log_err(int err, const char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ openlog(HELPER_COMPILE, LOG_CONS | LOG_PID, LOG_AUTHPRIV); ++ vsyslog(err, format, args); ++ va_end(args); ++ closelog(); ++} ++#endif + + static int + parse_entry (char *line, opwd *data) +@@ -117,8 +140,8 @@ compare_password(const char *newpass, co + } + + /* Check, if the new password is already in the opasswd file. */ +-int +-check_old_pass (pam_handle_t *pamh, const char *user, ++PAMH_ARG_DECL(int ++check_old_pass, const char *user, + const char *newpass, int debug) + { + int retval = PAM_SUCCESS; +@@ -128,6 +151,11 @@ check_old_pass (pam_handle_t *pamh, cons + opwd entry; + int found = 0; + ++#ifndef HELPER_COMPILE ++ if (SELINUX_ENABLED) ++ return PAM_PWHISTORY_RUN_HELPER; ++#endif ++ + if ((oldpf = fopen (OLD_PASSWORDS_FILE, "r")) == NULL) + { + if (errno != ENOENT) +@@ -213,9 +241,9 @@ check_old_pass (pam_handle_t *pamh, cons + return retval; + } + +-int +-save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid, +- const char *oldpass, int howmany, int debug UNUSED) ++PAMH_ARG_DECL(int ++save_old_pass, const char *user, ++ int howmany, int debug UNUSED) + { + char opasswd_tmp[] = TMP_PASSWORDS_FILE; + struct stat opasswd_stat; +@@ -226,10 +254,35 @@ save_old_pass (pam_handle_t *pamh, const + char *buf = NULL; + size_t buflen = 0; + int found = 0; ++ struct passwd *pwd; ++ const char *oldpass; ++ ++ pwd = pam_modutil_getpwnam (pamh, user); ++ if (pwd == NULL) ++ return PAM_USER_UNKNOWN; + + if (howmany <= 0) + return PAM_SUCCESS; + ++#ifndef HELPER_COMPILE ++ if (SELINUX_ENABLED) ++ return PAM_PWHISTORY_RUN_HELPER; ++#endif ++ ++ if ((strcmp(pwd->pw_passwd, "x") == 0) || ++ ((pwd->pw_passwd[0] == '#') && ++ (pwd->pw_passwd[1] == '#') && ++ (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0))) ++ { ++ struct spwd *spw = pam_modutil_getspnam (pamh, user); ++ ++ if (spw == NULL) ++ return PAM_USER_UNKNOWN; ++ oldpass = spw->sp_pwdp; ++ } ++ else ++ oldpass = pwd->pw_passwd; ++ + if (oldpass == NULL || *oldpass == '\0') + return PAM_SUCCESS; + +@@ -452,7 +505,7 @@ save_old_pass (pam_handle_t *pamh, const + { + char *out; + +- if (asprintf (&out, "%s:%d:1:%s\n", user, uid, oldpass) < 0) ++ if (asprintf (&out, "%s:%d:1:%s\n", user, pwd->pw_uid, oldpass) < 0) + { + retval = PAM_AUTHTOK_ERR; + if (oldpf) +diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.h.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.h +--- Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.h.pwhhelper 2016-03-24 12:45:42.000000000 +0100 ++++ Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.h 2016-05-06 15:18:42.307637933 +0200 +@@ -1,5 +1,6 @@ + /* + * Copyright (c) 2008 Thorsten Kukuk <kukuk@suse.de> ++ * Copyright (c) 2013 Red Hat, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -36,10 +37,32 @@ + #ifndef __OPASSWD_H__ + #define __OPASSWD_H__ + +-extern int check_old_pass (pam_handle_t *pamh, const char *user, +- const char *newpass, int debug); +-extern int save_old_pass (pam_handle_t *pamh, const char *user, +- uid_t uid, const char *oldpass, +- int howmany, int debug); ++#define PAM_PWHISTORY_RUN_HELPER PAM_CRED_INSUFFICIENT ++ ++#ifdef WITH_SELINUX ++#include <selinux/selinux.h> ++#define SELINUX_ENABLED is_selinux_enabled()>0 ++#else ++#define SELINUX_ENABLED 0 ++#endif ++ ++#ifdef HELPER_COMPILE ++#define PAMH_ARG_DECL(fname, ...) fname(__VA_ARGS__) ++#define PAMH_ARG(...) __VA_ARGS__ ++#else ++#define PAMH_ARG_DECL(fname, ...) fname(pam_handle_t *pamh, __VA_ARGS__) ++#define PAMH_ARG(...) pamh, __VA_ARGS__ ++#endif ++ ++#ifdef HELPER_COMPILE ++void ++helper_log_err(int err, const char *format, ...); ++#endif ++ ++PAMH_ARG_DECL(int ++check_old_pass, const char *user, const char *newpass, int debug); ++ ++PAMH_ARG_DECL(int ++save_old_pass, const char *user, int howmany, int debug); + + #endif /* __OPASSWD_H__ */ +diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/pam_pwhistory.c.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/pam_pwhistory.c +--- Linux-PAM-1.3.0/modules/pam_pwhistory/pam_pwhistory.c.pwhhelper 2016-04-04 11:22:28.000000000 +0200 ++++ Linux-PAM-1.3.0/modules/pam_pwhistory/pam_pwhistory.c 2016-05-06 15:19:31.610785512 +0200 +@@ -1,6 +1,7 @@ + /* + * Copyright (c) 2008, 2012 Thorsten Kukuk + * Author: Thorsten Kukuk <kukuk@thkukuk.de> ++ * Copyright (c) 2013 Red Hat, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -46,10 +47,14 @@ + #include <stdlib.h> + #include <string.h> + #include <unistd.h> +-#include <shadow.h> + #include <syslog.h> + #include <sys/types.h> + #include <sys/stat.h> ++#include <sys/time.h> ++#include <sys/resource.h> ++#include <sys/wait.h> ++#include <signal.h> ++#include <fcntl.h> + + #include <security/pam_modules.h> + #include <security/pam_modutil.h> +@@ -59,6 +64,7 @@ + #include "opasswd.h" + + #define DEFAULT_BUFLEN 2048 ++#define MAX_FD_NO 20000 + + struct options_t { + int debug; +@@ -102,6 +108,184 @@ parse_option (pam_handle_t *pamh, const + pam_syslog (pamh, LOG_ERR, "pam_pwhistory: unknown option: %s", argv); + } + ++static int ++run_save_helper(pam_handle_t *pamh, const char *user, ++ int howmany, int debug) ++{ ++ int retval, child; ++ struct sigaction newsa, oldsa; ++ ++ memset(&newsa, '\0', sizeof(newsa)); ++ newsa.sa_handler = SIG_DFL; ++ sigaction(SIGCHLD, &newsa, &oldsa); ++ ++ child = fork(); ++ if (child == 0) ++ { ++ int i = 0; ++ struct rlimit rlim; ++ int dummyfds[2]; ++ static char *envp[] = { NULL }; ++ char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL }; ++ ++ /* replace std file descriptors with a dummy pipe */ ++ if (pipe2(dummyfds, O_NONBLOCK) == 0) ++ { ++ dup2(dummyfds[0], STDIN_FILENO); ++ dup2(dummyfds[1], STDOUT_FILENO); ++ dup2(dummyfds[1], STDERR_FILENO); ++ } ++ ++ if (getrlimit(RLIMIT_NOFILE,&rlim) == 0) ++ { ++ if (rlim.rlim_max >= MAX_FD_NO) ++ rlim.rlim_max = MAX_FD_NO; ++ for (i = STDERR_FILENO + 1; i < (int)rlim.rlim_max; i++) ++ { ++ if (i != dummyfds[0]) ++ close(i); ++ } ++ } ++ ++ /* exec binary helper */ ++ args[0] = strdup(PWHISTORY_HELPER); ++ args[1] = strdup("save"); ++ args[2] = x_strdup(user); ++ asprintf(&args[3], "%d", howmany); ++ asprintf(&args[4], "%d", debug); ++ ++ execve(args[0], args, envp); ++ ++ _exit(PAM_SYSTEM_ERR); ++ } ++ else if (child > 0) ++ { ++ /* wait for child */ ++ int rc = 0; ++ rc = waitpid(child, &retval, 0); /* wait for helper to complete */ ++ if (rc < 0) ++ { ++ pam_syslog(pamh, LOG_ERR, "pwhistory_helper save waitpid returned %d: %m", rc); ++ retval = PAM_SYSTEM_ERR; ++ } ++ else if (!WIFEXITED(retval)) ++ { ++ pam_syslog(pamh, LOG_ERR, "pwhistory_helper save abnormal exit: %d", retval); ++ retval = PAM_SYSTEM_ERR; ++ } ++ else ++ { ++ retval = WEXITSTATUS(retval); ++ } ++ } ++ else ++ { ++ retval = PAM_SYSTEM_ERR; ++ } ++ ++ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */ ++ ++ return retval; ++} ++ ++static int ++run_check_helper(pam_handle_t *pamh, const char *user, ++ const char *newpass, int debug) ++{ ++ int retval, child, fds[2]; ++ struct sigaction newsa, oldsa; ++ ++ /* create a pipe for the password */ ++ if (pipe(fds) != 0) ++ return PAM_SYSTEM_ERR; ++ ++ memset(&newsa, '\0', sizeof(newsa)); ++ newsa.sa_handler = SIG_DFL; ++ sigaction(SIGCHLD, &newsa, &oldsa); ++ ++ child = fork(); ++ if (child == 0) ++ { ++ int i = 0; ++ struct rlimit rlim; ++ int dummyfds[2]; ++ static char *envp[] = { NULL }; ++ char *args[] = { NULL, NULL, NULL, NULL, NULL }; ++ ++ /* reopen stdin as pipe */ ++ dup2(fds[0], STDIN_FILENO); ++ ++ /* replace std file descriptors with a dummy pipe */ ++ if (pipe2(dummyfds, O_NONBLOCK) == 0) ++ { ++ dup2(dummyfds[1], STDOUT_FILENO); ++ dup2(dummyfds[1], STDERR_FILENO); ++ } ++ ++ if (getrlimit(RLIMIT_NOFILE,&rlim) == 0) ++ { ++ if (rlim.rlim_max >= MAX_FD_NO) ++ rlim.rlim_max = MAX_FD_NO; ++ for (i = STDERR_FILENO + 1; i < (int)rlim.rlim_max; i++) ++ { ++ if (i != dummyfds[0]) ++ close(i); ++ } ++ } ++ ++ /* exec binary helper */ ++ args[0] = strdup(PWHISTORY_HELPER); ++ args[1] = strdup("check"); ++ args[2] = x_strdup(user); ++ asprintf(&args[3], "%d", debug); ++ ++ execve(args[0], args, envp); ++ ++ _exit(PAM_SYSTEM_ERR); ++ } ++ else if (child > 0) ++ { ++ /* wait for child */ ++ int rc = 0; ++ if (newpass == NULL) ++ newpass = ""; ++ ++ /* send the password to the child */ ++ if (write(fds[1], newpass, strlen(newpass)+1) == -1) ++ { ++ pam_syslog(pamh, LOG_ERR, "Cannot send password to helper: %m"); ++ retval = PAM_SYSTEM_ERR; ++ } ++ newpass = NULL; ++ close(fds[0]); /* close here to avoid possible SIGPIPE above */ ++ close(fds[1]); ++ rc = waitpid(child, &retval, 0); /* wait for helper to complete */ ++ if (rc < 0) ++ { ++ pam_syslog(pamh, LOG_ERR, "pwhistory_helper check waitpid returned %d: %m", rc); ++ retval = PAM_SYSTEM_ERR; ++ } ++ else if (!WIFEXITED(retval)) ++ { ++ pam_syslog(pamh, LOG_ERR, "pwhistory_helper check abnormal exit: %d", retval); ++ retval = PAM_SYSTEM_ERR; ++ } ++ else ++ { ++ retval = WEXITSTATUS(retval); ++ } ++ } ++ else ++ { ++ close(fds[0]); ++ close(fds[1]); ++ retval = PAM_SYSTEM_ERR; ++ } ++ ++ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */ ++ ++ return retval; ++} + + /* This module saves the current crypted password in /etc/security/opasswd + and then compares the new password with all entries in this file. */ +@@ -109,7 +293,6 @@ parse_option (pam_handle_t *pamh, const + int + pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv) + { +- struct passwd *pwd; + const char *newpass; + const char *user; + int retval, tries; +@@ -154,31 +337,13 @@ pam_sm_chauthtok (pam_handle_t *pamh, in + return PAM_SUCCESS; + } + +- pwd = pam_modutil_getpwnam (pamh, user); +- if (pwd == NULL) +- return PAM_USER_UNKNOWN; +- +- if ((strcmp(pwd->pw_passwd, "x") == 0) || +- ((pwd->pw_passwd[0] == '#') && +- (pwd->pw_passwd[1] == '#') && +- (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0))) +- { +- struct spwd *spw = pam_modutil_getspnam (pamh, user); +- if (spw == NULL) +- return PAM_USER_UNKNOWN; ++ retval = save_old_pass (pamh, user, options.remember, options.debug); + +- retval = save_old_pass (pamh, user, pwd->pw_uid, spw->sp_pwdp, +- options.remember, options.debug); +- if (retval != PAM_SUCCESS) +- return retval; +- } +- else +- { +- retval = save_old_pass (pamh, user, pwd->pw_uid, pwd->pw_passwd, +- options.remember, options.debug); +- if (retval != PAM_SUCCESS) +- return retval; +- } ++ if (retval == PAM_PWHISTORY_RUN_HELPER) ++ retval = run_save_helper(pamh, user, options.remember, options.debug); ++ ++ if (retval != PAM_SUCCESS) ++ return retval; + + newpass = NULL; + tries = 0; +@@ -207,8 +372,11 @@ pam_sm_chauthtok (pam_handle_t *pamh, in + if (options.debug) + pam_syslog (pamh, LOG_DEBUG, "check against old password file"); + +- if (check_old_pass (pamh, user, newpass, +- options.debug) != PAM_SUCCESS) ++ retval = check_old_pass (pamh, user, newpass, options.debug); ++ if (retval == PAM_PWHISTORY_RUN_HELPER) ++ retval = run_check_helper(pamh, user, newpass, options.debug); ++ ++ if (retval != PAM_SUCCESS) + { + if (getuid() || options.enforce_for_root || + (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) +diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.c.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.c +--- Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.c.pwhhelper 2016-05-06 15:18:42.308637957 +0200 ++++ Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.c 2016-05-06 15:18:42.308637957 +0200 +@@ -0,0 +1,209 @@ ++/* ++ * Copyright (c) 2013 Red Hat, Inc. ++ * Author: Tomas Mraz <tmraz@redhat.com> ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, and the entire permission notice in its entirety, ++ * including the disclaimer of warranties. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * ALTERNATIVELY, this product may be distributed under the terms of ++ * the GNU Public License, in which case the provisions of the GPL are ++ * required INSTEAD OF the above restrictions. (This clause is ++ * necessary due to a potential bad interaction between the GPL and ++ * the restrictions contained in a BSD-style copyright.) ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ++ * OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "config.h" ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <syslog.h> ++#include <errno.h> ++#include <unistd.h> ++#include <signal.h> ++#include <security/_pam_types.h> ++#include <security/_pam_macros.h> ++#include "opasswd.h" ++ ++#define MAXPASS 200 ++ ++static void ++su_sighandler(int sig) ++{ ++#ifndef SA_RESETHAND ++ /* emulate the behaviour of the SA_RESETHAND flag */ ++ if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) { ++ struct sigaction sa; ++ memset(&sa, '\0', sizeof(sa)); ++ sa.sa_handler = SIG_DFL; ++ sigaction(sig, &sa, NULL); ++ } ++#endif ++ if (sig > 0) { ++ _exit(sig); ++ } ++} ++ ++static void ++setup_signals(void) ++{ ++ struct sigaction action; /* posix signal structure */ ++ ++ /* ++ * Setup signal handlers ++ */ ++ (void) memset((void *) &action, 0, sizeof(action)); ++ action.sa_handler = su_sighandler; ++#ifdef SA_RESETHAND ++ action.sa_flags = SA_RESETHAND; ++#endif ++ (void) sigaction(SIGILL, &action, NULL); ++ (void) sigaction(SIGTRAP, &action, NULL); ++ (void) sigaction(SIGBUS, &action, NULL); ++ (void) sigaction(SIGSEGV, &action, NULL); ++ action.sa_handler = SIG_IGN; ++ action.sa_flags = 0; ++ (void) sigaction(SIGTERM, &action, NULL); ++ (void) sigaction(SIGHUP, &action, NULL); ++ (void) sigaction(SIGINT, &action, NULL); ++ (void) sigaction(SIGQUIT, &action, NULL); ++} ++ ++static int ++read_passwords(int fd, int npass, char **passwords) ++{ ++ int rbytes = 0; ++ int offset = 0; ++ int i = 0; ++ char *pptr; ++ while (npass > 0) ++ { ++ rbytes = read(fd, passwords[i]+offset, MAXPASS-offset); ++ ++ if (rbytes < 0) ++ { ++ if (errno == EINTR) continue; ++ break; ++ } ++ if (rbytes == 0) ++ break; ++ ++ while (npass > 0 && (pptr=memchr(passwords[i]+offset, '\0', rbytes)) ++ != NULL) ++ { ++ rbytes -= pptr - (passwords[i]+offset) + 1; ++ i++; ++ offset = 0; ++ npass--; ++ if (rbytes > 0) ++ { ++ if (npass > 0) ++ memcpy(passwords[i], pptr+1, rbytes); ++ memset(pptr+1, '\0', rbytes); ++ } ++ } ++ offset += rbytes; ++ } ++ ++ /* clear up */ ++ if (offset > 0 && npass > 0) ++ memset(passwords[i], '\0', offset); ++ ++ return i; ++} ++ ++ ++static int ++check_history(const char *user, const char *debug) ++{ ++ char pass[MAXPASS + 1]; ++ char *passwords[] = { pass }; ++ int npass; ++ int dbg = atoi(debug); /* no need to be too fancy here */ ++ int retval; ++ ++ /* read the password from stdin (a pipe from the pam_pwhistory module) */ ++ npass = read_passwords(STDIN_FILENO, 1, passwords); ++ ++ if (npass != 1) ++ { /* is it a valid password? */ ++ helper_log_err(LOG_DEBUG, "no password supplied"); ++ return PAM_AUTHTOK_ERR; ++ } ++ ++ retval = check_old_pass(user, pass, dbg); ++ ++ memset(pass, '\0', MAXPASS); /* clear memory of the password */ ++ ++ return retval; ++} ++ ++static int ++save_history(const char *user, const char *howmany, const char *debug) ++{ ++ int num = atoi(howmany); ++ int dbg = atoi(debug); /* no need to be too fancy here */ ++ int retval; ++ ++ retval = save_old_pass(user, num, dbg); ++ ++ return retval; ++} ++ ++int ++main(int argc, char *argv[]) ++{ ++ const char *option; ++ const char *user; ++ ++ /* ++ * Catch or ignore as many signal as possible. ++ */ ++ setup_signals(); ++ ++ /* ++ * we establish that this program is running with non-tty stdin. ++ * this is to discourage casual use. ++ */ ++ ++ if (isatty(STDIN_FILENO) || argc < 4) ++ { ++ fprintf(stderr, ++ "This binary is not designed for running in this way.\n"); ++ sleep(10); /* this should discourage/annoy the user */ ++ return PAM_SYSTEM_ERR; ++ } ++ ++ option = argv[1]; ++ user = argv[2]; ++ ++ if (strcmp(option, "check") == 0 && argc == 4) ++ return check_history(user, argv[3]); ++ else if (strcmp(option, "save") == 0 && argc == 5) ++ return save_history(user, argv[3], argv[4]); ++ ++ return PAM_SYSTEM_ERR; ++} ++ +diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.8.xml.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.8.xml +--- Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.8.xml.pwhhelper 2016-05-06 15:18:42.308637957 +0200 ++++ Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.8.xml 2016-05-06 15:18:42.308637957 +0200 +@@ -0,0 +1,68 @@ ++<?xml version="1.0" encoding='UTF-8'?> ++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" ++ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"> ++ ++<refentry id="pwhistory_helper"> ++ ++ <refmeta> ++ <refentrytitle>pwhistory_helper</refentrytitle> ++ <manvolnum>8</manvolnum> ++ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo> ++ </refmeta> ++ ++ <refnamediv id="pwhistory_helper-name"> ++ <refname>pwhistory_helper</refname> ++ <refpurpose>Helper binary that transfers password hashes from passwd or shadow to opasswd</refpurpose> ++ </refnamediv> ++ ++ <refsynopsisdiv> ++ <cmdsynopsis id="pwhistory_helper-cmdsynopsis"> ++ <command>pwhistory_helper</command> ++ <arg choice="opt"> ++ ... ++ </arg> ++ </cmdsynopsis> ++ </refsynopsisdiv> ++ ++ <refsect1 id="pwhistory_helper-description"> ++ ++ <title>DESCRIPTION</title> ++ ++ <para> ++ <emphasis>pwhistory_helper</emphasis> is a helper program for the ++ <emphasis>pam_pwhistory</emphasis> module that transfers password hashes ++ from passwd or shadow file to the opasswd file and checks a password ++ supplied by user against the existing hashes in the opasswd file. ++ </para> ++ ++ <para> ++ The purpose of the helper is to enable tighter confinement of ++ login and password changing services. The helper is thus called only ++ when SELinux is enabled on the system. ++ </para> ++ ++ <para> ++ The interface of the helper - command line options, and input/output ++ data format are internal to the <emphasis>pam_pwhistory</emphasis> ++ module and it should not be called directly from applications. ++ </para> ++ </refsect1> ++ ++ <refsect1 id='pwhistory_helper-see_also'> ++ <title>SEE ALSO</title> ++ <para> ++ <citerefentry> ++ <refentrytitle>pam_pwhistory</refentrytitle><manvolnum>8</manvolnum> ++ </citerefentry> ++ </para> ++ </refsect1> ++ ++ <refsect1 id='pwhistory_helper-author'> ++ <title>AUTHOR</title> ++ <para> ++ Written by Tomas Mraz based on the code originally in ++ <emphasis>pam_pwhistory and pam_unix</emphasis> modules. ++ </para> ++ </refsect1> ++ ++</refentry> diff --git a/source/a/pam/fedora-patches/pam-1.3.0-unix-nomsg.patch b/source/a/pam/fedora-patches/pam-1.3.0-unix-nomsg.patch new file mode 100644 index 00000000..33c22677 --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.0-unix-nomsg.patch @@ -0,0 +1,16 @@ +diff -up Linux-PAM-1.3.0/modules/pam_unix/pam_unix_passwd.c.nomsg Linux-PAM-1.3.0/modules/pam_unix/pam_unix_passwd.c +--- Linux-PAM-1.3.0/modules/pam_unix/pam_unix_passwd.c.nomsg 2016-04-11 13:08:47.000000000 +0200 ++++ Linux-PAM-1.3.0/modules/pam_unix/pam_unix_passwd.c 2017-04-20 16:51:24.853106709 +0200 +@@ -687,12 +687,6 @@ pam_sm_chauthtok(pam_handle_t *pamh, int + return PAM_SUCCESS; + } else if (off(UNIX__IAMROOT, ctrl) || + (on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, user, 0, 1))) { +- /* instruct user what is happening */ +- if (off(UNIX__QUIET, ctrl)) { +- retval = pam_info(pamh, _("Changing password for %s."), user); +- if (retval != PAM_SUCCESS) +- return retval; +- } + retval = pam_get_authtok(pamh, PAM_OLDAUTHTOK, &pass_old, NULL); + + if (retval != PAM_SUCCESS) { diff --git a/source/a/pam/fedora-patches/pam-1.3.1-coverity.patch b/source/a/pam/fedora-patches/pam-1.3.1-coverity.patch new file mode 100644 index 00000000..cecf768f --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.1-coverity.patch @@ -0,0 +1,185 @@ +diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c +index 106ef7c..b2e94c7 100644 +--- a/libpam/pam_handlers.c ++++ b/libpam/pam_handlers.c +@@ -282,7 +282,6 @@ _pam_open_config_file(pam_handle_t *pamh + { + char *p; + FILE *f; +- int err = 0; + + /* Absolute path */ + if (service[0] == '/') { +diff --git a/libpam_misc/misc_conv.c b/libpam_misc/misc_conv.c +index be53f34..07dce36 100644 +--- a/libpam_misc/misc_conv.c ++++ b/libpam_misc/misc_conv.c +@@ -211,7 +211,7 @@ static int read_string(int echo, const char *prompt, char **retstr) + line[nc] = '\0'; + } + *retstr = strdup(line); +- _pam_overwrite(line); ++ _pam_overwrite_n(line, sizeof(line)); + if (!*retstr) { + D(("no memory for response string")); + nc = -1; +@@ -244,7 +244,7 @@ static int read_string(int echo, const char *prompt, char **retstr) + D(("the timer appears to have expired")); + + *retstr = NULL; +- _pam_overwrite(line); ++ _pam_overwrite_n(line, sizeof(line)); + + cleanexit: + +diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c +index 80d885d..3801862 100644 +--- a/modules/pam_access/pam_access.c ++++ b/modules/pam_access/pam_access.c +@@ -806,7 +806,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, + const char *user=NULL; + const void *void_from=NULL; + const char *from; +- const char const *default_config = PAM_ACCESS_CONFIG; ++ const char * const default_config = PAM_ACCESS_CONFIG; + struct passwd *user_pw; + char hostname[MAXHOSTNAMELEN + 1]; + int rv; +diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c +index 4bc4ae7..f8476b4 100644 +--- a/modules/pam_limits/pam_limits.c ++++ b/modules/pam_limits/pam_limits.c +@@ -342,7 +342,7 @@ static const char *lnames[RLIM_NLIMITS] = { + #endif + }; + +-static int str2rlimit(char *name) { ++static int str2rlimit(const char *name) { + int i; + if (!name || *name == '\0') + return -1; +@@ -352,7 +352,7 @@ static int str2rlimit(char *name) { + return -1; + } + +-static rlim_t str2rlim_t(char *value) { ++static rlim_t str2rlim_t(const char *value) { + unsigned long long rlimit = 0; + + if (!value) return (rlim_t)rlimit; +@@ -384,7 +384,7 @@ static void parse_kernel_limits(pam_handle_t *pamh, struct pam_limit_s *pl, int + FILE *limitsfile; + const char *proclimits = "/proc/1/limits"; + char line[256]; +- char *units, *hard, *soft, *name; ++ const char *units, *hard, *soft, *name; + + if (!(limitsfile = fopen(proclimits, "r"))) { + pam_syslog(pamh, LOG_WARNING, "Could not read %s (%s), using PAM defaults", proclimits, strerror(errno)); +diff --git a/modules/pam_loginuid/pam_loginuid.c b/modules/pam_loginuid/pam_loginuid.c +index 96bfd98..66d202c 100644 +--- a/modules/pam_loginuid/pam_loginuid.c ++++ b/modules/pam_loginuid/pam_loginuid.c +@@ -64,7 +64,7 @@ static int set_loginuid(pam_handle_t *pamh, uid_t uid) + fd = open("/proc/self/uid_map", O_RDONLY); + if (fd >= 0) { + count = pam_modutil_read(fd, uid_map, sizeof(uid_map)); +- if (strncmp(uid_map, host_uid_map, count) != 0) ++ if (count <= 0 || strncmp(uid_map, host_uid_map, count) != 0) + rc = PAM_IGNORE; + close(fd); + } +diff --git a/modules/pam_mkhomedir/mkhomedir_helper.c b/modules/pam_mkhomedir/mkhomedir_helper.c +index 9e204c1..4b8d6b7 100644 +--- a/modules/pam_mkhomedir/mkhomedir_helper.c ++++ b/modules/pam_mkhomedir/mkhomedir_helper.c +@@ -232,6 +232,8 @@ create_homedir(const struct passwd *pwd, + { + pam_syslog(NULL, LOG_DEBUG, + "unable to open or stat src file %s: %m", newsource); ++ if (srcfd >= 0) ++ close(srcfd); + closedir(d); + + #ifndef PATH_MAX +diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c +index f541f89..85f5efa 100644 +--- a/modules/pam_namespace/pam_namespace.c ++++ b/modules/pam_namespace/pam_namespace.c +@@ -1418,6 +1418,7 @@ static int create_instance(struct polydir_s *polyptr, char *ipath, struct stat * + if (fstat(fd, &newstatbuf) < 0) { + pam_syslog(idata->pamh, LOG_ERR, "Error stating %s, %m", + ipath); ++ close(fd); + rmdir(ipath); + return PAM_SESSION_ERR; + } +diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c +index e6cf346..813f579 100644 +--- a/modules/pam_pwhistory/opasswd.c ++++ b/modules/pam_pwhistory/opasswd.c +@@ -326,6 +326,9 @@ save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid, + n = strlen (buf); + #endif /* HAVE_GETLINE / HAVE_GETDELIM */ + ++ if (n < 1) ++ break; ++ + cp = buf; + save = strdup (buf); /* Copy to write the original data back. */ + if (save == NULL) +@@ -336,9 +339,6 @@ save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid, + goto error_opasswd; + } + +- if (n < 1) +- break; +- + tmp = strchr (cp, '#'); /* remove comments */ + if (tmp) + *tmp = '\0'; +diff --git a/modules/pam_rootok/pam_rootok.c b/modules/pam_rootok/pam_rootok.c +index 17baabe..a9d9140 100644 +--- a/modules/pam_rootok/pam_rootok.c ++++ b/modules/pam_rootok/pam_rootok.c +@@ -66,14 +66,17 @@ log_callback (int type, const char *fmt, ...) + int audit_fd; + va_list ap; + +- va_start(ap, fmt); + #ifdef HAVE_LIBAUDIT + audit_fd = audit_open(); + + if (audit_fd >= 0) { + char *buf; ++ int ret; + +- if (vasprintf (&buf, fmt, ap) < 0) ++ va_start(ap, fmt); ++ ret = vasprintf (&buf, fmt, ap); ++ va_end(ap); ++ if (ret < 0) + return 0; + audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, + NULL, 0); +@@ -83,6 +86,7 @@ log_callback (int type, const char *fmt, ...) + } + + #endif ++ va_start(ap, fmt); + vsyslog (LOG_USER | LOG_INFO, fmt, ap); + va_end(ap); + return 0; +diff --git a/modules/pam_sepermit/pam_sepermit.c b/modules/pam_sepermit/pam_sepermit.c +index c653290..f37af0f 100644 +--- a/modules/pam_sepermit/pam_sepermit.c ++++ b/modules/pam_sepermit/pam_sepermit.c +@@ -353,7 +353,7 @@ sepermit_match(pam_handle_t *pamh, const char *cfgfile, const char *user, + if (*sense == PAM_SUCCESS) { + if (ignore) + *sense = PAM_IGNORE; +- if (geteuid() == 0 && exclusive && get_loginuid(pamh) == -1) ++ if (geteuid() == 0 && exclusive && get_loginuid(pamh) == (uid_t)-1) + if (sepermit_lock(pamh, user, debug) < 0) + *sense = PAM_AUTH_ERR; + } diff --git a/source/a/pam/fedora-patches/pam-1.3.1-motd-multiple-paths.patch b/source/a/pam/fedora-patches/pam-1.3.1-motd-multiple-paths.patch new file mode 100644 index 00000000..a0b06981 --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.1-motd-multiple-paths.patch @@ -0,0 +1,755 @@ +diff --git a/modules/pam_motd/pam_motd.8.xml b/modules/pam_motd/pam_motd.8.xml +index 906c4ed..4e2110c 100644 +--- a/modules/pam_motd/pam_motd.8.xml ++++ b/modules/pam_motd/pam_motd.8.xml +@@ -21,6 +21,9 @@ + <arg choice="opt"> + motd=<replaceable>/path/filename</replaceable> + </arg> ++ <arg choice="opt"> ++ motd_dir=<replaceable>/path/dirname.d</replaceable> ++ </arg> + </cmdsynopsis> + </refsynopsisdiv> + +@@ -31,10 +34,49 @@ + <para> + pam_motd is a PAM module that can be used to display + arbitrary motd (message of the day) files after a successful +- login. By default the <filename>/etc/motd</filename> file is +- shown. The message size is limited to 64KB. ++ login. By default, pam_motd shows files in the ++ following locations: ++ </para> ++ <para> ++ <simplelist type='vert'> ++ <member><filename>/etc/motd</filename></member> ++ <member><filename>/run/motd</filename></member> ++ <member><filename>/usr/lib/motd</filename></member> ++ <member><filename>/etc/motd.d/</filename></member> ++ <member><filename>/run/motd.d/</filename></member> ++ <member><filename>/usr/lib/motd.d/</filename></member> ++ </simplelist> ++ </para> ++ <para> ++ Each message size is limited to 64KB. ++ </para> ++ <para> ++ If <filename>/etc/motd</filename> does not exist, ++ then <filename>/run/motd</filename> is shown. If ++ <filename>/run/motd</filename> does not exist, then ++ <filename>/usr/lib/motd</filename> is shown. ++ </para> ++ <para> ++ Similar overriding behavior applies to the directories. ++ Files in <filename>/etc/motd.d/</filename> override files ++ with the same name in <filename>/run/motd.d/</filename> and ++ <filename>/usr/lib/motd.d/</filename>. Files in <filename>/run/motd.d/</filename> ++ override files with the same name in <filename>/usr/lib/motd.d/</filename>. ++ </para> ++ <para> ++ Files the in the directories listed above are displayed in ++ lexicographic order by name. ++ </para> ++ <para> ++ To silence a message, ++ a symbolic link with target <filename>/dev/null</filename> ++ may be placed in <filename>/etc/motd.d</filename> with ++ the same filename as the message to be silenced. Example: ++ Creating a symbolic link as follows silences <filename>/usr/lib/motd.d/my_motd</filename>. ++ </para> ++ <para> ++ <command>ln -s /dev/null /etc/motd.d/my_motd</command> + </para> +- + </refsect1> + + <refsect1 id="pam_motd-options"> +@@ -47,8 +89,10 @@ + </term> + <listitem> + <para> +- The <filename>/path/filename</filename> file is displayed +- as message of the day. ++ The <filename>/path/filename</filename> file is displayed ++ as message of the day. Multiple paths to try can be ++ specified as a colon-separated list. By default this option ++ is set to <filename>/etc/motd:/run/motd:/usr/lib/motd</filename>. + </para> + </listitem> + </varlistentry> +@@ -59,16 +103,17 @@ + <listitem> + <para> + The <filename>/path/dirname.d</filename> directory is scanned +- and each file contained inside of it is displayed. ++ and each file contained inside of it is displayed. Multiple ++ directories to scan can be specified as a colon-separated list. ++ By default this option is set to <filename>/etc/motd.d:/run/motd.d:/usr/lib/motd.d</filename>. + </para> + </listitem> + </varlistentry> + </variablelist> + <para> +- When no options are given, the default is to display both +- <filename>/etc/motd</filename> and the contents of +- <filename>/etc/motd.d</filename>. Specifying either option (or both) +- will disable this default behavior. ++ When no options are given, the default behavior applies for both ++ options. Specifying either option (or both) will disable the ++ default behavior for both options. + </para> + </refsect1> + +diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c +index cc828d7..ec3ebd5 100644 +--- a/modules/pam_motd/pam_motd.c ++++ b/modules/pam_motd/pam_motd.c +@@ -33,8 +33,8 @@ + */ + + #define PAM_SM_SESSION +-#define DEFAULT_MOTD "/etc/motd" +-#define DEFAULT_MOTD_D "/etc/motd.d" ++#define DEFAULT_MOTD "/etc/motd:/run/motd:/usr/lib/motd" ++#define DEFAULT_MOTD_D "/etc/motd.d:/run/motd.d:/usr/lib/motd.d" + + #include <security/pam_modules.h> + #include <security/pam_modutil.h> +@@ -97,12 +97,234 @@ static void try_to_display_directory(pam_handle_t *pamh, const char *dirname) + } + } + ++/* ++ * Split a DELIM-separated string ARG into an array. ++ * Outputs a newly allocated array of strings OUT_ARG_SPLIT ++ * and the number of strings OUT_NUM_STRS. ++ * Returns 0 in case of error, 1 in case of success. ++ */ ++static int pam_split_string(const pam_handle_t *pamh, char *arg, char delim, ++ char ***out_arg_split, uint *out_num_strs) ++{ ++ char *arg_extracted = NULL; ++ const char *arg_ptr = arg; ++ char **arg_split = NULL; ++ char delim_str[2]; ++ int i = 0; ++ uint num_strs = 0; ++ int retval = 0; ++ ++ delim_str[0] = delim; ++ delim_str[1] = '\0'; ++ ++ if (arg == NULL) { ++ goto out; ++ } ++ ++ while (arg_ptr != NULL) { ++ num_strs++; ++ arg_ptr = strchr(arg_ptr + sizeof(const char), delim); ++ } ++ ++ arg_split = (char **)calloc(num_strs, sizeof(char *)); ++ if (arg_split == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate string array"); ++ goto out; ++ } ++ ++ arg_extracted = strtok_r(arg, delim_str, &arg); ++ while (arg_extracted != NULL && i < num_strs) { ++ arg_split[i++] = arg_extracted; ++ arg_extracted = strtok_r(NULL, delim_str, &arg); ++ } ++ ++ retval = 1; ++ ++ out: ++ *out_num_strs = num_strs; ++ *out_arg_split = arg_split; ++ ++ return retval; ++} ++ ++/* Join A_STR and B_STR, inserting a "/" between them if one is not already trailing ++ * in A_STR or beginning B_STR. A pointer to a newly allocated string holding the ++ * joined string is returned in STRP_OUT. ++ * Returns -1 in case of error, or the number of bytes in the joined string in ++ * case of success. */ ++static int join_dir_strings(char **strp_out, const char *a_str, const char *b_str) ++{ ++ int has_sep = 0; ++ int retval = -1; ++ char *join_strp = NULL; ++ ++ if (strp_out == NULL || a_str == NULL || b_str == NULL) { ++ goto out; ++ } ++ if (strlen(a_str) == 0) { ++ goto out; ++ } ++ ++ has_sep = (a_str[strlen(a_str) - 1] == '/') || (b_str[0] == '/'); ++ ++ retval = asprintf(&join_strp, "%s%s%s", a_str, ++ (has_sep == 1) ? "" : "/", b_str); ++ ++ if (retval < 0) { ++ goto out; ++ } ++ ++ *strp_out = join_strp; ++ ++ out: ++ return retval; ++} ++ ++static int compare_strings(const void * a, const void * b) ++{ ++ const char *a_str = *(char **)a; ++ const char *b_str = *(char **)b; ++ ++ if (a_str == NULL && b_str == NULL) { ++ return 0; ++ } ++ else if (a_str == NULL) { ++ return -1; ++ } ++ else if (b_str == NULL) { ++ return 1; ++ } ++ else { ++ return strcmp(a_str, b_str); ++ } ++} ++ ++static int filter_dirents(const struct dirent *d) ++{ ++ return (d->d_type == DT_REG || d->d_type == DT_LNK); ++} ++ ++static void try_to_display_directories_with_overrides(pam_handle_t *pamh, ++ char **motd_dir_path_split, int num_motd_dirs) ++{ ++ struct dirent ***dirscans = NULL; ++ int *dirscans_sizes = NULL; ++ int dirscans_size_total = 0; ++ char **dirnames_all = NULL; ++ int i; ++ int i_dirnames = 0; ++ ++ if (pamh == NULL || motd_dir_path_split == NULL) { ++ goto out; ++ } ++ if (num_motd_dirs < 1) { ++ goto out; ++ } ++ ++ if ((dirscans = (struct dirent ***)calloc(num_motd_dirs, ++ sizeof(struct dirent **))) == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirent arrays"); ++ goto out; ++ } ++ if ((dirscans_sizes = (int *)calloc(num_motd_dirs, sizeof(int))) == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirent array sizes"); ++ goto out; ++ } ++ ++ for (i = 0; i < num_motd_dirs; i++) { ++ dirscans_sizes[i] = scandir(motd_dir_path_split[i], &(dirscans[i]), ++ filter_dirents, alphasort); ++ if (dirscans_sizes[i] < 0) { ++ pam_syslog(pamh, LOG_ERR, "pam_motd: error scanning directory %s", motd_dir_path_split[i]); ++ dirscans_sizes[i] = 0; ++ } ++ dirscans_size_total += dirscans_sizes[i]; ++ } ++ ++ /* Allocate space for all file names found in the directories, including duplicates. */ ++ if ((dirnames_all = (char **)calloc(dirscans_size_total, ++ sizeof(char *))) == NULL) { ++ pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirname array"); ++ goto out; ++ } ++ ++ for (i = 0; i < dirscans_size_total; i++) { ++ dirnames_all[i] = NULL; ++ } ++ ++ for (i = 0; i < num_motd_dirs; i++) { ++ int j; ++ ++ for (j = 0; j < dirscans_sizes[i]; j++) { ++ dirnames_all[i_dirnames] = dirscans[i][j]->d_name; ++ i_dirnames++; ++ } ++ } ++ ++ qsort(dirnames_all, dirscans_size_total, ++ sizeof(const char *), compare_strings); ++ ++ for (i = 0; i < dirscans_size_total; i++) { ++ int j; ++ ++ if (dirnames_all[i] == NULL) { ++ continue; ++ } ++ ++ /* Skip duplicate file names. */ ++ if (i > 0 && strcmp(dirnames_all[i], dirnames_all[i - 1]) == 0) { ++ continue; ++ } ++ ++ for (j = 0; j < num_motd_dirs; j++) { ++ char *abs_path = NULL; ++ ++ if (join_dir_strings(&abs_path, motd_dir_path_split[j], ++ dirnames_all[i]) < 0) { ++ continue; ++ } ++ ++ if (abs_path != NULL) { ++ int fd = open(abs_path, O_RDONLY, 0); ++ if (fd >= 0) { ++ try_to_display_fd(pamh, fd); ++ close(fd); ++ ++ /* We displayed a file, skip to the next file name. */ ++ break; ++ } ++ } ++ _pam_drop(abs_path); ++ } ++ } ++ ++ out: ++ _pam_drop(dirnames_all); ++ for (i = 0; i < num_motd_dirs; i++) { ++ int j; ++ for (j = 0; j < dirscans_sizes[i]; j++) { ++ _pam_drop(dirscans[i][j]); ++ } ++ _pam_drop(dirscans[i]); ++ } ++ _pam_drop(dirscans_sizes); ++ _pam_drop(dirscans); ++ ++ return; ++} ++ + int pam_sm_open_session(pam_handle_t *pamh, int flags, + int argc, const char **argv) + { + int retval = PAM_IGNORE; + const char *motd_path = NULL; ++ char *motd_path_copy = NULL; ++ int num_motd_paths = 0; ++ char **motd_path_split = NULL; + const char *motd_dir_path = NULL; ++ char *motd_dir_path_copy = NULL; ++ int num_motd_dir_paths = 0; ++ char **motd_dir_path_split = NULL; + + if (flags & PAM_SILENT) { + return retval; +@@ -141,16 +363,52 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, + } + + if (motd_path != NULL) { +- int fd = open(motd_path, O_RDONLY, 0); ++ motd_path_copy = strdup(motd_path); ++ } ++ ++ if (motd_path_copy != NULL) { ++ if (pam_split_string(pamh, motd_path_copy, ':', ++ &motd_path_split, &num_motd_paths) == 0) { ++ goto out; ++ } ++ } ++ ++ if (motd_dir_path != NULL) { ++ motd_dir_path_copy = strdup(motd_dir_path); ++ } + +- if (fd >= 0) { +- try_to_display_fd(pamh, fd); +- close(fd); ++ if (motd_dir_path_copy != NULL) { ++ if (pam_split_string(pamh, motd_dir_path_copy, ':', ++ &motd_dir_path_split, &num_motd_dir_paths) == 0) { ++ goto out; + } + } + +- if (motd_dir_path != NULL) +- try_to_display_directory(pamh, motd_dir_path); ++ if (motd_path_split != NULL) { ++ int i; ++ ++ for (i = 0; i < num_motd_paths; i++) { ++ int fd = open(motd_path_split[i], O_RDONLY, 0); ++ ++ if (fd >= 0) { ++ try_to_display_fd(pamh, fd); ++ close(fd); ++ ++ /* We found and displayed a file, move onto next filename. */ ++ break; ++ } ++ } ++ } ++ ++ if (motd_dir_path_split != NULL) ++ try_to_display_directories_with_overrides(pamh, motd_dir_path_split, ++ num_motd_dir_paths); ++ ++ out: ++ _pam_drop(motd_path_copy); ++ _pam_drop(motd_path_split); ++ _pam_drop(motd_dir_path_copy); ++ _pam_drop(motd_dir_path_split); + + return retval; + } +diff --git a/xtests/Makefile.am b/xtests/Makefile.am +index a6d6f8d..4d5aba3 100644 +--- a/xtests/Makefile.am ++++ b/xtests/Makefile.am +@@ -32,7 +32,10 @@ EXTRA_DIST = run-xtests.sh tst-pam_dispatch1.pamd tst-pam_dispatch2.pamd \ + tst-pam_substack5.pamd tst-pam_substack5a.pamd tst-pam_substack5.sh \ + tst-pam_assemble_line1.pamd tst-pam_assemble_line1.sh \ + tst-pam_pwhistory1.pamd tst-pam_pwhistory1.sh \ +- tst-pam_time1.pamd time.conf ++ tst-pam_time1.pamd time.conf \ ++ tst-pam_motd.sh tst-pam_motd1.sh tst-pam_motd2.sh \ ++ tst-pam_motd3.sh tst-pam_motd4.sh tst-pam_motd1.pamd \ ++ tst-pam_motd2.pamd tst-pam_motd3.pamd tst-pam_motd4.pamd + + XTESTS = tst-pam_dispatch1 tst-pam_dispatch2 tst-pam_dispatch3 \ + tst-pam_dispatch4 tst-pam_dispatch5 \ +@@ -41,7 +44,7 @@ XTESTS = tst-pam_dispatch1 tst-pam_dispatch2 tst-pam_dispatch3 \ + tst-pam_access1 tst-pam_access2 tst-pam_access3 \ + tst-pam_access4 tst-pam_limits1 tst-pam_succeed_if1 \ + tst-pam_group1 tst-pam_authfail tst-pam_authsucceed \ +- tst-pam_pwhistory1 tst-pam_time1 ++ tst-pam_pwhistory1 tst-pam_time1 tst-pam_motd + + NOSRCTESTS = tst-pam_substack1 tst-pam_substack2 tst-pam_substack3 \ + tst-pam_substack4 tst-pam_substack5 tst-pam_assemble_line1 +diff --git a/xtests/tst-pam_motd.c b/xtests/tst-pam_motd.c +new file mode 100644 +index 0000000..bba2f9d +--- /dev/null ++++ b/xtests/tst-pam_motd.c +@@ -0,0 +1,69 @@ ++/* ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, and the entire permission notice in its entirety, ++ * including the disclaimer of warranties. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * ALTERNATIVELY, this product may be distributed under the terms of ++ * the GNU Public License, in which case the provisions of the GPL are ++ * required INSTEAD OF the above restrictions. (This clause is ++ * necessary due to a potential bad interaction between the GPL and ++ * the restrictions contained in a BSD-style copyright.) ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ++ * OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include <config.h> ++#endif ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <security/pam_appl.h> ++#include <security/pam_misc.h> ++ ++static struct pam_conv conv = { ++ misc_conv, ++ NULL ++}; ++ ++int main(int argc, char *argv[]) ++{ ++ pam_handle_t *pamh=NULL; ++ char *tst_arg = NULL; ++ int retval; ++ ++ if (argc > 1) ++ tst_arg = argv[1]; ++ ++ retval = pam_start(tst_arg, NULL, &conv, &pamh); ++ ++ retval = pam_open_session(pamh, 0); ++ ++ retval = pam_close_session(pamh, 0); ++ ++ if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */ ++ pamh = NULL; ++ exit(1); ++ } ++ ++ return ( retval == PAM_SUCCESS ? 0:1 ); /* indicate success */ ++} +diff --git a/xtests/tst-pam_motd.sh b/xtests/tst-pam_motd.sh +new file mode 100755 +index 0000000..9080128 +--- /dev/null ++++ b/xtests/tst-pam_motd.sh +@@ -0,0 +1,8 @@ ++#!/bin/bash ++ ++set -e ++ ++./tst-pam_motd1.sh ++./tst-pam_motd2.sh ++./tst-pam_motd3.sh ++./tst-pam_motd4.sh +diff --git a/xtests/tst-pam_motd1.pamd b/xtests/tst-pam_motd1.pamd +new file mode 100644 +index 0000000..ddea82c +--- /dev/null ++++ b/xtests/tst-pam_motd1.pamd +@@ -0,0 +1,3 @@ ++#%PAM-1.0 ++session required pam_permit.so ++session optional pam_motd.so motd=tst-pam_motd1.d/etc/motd motd_dir=tst-pam_motd1.d/etc/motd.d +diff --git a/xtests/tst-pam_motd1.sh b/xtests/tst-pam_motd1.sh +new file mode 100755 +index 0000000..cc88854 +--- /dev/null ++++ b/xtests/tst-pam_motd1.sh +@@ -0,0 +1,36 @@ ++#!/bin/bash ++ ++TST_DIR="tst-pam_motd1.d" ++ ++function tst_cleanup() { ++ rm -rf "${TST_DIR}" ++ rm -f tst-pam_motd1.out ++} ++ ++mkdir -p ${TST_DIR} ++mkdir -p ${TST_DIR}/etc/motd.d ++ ++# Verify the case of single motd and motd.d directory works ++echo "motd: /etc/motd" > ${TST_DIR}/etc/motd ++echo "motd: /etc/motd.d/test" > ${TST_DIR}/etc/motd.d/test ++ ++./tst-pam_motd tst-pam_motd1 > tst-pam_motd1.out ++ ++RET=$? ++ ++motd_to_show_output=$(cat tst-pam_motd1.out | grep "motd: /etc/motd") ++if [ -z "${motd_to_show_output}" ]; ++then ++ tst_cleanup ++ exit 1 ++fi ++ ++motd_dir_to_show_output=$(cat tst-pam_motd1.out | grep "motd: /etc/motd.d/test") ++if [ -z "${motd_dir_to_show_output}" ]; ++then ++ tst_cleanup ++ exit 1 ++fi ++ ++tst_cleanup ++exit $RET +diff --git a/xtests/tst-pam_motd2.pamd b/xtests/tst-pam_motd2.pamd +new file mode 100644 +index 0000000..8200191 +--- /dev/null ++++ b/xtests/tst-pam_motd2.pamd +@@ -0,0 +1,3 @@ ++#%PAM-1.0 ++session required pam_permit.so ++session optional pam_motd.so motd=tst-pam_motd2.d/etc/motd:tst-pam_motd2.d/run/motd:tst-pam_motd2.d/usr/lib/motd motd_dir=tst-pam_motd2.d/etc/motd.d:tst-pam_motd2.d/run/motd.d:tst-pam_motd2.d/usr/lib/motd.d +diff --git a/xtests/tst-pam_motd2.sh b/xtests/tst-pam_motd2.sh +new file mode 100755 +index 0000000..d26ea92 +--- /dev/null ++++ b/xtests/tst-pam_motd2.sh +@@ -0,0 +1,53 @@ ++#!/bin/bash ++ ++TST_DIR="tst-pam_motd2.d" ++ ++function tst_cleanup() { ++ rm -rf "${TST_DIR}" ++ rm -f tst-pam_motd2.out ++} ++ ++mkdir -p ${TST_DIR} ++mkdir -p ${TST_DIR}/etc/motd.d ++mkdir -p ${TST_DIR}/run/motd.d ++mkdir -p ${TST_DIR}/usr/lib/motd.d ++ ++echo "motd: /etc/motd" > ${TST_DIR}/etc/motd ++echo "motd: /run/motd" > ${TST_DIR}/run/motd ++echo "motd: /usr/lib/motd" > ${TST_DIR}/usr/lib/motd ++ ++# Drop a motd file in test directories such that every overriding ++# condition (for 3 directories in this case) will be seen. ++echo "motd: e0r0u1 in usr/lib - will show" > ${TST_DIR}/usr/lib/motd.d/e0r0u1.motd ++echo "motd: e0r1u0 in run - will show" > ${TST_DIR}/run/motd.d/e0r1u0.motd ++echo "motd: e0r1u1 in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/e0r1u1.motd ++echo "motd: e0r1u1 in run - will show" > ${TST_DIR}/run/motd.d/e0r1u1.motd ++echo "motd: e1r0u0 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r0u0.motd ++echo "motd: e1r0u1 in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/e1r0u1.motd ++echo "motd: e1r0u1 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r0u1.motd ++echo "motd: e1r1u0 in run - not show" > ${TST_DIR}/run/motd.d/e1r1u0.motd ++echo "motd: e1r1u0 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r1u0.motd ++echo "motd: e1r1u1 in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/e1r1u1.motd ++echo "motd: e1r1u1 in run - not show" > ${TST_DIR}/run/motd.d/e1r1u1.motd ++echo "motd: e1r1u1 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r1u1.motd ++ ++./tst-pam_motd tst-pam_motd2 > tst-pam_motd2.out ++ ++RET=$? ++ ++motd_to_show_output=$(cat tst-pam_motd2.out | grep "motd: /etc/motd") ++if [ -z "${motd_to_show_output}" ]; ++then ++ tst_cleanup ++ exit 1 ++fi ++ ++motd_dir_not_show_output=$(cat tst-pam_motd2.out | grep "not show") ++if [ -n "${motd_dir_not_show_output}" ]; ++then ++ tst_cleanup ++ exit 1 ++fi ++ ++tst_cleanup ++exit $RET +diff --git a/xtests/tst-pam_motd3.pamd b/xtests/tst-pam_motd3.pamd +new file mode 100644 +index 0000000..a8b8cbf +--- /dev/null ++++ b/xtests/tst-pam_motd3.pamd +@@ -0,0 +1,3 @@ ++#%PAM-1.0 ++session required pam_permit.so ++session optional pam_motd.so motd=tst-pam_motd3.d/etc/motd:tst-pam_motd3.d/run/motd:tst-pam_motd3.d/usr/lib/motd motd_dir=tst-pam_motd3.d/etc/motd.d:tst-pam_motd3.d/run/motd.d:tst-pam_motd3.d/usr/lib/motd.d +diff --git a/xtests/tst-pam_motd3.sh b/xtests/tst-pam_motd3.sh +new file mode 100755 +index 0000000..e18856b +--- /dev/null ++++ b/xtests/tst-pam_motd3.sh +@@ -0,0 +1,53 @@ ++#!/bin/bash ++ ++TST_DIR="tst-pam_motd3.d" ++ ++function tst_cleanup() { ++ rm -rf "${TST_DIR}" ++ rm -f tst-pam_motd3.out ++} ++ ++mkdir -p ${TST_DIR} ++mkdir -p ${TST_DIR}/etc/motd.d ++mkdir -p ${TST_DIR}/run/motd.d ++mkdir -p ${TST_DIR}/usr/lib/motd.d ++ ++# Verify motd is still displayed when not overridden ++echo "motd: test-show in run - show" > ${TST_DIR}/run/motd.d/test-show.motd ++ ++# Test overridden by a symlink to a file that isn't /dev/null; symlink target should show ++echo "motd: hidden-by-symlink in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/hidden-by-symlink.motd ++echo "motd: test-from-symlink - show" > ${TST_DIR}/test-from-symlink.motd ++ln -sr ${TST_DIR}/test-from-symlink.motd ${TST_DIR}/run/motd.d/hidden-by-symlink.motd ++ ++# Test hidden by a null symlink ++echo "motd: hidden-by-null-symlink in run - not show" > ${TST_DIR}/run/motd.d/hidden-by-null-symlink.motd ++ln -s /dev/null ${TST_DIR}/etc/motd.d/hidden-by-null-symlink.motd ++ ++./tst-pam_motd tst-pam_motd3 > tst-pam_motd3.out ++ ++RET=$? ++ ++motd_dir_not_show_output=$(cat tst-pam_motd3.out | grep "not show") ++if [ -n "${motd_dir_not_show_output}" ]; ++then ++ tst_cleanup ++ exit 1 ++fi ++ ++motd_test_show_output=$(cat tst-pam_motd3.out | grep "test-show.*- show") ++if [ -z "${motd_test_show_output}" ]; ++then ++ tst_cleanup ++ exit 1 ++fi ++ ++motd_general_symlink_show_output=$(cat tst-pam_motd3.out | grep "test-from-symlink.*- show") ++if [ -z "${motd_general_symlink_show_output}" ]; ++then ++ tst_cleanup ++ exit 1 ++fi ++ ++tst_cleanup ++exit $RET +diff --git a/xtests/tst-pam_motd4.pamd b/xtests/tst-pam_motd4.pamd +new file mode 100644 +index 0000000..9dc311a +--- /dev/null ++++ b/xtests/tst-pam_motd4.pamd +@@ -0,0 +1,3 @@ ++#%PAM-1.0 ++session required pam_permit.so ++session optional pam_motd.so motd=tst-pam_motd4.d/etc/motd +diff --git a/xtests/tst-pam_motd4.sh b/xtests/tst-pam_motd4.sh +new file mode 100755 +index 0000000..6022177 +--- /dev/null ++++ b/xtests/tst-pam_motd4.sh +@@ -0,0 +1,27 @@ ++#!/bin/bash ++ ++TST_DIR="tst-pam_motd4.d" ++ ++function tst_cleanup() { ++ rm -rf "${TST_DIR}" ++ rm -f tst-pam_motd4.out ++} ++ ++mkdir -p ${TST_DIR}/etc ++ ++# Verify the case of single motd with no motd_dir given in tst-pam_motd4.pamd ++echo "motd: /etc/motd" > ${TST_DIR}/etc/motd ++ ++./tst-pam_motd tst-pam_motd4 > tst-pam_motd4.out ++ ++RET=$? ++ ++motd_to_show_output=$(cat tst-pam_motd4.out | grep "motd: /etc/motd") ++if [ -z "${motd_to_show_output}" ]; ++then ++ tst_cleanup ++ exit 1 ++fi ++ ++tst_cleanup ++exit $RET diff --git a/source/a/pam/fedora-patches/pam-1.3.1-noflex.patch b/source/a/pam/fedora-patches/pam-1.3.1-noflex.patch new file mode 100644 index 00000000..c65d2253 --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.1-noflex.patch @@ -0,0 +1,24 @@ +diff -up Linux-PAM-1.3.1/doc/Makefile.am.noflex Linux-PAM-1.3.1/doc/Makefile.am +--- Linux-PAM-1.3.1/doc/Makefile.am.noflex 2017-02-10 11:10:15.000000000 +0100 ++++ Linux-PAM-1.3.1/doc/Makefile.am 2018-05-18 14:53:50.300997606 +0200 +@@ -2,7 +2,7 @@ + # Copyright (c) 2005, 2006 Thorsten Kukuk <kukuk@suse.de> + # + +-SUBDIRS = man specs sag adg mwg ++SUBDIRS = man sag adg mwg + + CLEANFILES = *~ + +diff -up Linux-PAM-1.3.1/Makefile.am.noflex Linux-PAM-1.3.1/Makefile.am +--- Linux-PAM-1.3.1/Makefile.am.noflex 2018-05-18 14:53:50.301997629 +0200 ++++ Linux-PAM-1.3.1/Makefile.am 2018-05-18 14:55:31.576353800 +0200 +@@ -4,7 +4,7 @@ + + AUTOMAKE_OPTIONS = 1.9 gnu dist-bzip2 dist-xz check-news + +-SUBDIRS = libpam tests libpamc libpam_misc modules po conf doc examples xtests ++SUBDIRS = libpam tests libpamc libpam_misc modules po doc examples xtests + + CLEANFILES = *~ + diff --git a/source/a/pam/fedora-patches/pam-1.3.1-redhat-modules.patch b/source/a/pam/fedora-patches/pam-1.3.1-redhat-modules.patch new file mode 100644 index 00000000..4d3f3741 --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.1-redhat-modules.patch @@ -0,0 +1,78 @@ +diff -up Linux-PAM-1.3.1/configure.ac.redhat-modules Linux-PAM-1.3.1/configure.ac +--- Linux-PAM-1.3.1/configure.ac.redhat-modules 2018-05-18 12:57:57.000000000 +0200 ++++ Linux-PAM-1.3.1/configure.ac 2018-11-26 12:58:14.623545121 +0100 +@@ -611,10 +611,12 @@ AC_CONFIG_FILES([Makefile libpam/Makefil + libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile \ + po/Makefile.in \ + modules/Makefile \ ++ modules/pam_chroot/Makefile modules/pam_console/Makefile \ ++ modules/pam_postgresok/Makefile \ + modules/pam_access/Makefile modules/pam_cracklib/Makefile \ + modules/pam_debug/Makefile modules/pam_deny/Makefile \ + modules/pam_echo/Makefile modules/pam_env/Makefile \ +- modules/pam_faildelay/Makefile \ ++ modules/pam_faildelay/Makefile modules/pam_faillock/Makefile \ + modules/pam_filter/Makefile modules/pam_filter/upperLOWER/Makefile \ + modules/pam_ftp/Makefile modules/pam_group/Makefile \ + modules/pam_issue/Makefile modules/pam_keyinit/Makefile \ +diff -up Linux-PAM-1.3.1/doc/sag/pam_faillock.xml.redhat-modules Linux-PAM-1.3.1/doc/sag/pam_faillock.xml +--- Linux-PAM-1.3.1/doc/sag/pam_faillock.xml.redhat-modules 2018-11-26 12:58:14.623545121 +0100 ++++ Linux-PAM-1.3.1/doc/sag/pam_faillock.xml 2018-11-26 12:58:14.623545121 +0100 +@@ -0,0 +1,38 @@ ++<?xml version='1.0' encoding='UTF-8'?> ++<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" ++ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> ++<section id='sag-pam_faillock'> ++ <title>pam_faillock - temporarily locking access based on failed authentication attempts during an interval</title> ++ <cmdsynopsis> ++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" ++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//cmdsynopsis[@id = "pam_faillock-cmdsynopsisauth"]/*)'/> ++ </cmdsynopsis> ++ <cmdsynopsis> ++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" ++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//cmdsynopsis[@id = "pam_faillock-cmdsynopsisacct"]/*)'/> ++ </cmdsynopsis> ++ <section id='sag-pam_faillock-description'> ++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" ++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-description"]/*)'/> ++ </section> ++ <section id='sag-pam_faillock-options'> ++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" ++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-options"]/*)'/> ++ </section> ++ <section id='sag-pam_faillock-types'> ++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" ++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-types"]/*)'/> ++ </section> ++ <section id='sag-pam_faillock-return_values'> ++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" ++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-return_values"]/*)'/> ++ </section> ++ <section id='sag-pam_faillock-examples'> ++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" ++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-examples"]/*)'/> ++ </section> ++ <section id='sag-pam_faillock-author'> ++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" ++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-author"]/*)'/> ++ </section> ++</section> +diff -up Linux-PAM-1.3.1/modules/Makefile.am.redhat-modules Linux-PAM-1.3.1/modules/Makefile.am +--- Linux-PAM-1.3.1/modules/Makefile.am.redhat-modules 2017-02-10 11:10:15.000000000 +0100 ++++ Linux-PAM-1.3.1/modules/Makefile.am 2018-11-26 12:58:14.623545121 +0100 +@@ -3,13 +3,14 @@ + # + + SUBDIRS = pam_access pam_cracklib pam_debug pam_deny pam_echo \ ++ pam_chroot pam_console pam_postgresok pam_faillock \ + pam_env pam_exec pam_faildelay pam_filter pam_ftp \ + pam_group pam_issue pam_keyinit pam_lastlog pam_limits \ + pam_listfile pam_localuser pam_loginuid pam_mail \ + pam_mkhomedir pam_motd pam_namespace pam_nologin \ + pam_permit pam_pwhistory pam_rhosts pam_rootok pam_securetty \ + pam_selinux pam_sepermit pam_shells pam_stress \ +- pam_succeed_if pam_tally pam_tally2 pam_time pam_timestamp \ ++ pam_succeed_if pam_time pam_timestamp \ + pam_tty_audit pam_umask \ + pam_unix pam_userdb pam_warn pam_wheel pam_xauth + diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-bcrypt_b.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-bcrypt_b.patch new file mode 100644 index 00000000..bff9d47e --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-bcrypt_b.patch @@ -0,0 +1,34 @@ +From f7abb8c1ef3aa31e6c2564a8aaf69683a77c2016 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org> +Date: Thu, 15 Nov 2018 15:01:57 +0100 +Subject: [PATCH] pam_unix: Use bcrypt b-variant for computing new hashes. + +Bcrypt hashes used the "$2a$" prefix since 1997. +However, in 2011 an implementation bug was discovered in bcrypt +affecting the handling of characters in passphrases with the 8th +bit set. + +Besides fixing the bug, OpenBSD 5.5 introduced the "$2b$" prefix +for a behavior that exactly matches crypt_blowfish's "$2y$", and +the crypt_blowfish implementation supports it as well since v1.1. + +That said new computed bcrypt hashes should use the "$2b$" prefix. + +* modules/pam_unix/passverify.c: Use bcrypt b-variant. +--- + modules/pam_unix/passverify.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c +index 9c1771e2..1f433b3a 100644 +--- a/modules/pam_unix/passverify.c ++++ b/modules/pam_unix/passverify.c +@@ -385,7 +385,7 @@ PAMH_ARG_DECL(char * create_password_hash, + /* algoid = "$1" */ + return crypt_md5_wrapper(password); + } else if (on(UNIX_BLOWFISH_PASS, ctrl)) { +- algoid = "$2a$"; ++ algoid = "$2b$"; + } else if (on(UNIX_SHA256_PASS, ctrl)) { + algoid = "$5$"; + } else if (on(UNIX_SHA512_PASS, ctrl)) { diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-checksalt_syslog.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-checksalt_syslog.patch new file mode 100644 index 00000000..5cbc35b0 --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-checksalt_syslog.patch @@ -0,0 +1,73 @@ +From 86eed7ca01864b9fd17099e57f10f2b9b6b568a1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org> +Date: Mon, 26 Nov 2018 22:33:17 +0100 +Subject: [PATCH] pam_unix: Report unusable hashes found by checksalt to + syslog. + +libxcrypt can be build-time configured to support (or not support) +various hashing methods. Future versions will also have support for +runtime configuration by the system's vendor and/or administrator. + +For that reason adminstrator should be notified by pam if users cannot +log into their account anymore because of such a change in the system's +configuration of libxcrypt. + +Also check for malformed hashes, like descrypt hashes starting with +"$2...", which might have been generated by unsafe base64 encoding +functions as used in glibc <= 2.16. +Such hashes are likely to be rejected by many recent implementations +of libcrypt. + +* modules/pam_unix/passverify.c (verify_pwd_hash): Report unusable +hashes found by checksalt to syslog. +--- + modules/pam_unix/passverify.c | 36 +++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c +index eb2444bb..2c808eb5 100644 +--- a/modules/pam_unix/passverify.c ++++ b/modules/pam_unix/passverify.c +@@ -103,6 +103,42 @@ verify_pwd_hash(const char *p, char *hash, unsigned int nullok) + * Ok, we don't know the crypt algorithm, but maybe + * libcrypt knows about it? We should try it. + */ ++#if defined(CRYPT_CHECKSALT_AVAILABLE) && CRYPT_CHECKSALT_AVAILABLE ++ /* Get the status of the hash from checksalt */ ++ int retval_checksalt = crypt_checksalt(hash); ++ ++ /* ++ * Check for hashing methods that are disabled by ++ * libcrypt configuration and/or system preset. ++ */ ++ if (retval_checksalt == CRYPT_SALT_METHOD_DISABLED) { ++ /* ++ * pam_syslog() needs a pam handle, ++ * but that's not available here. ++ */ ++ helper_log_err(LOG_ERR, ++ "pam_unix(verify_pwd_hash): The method " ++ "for computing the hash \"%.6s\" has been " ++ "disabled in libcrypt by the preset from " ++ "the system's vendor and/or administrator.", ++ hash); ++ } ++ /* ++ * Check for malformed hashes, like descrypt hashes ++ * starting with "$2...", which might have been ++ * generated by unsafe base64 encoding functions ++ * as used in glibc <= 2.16. ++ * Such hashes are likely to be rejected by many ++ * recent implementations of libcrypt. ++ */ ++ if (retval_checksalt == CRYPT_SALT_INVALID) { ++ helper_log_err(LOG_ERR, ++ "pam_unix(verify_pwd_hash): The hash \"%.6s\"" ++ "does not use a method known by the version " ++ "of libcrypt this system is supplied with.", ++ hash); ++ } ++#endif + #ifdef HAVE_CRYPT_R + struct crypt_data *cdata; + cdata = malloc(sizeof(*cdata)); diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-crypt_checksalt.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-crypt_checksalt.patch new file mode 100644 index 00000000..0a74e940 --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-crypt_checksalt.patch @@ -0,0 +1,40 @@ +From 62425bf2a0c72d0e23139d0b285547a7add26251 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org> +Date: Thu, 15 Nov 2018 19:49:44 +0100 +Subject: [PATCH] pam_unix: Add support for crypt_checksalt, if libcrypt + supports it. + +libxcrypt v4.3 has added the crypt_checksalt function to whether +the prefix at the begining of a given hash string refers to a +supported hashing method. + +Future revisions of this function will add support to check whether +the hashing method, the prefix refers to, was disabled or considered +deprecated by the system's factory presets or system administrator. +Furthermore it will be able to detect whether the parameters, which +are used by the corresponding hashing method, being encoded in the +hash string are not considered to be strong enough anymore. + +*modules/pam_unix/passverify.c: Add support for crypt_checksalt. +--- + modules/pam_unix/passverify.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c +index 1f433b3a..6132130a 100644 +--- a/modules/pam_unix/passverify.c ++++ b/modules/pam_unix/passverify.c +@@ -244,7 +244,13 @@ PAMH_ARG_DECL(int check_shadow_expiry, + D(("account expired")); + return PAM_ACCT_EXPIRED; + } ++#if defined(CRYPT_CHECKSALT_AVAILABLE) && CRYPT_CHECKSALT_AVAILABLE ++ if (spent->sp_lstchg == 0 || ++ crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_METHOD_LEGACY || ++ crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_TOO_CHEAP) { ++#else + if (spent->sp_lstchg == 0) { ++#endif + D(("need a new password")); + *daysleft = 0; + return PAM_NEW_AUTHTOK_REQD; diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-fix_checksalt_syslog.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-fix_checksalt_syslog.patch new file mode 100644 index 00000000..41733ae0 --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-fix_checksalt_syslog.patch @@ -0,0 +1,104 @@ +From d8d11db2cef65da5d2afa7acf21aa9c8cd88abed Mon Sep 17 00:00:00 2001 +From: Tomas Mraz <tmraz@fedoraproject.org> +Date: Tue, 27 Nov 2018 16:11:03 +0100 +Subject: [PATCH] pam_unix: Use pam_syslog instead of helper_log_err. + +* modules/pam_unix/passverify.c (verify_pwd_hash): Add pamh argument via + PAMH_ARG_DECL. Call pam_syslog() instead of helper_log_err(). +* modules/pam_unix/passverify.h: Adjust the declaration of verify_pwd_hash(). +* modules/pam_unix/support.c (_unix_verify_password): Add the pamh argument + to verify_pwd_hash() call. +--- + modules/pam_unix/passverify.c | 24 +++++++++++++----------- + modules/pam_unix/passverify.h | 6 +++--- + modules/pam_unix/support.c | 2 +- + 3 files changed, 17 insertions(+), 15 deletions(-) + +diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c +index 2c808eb5..80e32767 100644 +--- a/modules/pam_unix/passverify.c ++++ b/modules/pam_unix/passverify.c +@@ -65,8 +65,8 @@ strip_hpux_aging(char *hash) + } + } + +-int +-verify_pwd_hash(const char *p, char *hash, unsigned int nullok) ++PAMH_ARG_DECL(int verify_pwd_hash, ++ const char *p, char *hash, unsigned int nullok) + { + size_t hash_len; + char *pp = NULL; +@@ -116,11 +116,10 @@ verify_pwd_hash(const char *p, char *hash, unsigned int nullok) + * pam_syslog() needs a pam handle, + * but that's not available here. + */ +- helper_log_err(LOG_ERR, +- "pam_unix(verify_pwd_hash): The method " +- "for computing the hash \"%.6s\" has been " +- "disabled in libcrypt by the preset from " +- "the system's vendor and/or administrator.", ++ pam_syslog(pamh, LOG_ERR, ++ "The support for password hash \"%.6s\" " ++ "has been disabled in libcrypt " ++ "configuration.", + hash); + } + /* +@@ -132,12 +131,15 @@ verify_pwd_hash(const char *p, char *hash, unsigned int nullok) + * recent implementations of libcrypt. + */ + if (retval_checksalt == CRYPT_SALT_INVALID) { +- helper_log_err(LOG_ERR, +- "pam_unix(verify_pwd_hash): The hash \"%.6s\"" +- "does not use a method known by the version " +- "of libcrypt this system is supplied with.", ++ pam_syslog(pamh, LOG_ERR, ++ "The password hash \"%.6s\" is unknown to " ++ "libcrypt.", + hash); + } ++#else ++#ifndef HELPER_COMPILE ++ (void)pamh; ++#endif + #endif + #ifdef HAVE_CRYPT_R + struct crypt_data *cdata; +diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h +index 086c28ac..e9a88fbf 100644 +--- a/modules/pam_unix/passverify.h ++++ b/modules/pam_unix/passverify.h +@@ -12,9 +12,6 @@ + + #define OLD_PASSWORDS_FILE "/etc/security/opasswd" + +-int +-verify_pwd_hash(const char *p, char *hash, unsigned int nullok); +- + int + is_pwd_shadowed(const struct passwd *pwd); + +@@ -65,6 +62,9 @@ read_passwords(int fd, int npass, char **passwords); + #define PAMH_ARG(...) pamh, __VA_ARGS__ + #endif + ++PAMH_ARG_DECL(int verify_pwd_hash, ++ const char *p, char *hash, unsigned int nullok); ++ + PAMH_ARG_DECL(char * create_password_hash, + const char *password, unsigned long long ctrl, int rounds); + +diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c +index 6894288d..ea5594d2 100644 +--- a/modules/pam_unix/support.c ++++ b/modules/pam_unix/support.c +@@ -770,7 +770,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name + } + } + } else { +- retval = verify_pwd_hash(p, salt, off(UNIX__NONULL, ctrl)); ++ retval = verify_pwd_hash(pamh, p, salt, off(UNIX__NONULL, ctrl)); + } + + if (retval == PAM_SUCCESS) { diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-gensalt-autoentropy.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-gensalt-autoentropy.patch new file mode 100644 index 00000000..8ae4abfd --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-gensalt-autoentropy.patch @@ -0,0 +1,95 @@ +From 05aa693b7db6b818d31e41f0cab1d5fb4f49600e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org> +Date: Thu, 15 Nov 2018 15:58:56 +0100 +Subject: [PATCH] pam_unix: Prefer a gensalt function, that supports auto + entropy. + +* modules/pam_unix/pam_unix_passwd.c: Initialize rounds parameter to 0. +* modules/pam_unix/passverify.c: Prefer gensalt with auto entropy. +* modules/pam_unix/support.c: Fix sanitizing of rounds parameter. +--- + modules/pam_unix/pam_unix_passwd.c | 2 +- + modules/pam_unix/passverify.c | 13 +++++++++++++ + modules/pam_unix/support.c | 7 +++++-- + 3 files changed, 19 insertions(+), 3 deletions(-) + +Index: Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c +=================================================================== +--- Linux-PAM-1.3.1.orig/modules/pam_unix/pam_unix_passwd.c ++++ Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c +@@ -607,7 +607,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int + unsigned int ctrl, lctrl; + int retval; + int remember = -1; +- int rounds = -1; ++ int rounds = 0; + int pass_min_len = 0; + + /* <DO NOT free() THESE> */ +Index: Linux-PAM-1.3.1/modules/pam_unix/passverify.c +=================================================================== +--- Linux-PAM-1.3.1.orig/modules/pam_unix/passverify.c ++++ Linux-PAM-1.3.1/modules/pam_unix/passverify.c +@@ -375,7 +375,12 @@ PAMH_ARG_DECL(char * create_password_has + const char *password, unsigned int ctrl, int rounds) + { + const char *algoid; ++#if defined(CRYPT_GENSALT_OUTPUT_SIZE) && CRYPT_GENSALT_OUTPUT_SIZE > 64 ++ /* Strings returned by crypt_gensalt_rn will be no longer than this. */ ++ char salt[CRYPT_GENSALT_OUTPUT_SIZE]; ++#else + char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */ ++#endif + char *sp; + #ifdef HAVE_CRYPT_R + struct crypt_data *cdata = NULL; +@@ -406,6 +411,13 @@ PAMH_ARG_DECL(char * create_password_has + return crypted; + } + ++#if defined(CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY) && CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY ++ /* ++ * Any version of libcrypt supporting auto entropy is ++ * guaranteed to have crypt_gensalt_rn(). ++ */ ++ sp = crypt_gensalt_rn(algoid, rounds, NULL, 0, salt, sizeof(salt)); ++#else + #ifdef HAVE_CRYPT_GENSALT_R + if (on(UNIX_BLOWFISH_PASS, ctrl)) { + char entropy[17]; +@@ -423,6 +435,7 @@ PAMH_ARG_DECL(char * create_password_has + #ifdef HAVE_CRYPT_GENSALT_R + } + #endif ++#endif /* CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY */ + #ifdef HAVE_CRYPT_R + sp = NULL; + cdata = malloc(sizeof(*cdata)); +Index: Linux-PAM-1.3.1/modules/pam_unix/support.c +=================================================================== +--- Linux-PAM-1.3.1.orig/modules/pam_unix/support.c ++++ Linux-PAM-1.3.1/modules/pam_unix/support.c +@@ -175,6 +175,7 @@ int _set_ctrl(pam_handle_t *pamh, int fl + + if (val) { + *rounds = strtol(val, NULL, 10); ++ set(UNIX_ALGO_ROUNDS, ctrl); + free (val); + } + } +@@ -254,11 +255,13 @@ int _set_ctrl(pam_handle_t *pamh, int fl + if (*rounds < 4 || *rounds > 31) + *rounds = 5; + } else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl)) { +- if ((*rounds < 1000) || (*rounds == INT_MAX)) ++ if ((*rounds < 1000) || (*rounds == INT_MAX)) { + /* don't care about bogus values */ ++ *rounds = 0; + unset(UNIX_ALGO_ROUNDS, ctrl); +- if (*rounds >= 10000000) ++ } else if (*rounds >= 10000000) { + *rounds = 9999999; ++ } + } + } + diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-no-fallback.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-no-fallback.patch new file mode 100644 index 00000000..8755cf60 --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-no-fallback.patch @@ -0,0 +1,105 @@ +Index: Linux-PAM-1.3.1/modules/pam_unix/pam_unix.8.xml +=================================================================== +--- Linux-PAM-1.3.1.orig/modules/pam_unix/pam_unix.8.xml ++++ Linux-PAM-1.3.1/modules/pam_unix/pam_unix.8.xml +@@ -293,11 +293,10 @@ + <listitem> + <para> + When a user changes their password next, +- encrypt it with the SHA256 algorithm. If the +- SHA256 algorithm is not known to the <citerefentry> ++ encrypt it with the SHA256 algorithm. The ++ SHA256 algorithm must be supported by the <citerefentry> + <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum> +- </citerefentry> function, +- fall back to MD5. ++ </citerefentry> function. + </para> + </listitem> + </varlistentry> +@@ -308,11 +307,10 @@ + <listitem> + <para> + When a user changes their password next, +- encrypt it with the SHA512 algorithm. If the +- SHA512 algorithm is not known to the <citerefentry> ++ encrypt it with the SHA512 algorithm. The ++ SHA512 algorithm must be supported by the <citerefentry> + <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum> +- </citerefentry> function, +- fall back to MD5. ++ </citerefentry> function. + </para> + </listitem> + </varlistentry> +@@ -323,11 +321,10 @@ + <listitem> + <para> + When a user changes their password next, +- encrypt it with the blowfish algorithm. If the +- blowfish algorithm is not known to the <citerefentry> ++ encrypt it with the blowfish algorithm. The ++ blowfish algorithm must be supported by the <citerefentry> + <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum> +- </citerefentry> function, +- fall back to MD5. ++ </citerefentry> function. + </para> + </listitem> + </varlistentry> +@@ -338,11 +335,10 @@ + <listitem> + <para> + When a user changes their password next, +- encrypt it with the gost-yescrypt algorithm. If the +- gost-yescrypt algorithm is not known to the <citerefentry> ++ encrypt it with the gost-yescrypt algorithm. The ++ gost-yescrypt algorithm must be supported by the <citerefentry> + <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum> +- </citerefentry> function, +- fall back to MD5. ++ </citerefentry> function. + </para> + </listitem> + </varlistentry> +@@ -353,11 +349,10 @@ + <listitem> + <para> + When a user changes their password next, +- encrypt it with the yescrypt algorithm. If the +- yescrypt algorithm is not known to the <citerefentry> ++ encrypt it with the yescrypt algorithm. The ++ yescrypt algorithm must be supported by the <citerefentry> + <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum> +- </citerefentry> function, +- fall back to MD5. ++ </citerefentry> function. + </para> + </listitem> + </varlistentry> +Index: Linux-PAM-1.3.1/modules/pam_unix/passverify.c +=================================================================== +--- Linux-PAM-1.3.1.orig/modules/pam_unix/passverify.c ++++ Linux-PAM-1.3.1/modules/pam_unix/passverify.c +@@ -466,10 +466,9 @@ PAMH_ARG_DECL(char * create_password_has + sp = crypt(password, salt); + #endif + if (!sp || strncmp(algoid, sp, strlen(algoid)) != 0) { +- /* libxcrypt/libc doesn't know the algorithm, use MD5 */ ++ /* libxcrypt/libc doesn't know the algorithm, error out */ + pam_syslog(pamh, LOG_ERR, +- "Algo %s not supported by the crypto backend, " +- "falling back to MD5\n", ++ "Algo %s not supported by the crypto backend.\n", + on(UNIX_YESCRYPT_PASS, ctrl) ? "yescrypt" : + on(UNIX_GOST_YESCRYPT_PASS, ctrl) ? "gost_yescrypt" : + on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" : +@@ -481,7 +480,7 @@ PAMH_ARG_DECL(char * create_password_has + #ifdef HAVE_CRYPT_R + free(cdata); + #endif +- return crypt_md5_wrapper(password); ++ return NULL; + } + sp = x_strdup(sp); + #ifdef HAVE_CRYPT_R diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-remove-obsolete-_unix_read_password-prototype.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-remove-obsolete-_unix_read_password-prototype.patch new file mode 100644 index 00000000..14f285de --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-remove-obsolete-_unix_read_password-prototype.patch @@ -0,0 +1,34 @@ +From a2b72aeb86f297d349bc9e6a8f059fedf97a499a Mon Sep 17 00:00:00 2001 +From: "Dmitry V. Levin" <ldv@altlinux.org> +Date: Thu, 31 May 2018 00:20:18 +0000 +Subject: [PATCH] pam_unix: remove obsolete _unix_read_password prototype + +The function was removed by commit Linux-PAM-1.3.0~5 +so the function prototype should go as well. + +* modules/pam_unix/support.h (_unix_read_password): Remove. + +Complements: 7e09188c5dc4 ("pam_unix: Use pam_get_authtok() instead of +direct pam_prompt() calls.") +--- + modules/pam_unix/support.h | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h +index b4c279c3..543e9b9f 100644 +--- a/modules/pam_unix/support.h ++++ b/modules/pam_unix/support.h +@@ -164,13 +164,6 @@ extern int _unix_blankpasswd(pam_handle_t *pamh,unsigned int ctrl, + const char *name); + extern int _unix_verify_password(pam_handle_t * pamh, const char *name + ,const char *p, unsigned int ctrl); +-extern int _unix_read_password(pam_handle_t * pamh +- ,unsigned int ctrl +- ,const char *comment +- ,const char *prompt1 +- ,const char *prompt2 +- ,const char *data_name +- ,const void **pass); + + extern int _unix_run_verify_binary(pam_handle_t *pamh, + unsigned int ctrl, const char *user, int *daysleft); diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-yescrypt.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-yescrypt.patch new file mode 100644 index 00000000..f04a59ce --- /dev/null +++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-yescrypt.patch @@ -0,0 +1,479 @@ +From 16bd523f85ede9fa9115f80e826f2d803d7e61d4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org> +Date: Thu, 15 Nov 2018 16:38:05 +0100 +Subject: [PATCH] pam_unix: Add support for (gost-)yescrypt hashing methods. + +libxcrypt (v4.2 and later) has added support for the yescrypt +hashing method; gost-yescrypt has been added in v4.3. + +* modules/pam_unix/pam_unix.8.xml: Documentation for (gost-)yescrypt. +* modules/pam_unix/pam_unix_acct.c: Use 64 bit type for control flags. +* modules/pam_unix/pam_unix_auth.c: Likewise. +* modules/pam_unix/pam_unix_passwd.c: Likewise. +* modules/pam_unix/pam_unix_sess.c: Likewise. +* modules/pam_unix/passverify.c: Add support for (gost-)yescrypt. +* modules/pam_unix/passverify.h: Use 64 bit type for control flags. +* modules/pam_unix/support.c: Set sane rounds for (gost-)yescrypt. +* modules/pam_unix/support.h: Add support for (gost-)yescrypt. +--- + modules/pam_unix/pam_unix.8.xml | 35 +++++++++- + modules/pam_unix/pam_unix_acct.c | 4 +- + modules/pam_unix/pam_unix_auth.c | 4 +- + modules/pam_unix/pam_unix_passwd.c | 12 ++-- + modules/pam_unix/pam_unix_sess.c | 4 +- + modules/pam_unix/passverify.c | 8 ++- + modules/pam_unix/passverify.h | 2 +- + modules/pam_unix/support.c | 33 ++++++---- + modules/pam_unix/support.h | 101 +++++++++++++++-------------- + 9 files changed, 128 insertions(+), 75 deletions(-) + +diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml +index 1b318f11..cae2aeaa 100644 +--- a/modules/pam_unix/pam_unix.8.xml ++++ b/modules/pam_unix/pam_unix.8.xml +@@ -331,14 +331,45 @@ + </para> + </listitem> + </varlistentry> ++ <varlistentry> ++ <term> ++ <option>gost_yescrypt</option> ++ </term> ++ <listitem> ++ <para> ++ When a user changes their password next, ++ encrypt it with the gost-yescrypt algorithm. If the ++ gost-yescrypt algorithm is not known to the <citerefentry> ++ <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum> ++ </citerefentry> function, ++ fall back to MD5. ++ </para> ++ </listitem> ++ </varlistentry> ++ <varlistentry> ++ <term> ++ <option>yescrypt</option> ++ </term> ++ <listitem> ++ <para> ++ When a user changes their password next, ++ encrypt it with the yescrypt algorithm. If the ++ yescrypt algorithm is not known to the <citerefentry> ++ <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum> ++ </citerefentry> function, ++ fall back to MD5. ++ </para> ++ </listitem> ++ </varlistentry> + <varlistentry> + <term> + <option>rounds=<replaceable>n</replaceable></option> + </term> + <listitem> + <para> +- Set the optional number of rounds of the SHA256, SHA512 +- and blowfish password hashing algorithms to ++ Set the optional number of rounds of the SHA256, SHA512, ++ blowfish, gost-yescrypt, and yescrypt password hashing ++ algorithms to + <replaceable>n</replaceable>. + </para> + </listitem> +diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c +index fbc84e2f..d8d084ac 100644 +--- a/modules/pam_unix/pam_unix_acct.c ++++ b/modules/pam_unix/pam_unix_acct.c +@@ -62,7 +62,7 @@ + #include "support.h" + #include "passverify.h" + +-int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, ++int _unix_run_verify_binary(pam_handle_t *pamh, unsigned long long ctrl, + const char *user, int *daysleft) + { + int retval=0, child, fds[2]; +@@ -185,7 +185,7 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, + int + pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) + { +- unsigned int ctrl; ++ unsigned long long ctrl; + const void *void_uname; + const char *uname; + int retval, daysleft; +diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c +index 9d9f709d..905fc66c 100644 +--- a/modules/pam_unix/pam_unix_auth.c ++++ b/modules/pam_unix/pam_unix_auth.c +@@ -96,7 +96,7 @@ setcred_free (pam_handle_t *pamh UNUSED, void *ptr, int err UNUSED) + int + pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) + { +- unsigned int ctrl; ++ unsigned long long ctrl; + int retval, *ret_data = NULL; + const char *name; + const char *p; +@@ -194,7 +194,7 @@ pam_sm_setcred (pam_handle_t *pamh, int flags, + { + int retval; + const void *pretval = NULL; +- unsigned int ctrl; ++ unsigned long long ctrl; + + D(("called.")); + +diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c +index f2c42513..df4c1233 100644 +--- a/modules/pam_unix/pam_unix_passwd.c ++++ b/modules/pam_unix/pam_unix_passwd.c +@@ -138,7 +138,7 @@ __taddr2port (const struct netconfig *nconf, const struct netbuf *nbuf) + } + #endif + +-static char *getNISserver(pam_handle_t *pamh, unsigned int ctrl) ++static char *getNISserver(pam_handle_t *pamh, unsigned long long ctrl) + { + char *master; + char *domainname; +@@ -233,7 +233,7 @@ static char *getNISserver(pam_handle_t *pamh, unsigned int ctrl) + + #ifdef WITH_SELINUX + +-static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user, ++static int _unix_run_update_binary(pam_handle_t *pamh, unsigned long long ctrl, const char *user, + const char *fromwhat, const char *towhat, int remember) + { + int retval, child, fds[2]; +@@ -388,7 +388,7 @@ static int check_old_password(const char *forwho, const char *newpass) + + static int _do_setpass(pam_handle_t* pamh, const char *forwho, + const char *fromwhat, +- char *towhat, unsigned int ctrl, int remember) ++ char *towhat, unsigned long long ctrl, int remember) + { + struct passwd *pwd = NULL; + int retval = 0; +@@ -512,7 +512,7 @@ static int _do_setpass(pam_handle_t* pamh, const char *forwho, + return retval; + } + +-static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned int ctrl) ++static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned long long ctrl) + { + struct passwd *pwent = NULL; /* Password and shadow password */ + struct spwd *spent = NULL; /* file entries for the user */ +@@ -542,7 +542,7 @@ static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned in + } + + static int _pam_unix_approve_pass(pam_handle_t * pamh +- ,unsigned int ctrl ++ ,unsigned long long ctrl + ,const char *pass_old + ,const char *pass_new, + int pass_min_len) +@@ -600,7 +600,7 @@ static int _pam_unix_approve_pass(pam_handle_t * pamh + int + pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) + { +- unsigned int ctrl, lctrl; ++ unsigned long long ctrl, lctrl; + int retval; + int remember = -1; + int rounds = 0; +diff --git a/modules/pam_unix/pam_unix_sess.c b/modules/pam_unix/pam_unix_sess.c +index 03e7dcd9..4b8af530 100644 +--- a/modules/pam_unix/pam_unix_sess.c ++++ b/modules/pam_unix/pam_unix_sess.c +@@ -67,7 +67,7 @@ int + pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) + { + char *user_name, *service; +- unsigned int ctrl; ++ unsigned long long ctrl; + int retval; + const char *login_name; + +@@ -103,7 +103,7 @@ int + pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) + { + char *user_name, *service; +- unsigned int ctrl; ++ unsigned long long ctrl; + int retval; + + D(("called.")); +diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c +index 95dfe528..39e2bfac 100644 +--- a/modules/pam_unix/passverify.c ++++ b/modules/pam_unix/passverify.c +@@ -387,7 +387,7 @@ crypt_md5_wrapper(const char *pass_new) + } + + PAMH_ARG_DECL(char * create_password_hash, +- const char *password, unsigned int ctrl, int rounds) ++ const char *password, unsigned long long ctrl, int rounds) + { + const char *algoid; + #if defined(CRYPT_GENSALT_OUTPUT_SIZE) && CRYPT_GENSALT_OUTPUT_SIZE > 64 +@@ -404,6 +404,10 @@ PAMH_ARG_DECL(char * create_password_hash, + if (on(UNIX_MD5_PASS, ctrl)) { + /* algoid = "$1" */ + return crypt_md5_wrapper(password); ++ } else if (on(UNIX_YESCRYPT_PASS, ctrl)) { ++ algoid = "$y$"; ++ } else if (on(UNIX_GOST_YESCRYPT_PASS, ctrl)) { ++ algoid = "$gy$"; + } else if (on(UNIX_BLOWFISH_PASS, ctrl)) { + algoid = "$2b$"; + } else if (on(UNIX_SHA256_PASS, ctrl)) { +@@ -466,6 +470,8 @@ PAMH_ARG_DECL(char * create_password_hash, + pam_syslog(pamh, LOG_ERR, + "Algo %s not supported by the crypto backend, " + "falling back to MD5\n", ++ on(UNIX_YESCRYPT_PASS, ctrl) ? "yescrypt" : ++ on(UNIX_GOST_YESCRYPT_PASS, ctrl) ? "gost_yescrypt" : + on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" : + on(UNIX_SHA256_PASS, ctrl) ? "sha256" : + on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid); +diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h +index caf7ae8a..086c28ac 100644 +--- a/modules/pam_unix/passverify.h ++++ b/modules/pam_unix/passverify.h +@@ -66,7 +66,7 @@ read_passwords(int fd, int npass, char **passwords); + #endif + + PAMH_ARG_DECL(char * create_password_hash, +- const char *password, unsigned int ctrl, int rounds); ++ const char *password, unsigned long long ctrl, int rounds); + + PAMH_ARG_DECL(int get_account_info, + const char *name, struct passwd **pwd, struct spwd **spwdent); +diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c +index 8cbc4217..6894288d 100644 +--- a/modules/pam_unix/support.c ++++ b/modules/pam_unix/support.c +@@ -107,7 +107,7 @@ search_key (const char *key, const char *filename) + + /* this is a front-end for module-application conversations */ + +-int _make_remark(pam_handle_t * pamh, unsigned int ctrl, ++int _make_remark(pam_handle_t * pamh, unsigned long long ctrl, + int type, const char *text) + { + int retval = PAM_SUCCESS; +@@ -122,10 +122,11 @@ int _make_remark(pam_handle_t * pamh, unsigned int ctrl, + * set the control flags for the UNIX module. + */ + +-int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds, +- int *pass_min_len, int argc, const char **argv) ++unsigned long long _set_ctrl(pam_handle_t *pamh, int flags, int *remember, ++ int *rounds, int *pass_min_len, int argc, ++ const char **argv) + { +- unsigned int ctrl; ++ unsigned long long ctrl; + char *val; + int j; + +@@ -243,15 +244,23 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds, + set(UNIX__NONULL, ctrl); + } + +- /* Set default rounds for blowfish */ +- if (on(UNIX_BLOWFISH_PASS, ctrl) && off(UNIX_ALGO_ROUNDS, ctrl) && rounds != NULL) { +- *rounds = 5; +- set(UNIX_ALGO_ROUNDS, ctrl); ++ /* Set default rounds for blowfish, gost-yescrypt and yescrypt */ ++ if (off(UNIX_ALGO_ROUNDS, ctrl) && rounds != NULL) { ++ if (on(UNIX_BLOWFISH_PASS, ctrl) || ++ on(UNIX_GOST_YESCRYPT_PASS, ctrl) || ++ on(UNIX_YESCRYPT_PASS, ctrl)) { ++ *rounds = 5; ++ set(UNIX_ALGO_ROUNDS, ctrl); ++ } + } + + /* Enforce sane "rounds" values */ + if (on(UNIX_ALGO_ROUNDS, ctrl)) { +- if (on(UNIX_BLOWFISH_PASS, ctrl)) { ++ if (on(UNIX_GOST_YESCRYPT_PASS, ctrl) || ++ on(UNIX_YESCRYPT_PASS, ctrl)) { ++ if (*rounds < 3 || *rounds > 11) ++ *rounds = 5; ++ } else if (on(UNIX_BLOWFISH_PASS, ctrl)) { + if (*rounds < 4 || *rounds > 31) + *rounds = 5; + } else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl)) { +@@ -532,7 +541,7 @@ int _unix_comesfromsource(pam_handle_t *pamh, + #include <sys/wait.h> + + static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, +- unsigned int ctrl, const char *user) ++ unsigned long long ctrl, const char *user) + { + int retval, child, fds[2]; + struct sigaction newsa, oldsa; +@@ -658,7 +667,7 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, + */ + + int +-_unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name) ++_unix_blankpasswd (pam_handle_t *pamh, unsigned long long ctrl, const char *name) + { + struct passwd *pwd = NULL; + char *salt = NULL; +@@ -706,7 +715,7 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name) + } + + int _unix_verify_password(pam_handle_t * pamh, const char *name +- ,const char *p, unsigned int ctrl) ++ ,const char *p, unsigned long long ctrl) + { + struct passwd *pwd = NULL; + char *salt = NULL; +diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h +index 543e9b9f..e02c05e0 100644 +--- a/modules/pam_unix/support.h ++++ b/modules/pam_unix/support.h +@@ -22,8 +22,8 @@ + + typedef struct { + const char *token; +- unsigned int mask; /* shall assume 32 bits of flags */ +- unsigned int flag; ++ unsigned long long mask; /* shall assume 64 bits of flags */ ++ unsigned long long flag; + unsigned int is_hash_algo; + } UNIX_Ctrls; + +@@ -48,7 +48,7 @@ typedef struct { + + /* the generic mask */ + +-#define _ALL_ON_ (~0U) ++#define _ALL_ON_ (~0ULL) + + /* end of macro definitions definitions for the control flags */ + +@@ -98,47 +98,51 @@ typedef struct { + #define UNIX_QUIET 28 /* Don't print informational messages */ + #define UNIX_NO_PASS_EXPIRY 29 /* Don't check for password expiration if not used for authentication */ + #define UNIX_DES 30 /* DES, default */ ++#define UNIX_GOST_YESCRYPT_PASS 31 /* new password hashes will use gost-yescrypt */ ++#define UNIX_YESCRYPT_PASS 32 /* new password hashes will use yescrypt */ + /* -------------- */ +-#define UNIX_CTRLS_ 31 /* number of ctrl arguments defined */ ++#define UNIX_CTRLS_ 33 /* number of ctrl arguments defined */ + +-#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)) ++#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)&&off(UNIX_GOST_YESCRYPT_PASS,ctrl)&&off(UNIX_YESCRYPT_PASS,ctrl)) + + static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = + { +-/* symbol token name ctrl mask ctrl * +- * ----------------------- ------------------- --------------------- -------- */ +- +-/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01, 0}, +-/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02, 0}, +-/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04, 0}, +-/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010, 0}, +-/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060), 020, 0}, +-/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060), 040, 0}, +-/* UNIX_AUTHTOK_TYPE */ {"authtok_type=", _ALL_ON_, 0100, 0}, +-/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600), 0200, 0}, +-/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600), 0400, 0}, +-/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000, 0}, +-/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000, 0}, +-/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000, 0}, +-/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000, 0}, +-/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0260420000), 020000, 1}, +-/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000), 0, 0}, +-/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000, 0}, +-/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000, 0}, +-/* UNIX_NIS */ {"nis", _ALL_ON_, 0200000, 0}, +-/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(0260420000), 0400000, 1}, +-/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000, 0}, +-/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000, 0}, +-/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000, 0}, +-/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000, 0}, +-/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(0260420000), 020000000, 1}, +-/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(0260420000), 040000000, 1}, +-/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000, 0}, +-/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(0260420000), 0200000000, 1}, +-/* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0400000000, 0}, +-/* UNIX_QUIET */ {"quiet", _ALL_ON_, 01000000000, 0}, +-/* UNIX_NO_PASS_EXPIRY */ {"no_pass_expiry", _ALL_ON_, 02000000000, 0}, +-/* UNIX_DES */ {"des", _ALL_ON_^(0260420000), 0, 1}, ++/* symbol token name ctrl mask ctrl * ++ * --------------------------- -------------------- ------------------------- ---------------- */ ++ ++/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01, 0}, ++/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02, 0}, ++/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04, 0}, ++/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010, 0}, ++/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060ULL), 020, 0}, ++/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060ULL), 040, 0}, ++/* UNIX_AUTHTOK_TYPE */ {"authtok_type=", _ALL_ON_, 0100, 0}, ++/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600ULL), 0200, 0}, ++/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600ULL), 0400, 0}, ++/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000, 0}, ++/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000, 0}, ++/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000, 0}, ++/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000, 0}, ++/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(015660420000ULL), 020000, 1}, ++/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000ULL), 0, 0}, ++/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000, 0}, ++/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000, 0}, ++/* UNIX_NIS */ {"nis", _ALL_ON_, 0200000, 0}, ++/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(015660420000ULL), 0400000, 1}, ++/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000, 0}, ++/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000, 0}, ++/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000, 0}, ++/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000, 0}, ++/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(015660420000ULL), 020000000, 1}, ++/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(015660420000ULL), 040000000, 1}, ++/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000, 0}, ++/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(015660420000ULL), 0200000000, 1}, ++/* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0400000000, 0}, ++/* UNIX_QUIET */ {"quiet", _ALL_ON_, 01000000000, 0}, ++/* UNIX_NO_PASS_EXPIRY */ {"no_pass_expiry", _ALL_ON_, 02000000000, 0}, ++/* UNIX_DES */ {"des", _ALL_ON_^(015660420000ULL), 0, 1}, ++/* UNIX_GOST_YESCRYPT_PASS */ {"gost_yescrypt", _ALL_ON_^(015660420000ULL), 04000000000, 1}, ++/* UNIX_YESCRYPT_PASS */ {"yescrypt", _ALL_ON_^(015660420000ULL), 010000000000, 1}, + }; + + #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) +@@ -151,20 +155,23 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = + _pam_drop(xx); \ + } + +-extern int _make_remark(pam_handle_t * pamh, unsigned int ctrl +- ,int type, const char *text); +-extern int _set_ctrl(pam_handle_t * pamh, int flags, int *remember, int *rounds, +- int *pass_min_len, int argc, const char **argv); ++extern int _make_remark(pam_handle_t * pamh, unsigned long long ctrl, ++ int type, const char *text); ++extern unsigned long long _set_ctrl(pam_handle_t * pamh, int flags, ++ int *remember, int *rounds, ++ int *pass_min_len, ++ int argc, const char **argv); + extern int _unix_getpwnam (pam_handle_t *pamh, + const char *name, int files, int nis, + struct passwd **ret); + extern int _unix_comesfromsource (pam_handle_t *pamh, + const char *name, int files, int nis); +-extern int _unix_blankpasswd(pam_handle_t *pamh,unsigned int ctrl, ++extern int _unix_blankpasswd(pam_handle_t *pamh, unsigned long long ctrl, + const char *name); +-extern int _unix_verify_password(pam_handle_t * pamh, const char *name +- ,const char *p, unsigned int ctrl); ++extern int _unix_verify_password(pam_handle_t * pamh, const char *name, ++ const char *p, unsigned long long ctrl); + + extern int _unix_run_verify_binary(pam_handle_t *pamh, +- unsigned int ctrl, const char *user, int *daysleft); ++ unsigned long long ctrl, ++ const char *user, int *daysleft); + #endif /* _PAM_UNIX_SUPPORT_H */ |